So I had a simple program that was roughly click a button and it preformed a task, nothing fancy, very simple. Now, I have added a LOT more features task for it to do. It does about 5 different main more complex tasks. The task have little input in the sense of like the common class/namespace examples dealing with insert name, address, phone number, etc. The task is more like set up the settings(check/uncheck the checkboxes) on how you want to preform the task and then click the button to preform it. The code has grown out of control. So I am now trying to organize it. I am self taught, so I am running into some trouble, but this is what I am thinking so far for organization. Any comments about the proper way to organize this would be appreciated.
namespace namespaceName
class task1Name
methods for task1
class task1Name
methods for task2
class task2Name
methods for task3
class task3Name
methods for task4
class task5Name
methods for task5
Now I also have a windows form for the program and another windows form for the pop up settings window. The big question is where do these fit in exactly? public partial class className : Form? Will this setup allow the methods in the different task classes to still interact with the form webbrowser control? The form has a couple of webbrowser controls and the task are prformed in the webbrowser control.
I guess in general I am just trying to find the best way to manage the code and to properly setup/structure the code. From reading this How to use separate .cs files in C#? maybe I just stick with the one class/file, since the task involve the webbrowser in windows form.
Ive been looking at http://msdn.microsoft.com/en-us/library/w2a9a9s3%28v=vs.100%29.aspx and the related sections listed below the code example
Breaking out your program into more maintainable chunks - the art of refactoring - can be a very challenging, but also a very rewarding, part of programming. Like #Keith said, you'll learn by doing.
The most important advice is to refactor in small, self-contained steps.
There are a number of ways that you could start this. If you want detailed advice, it would help to know what some of the code looks like. For example, what are the "task" methods' signatures (their names, arguments, and return type) and how do they interact with the "settings".
Here's one suggestion I would make. The single-responsibility principle suggests that the separate tasks should be in separate classes (and, usually, that means they should be in separate files - but that doesn't matter to the compiler at all, it's just for readability). If the tasks are in separate classes, they'll need a way to know what the settings on the form are. But the tasks don't care about the fact that the settings are on a form - they just want the values of the settings. So, create a data structure that contains all the settings from the form. Then, write a single method in the form class that reads all the settings from the controls, so you have that all in one place. Then, in your button click handler for each task's button, just call that method to get the settings, and pass the settings to the particular task that you're trying to run. Presto!
Your code would then look something like this: EDIT: I forgot that the WebBrowser control needs to be passed to the tasks. Fixed.
// Note: All classes and structs go in the same namespace, but each goes in its own .cs file.
// Use a struct, rather than a class, when you just need a small set of values to pass around
struct MySettings
{
public int NumberOfWidgets { get; set; }
public string GadgetFilename { get; set; }
public bool LaunchRocket { get; set; }
}
partial class MyForm
{
// ...constructor, etc.
private void ButtonForTask1_Clicked(object sender, EventArgs e)
{
var settings = ReadSettingsFromControls();
var task1 = new Task1(settings);
task1.DoTheTask(ref this.WebBrowserControl1);
}
private void ButtonForTask2_Clicked(object sender, EventArgs e)
{
var settings = ReadSettingsFromControls();
var task2 = new Task2(settings);
task2.DoTheTask(ref this.WebBrowserControl1);
}
// ... and so on for the other tasks
private MySettings ReadSettingsFromControls()
{
return new MySettings
{
NumberOfWidgets = int.Parse(this.txt_NumWidgetsTextBox.Text),
GadgetFilename = this.txt_GadgetFilenameTextBox.Text,
LaunchRocket = this.chk_LaunchPermission.Checked
};
}
}
class Task1
{
// Readonly so it can only be set in the constructor.
// (You generally don't want settings changing while you're running. :))
private readonly MySettings _settings;
public Task1(MySettings settings)
{
_settings = settings;
}
public void DoTheTask(ref WebBrowser browserControl)
{
// TODO: Do something with _settings.NumberOfWidgets and browserControl
// You can use private helper methods in this class to break out the work better
}
}
class Task2 { /* Like Task1... */ }
Hope that helps! Again, if you post some example code, you'll probably get much better advice on how to refactor it.
Related
I am trying to create a system, which processes tasks according to a dataflow network. The network is supposed to be created as something like a plug-in by the users of my system. It is created as a C# assembly containing the network as a type (class) and I would like to provide a visual editor to the user for creating and editing the network. (Editing would consist of adding/removing tasks, moving them around, creating connections between them, ...)
Ideally this would work like the WinForms designer providing visual and interactive editing capabilities integrated into Visual Studio (if possible with the ability to also view the auto-generated source code simultaneously).
Is there a way to create such an editor and register it in VS to be used for types derived from my base type? Any hint regarding feasability, which interface needs to be implemented (?), where stuff needs to be registered and how it needs to be distributed to my user would be greatly appreciated.
For Clarification: I am not looking for a tool to create a data model (visually). To be precise, it is more like this:
// for declaring the content of a task group
public class TaskAttribute: Attribute
{
public TaskAttribute(Type type, string name) {...}
}
// for declaring the flow of data
public class ConnectionAttribute : Attribute
{
public ConnectionAttribute(string source, string output, string destination, string input) {...}
}
// basic task class
public abstract class Task
{
...
}
// basic task group class
public abstract class TaskGroup : Task
{
...
}
// one actual task with a payload of executable code
public class Foo : Task
{
...
}
// a second task with payload code
public class Bar : Task
{
...
}
/* this construct is, what I want to visually create and edit
through some extension of visual studio:
the group of subtasks (or more like a tree)
and all data flowing between these tasks
*/
[Task(typeof(Foo), "foo")]
[Task(typeof(Bar), "bar")]
[Connection("foo", "output2", "bar", "input1")]
public class FooBar : TaskGroup
{
}
Now I am looking for a way, to create a visual editor, which would allow me to create and edit things like this $FooBar$ class, and tell visual studio to use said editor/designer, so my users do not need to write or read and interpret the textual description in the source code, but can use some visualization and mouse interaction instead.
The solution to use a data modelling SDK as mentioned in the comments seems excessive for this purpose and judging from a first glanse at the referenced introduction, I am not really sure, how much freedom there is in creating the actual editor for the my users data. Is there a way to just hook up a dedicated editor without the formal overhead?
See Create custom editors and designers and Document data and document view in custom editors in VS extensibility documentation.
I have WinForms app and multiple forms and want to use ErrorProvider component on each of them EDIT: to check if user input is OK (for example if entered number is in the range etc...) It seems to me useless to drop this component onto each and every form. What if I make one global object (or how to call it) and use it on every form?
My idea:
namespace MyApplication {
static class Program {
public static ErrorProvider EP = new ErrorProvider();
...
And then in that individual form to handle Validating and Validated events:
private void txtBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
if (txtBox1.Text != "correct text") {
e.Cancel = true;
Program.EP.SetError(txtBox1, "You have error in your input");
...
Is this correct approach or should I do it somehow else?
And if I need more global objects, maybe I should put them all together to some separate static class and in the Program create just this one (?)
Thanks.
This approach is valid as long as your individual forms are never running concurrently or your error provider is re-entrant, and your error provider does not need a permanent link back to your forms. From the example that you show it appears that your provider requires you to pass the control on which to set the error state, so it has a good chance of being re-entrant.
It is ok to have global object but I would rather make it a static stateless class if possible. Statelessness will allow for easy thread safety. It is common across .NET to have global (within namespace) static classes, for example FileInfo or Convert.
If you only need a few global methods and they operate on UI elements you can also write some extension methods for System.Windows.Controls.Control or even System.Windows.Controls.TextBox if that's the only control you want. This will give you a bit nicer code:
txtBox1.Validate("correct text", "You have error in your input");
Extension method could look like this:
public static class MyExtension
{
public static void Validate(this TextBox myTextBox, string correctText, string error)
{
if(myTextBox.Text != correctText)
Console.WriteLine(string.Format("{0} [{1} == '{2}']", error, myTextBox.Name, myTextBox.Text));
}
}
Which would give you this message in the console:
You have error in your input [txtBox1 == 'some text']
Look at extension methods documentation if you need more info.
I think you can create a new class that inherits textbox class and add your validations there, then create a new control which is your class and use it where ever you need, in this case you will edit/modify your validations in one place later on.
I f you have very different validations create 2 classes for example: NumericTextBox and StringTextBox
My main MainWindow.xaml.cs has a lot of Task variables and as a consequence a lot of
private void ContentManagerUpdateUI()
{
// ... UI update work here ...
}
private void StartContentManager()
{
contentManager = Task.Factory.StartNew(() => { ContentManagerJob(); }, TaskCreationOptions.LongRunning);
contentManager.ContinueWith((t) => { ContentManagerUpdateUI(); }, TaskScheduler.FromCurrentSynchronizationContext());
}
private void ContentManagerJob()
{
...
}
My question is if there is any best way to take these methods away from the main file?
I just want to make code more logical and cleaner.
Thank you!
==================================
P.S. Hey... I use #region ... #endregion :) But I guess it must be implemented with some static classes or something that lives outside of MainWindow.xaml.cs...
Also I don't think about MVVM because this application doesn't have any user's input at all.
May be I have to redefine my question... I mean what is the best way to arrange multiple variables and methods of Task class of MS TPL.
I am not quite sure whether i understood your question but if you want to logically structure your code without altering its meaning try to think about partial classes.
The .cs code-behind file of a XAML file is declared as partial by default so you can add as much additional partial classes as you want. Of course you have to meet the restrictions for using partial class e.g. all classes that are declared as partial have to be in the same namespace but you find plenty of information on that over the internet.
Hope this helps :)
When thinking of the SRP, I find that an application that I'm writing is getting out of hand for our main interface/form. I'd like to change it before we get too far into the project.
What are some techniques for making a large interface that has a "drawing surface" with toolbars, menus etc? I'd also like it to be easy for this form to be testable. Should there be other classes that know how to control the MainForm such as a ChangedStateTracker (to monitor dirty state), DocumentCreator or something along those lines to "File > New" a new document?
The problem that I'm running into is there are so many methods inside the MainForm.cs and it's really starting to get ugly to maintain.
This can be marked CW if necessary. Any other hints/tips would be greatly appreciated.
If this is an option, I would create a set of user controls that together produce the entire form.
These separate user controls can then have their own responsibility and can be tested separately.
For the logic itself, create classes.
You can create classes like CreateDocumentCommand that implement some functionality. When e.g. the new document button/menu item is clicked, create an instance of this class and execute it.
public interface ICommand
{
bool CanExecute { get; }
void Execute();
}
public class SaveDocumentCommand : ICommand
{
public bool CanExecute
{
get
{
return MainForm.Instance.CurrentDocument.IsDirty;
}
}
public void Execute()
{
// Save your document here.
}
}
This by the way is how WPF does it.
Jeremy Miller has written about this a few times - these should get you started:
http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx
http://www.jeremydmiller.com/ppatterns/default.aspx
Say I have a number of usercontrols, each usercontrol inside a tabitem, inside a window.
For example, let say this is a food collection application. Then we have tabs Fruit, Vegetables and Snacks. Each tab will show a list of food of that subject, and allow the user to add, delete, modify the food in each section. The food is stored in seperate textfiles, i.e. Fruit.txt, Vegetable.txt, Snack.txt
The actual text files might look something like this (vegetable.txt):
Name Carbs Fat
Eggplant 2 1.1
Cucumber 3 0.5
etc
Now this is a large list and there is a load method which pulls all the vegetables out into a List
The question I have is this loadVegetables method is in the code behind file, and I end up repeating this load method all over the place, because I have another of other screens like ReviewAllFood, AddVegetable, etc. along with all the other load methods for fruit and snacks.
This is more of a design question, I'm wondering how I set this up to not repeat this code. I could have a VegetableManager (or something) class where the load method is, but does this actually mean less repeated code? Then in each screen I have to create object of VegetableManager and call its load method anyway. So I guess efficiency wise its no better, but I do achieve a better design.
I think I'm missing something here. It's been a while since I studied cohesion and coupling and I think i'm confusing myself with these concepts at the moment. Appreciate if someone could suggest a design for this situation and explain why they chose it and why its better than how i'm doing it at the moment.
Thanks for reading.
I could have a VegetableManager (or
something) class where the load method
is, but does this actually mean less
repeated code? Then in each screen I
have to create object of
VegetableManager and call its load
method anyway.
The point of doing this is not efficiency (i.e. performance). The point is to encapsulate the details of loading that data into a single isolated object. Say for example that your site gets really big and you decide to move the data storage to a database for scalability and performance. In the existing code as you described, you'll have to go through each user control or page and change the logic of the load method. At the best this is a pain, and at the worst you miss some or copy-paste incorrectly. If the logic is encapsulated into a dedicated object, whose only responsibility is to know how to load the data from somewhere, then you only have to make the change once.
codebehind of user control:
protected void Page_Load(object sender, EventArgs e) {
var veggieManager = new VegetableManager();
VeggieListControl.DataSource = veggieManager.GetAll();
VeggieListControl.DataBind();
}
VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
public ReadOnlyCollection<Vegetable> GetAll() {
if (_veggies == null) {
lock(_veggieLock) { //synchronize access to shared data
if (_veggies == null) { // double-checked lock
// logic to load the data into _veggies
}
}
}
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
GetAll(); // call this to ensure that the data is loaded into _veggies
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Because _veggies is static, there is only one collection of veggies in memory, despite the fact that multiple callers will instantiate VegetableManager. But because it's static, if you have a multi-threaded application (e.g. a website) you must synchronize access to that field across all threads (hence the locks).
This is the tip of the iceberg in terms of good object-orientation. I recommend perusing UncleBob's SOLID principles, and Domain-Driven Design (free e-book).
So, yes you are repeating something, but all you're repeating is a method call, and that is ok to repeat. DRY means to mitigate the duplication of "logical" code, i.e. decision-making and algorithms; simple method calls do not fall under this. However, if you want, you can consolidate logic into a base class do this, effectively isolating the user controls from having to know about VegetableManager, though I think this is object-orientation overkill, or OOO :-)
public abstract class FoodUserControl : UserControl {
protected List<Vegetable> GetVeggies() {
return new VegetableManager().GetAll();
}
}
Then your actual controls would derive from this instead of from UserControl.
Update
Eager-loading VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
static VegetableManager() {
// logic to load veggies from file
}
public ReadOnlyCollection<Vegetable> GetAll() {
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Notice this eager-loading version doesn't have to do double-checked locking around the load code in the constructor. Also notice that the load code is in a static constructor, since this code initializes a static field (otherwise, you'd be reloading the data from the file on every construction into the same shared static field). Because veggies are eager-loaded, you don't need to load in GetAll or Add.
I would suggest pulling the vegetables (or whatever it is you're loading) out once when you read the file. Then you store them in some underlying data model. You can bind the list, and whatever other controls you need to, to the underlying data model. The data gets loaded once, but various views can display it.
EDIT: Adding code
List<T> loadObjects(File file, ILineConversionStrategy strategy) {
// read eaqch line of the file
// for each line
T object = strategy.readLine(line);
list.add(object);
return listOfObjects;
}
EDIT 2: Data model
class FoodModel {
List<Vegetable> getVegetables();
List<Fruit> getFruit();
// etc
}
I would use the repository pattern for this. As a start, create one class containing methods to retrieve the objects from each text file:
public class FoodRepository
{
public IList<Vegetable> GetVegetables() { ... }
public IList<Fruit> GetFruit() { ... }
// etc.
}
This class should be the only class in your application that is aware that foods are actually stored in text files.
Once you get that working you might want to consider caching frequently used data to improve performance.
public interface IEatable {}
class Vegitable : IEatable
{ string Name { get; set; } }
class Fruit : IEatable
{ string Name { get; set; } }
public interface IEatableManager
{
List<Vegitables> LoadEatables(string filePath);
}
public class VetabaleManager : IEatableManager
{
#region IEatableManagerMembers
public List<Vegitable> LoadVegs(string filePath)
{
throw new NotImplementedException();
}
#endregion
}
.
.
.
There are several things you need to consider for using a design like above
Dependency Injection pattern
Continuous Integration
DRY
and a must read:
How can I practice better
object-oriented programming?