|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article is the first in the two part series, and demonstrates a technique to auto-populate Windows Forms using an
The downloadable source and executable code provided includes the example application. I am using Visual Studio .NET 2003 with Framework SDK 1.1 to create this example. Patterns, Levels, Layers and TiersEnterprise solutions should not only be highly available and scalable, but also flexible and reusable to adapt to rapidly changing business requirements. Designing reusable software is not an easy task. It is relatively easy to write not so reusable software than designing and writing software which consists of reusable components. While the former may be a good idea for prototyping, it does not serve us well in the long run. Software designed with reuse in mind is very powerful since it saves a lot of precious time (and thus cost) in developing and debugging code when it can be readily "plugged-in". Design Patterns occupy center stage when it comes to software component reusability. A Pattern describes a recurring problem that occurs in a given context, and based on a set of guiding forces recommends a solution. Patterns make software flexible, elegant and thus reusable. Patterns exist at many different levels of abstraction. Each of these levels can be thought of as being a cluster of design patterns.
Each level could consist of multiple layers e.g. Presentation, Services, Business, Data Access etc. A layer consists of elements at roughly the same level of abstraction. The dependencies in each layer have to be identified to formulate a layering strategy. Building applications without a good strategy for dependency management leads to brittle and fragile components, which are difficult and expensive to maintain, extend, and substitute. If the levels can be thought of as being laid out vertically, the layers would be laid out horizontally. This results in a matrix consisting of cells that define and use proven software design patterns. Each layer from the infrastructure viewpoint has a corresponding tier which in a multi-tier architectural model could be classified as follows...
Best PracticesSeparating disparate code is the key to successful implementation of a well structured application. Keep the code closer to the tier which it needs to interact with. Components that create a user interface and perform user interaction should be factored into the Presentation tier while components that perform database inserts, updates and queries should be a part of the Integration tier. Tight coupling between tiers result in code which is difficult to maintain and reuse. For e.g. consider a windows application which presents a user interface for registering a user in the system. If the code in the Business tier were to use a component from the Presentation tier, a problem could arise when the user interface was changed from a windows form to a web form. using System.Windows.Forms; // Windows Forms
// Windows Application
namespace Win
{
// Windows Form
public class AutoForm : System.Windows.Forms.Form
{
// Members
// Store the state of the form
private void SaveButton_Click(object sender, System.EventArgs e)
{
// Register a new user
AccountManager.Register(this);
}
}
// A class to manage user accounts
public sealed class AccountManager
{
// Register a new user
public static void Register(AutoForm form) { // Process Registration }
}
}
The code for // Windows Application
using System.Windows.Forms; // Windows Forms
using Lib; // For the AccountManager and Registration class
// Presentation Tier (Windows)
namespace Win
{
// Windows Form
public class AutoForm : System.Windows.Forms.Form
{
// The registration information
private State state = new State();
// Members
// Store the state of the form
private void SaveButton_Click(object sender, System.EventArgs e)
{
// Populate state with values from the UI controls
AccountManager.Register(this.state);
}
}
}
// ASP.NET Web Application
using System.Web.UI; // Web Forms
using Lib; // For the AccountManager and Registration class
// Presentation Tier (Web)
namespace Web
{
// Web Form
public class AutoForm : System.Web.UI.Page
{
// The registration information
private State state = new State();
// Members
// Store the state of the form
private void SaveButton_Click(object sender, System.EventArgs e)
{
// Populate state with values from the UI
AccountManager.Register(this.state);
}
}
}
// Class Library
using System;
// Business/Domain Tier
namespace Lib
{
// A class to hold registration information
public class State
{
// Properties corresponding to the controls on the UI
}
// A class to manage user accounts
public sealed class AccountManager
{
// Register a new user
public static void Register(State state) { // Process Registration }
}
}
The dependency on the Introducing AutomatorThe // Store the state of the form
private void SaveButton_Click(object sender, System.EventArgs e)
{
// Store TextBox value
this.state.Username = usernameTextBox.Text;
// Store CheckBox value
this.state.Subscribe = subscribeCheckBox.Checked;
AccountManager.Register(state);
}
Assuming that there is a // Restore the state of the form
private void LoadButton_Click(object sender, System.EventArgs e)
{
// Restore TextBox value
usernameTextBox.Text = this.state.Username;
// Restore CheckBox value
subscribeCheckBox.Checked = this.state.Subscribe;
}
This could be cumbersome and error-prone especially when using complex forms which house a lot of controls. What we need is a utility class namespace Win
{
// Windows Form
public class AutoForm : System.Windows.Forms.Form
{
// Members
// The form automator
private Automator automator;
public AutoForm
{
automator = new Automator(this, this.state);
}
// Store the state of the form
private void SaveButton_Click(object sender, System.EventArgs e)
{
// Store the state using the automator
automator.Store();
// Register the user
AccountManager.Register(this.state);
}
// Restore the state of the form
private void LoadButton_Click(object sender, System.EventArgs e)
{
// Restore the state using the automator
automator.Restore();
}
}
}
Great! But how will this happen? This is done by using the magic of reflection. The property names on the
Closing NoteThis article demonstrates a technique to auto-populate a Windows Form. My next article will abstract some of the code out to make it more flexible and reusable. We will introduce a new Service tier in addition to the Presentation and Business tiers described in this article. The follow up article will demonstrate code reusability in three different types of applications viz. Windows, Web and Web Services. References/Links
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||