Mijn eerste Tech Ed wordt die van 2005. Weliswaar zal ik niet alle dagen aanwezig zijn, omdat ik de toegangskaart van een collega ga delen. De Indigo en Architecture tracks hebben voor mij de voorkeur. Nog een paar weken :D
Interested in accelerating software project that have to deal with complicated domains?
Of course many things can put a project off course, bureaucracy, unclear objectives, lack of resources, to name a few, but it is the approach to design that largely determines how complex software can become. When complexity gets out of hand, the software can no longer be understood well enough to be easily changed or extended. By contrast, a good design can make opportunities out of those complex features.
Some of these design factors are technological, and a great deal of effort has gone into the design of networks, databases, and other technical dimension of software. Books have been written about how to solve these problems. Developers have cultivated their skills.
Yet the most significant complexity of many applications is not technical. It is in the domain itself, the activity or business of the user. When this domain complexity is not dealt with in the design, it won’t matter that the infrastructural technology is well-conceived. A successful design must systematically deal with this central aspect of the software.
It has been a while since I have visited the DDD website and apparently both the pattern summaries and the managers tour guide have been added. Lately I have spend a fair deal of time on bringing DDD to the discussion table, and noticed that my Java oriented developer buddies where able to grasp the concepts straight away. The Microsofters on the other hand are having a difficult time stepping away from the DNA like view on software projects (good old COM) where each project its domain and application logic is crippled to fit in a business logic layer (remember the Customer CustomerManager or Customers classes?). But that is all good… I agree that applications should be logically separated into partitions (tiers) but not in the way it was done because of technology restrictions in the COM era.
Developers get your hands on the Patterns Summaries. Drop me an email with your thoughts afterwards. Manager should take a glimps at the less technical and more organizational information in the Managers Tour.
Sander Gertz posted an excellent summary of our Dutch .NET user group meeting yesterday evening. Frans briefly mentioned the options for Object Relational Mapping: Table, Entity, Domain. Perhaps you’ve noticed (or read) my preference for the Domain approach. I find it hard or impossible to come up with a stable Entity Relation design worthy enough to generate my Data Access and Business support code upon. On top of that, keeping pace with changes in both the ER design and object models while moving forward. We should let go of “the database” and keep a Domain Centric focus maintaining flexibility in a pool of changing requirements. I hope Evans (Domain Driven Design) and Jimmy’s writings (Applying Domain Driven Design and Patterns) will help you as a developer to shift your focus to Domain Driven Design or at least help you to make the trade-off between the options mentioned above. Yesterday I was astonished how few .NET developers actually make the leap to OR-mapping which our Java colleagues made (successfully) a long time ago.
Since the link is still bubbling through the server farm, Drew Marsh supplied a direct link to the files. Do I dare to wreck my VS.NET beta2 VPC :D
update: Sam has beat me to this one.
Imagine a ASP.NET Web Application where we configure each WebForm with a FilePath attribute which points to the physical directory where the WebForm’s ASPX file resides and a Secure attribute indicating whether the WebForm requires authentication. As soon as we mark the WebForm being secure we’ll also need to set the SecureFilePath attribute which points (as you would have guessed) to the physical directory where all secure WebForms live. Since we’re already using Enterprise Library Building Blocks in our application we might just as we’ll integrate in the Enterprise Library Configuration Tool.
The next couple of steps briefly describe this integration process. You can download the accompanied source code here.
We’ll start out by creating a Settings class which wraps the XML configuration data. This class provides our application with a nice typed view of the underlying configuration data as well as the handlebars to accomplish design time configuration support.
[Serializable, XmlRoot("formsSettings"), XmlInclude(typeof (FormData))]
public class FormsSettings
{
public static string SectionName = "paulGielens.formsConfiguration";
private string filePath;
private string secureFilePath;
private FormDataList forms = new FormDataList();
public FormsSettings()
{
}
[XmlAttribute("filePath")]
public string FilePath
{
get { return filePath; }
set { filePath = value; }
}
[XmlAttribute("secureFilePath")]
public string SecureFilePath
{
get { return secureFilePath; }
set { secureFilePath = value; }
}
[XmlArray("forms"), XmlArrayItem("form", typeof (FormData))]
public FormDataList Forms
{
get { return forms; }
}
}
The FormsSettings class consist of a FilePath property and a SecureFilePath property. In our deployment plan we agreed on splitting the secure and non-secure files in separate folders on the web server. If you look closely you’ll notice the Forms property. The Forms property is of the type of FormDataList which is a typed collection class generated by CodeSmith. We’ll use the FormDataList collection to store all our WebForm specific configuration data. And again we’ll need to encapsulate this configuration data in a typed class. In this case the FormsData class.
[Serializable, XmlRoot("form")]
public class FormData
{
string name;
string filePath;
bool secure;
public FormData()
{
}
[XmlAttribute("name")]
public string Name
{
get { return name; }
set { name = value; }
}
[XmlAttribute("filePath")]
public string FilePath
{
get { return filePath; }
set { filePath = value; }
}
[XmlAttribute("secure")]
public bool Secure
{
get { return secure; }
set { secure = value; }
}
}
The FormsData class consists of a Name and Secure property.
So much for the runtime part. Next we’ll look at the hooks provided by the Enterprise Library Configuration Tool to enable design time support over the FormsSettings and FormsData classes.
If you’ll spend some time in the Enterprise Library documentation you’ll find “Configuration Node class. Represents a node from runtime configuration. It allows a visual hierarchical representation of configuration data.“ In other words we have to provide our own ConfigurationNode implementation we’ll call FormsSettingsNode, so that the Enterprise Library Configuration Tool can represent our XML configuration data as a tree node in its “explorer like tree view”.
public class FormsSettingsNode : ConfigurationNode
{
private FormsSettings settings;
public FormsSettingsNode() : this(new FormsSettings())
{
}
public FormsSettingsNode(FormsSettings settings) : base()
{
this.settings = settings;
}
public string FilePath
{
get { return settings.FilePath; }
set { settings.FilePath = value; }
}
public string SecureFilePath
{
get { return settings.SecureFilePath; }
set { settings.SecureFilePath = value; }
}
public FormDataList Forms
{
get { return settings.Forms; }
}
[ReadOnly(true)]
public override string Name
{
get { return base.Name; }
set { base.Name = value; }
}
[Browsable(false)]
public virtual FormsSettings FormsSettings
{
get { return settings; }
}
protected override void OnSited()
{
base.OnSited();
Site.Name = "Paul Gielens Forms Configuration";
}
}
The FormsSettingsNode class has two constructors. The first is used to start up a new configuration file and thus initializes a new instance of the FormsSettings class. The second constructor takes a FormsSettings instance which contains data from a previously saved configuration file. A couple of public properties on the FormSettingsNode class expose the internals of the FormSettings class in the Enterprise Library Configuration Tool’s user interface.
And finally the design manager which registers the new functionality in the Enterprise Library Configuration Tool making good use of the Command Pattern. The design manager also controls all interaction involved in opening and saving our new configuration file. This is all stacked in the the FormsDesignManager class. The new FormsDesignManager class communicates the Enterprise Configurations Tool’s contract by implementing the IConfigurationDesignManager interface.
public class FormsDesignManager : IConfigurationDesignManager
{
public FormsDesignManager()
{
}
public void Register(IServiceProvider serviceProvider)
{
CreateCommands(serviceProvider);
}
public void Open(IServiceProvider serviceProvider)
{
ConfigurationContext configurationContext = ServiceHelper.GetCurrentConfigurationContext(serviceProvider);
if (configurationContext.IsValidSection(FormsSettings.SectionName))
{
FormsSettings settings = null;
FormsSettingsNode node = null;
try
{
settings = (FormsSettings) configurationContext.GetConfiguration(FormsSettings.SectionName);
node = new FormsSettingsNode(settings);
ConfigurationNode configurationNode = ServiceHelper.GetCurrentRootNode(serviceProvider);
configurationNode.Nodes.Add(node);
}
catch (ConfigurationException e)
{
ServiceHelper.LogError(serviceProvider, node, e);
}
}
}
public void Save(IServiceProvider serviceProvider)
{
ConfigurationContext configurationContext = ServiceHelper.GetCurrentConfigurationContext(serviceProvider);
if (configurationContext.IsValidSection(FormsSettings.SectionName))
{
FormsSettingsNode node = null;
try
{
IUIHierarchy hierarchy = ServiceHelper.GetCurrentHierarchy(serviceProvider);
node = hierarchy.FindNodeByType(typeof (FormsSettingsNode)) as FormsSettingsNode;
if (node == null)