Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

code.google.com/p/jpboodhoo!!!
The Static Gateway Pattern
Screen Bound DTO Update (Getting the terminology right)
Nothin But .Net - New York , NY ( October 22nd - 26th, 2007 )
Refactoring to reveal intent
November MSDN Mini-Tour Content
Layering Schemes For Projects (One approach)
Who Said Being Passive Was A Bad Thing?
One Refactoring Missed
Applied Test Driven Development For Web Applications - Part 1 (Video)
Applied Test Driven Development For Web Applications Update
Coding to interfaces
Applied Test Driven Development For Web Applications - Part 1
Enhancing Images With The Decorator Pattern
Dealing with drop down lists with the MVP pattern
Answers To Some Good Questions
Recommended Reading
Webcast Links
Time Is Counting Down To Register For Nothin' But .Net 2.0!!

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 337
This Year: 62
This Month: 13
This Week: 3
Comments: 889

 Wednesday, November 28, 2007
Wednesday, November 28, 2007 11:01:52 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Continuous Integration | Patterns | Programming | Tools )

I finally set up a googlecode project to host source code for the various things I have been doing over the last year. The first major significant contribution is of course the code drop that I promised a week ago now!!

The application is the start of what I hope will evolve to be a great learning resource for lots of things related to .Net development. The application does not currently cover any of the “extra” topics that I did not have time to get covered in the course. This is perfect because as request come in from people (including past students) asking how to tackle a certain problem, I will use this application as the demonstration area where I can tackle the problem, and update the code base, and you will be able to update your local copy and carry on.

I am currently in the midst of a large Smart Client application that I am hoping to be able to harvest pieces of code out and do the exact same thing except for the smart client realm. I have much more experience developing in the smart client realm and that is where I feel most comfortable, so I am looking forward to be able to do another code drop (for a different application) in a couple of months.

I am going to write up another post about the Web Application as it is built very differently from traditional .Net based web applications. In following with the theme for my courses, there are currently no 3rd party frameworks (other than log4net) that have come into play. My goal with this web app is to demonstrate to people how far we can push raw .Net. The goal being that expanding their knowledge of how to creatively leverage .Net, they will be better prepared to jump into frameworks that they may currently feel daunted by. As time goes by, I will swap pieces of the application out with components that people are asking to see meaningful samples on:

  • NHibernate
  • Castle
  • Prototype
  • JQuery
  • ..*

As the app stands right now I see it as the beginning of what will shape up to be a pretty mean machine!!

I am going to post a screencast that will show people how to get started working with the web application. For people who are eager to get going right now, here are the quick and simple steps without a lot of explanation (that will come in the next post):

  • Anonymously checkout the trunk from the google code repository using the following svn command line:
    svn checkout http://jpboodhoo.googlecode.com/svn/trunk/ jpboodhoo-read-only
  • Navigate to the checkout folder
  • Go into the build folder
  • Copy local.properties.xml.template and paste it into the same directory, then rename the copied file to local.properties.xml
  • Open up the local.properties.xml file with your favourite text editor.
  • Modify any of the settings in the file that are different on your machine.
  • Open up a command prompt and navigate to the build directory of the code.
  • type: build load.data and hit enter.
  • type: build test.all.woc
  • type: build run
  • The last task should fail (I haven’t automated everything yet)
  • Create a virtual directory called nothinbutdotnetstore that points at the following location (this location is created after you attempt to run the build run task) : ${checkoutfolder)\build\deploy\web\app
  • After successfully creating the virtual directory try the build run task again.
  • If the web browser pops up pointed at a web page (for the app) you are in business. Feel free to click through the first set of pages that are implemented (only 3 pages are currently implemented).

As far as what I have planned to implement in the web app (that is currently not implemented):

  • Build out a more extensive domain model that encompasses some more advanced scenarios of the application (especially around order processing).
  • Unit Of Work for the service layer
  • Implement a lightweight OR/M layer
  • Integrate some UI frameworks like prototype
  • Eliminate Master Pages completely and switch to a much more elegant template view pattern.
  • Introduce a more robust container (as the current one is a simple dictionary wired up in a simple procedural fashion).
  • Introduce the concepts of lifecycles for the items in the container. Right now, everything wired into the container is essentially a singleton.
  • Introduce CSS based layout for the web pages (working with a designer on this one).
  • Bring security concerns into play
  • Demonstrate how to effectively manage sessions
  • ……lots,lots,lots more!!!

Obviously I will be leaning on people checking out the code and playing around with it and submitting requests for things they would like to see.

There are a couple of things that you will immediately notice about the application:

  • Clean front controller implementation with ASPX pages as the template views. There are no code behind pages in this web application. All web requests are handled by command objects that interact with the service layer, push the details into a “ViewBag” and then choose which view to render.
  • Logical layers in the project are separated using simple folders and namespaces (not full blown projects)
  • Build automation is its own project in the solution (props to Jay Flowers for this inspiration)
  • The current container implements (CustomDependencyContainer) is very simple and is handled by a big procedural application startup task.
  • Compile time support for the database layer. A couple of classes ago I introduced the concept of a generic TableColumn<T> type. In England after introducing this concept Scott Cowan leveraged his knowledge of MyGeneration to automatically generate strongly typed table definitions that we could leverage to do mapping (trust me when I say, this is nothing like datasets). Until moving into OR/M concepts deeper this gives a good place to start as the generation of the TableDefinitions is linked to whenever the SQL files change, so you will get compile errors if column types are now mismatched etc…

There are lots of other things I could talk about, but this code really is the start of what I see being a long running conversation between myself and other people wanting to learn. In all honesty for all of the emails I have not paid attention to this year, hosting code through google will allow me to answer peoples questions in a much more meaningful way as I can point them at this site to see the implementation of the code they had questions about.

I am going to be placing all of the code for presentations that I have done for the last year as well as continue to update it with the source code that comes out of new courses that will be coming out in the new year, and the DNRTv episodes.

Once again, the application is currently in its infancy, but as people start sending in the requests I now will have a venue and example to add upon to answer questions in a much more timely fashion!!!

 

Develop With Passion!!!

 

 

Comments [6] | | # 
 Monday, October 15, 2007
Monday, October 15, 2007 5:50:32 AM (Mountain Standard Time, UTC-07:00) ( Patterns | Programming )

Now I am by no means claiming to be any sort of patterns naming authority, but after you see the same occurent pattern in your applications you often will try to formulate some sort of vocabulary among the team to express the concept that you see occurring over and over again. This is the very nature of how patterns popped up in the first place. This is a pet name that I have come up with for the “recurring” theme you will see demonstrated here. If you are not familiar with the Gateway pattern check out the definition here.

I am going to demonstrate this pattern with an example that most people should have in place at the beginning of a project. Logging.

One of the things about Logging, is that it should be simple. Let’s assume that to get things rolling I really only care about logging informational messages. Assume I have a Calculator class that wants to do some logging, here are some possible code fragments that demonstrate the calculator class taking advantage of logging capabilities:

    public class Calculator
    {
        private ILog log;

        public Calculator(ILog log)
        {
            this.log = log;
        }

        public int Add(int number1,int number2)
        {
            log.InformationalMessage("About to add two numbers");
            return number1 + number2;
        }
    }

In this scenario the calculator is constructed with a log which will take care of logging behaviour on its behalf. I don’t like this as Logging falls under that set of “cross-cutting” concerns, and I don’t want to have to provide all of the objects in my application (domain layer or not) with this extra dependency. Here is another option:

public class Calculator { private ILog log; public Calculator() { } public ILog Log { set { this.log = value; } } public int Add(int number1,int number2) { log.InformationalMessage("About to add two numbers");
return number1 + number2; } }

Again, this is not optimal as it clutters up my object with unecessary noise. From a simplicity perspective, is it simpe for me to specify that “all objects should have a field of type ILog if they want to consume logging functionality? I think that the simplest api would be something like this:

public class Calculator { public int Add(int number1,int number2) { Log.InformationalMessage("About to add two numbers");
return number1 + number2; } }

Right now someone somewhere is screaming about the fact that I just introduced, what looks like, a Singleton. From an API perspective, the line above imposes the least design restrictions on my classes that want to consume logging functionality. The only caveat is that any class that wants to leverage logging is now coupled to the Log class. IMHO this is only an issue if it decreases the ability for me to test or if it decreases the option for me to swap out logging implementations (ex. Log4Net, MS Logging etc).

By the looks of the code above, it would seem that I have pinned myself into a fairly rigid design. I am not going to focus on how I test drive this out, but taking the API above, how could I go about testing the Log class?

With the Static Gateway pattern, the Gateway (in this case the Log class) does not actually do any of the work. It just serves as the entry point to the functionality. If that is the case here is a cut at what the Log class could look like:

public class Log { private static ILogFactory logFactory; public static void InitializeLogFactory(ILogFactory logFactory) { Log.logFactory = logFactory; } public void InformationalMessage(string informationalMessage) { logFactory.Create().InformationalMessage(informationalMessage); } } public interface ILogFactory { ILog Create(); } public interface ILog { void InformationalMessage(string message); }

How could you go about testing this class (I am demonstrating test-after, though the end solution was driven out test first). Here are two tests that prove out the functionality of the log class:

 

[Test] public void Factory_should_be_leveraged_to_create_logger() { MockRepository mockery = new MockRepository(); ILogFactory mockLogFactory = mockery.DynamicMock<ILogFactory>(); ILog mockLog = mockery.DynamicMock<ILog>(); using (mockery.Record()) { Expect.Call(mockLogFactory.Create()).Return(mockLog); } Log.InitializeLogFactory(mockLogFactory); using (mockery.Playback()) { Log.InformationalMessage("blah"); } Log.InitializeLogFactory(null); } [Test] public void Informational_message_call_should_be_delegated_to_created_logger() { MockRepository mockery = new MockRepository(); ILogFactory mockLogFactory = mockery.DynamicMock<ILogFactory>(); ILog mockLog = mockery.DynamicMock<ILog>(); using (mockery.Record()) { SetupResult.For(mockLogFactory.Create()).Return(mockLog); mockLog.InformationalMessage("blah"); } Log.InitializeLogFactory(mockLogFactory); using (mockery.Playback()) { Log.InformationalMessage("blah"); } Log.InitializeLogFactory(null); }

As you can see, these are completely interaction based tests (hence the lack of assertions). I broke up the test for leveraging the factory to create the logger and the delegation to the actual logger into 2 separate tests. I am also using the SetupResult vs Expect in the second test to indicate that, it is not the behaviour I care about testing. It just needs to be there to focus on what I actually care about, the delegation of the Log class to the created ILog implementation (which is currently a mock itself).

The nice thing about this scenario is that neither the Log class, or the clients of the Log class are aware/tied to any one particular ILog implementation. As long as I can prove out the correct interaction between the Log class and it’s dependency, I should be able to swap in any implementation of ILogFactory and the Log class is none the wiser.

The only downside to the current implementation of the Log class is the need for the static field and static method to initialize that field. Outside of introducing other concepts too early, the initialization of the Log class with an ILogFactory implementation is something that can be done at application startup. It is very likely that is should be one of the first things that should happen, as many other objects in the system may rely on the functionality of the Log class.

The only problem with the current solution is that the Log class is coupled to any changes that may occur in the ILog interface. To ensure that the ILog interface can vary independently of the Log class, I am going to make a small change to the API. Instead of calling methods on Log directly. I am going to change Log, and ILogFactory to the following:

public class Log { private static ILogFactory logFactory; public static void InitializeLogFactory(ILogFactory logFactory) { Log.logFactory = logFactory; } public static ILog For(Type type) { return logFactory.CreateFor(type); } public static ILog For(object itemThatRequiresLoggingServices) { return For(itemThatRequiresLoggingServices.GetType()); } }

The nice thing about this change is that now the Log class does not need to have a mirroring method for every method that may exist on the ILog interface. The ILog interface is now free to change independently of the Log class. Which means I could easily add methods to log with a specific logging level, etc. The Log class is now strictly a “Static Gateway” to Logging functionality.

I'll finish up by making a call into this API from the Calculator class: 

public class Calculator { public int Add(int number1,int number2) { Log.For(this).InformationalMessage("About to add 2 numbers"); return number1 + number2; } }

At this point the Calculator class is completely oblivious to the fact that there is currently no concrete ILogFactory/ILog implementation. It just cares about leveraging the Logging gateways “Static” method to have it log on its behalf. When we actually swap in a real ILogFactory & ILog, neither the Calculator or Log class will have to change at all.

In completion here is a quick implementation of an ILogFactory/ILog pair that will output log messages to the console (I’ll leave it up to you to come up with a more testable implementation of the following 2 classes):

public class ConsoleLogFactory : ILogFactory { public ILog CreateFor(Type type) { return new ConsoleLogger(); } private class ConsoleLogger : ILog { public void InformationalMessage(string message) { System.Console.Out.WriteLine(message); } } }

If you were to run the application now (after initializing the Log class with this ILogFactory implementation), you would see messages output to the Console, whenever the Add method on Calcuator was invoked.

In my next post, I’ll demonstrate how to leverage the Static Gateway pattern with respect to an IOC gateway, that will allow me to remove the static field and initilization method on the Log class.

Comments [7] | | # 
 Friday, September 28, 2007
Friday, September 28, 2007 1:12:49 PM (Mountain Standard Time, UTC-07:00) ( Patterns | Programming )

I am going to be posting a small sample that demonstrates what I was talking about in my post describing using Screen Bound DTO’s Presentation Model.

In chatting with a couple of people, they correctly fixed my terminology to use lingo that most people have already got a cursory knowledge of. So with that said, the technique that I described with regards to objects that are designed specific to the screens that they are servicing is the concept of a Presentation Model. DTO’s are still in the picture with respect to the messaging that can occur between presenter and service (and vice versa). The presentation model is their to satisfy the needs of the UI, be if for databinding or other UI needs (such as coloring for rows in a grid, highlighting customers with bad credit etc).

Ok, now we are all on the same page.

 

Comments [0] | | # 
 Monday, June 25, 2007
Monday, June 25, 2007 3:52:19 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Patterns | Programming | Training )

That’s right folks. Nothin But .Net is coming to New York.

The course is going to be held at TCCIT Solutions.

 The course runs for the week of October 22nd – 26th, 2007.

Overview

Nothin But .Net is a five day boot camp that will focus on pragmatically applying .Net within the context of developing a working N-Tiered application. Registrants will learn about advanced features of .Net (2.0/3.0) as they are applied to the task of building a complete application from the UI layer all the way down to the mapping layer.

WARNING!!!!

If you are expecting to come to this course to learn about how to have VS.Net automatically generate an “application” for you, then this course is NOT for you.

This course is all about taking control of the .Net framework and having it work the way you want. This course will place a heavy emphasis on getting back to the basics and making .Net do things the way you want it to, in a predictable and testable way.

This course will focus on a code centric view of application development vs. the typical databinding/designer magic covered by many typical .Net courses. You will walk away with a deep understanding of fundamental aspects of .Net and how these pieces can be used to develop and deliver enterprise scale applications.

Core Concepts Overview

  • Expanding the capabilities of developing with VS.Net - Enter ReSharper (a productivity add-in for Visual Studio .Net)
  • There’s more to life than generated code
  • Automation for the developer
  • Generics ( they’re not just for collections )
  • Back to basics - Rules Of Good Object Oriented Design
  • Dependency Injection
  • Object Relational Mapping in .Net
  • Applying the dependency inversion principle
  • Domain Driven Design
  • Passive View/Supervising Controller (Model View Presenter)
  • Creating layered architectures
  • Driving out functionality and design through testing
  • Taking Control Of Databinding
  • Behavior (Test) Driven Development
  • Core design patterns applied
  • Pragmatic Productivity Tools For Developers

Although the list may look rather daunting, the majority of the bullet points will be covered during the evolutionary design and construction of the sample project.

One of the main goals of the course is to show how to effectively use behavior (test) driven development, design patterns and a solid toolset to develop a portion of a non-trivial application.

The course will allow students to pragmatically apply BDD practices as well as teach people how to utilize fundamental OO concepts and techniques that will allow for them to have cleaner, more loosely coupled architectures. It will also be an opportunity for students to see what is involved in creating applications that utilize a Rich Domain Model,and the supporting infrastructure that is required to use "Plain Old Objects".

I have successfully delivered this course several times with great success. I anticipate that people who are interested will find that this is a very unique course offering, not typical of what is being delivered in the mainstream.

Seats are limited. The course costs $3000/US for a full 5 days. The fee covers:

  • 5 (8 - 14 hour days, depending on the audience availability) of bootcamp style instruction
  • Breakfast
  • Hot Lunch
  • Book - Patterns Of Application Architecture
  • Software – ReSharper 3.0 License

If you have any questions please don't hesitate to contact me at jp@jpboodhoo.com.

To Register for the course please use the following link:

Comments [2] | | # 
 Wednesday, June 13, 2007
Wednesday, June 13, 2007 11:19:35 AM (Mountain Standard Time, UTC-07:00) ( C# | Patterns )

Bil Simser had a post up the other day about Refactoring Dumb, Dumber, and Dumbest away. I had some small suggestions that I offered up and Bil implemented some of the changes that I had mentioned. Here is the code as it stands right now :

public class SegmentConfigurationFactory { /// <summary> /// Gets the configuration given the values provided. /// </summary> /// <param name="cableSegmentCount">The cable segment count.</param> /// <param name="segmentCount">The segment count.</param> /// <param name="passesCount">The passes count.</param> /// <param name="segmentIndex">Index of the segment.</param> /// <param name="supplyVoltage">The supply voltage.</param> /// <param name="voltageDrop">The voltage drop.</param> /// <param name="segmentPercentage">The segment percentage.</param> /// <returns></returns> public ISegmentConfiguration GetConfigurationGiven( int cableSegmentCount, int segmentCount, int passesCount, int segmentIndex, int supplyVoltage, decimal voltageDrop, decimal segmentPercentage ) { ISegmentConfiguration configuration = new DefaultSegmentConfiguration(1, supplyVoltage, voltageDrop); if (segmentCount > 1) { if (cableSegmentCount == 1) { if (passesCount > 1 && (segmentIndex <= (segmentCount - 2))) { configuration = new MultiPassConfiguration(passesCount, supplyVoltage, voltageDrop, segmentPercentage); } else { configuration = new SinglePassConfiguration(cableSegmentCount, supplyVoltage, voltageDrop, segmentPercentage); } } else { configuration = new MultipleCableCountConfiguration(cableSegmentCount, supplyVoltage, voltageDrop, segmentPercentage, passesCount); } } return configuration; } }

I was then asked how I could potentially take the refactoring further. I had mentioned that there were a lot of “magic numbers” in the code, to which Bil correctly replied that there are, but they were numbers that represented real business rules, and as such were not that “magic”. Armed with the following set of rules that center around the messy if statement: 

  • If there is one pass we use a single pass configuration
  • If there is one segment we use the default configuration
  • If there are multiple cables in a segment then we use the multiple cable count configuration
  • If there are multiple passes or the segment we’re looking at is the 2nd last one we use a multiple pass configuration

I decided to take the refactoring a step further to introduce a bit more readability into the Model. I got into mad refactoring mode and decided to pair back the final implementation. The result of the refactoring is as follows: 

public class SegmentConfigurationFactory : ISegmentConfigurationFactory { public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters) { if (new MultiPassSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters)) return new MultiPassSegmentConfigurationFactory().CreateUsing(parameters); if (new SinglePassSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters)) return new SinglePassSegmentConfigurationFactory().CreateUsing(parameters); if (new MultipleCableCountSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters)) return new MultiCableCountSegmentConfigurationFactory().CreateUsing(parameters); return new DefaultSegmentConfigurationFactory().CreateUsing(parameters); } }

The first step to achieve this refactoring was to introduce a parameter object that encapsulated all of the arguments that use to be called on the method. This:

public ISegmentConfiguration GetConfigurationGiven( int cableSegmentCount, int segmentCount, int passesCount, int segmentIndex, int supplyVoltage, decimal voltageDrop, decimal segmentPercentage )

Became this:

public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)

I won’t bother showing the parameter object as it is just an object that exposes all of the original parameters as properties.

Now that I had the parameter object, I could leverage it from a new factory interface:

public interface ISegmentConfigurationFactory { ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters); }

If you look back to the original code you will realize that at each branch that is creating a configuration, a potential different set of arguments is being used. By coming up with an interface for the factory, I can now have specific factories that create specific configurations based on the configuration parameters:

    public class DefaultSegmentConfigurationFactory : ISegmentConfigurationFactory
    {
        public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
        {
            return new DefaultSegmentConfiguration(1, parameters.SupplyVoltage, parameters.VoltageDrop);
        }
    }

public class MultiPassSegmentConfigurationFactory : ISegmentConfigurationFactory { public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters) { return new MultiPassConfiguration(parameters.PassesCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage); } }

public class SinglePassSegmentConfigurationFactory : ISegmentConfigurationFactory { public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters) { return new SinglePassConfiguration(parameters.CableSegmentCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage); } }
 

public class MultiCableCountSegmentConfigurationFactory : ISegmentConfigurationFactory { public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters) { return new MultipleCableCountConfiguration(parameters.CableSegmentCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage, parameters.PassesCount); } }

Each factory is responsible for creating a specific configuration based on the parameters. This introduces a nice separation of responsibilities, because properties can be added to the SegmentConfigurationParameters without introducing any change to the individual factories and the original SegmentConfigurationFactory itself. It also allows each individual factory to only leverage the properties on the parameter object that it needs to. This allows fine grained tests against the individual factories to ensure that they are only pulling from properties that they should be, and that they are providing the configurations they create with the correct information.

That’s great JP, you’ve introduced discrete factories but we are still left with the if statements and “magic” numbers. Remember that at each branch in the if statement (where a configuration is being created) that configuration matches a certain “Specification”. I just gave it away!! I can introduce discrete specifications that encapsulate the business rules so that each conveys more clearly what “Cable” specification it matches. Once again I can use the parameter object in the new interface:

public interface ISegmentConfigurationParametersSpecification { bool IsSatisfiedBy(SegmentConfigurationParameters parameters); }

If you are not familiar with the specification pattern you can stay tuned to DNRTv as I am going to be drilling down deep into the pattern (way more than I am showing here!!). Here are specifications for the main types of configuration:

public class MultiPassSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification { public bool IsSatisfiedBy(SegmentConfigurationParameters parameters) { return parameters.SegmentCount > 1 && parameters.CableSegmentCount == 1 && parameters.PassesCount > 1 && (parameters.SegmentIndex <= (parameters.SegmentCount - 2)); } }
 

public class SinglePassSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification { public bool IsSatisfiedBy(SegmentConfigurationParameters parameters) { return parameters.SegmentCount > 1 && parameters.CableSegmentCount == 1 && parameters.PassesCount == 1; } }

public class MultipleCableCountSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification { public bool IsSatisfiedBy(SegmentConfigurationParameters parameters) { return parameters.SegmentCount > 1 && parameters.CableSegmentCount > 1; } }

As you can see, each specification is responsible for answering the question “Does this parameter object meet the ‘Specification’ of a certain type of configuration. Again, each class can be tested independently of one another. Notice that there is duplication between the classes that could be easily refactored out by using composite specifications. I tried to name the specifications and factories so they conveyed clearly to the developers what business rules they were encapsulating.

To recap, the refactorings are as follows:

  • Introduce Parameter Object
  • Replace business specific conditionals with Specification (that is not an actual Refactoring, but I think I’m going to coin that name!!)
  • Introduced discrete factories for the different configurations.

Of course, taken it to the Nth degree you could introduce the following interface (I won’t bother showing the implementation, but I’ll give you a hint ‘Use Object Composition’):

 

public interface ISegmentConfigurationSpecificationBasedFactory : ISegmentConfigurationParametersSpecification,ISegmentConfigurationFactory { }

With that interface in hand SegementConfigurationFactory can become:

public class SegmentConfigurationFactoryToTheMaxx : ISegmentConfigurationFactory { private IEnumerable<ISegmentConfigurationSpecificationBasedFactory> configurationFactories; public SegmentConfigurationFactoryToTheMaxx(ISegmentConfigurationFactory defaultConfigurationFactory, IEnumerable<ISegmentConfigurationSpecificationBasedFactory> configurationFactories) { this.configurationFactories = configurationFactories; } public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters) { foreach (ISegmentConfigurationSpecificationBasedFactory factory in configurationFactories) { if (factory.IsSatisfiedBy(parameters)) return factory.CreateUsing(parameters); } throw new ArgumentException( "There is no factory configured to create a configuration from the set of parameters"); } }

Which now leaves the SegmentConfigurationFactory adhering to OCP.

Once again, like all of the refactorings I have demonstrated on this blog, this is just an example to show that there are always ways you can refactor code. Whether the extent of the refactoring is warranted is something that you have to figure out between you and your team members. I am not suggesting that this is the route you want to go (although it could be).

Have I had to introduce more classes and interfaces? Absolutely. Do I have more testability from going this route? Absolutely. Have I made the domain more resilient to change? I think so.

When you are refactoring to reveal intent, don’t expect that your codebase is going to shrink. To make the model more expressive sometimes you will need to introduce new concepts into the codebase that up the LOC, but increase the readability and maintainability. 

At the end of the day, if the original code conveys intent more clearly (Good rule of thumb is to use the 6 month rule, in 6 months when you come back to look at the code, will it still convey its intent) then that trumps elegance of the code.

In all of this make sure that “Maintainability” trumps all the other “ilities”.

Comments [3] | | # 
 Friday, November 17, 2006
Friday, November 17, 2006 12:46:16 AM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | Patterns | Presentations )

Lots of people ask why I don't usually post my powerpoints and code that I deliver at presentations that I give. For the most part, because of my dynamic and on the fly presentation style, I often show up with no code and build out scenarios on the fly. The resulting code often only makes sense to look at in the context of being an attendee of the presentation.

The same can be equally said for my powerpoints. When I actually have slides prepared, they are used as mere launchpads into either conversation or demonstrations of a new concept.

That aside, I have had a lot of requests for the content from my first mini tour I conducted as part of the MSDN Canada Speakers bureau. I spoke in Regina, Winnipeg, and Saskatoon on three consecutive nights. The code that resulted from each session was quite different, so I decide to post the code that came out of the last session.

The presentation was focused on introducing people to the concept of design patterns. While meant to be a 100 level talk, I definitely threw one 400-500 level example into the mix to spice things up.

Here are the links to the content:

 

 

Feel free to use the slide deck and accompanying source code if you want to deliver your own presentations built on the material. If you do so, I would definitely appreciate being recognized for the work.

If you have any questions I will definitely try to get them answered.

Comments [3] | | # 
 Tuesday, October 31, 2006
Tuesday, October 31, 2006 9:26:10 PM (Mountain Standard Time, UTC-07:00) ( Patterns )

I was recently asked the following question in an email:

Do you know where I can find information (blog or book) on how you are setting up your Domain Object (i.e. in your demo it was Northwind.Domain)?  Is that basically where you keep your rules (i.e. if it such and such customer then give them a 10% discount)?

I took this as a question as to how to go about setting up the layers in the application. Which caused me to go