Archive for the ‘composition’ Tag
Refactoring Quickly with TDD
The situation. I have a class, Edc, that has an interface:
IEdcFinder
It needs to be composed with one of a few data lookup methods. Like a method connecting to SQL or a method connecting to XML. I don’t want the caller to have to configure this finder object with the data method. I’d like to make it easier. Especially since this finder object is already being injected into another class as a pluggable object.
So, logically, move the construction of the finder to a factory method and compose the data method with it then. I created a Factory class:
class EdcFinderFactory
But then, we have another class doing work. So, with TDD, I switched the interface to an abstract class thinking I could use inheritance to mark all subclasses with a private constructor as well – and made the tests pass. Good.
I was feeling OK about how things were going, but not thrilled. I had working code but something smelled. I realized something: there is only one class implementing IEdcFinder and that is EdcFinder. Let’s remove duplication.
Remove: EdcFinderFactory
Remove: IEdc
(There were actually many small steps in here making sure the system still passed.)
Left with:
EdcFinder
public EdcFinder(){..}
public Create(){…inside here we create an EdcFinder composed with IReadSomeData}
So, EdcFinder became a simple concrete class with it’s public constructor and the factory method. And, as always, I ran the tests: Pass. Then the constructor was marked private. Pass. Remove the old abstract class (which was an interface to start with).
Now there was less code, less interfaces and easier to read code. I was able to implement the “Replace Constructor with Factory Method” refactoring in just minutes and I know everything still works.
With TDD and my test suites I could change with out fear.
And two days later, I looked again and removed this entire class realizing it was unnecessary and the data method could be simplified with Func<T>. I switched everything in about an hour. Red, Green, Refactor.
Bon.
Delegate the Work
A staple of any good management class is pounding into young executives’ heads that they should delegate when possible. These gurus of commerce do not say to always delegate because it’s obvious that expert knowledge should sometimes directly handle a task or project. But the premise is solid. And the premise applies to our world of software.
The .NET Framework provides us with a staid and true mechanism for creating delegates and wiring up events. It’s a powerful platform provided for free to us, so taking advantage of it is something a developer should aspire to do without much hesitation. Events are brothers-in-arms with delegates. They work together so smoothly that you might not even realize that events in the Framework and Windows Forms applications are actually using delegates behind the scenes.
Delegates are useful to implement function pointers or callbacks. Here are the basics of a delegate: Defining a delegate lets you invoke other functions that match the definition of the delegate. Right – what does that mean?
First off, a delegate is really a class. It derives from System.Delegate (really, it could also derive from System.MulticastDelegate, but we’re trying to keep thing simple here). So, you can define a delegate and then call it like a method. See Listing 1.
Listing 1 – Define a delegate
Public delegate bool CookDinner(string MainCourse);
So, what does this get you? First notice that the delegate looks like a method definition with a return type and method parameters. That should feel pretty comfortable. But, like I mentioned above, this is actually getting created as a class, so under the hood it is much more than a method. Now that we have this delegate defined we can use set it up for use. See Listing 2.
Listing 2 – Setup the delegate
CookDinner cook = new CookDinner(CookingTacos);
Private bool CookingTacos(string Meat)
{
if(Meat != “vegetable”)
{return true;}
else
{return false;}
}
Note that when we initialize the instance of our delegate, CookDinner, with the variable cook we are passing in a method that matches the delegate’s definition to the constructor. This is very important. All it takes to instantiate an instance of the delegate is a logical pointer to a method. Now take a look at Listing 3 and you’ll see how the delegate is used.
Listing 3 – Use the delegate
FeedTheFamily(cook); //pass in the delegate
Private void FeedTheFamily(CookDinner cookIt)
{
cookIt(“Beef”);
}
This helps us decouple a specific action from each method. Here, we can pass in our delegate to FeedTheFamily and that method is then able to call the method we already defined. So now if we decide that FeedTheFamily needs to cook something else, we change the method that is passed in the CookDinner constructor.
Events owe their livelihood to delegates. Before reading this you should understand that delegates allow you to call a method indirectly through the delegate construct. The focus in discussing events here is not to go into an in depth analysis of invoking and handling different events in Windows Forms and the .NET Framework. Instead, the focus is to see how delegates and events work together and how you can create and use them to add flexibility and maturity to any type of application. Let’s take a look at a fresh example. This example handles events for when a record is read from a database. See Listing 4.
Listing 4 – Define a new delegate
Here we follow the traditional event programming idiom of passing the object reference of the sender along with an object inheriting from System.EventArgs that contains specific event information.
Listing 5 – Define the Event
Here we have an event and a method to raise the event. Both of these are internal to a class named Transform. The event is defined in terms of the delegate type. And the method OnRecordRead is called internally, which in turn raises the event up to the event. Let’s now see how a class hooks this up in Listing 6.
Listing 6 – Application using the event
Now we’re really getting somewhere. What you see in Listing 6 is a class named Client. Inside of Client a new instance of the class Transform is instantiated. Next, a handler is wired up to the RecordReadEvent that matches the delegate type of RecordReadEventHandler. And finally, the method HandlReadRead actually handles the information, or events, that are published. In essence, Client is acting as a subscriber to the information that Transform is publishing. Listing 7 below ties these last three diagrams all together.
Listing 7 – Tying it all together
To summarize this, here are the major parts.
· Delegate definition
· Event definition
· Event publishing
· Event subscription
· Event Handling
And what is the beauty of all this? The fact that it’s easily extendable and usable in your ASP.NET applications, console apps, utilities and smart applications makes it so. It goes way beyond Windows Forms and can add loose coupling and flexibility which is something that object oriented software should strive for.
Wait…Compose Yourself First
Of course, I am not the only one. If you are familiar with our friends, the Gang of Four, you have already heard this mind-bending concept. Make your objects connect to each other via well defined interfaces and hide their implementation. This is a sound, modern software practice. In fact, I just spent four days this past summer listing to speakers take composition for granted at the architectural level. They were assuming (not all of them of course) that composition and abstraction is a skill that is taken for granted by most developers. We know, being the folks in the trenches, that this is not always the case.
Favor Composition
Let us look at some simple composition here and discuss what the big deal is all about. To start, here are what I believe to be the three most important and beneficial things about using composition.
- Black Box design (where inheritance is white box design)
- Does not break encapsulation
- Relationships can be defined at runtime
Black box design means that the client using the object does not know the internal operations. This is in contrast to inheritance, where the class often knows the internals of its super class. Not breaking encapsulation is as good a reason to use composition as any. After all, encapsulation of operations and data is one of the main reasons to use object orientation. And lastly, “relationships can be defined at runtime” means that other objects can be plugged into, or composed with, other objects while the program is executing. This is a common use of the Strategy pattern, where an algorithm is set to the class at runtime.
Looking at an Example of Composition
Below, you will see a snapshot of part of a fictitious product component. ProductBase is composed of StockStatus, which in turn is composed of PurchaseOrderLine and IRunRate. Here, StockStatus does not know about the implementation of IRunRate, it only knows IRunRates interface. Here, we can then substitute any other object of type IRunRate into StockStatus and it would be none the wiser. You could of course, change behavior by having StockStatus be aware of its algorithms and change depending on what it is composed of – but that is not taking advantage of composition.
Figure 1 – UML Diagram
PurchaseOrderLine is the next object. Although StockStatus is not connected to an abstract class or “interface” type, the public methods and properties of PurchaseOrderLine make up its interface. So, again, StockStatus only knows about a well defined interface.
Conclusion
It is important to look at your design and try to understand the moving parts. These will let you know what the system will be composed of. In my next article, I will talk more about identifying the objects that make up your system, as well as why this design used an abstract class at its base and built upon it with composition.
Leave a Comment





