Reputation: 321
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.
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
Upvotes: 2
Views: 4381
Reputation: 5674
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.
Upvotes: 2