Archive

Archive for October, 2007

VSLive! Day One – Architecting ASP.NET Applications Part 2 – Custom Providers

October 16th, 2007

Custom Providers
The second part of the discussion is opening with a discussion of custom provider development.  This is of great interest to me as my recent work with the Model View Presenter pattern has caused me to research and implement dependency injection for many of the layers of my application.  The current product that I’m working on is implementing the MVP pattern and is using dependency injection to dynamically load a data layer at run time.  There is a need within the product to use a different data access layer assembly for the administrative tools than for the public side of the application.  The murky details behind this decision (which I shall leave aside) are to do with the deployment environment and maintenance cycles of the applications going forward.  There are a few mechanisms for achieving this dynamic load, however I’ve yet to find conclusive evidence that one method is preferable.

The idea behind dependency injection is improve the following fairly typical line of code:
MyClass myClass = new MyClass();

One potential drawback in this line is that the physical class MyClass has been hard-coded as the only implementation that can exist for myClass.  If MyClass implements an interface IMyClass then it might be desirable in the code to switch out the implementation of the interface IMyClass that is being used.  The example du jour is switching out an MS SQL data access library for an Oracle data access library.  In that example, both implement the same interface but the application wishes to decide which library to use at runtime via a configuration setting.  This is a common problem in applications that wish to implement several version of a library than perform very similar but ultimately different tasks.  The provider model is based around this need.

The suggested methodology presented in this talk is to use:
Type myType = Type.GetType(“MyNamespace.MyClassName”);
IMyClass myClass = System.Activator.CreateInstance(myType);

The theory here is that Type.GetType returns an object that describes the type to be created.  The System.Activator.CreateInstance line creates a concrete instance of the requested class except by this mechanism the class has been created using a string name versus a hard-coded class name.  This methodology works for classes that exist within the same assembly, however will not work for classes that exist outside of this assembly.  There is an extension to this will work for classes outside of this assembly.

Dynamically Loading Assemblies
In order to extend this methodology to work for classes that are in other assemblies, there is a need to first load that assembly.  This is achieved via the following methodology:
Assembly asm = Assembly.LoadFile(MyAssemblyFileName);
IMyClass myClass = asm.CreateInstance(MyClassName);

The basic change here is that now the concrete class instance is created from the assembly reference versus System.Activator.  This allows the dyanamically loaded class to reside in a separate assembly.  Now we have the ability to specify which data access layer library is being used within the application at run-time.  All calls within the application are made against the IMyClass interface, but the implementations now differ based upon the physical data access library that is loaded at run-time.

Interface Isolation
Finally, interfaces are isolated into a separate assembly from either (any) of the concrete implementations of that interface.  The reason for this is that we do not want to require a reference from the main application to either of the implementations of the interface.  Such a reference would defeat the purpose of the exercise as it would again tie the application directly to a particular implementation.  Instead the main application references only the assembly that contains the interface.  Now any implementation of that interface can be used from within the main application by dynamically instantiating the implementation using the mechanism above.

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

ASP.NET

VSLive! Day One – Architecting ASP.NET Applications Part 1

October 16th, 2007

Getting Situated
For the preconference, I decided to attend Paul Sherrif’s talk on Architecting ASP.NET Applications.  Fortunately, I was able to get to the room about an hour early and find one of the few seats situated close to a power outlet.  I really didn’t want to have to transfer my notes from paper to my laptop later; I’d rather just type them out directly!

N-Tier Development Benefits
The workshop has begun with a discussion of n-tier development; the benefits of logically separating services into different libraries and isolating functionality into discreet sections.  The advantages of this approach are that the maintenance and extension of your application are vastly simplified.  Refactoring common methods into reusable libraries minimizes the amount of work involved in fixing bugs because the buggy code needs only be fixed in one location.  Adapting to large-scale architectural changes in the application is also easier if a modular development model is adopted.  Switching out small components to adapt to technology shifts is far easier than making global code changes.  This means that large-scale changes can be handled cheaply and quickly.  The majority of the application libraries do not need to be run through a quality assurance cycle because they were not changed when the maintenance was performed.  Only the new library needs to be tested in addition to running a full integration test, which is still far cheaper that re-testing the entire system.  The following is a table detailing the suggested areas of isolation for an ASP.NET application:

Business Rules User Interface Configuration Management
Data Access Service Exception Management Security Management
Data Layer User Tracking Log Management

Configuration Management
As opposed to using the System.Configuration.ConfigurationManager.AppSettings["MyConfigItem"] approach for reading settings, a custom AppConfigManager class can be built that isolates access to configuration settings into static properties on that class.  The argument for this architecture is that when and if the access mechanism for configuration settings changes in future versions of .NET, the changes will be isolated to only the AppConfigManager class.  This is a valid argument because the mechanism for reading configuration settings changed from .NET 1.1 to .NET 2.0.  In .NET 1.1 we used System.Configuration.ConfigurationSettings, however in .NET 2.0 we are encouraged to use System.Configuration.ConfigurationManager instead.  Encapsulating application configuration settings is an architecture I’ve considered several times before but there is something that always makes me balk at the idea of a class full of statics.  The difference here, which I like, is that a sound justification exists and that the statics aren’t just returning constants.  Instead the static is returning a value using the System.Configuration.ConfigurationManager.AppSettings["MyConfigItem"] mechanism.  This does have the nice effect of isolating the final method of configuration management from the rest of the code in the application.  Should the mechanism for accessing configuration settings change in the future, only the AppConfigManager wrapper class will need to be updated.

I could be wrong, but I think Paul just compared using Intellisense to “using the force” ala Star Wars: <sigh>.  At least the humor hasn’t changed since the last conference I attended.  Actually, so far the guy has been pretty funny so I’ll give him a break.

Custom Collection Classes
The major philosophical question that has arisen so far is whether or not to use custom collection classes when transacting between a data layer and a business tier or user interface layer.  The code samples presented use DataTable instances.  The argument presented is that a DataTable is actually analogous to a custom collection class as it has proprietary column names within it that correspond to the unique properties and data types of the business object being modeled.  The only concession offered in the workshop is that this does open a potential window for failure if Microsoft decided to drop support for the DataTable class in favor of a superior class.

Code Generation
For a while now I have separated data adapter classes from object builder classes.  The data adapter classes are responsible for executing sql commands to a database and either writing or reading common data collection classes; such as IDataReader.  The builder classes are responsible for digesting those data collections and building concrete objects from them.  This allows for a nice separation between data interaction and data digestion.  However, I’ve always written both classes by hand.  They do not present a large chunk of work and I have usually disregarded the cost of coding such small functional classes as being negligible.  Code generation is something that has been suggested for these classes in the past, but I have often found that building the required code generation framework can be just as expensive as writing the classes that are needed.  However, the argument being presented in this workshop for code generation is that if the data builder level classes and stored procedures are generated then schema level changes are reflected more quickly.  This is an interesting advantage to note in the argument for using code generation for parts of the data layer.

Deriving Business Rule Objects
The next part of this discussion addresses a second common problem with code generation, that of custom rule application.  A code generator can easily intuit the basic rules that need to be enforced for objects built from a schema, for example that required fields are populated.  However, a code generator cannot easily imply that a cost field needs to be between certain threshold values.  To address this problem, Paul suggests that a custom business rule object be derived from the generated data class.  The data class implements validation as virtual methods that can be overridden in the custom business class.  The overridden method can then apply the additional validation to enforce proprietary business rules.

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

ASP.NET