Yesterday, I was involved two very separate yet very related conversations. One was via twitter with Colin Jack and Jimmy Bogard (which I was only a partial contributor to - mostly just reading their conversation) and another after work with a coworker. The short version of both conversations can be boiled down to encapsulation of logic surrounding collections that are held by entities. Rather than rehash all of the conversations, I wanted to specifically address a violation of encapsulation that I've seen many times when dealing with collections and business rules. Let's look at a small example where we have a medical system that deals with Patients that are having Consultations with doctors. There is a need to keep track of the historic consultations and also the current consultation, if any. For simplicity we'll say that the current consultation is identified as being the most recent, based on a starting date, and that any previous consultation must have an ending date. A very simplistic implementation of an object model to represent patients and consultations may look something like this: public class Patient { private IList<Consultation> _consultations = new List<Consultation>(); public IList<Consultation> Consultations { get { return _consultations; } } public Consultation CurrentConsultation { get; set; }} public class Consultation { public DateTime StartingDate { get; set; } public DateTime EndingDate { get; set; }}
Then, when the time comes to add a new consultation to the patient, making it the current one and closing a previous consultation, code may get called from somewhere in the application (like a code behind of a form, or if you're lucky, in the Presenter or Controller of an MVP/C setup), like this:
Consultation consultation = new Consultation{ StartingDate = DateTime.Now }; patient.Consultations.Add(consultation); if (patient.CurrentConsultation != null) patient.CurrentConsultation.EndingDate = DateTime.Now; patient.CurrentConsultation = consultation;
From a purely technical standpoint, there is nothing wrong with this code. It implements the business rule as defined. However, this code misses out on some great opportunities to encapsulate the rules we have into a process that can be called from anywhere that the system needs it - whether or not the code is in the specific presenter / controller that creates a new consultation or not. The very same code that comprises this implementation could easily be placed in the Patient object, abstracting the rules and process of creating a new consultation into a simple, single method call.
Before I show how I would approach that solution, though, there is one other implementation that I've seen recently that not only breaks encapsulation, but has to compensate for the lack of rules enforcement with logic in the wrong place. Instead of storing the current consultation as a set value, the CurrentConsultation property may have some logic in it to dynamically determine which consultation is the current one.
public class Patient { private IList<Consultation> _consultations = new List<Consultation>(); public IList<Consultation> Consultations { get { return _consultations; } } public Consultation CurrentConsultation { get { Consultation currentConsultation; DateTime mostRecent = DateTime.MinValue; foreach(Consultation consultation in _consultations) { if (consultation.StartingDate > mostRecent) { mostRecent = consultation.StartingDate; if (consultation.EndingDate == DateTime.MinValue) { currentConsultation = consultation; } } } } } }
This type of code is a huge encapsulation violation smell. Since our Patient object has no enforcement of the consultations that it holds, there is no way for us to really know which consultation is the current one. Because of this, the retrieval of the current consultation has to process the entire consultation collection and try to find the most recent consultation that has no ending date.
On top of the encapsulation issue, we have lost a great deal of performance. We now have to loop through the list every time we need the current consultation. If the list is small, this might not be such a bad problem, but as the list grows and as this code is used more and more, the performance problem may have a serious impact on the system.
Fortunately, the solution to the encapsulation violation, the enforcement of the business rules and the performance problem can all be wrapped up in to some very simple code. The first thing we want to do is prevent the ad-hoc addition of consultations to the patient. We still need to access the list of consultations, but we don't really have a need to modify it outside of the patient class itself. This can be done with a one-line code change to the Patient class's Consultations property:
public class Patient { private IList<Consultation> _consultations = new List<Consultation>(); public IEnumerable<Consultation> Consultations { get { return _consultations as IEnumerable; } } //ignoring other implementation details for the sake of illustrating the IEnumerable change }
Now that we have prevented the ability to do ad-hoc consultation additions, we need a way to actually add consultations. While we are doing this, we also want to enforce the business rules of the current consultation as described earlier. This is where we are going to take much of the original code that we found in the presenter / controller and place it into the patient class directly.
public class Patient { private IList<Consultation> _consultations = new List<Consultation>(); public IEnumerable<Consultation> Consultations { get { return _consultations as IEnumerable; } } public Consultation CurrentConsultation { get; private set; } public void StartConsultation() { Consultation newConsultation = new Consultation{ StartingDate = DateTime.Now }; if (CurrentConsultation != null) CurrentConsultation.EndingDate = DateTime.Now; CurrentConsultation = newConsultation; Consultations.Add(newConsultation); } }
In the end, this code shows a better encapsulation of the business rules and logic that surrounds the need to maintain a list of consultations and a current consultation. With this code in place, we could simplify the presenter / controller that we talked about initially. Rather than being forced to know all of that logic in the presenter, we can make one simple method call:
patient.StartConsultation();
With this one simple call, we have a guaranteed execution of the business rules that we need. This will allow us to recreate the ability to add a new consultation at any point in the application that we need, not just in the original presenter / controller that we were working with.
Side Note:
Part of the conversation via twitter revolved around where this type of logic should be encapsulated. From what I gathered, Colin tends to place this logic in custom collection objects, which would allow him to call patient.Consultations.Add() and still encapsulate the same business rules into that method. Like everything else in software development, there are multiple ways to solve the same problem. What does your specific situation, project, team, and business context need? Whatever your implementation needs are, though, we need to keep this type of logic and business rules enforcement well encapsulated in our systems.
Cross Posted From LostTechies.com
A coworker recently asked if we should always abstract every object into an interface in order to fulfill the Dependency Inversion Principle (DIP). The question stunned me at first, honestly. I knew in my head that this was a bad idea - abstracting into interfaces for the sake of abstraction leads down the path of needless complexity. However, I wasn't able to clearly answer his question with specific examples of when you would not want to do this, at the time. I've been thinking about this for a few days now and I think I have a good, albeit very long winded, answer. Before the question is answered, though, we need to step back and look at what DIP is all about. I've previously shown how to implement DIP and talked about why it's beneficial, so I won't be repeating that here. Rather, I want to talk about the language that describes DIP and what it really means. Robert Martin's original definition of DIP is this: A. High level modules should not depend upon low level modules. Both should depend upon abstractions. B. Abstractions should not depend upon details. Details should depend upon abstractions. The word 'abstraction' is used three times in the definition for DIP. So, in order to understand DIP, we have to first understand some of the basics of Abstraction. Some Background On Abstraction From Wikipedia (emphasis mine): "In computer science, abstraction is a mechanism and practice to reduce and factor out details so that one can focus on a few concepts at a time" I can't say it any better than this. Abstraction can very directly lead to a system that is more understandable by helping us ignore the detail and implementation specifics, allowing us to focus on something at a higher level. This reduction in cognitive load can benefit someone that is reading the code by not forcing them to know the detail immediately. Additionally, abstraction is a form of encapsulation or information hiding, which again helps us to reduce cognitive load and produce better systems. From Wikipedia's entry on Information Hiding: "In computer science, the principle of information hiding is the hiding of design decisions in a computer program that are most likely to change, thus protecting other parts of the program from change if the design decision is changed." At the heart of abstraction and information hiding, we find the ability to change the system. The ability to change is an absolute requirement in software development and produces good design that is easier to work with, modify, and put back together as needed. The inability to change is directly called "bad design" by Robert Martin, in the DIP article. Applying Abstraction And Encapsulation To DIP So how does our knowledge of abstraction and information hiding play into DIP? First and foremost, DIP never states that we should depend on explicit interfaces. Yes, in C# we have an explicit Interface as a form of abstraction. It is a separation of the implementation detail from the publicly available methods, properties, etc, of a class. Some languages, such as C++, don't have an explicit construct for interfaces, though. From Robert Martin's original DIP article, again: "In C++ however, there is no separation between interface and implementation. Rather, in C++, the separation is between the definition of the class and the definition of its member functions." A String As An Abstraction Abstraction does always mean explicit interface constructs, as evidenced in C++. Nor does it always mean an abstract base class, which we also have available in .NET. In fact, languages such as Ruby don't really need either of these constructs. The duck-type nature of Ruby allows an implementation to be replaced at any point, without any special constructs. In .NET, though, there are a number of abstraction forms that we can rely on, explicitly. We have the obvious interfaces and base classes (abstract or not) - but we also have constructs like delegates and lambda expressions, and even the simple types that are built into the base class library. Let's look at a simple string to illustrate abstraction. As I said in my SOLID presentation at ADNUG, we can invert our dependency on database connection information. Rather than putting a connection string directly into our code that calls the database, we can use the string as our dependency and our abstraction. All we need to do is follow the basic DIP principle and provide the string as a parameter to the class that calls the database. We certainly don't need (or want, for that matter) to introduce a new interface or base class at this point. Our abstraction is simple enough to use a common type found in the .NET framework. Other Forms Of Abstraction Even if we are talking about an object, who says that the interface we are depending on has to be an explicit interface construct or base class? When I write a Domain Service that uses an Entity from my Domain, I don't create an explicit interface for that Entity. Rather, I use the Entity's inherent interface - it's public methods, properties, etc. I also use delegates on a regular basis. By specifying my abstraction as a delegate, I can further decouple the depending object from the dependant code that it needs to call. I'd be willing to bet you have used delegates as abstractions as well. Have you ever created an event handler for something like a button click? There's a delegate's abstraction at work. Abstract Judgement The point is, there is not always a need to introduce an explicit interface or base class when inverting our dependencies. We still need to apply dependency inversion and provide our implementation as a constructor parameter (or setter, though I don't like setter injection). But, that dependency doesn't have to be anything more than the interface inherent to the object, or a simple type found in .NET. You do have to be careful when making the call to not use an explicit abstraction with DIP, though. You can quickly turn your system into a ball of mud if you rely on a concrete class that is not intention revealing or well encapsulated to begin with. At the same time, too many abstractions can lead to needless complexity and make it very difficult to see the big picture of a system. Too few abstractions, though, will certainly lead to a rigid, immobile design that is hard to change. All of these problems are equally vicious - and I've been bitten by all of them in recent months. It takes good judgement calls to determine when you do and do not need an explicit abstraction for a dependency. Unfortunately, good judgement comes from experience and experience comes from bad judgement. Don't be afraid to make bad decisions - make a decision, just be sure you can reverse that decision as easily as possible.
Let's say I have a small hierarchy of object: Faults and Parts. A Fault can contain many parts, and a part has no meaning without being associated to a Fault. To ensure that I have no Parts without a parent Fault, I have this basic code in place: public class Part { private Part() { } public string Description { get; set; } } public class Fault { private IList<Part> _parts = new List<Part>(); public IList<Part> Parts { get { return _parts; } } public Part CreatePart() { Part part = new Part; _parts.Add(part); return part; } }
This ensures that I never have a Part in an "invalid" state - without an owning parent.
I also have a business rule that say that I'm not allowed to have a Part without a description. My typical implementation of this business rule has been in the UI layer - my Presenter would have the logic to require a user to enter a description when creating adding a part to a fault.
public class PartCreationPresenter { Part _part; public PartCreationPresenter(Part part) { _part = part; } public DescriptionProvided(string desc) { if (string.IsNullOrEmpty(desc)) { view.ShowDescriptionRequiredMessage(); } else { _part.Description = desc; } } }
Here's the question:
Should this "require a description" logic be in the UI layer (Presenter) the way I have it, or should I put it in the Part object and have an IsValid flag of some sort on that object?
I don't like having this coded in the presenter only. It makes the business rule very easy to break - create a part from anywhere else, and you can ignore this rule. But I'm not sure I like it in the Part object, because it would make the presenter difficult to code. How would I execute the specific view.ShowDescriptionRequiredMessage() method if the rule is coded in the Part?
Any opinions, suggestions, articles, etc. are very welcome. I'm very interested in hearing how other people are handling this situation.
I had a lot of fun giving my SOLID Principles presentation at the Austin .NET User Group last night. It was a pleasure and an honor to be able to give back to the community that has supported me for so many years. I'd like to thank everyone that came out to see the presentation, for being such a great audience. There were a lot of great questions and comments and good discussion. I sincerely hope that I've inspired at least a few people to continue digging into the SOLID principles. As promised, I've posted my slides and the example code for download. Additional resources for SOLID: For the questions on legacy code from last night: If anyone has any questions about the SOLID principles, would like more information, etc, please feel free to contact me via the contact link on my blog(s) or via my email address listed at the end of the slides.
A coworker just asked me this question - what's the point of delegates in .NET? My answer was very short and one that he had not found online: to delay execution of a method. Consider this: if you pass a Method2 as a parameter to Method1, Method2 is evaluated immediately and the result is passed into Method1. public class SomeObject { public void Method1(int someValue) { //... code here } } ... someObject.Method1(anotherObject.Method2());
Additionally, Method2 must have a return value (not void) so that the value returned from Method2 can be passed as the parameter of Method1.
With a delegate, though, we get method pointers that can be used to delay the execution of the method in question until it's needed (if at all). We can also get rid of the requirement for a return value and we can pass values that were created by the host method, into the delegate method.
public class SomeObject { public void Method1(Action<int> someAction) { //.. do some stuff here int aValue = GetTheValueFromSomeWhere(); someAction(aValue); //... do some more here } } public class AnotherObject { public void Method2(int aValue) { //do something that is dependent on aValue, here. int i = aValue + 1; // or anything else that needs aValue. } }
FYI - Action (void return; with many parameterized variations) is a delegate that is build into .NET 3.5, along with Func<T> (return value of type T; with many parameterized variations). These are the two most common delegates that I use in my code.
Most .NET developers have used delegates without realizing it, too. The event system in .NET is nothing more than a multi-cast delegate - a delegate that points to more than one method - with a special signature and syntax (depending on the language being used).
There's a lot of good use for delegates. And like any other tools, there's a lot of bad uses. Take the time to learn what they are, how they work, and where they can be beneficial.
FYI - I'll be giving my S.O.L.I.D. Software Principles presentation at the Austin .NET User Group on Monday the 13th. This is the same presentation that I gave at Pablo's Day(s) of TDD last weekend, except I'll have the missing code in place and the slide errors fixed. Here's the abstract that was posted via the ADNUG mailing list: S.O.L.I.D. Software Development: Achieving Object Oriented Principles, One Step At A Time Almost every professional software developer understands the academic definitions of Coupling, Cohesion, and Encapsulation. However, many of us do not understand how to actually achieve Low Coupling, High Cohesion, and strong Encapsulation, as prescribed. Fortunately, there are a set of stepping stones that we can use to reach these end goals, giving us a clear cut path to software that is easier to read, easier to understand, and easier to change. This presentation will define not only the three object oriented goals, but also the five S.O.L.I.D. principle that lead us there, while walking through a sample application. At some point this week or next, I will have my slides and code posted for people to download. (I know I promised this at PDoTDD. I got busy. Sorry). And as usual, there will likely be a group of people heading to Rudy's after the meeting, for extended discussions and snappy banter.
A few months ago, I posted some thoughts and questions on the proper use of Inversion of Control (IoC) containers and the Dependency Inversion (DI) principle. Since then, I've had the opportunity to do some additional study and teaching of DI, and I've had that light bulb moment for the proper use of an IoC container. I haven't talked about it or tried to present the info to my team(s) yet, because I had not verified my thoughts were on the right track - until recently. I got to spend a few hours at the Dovetail office with Chad, Jeremy, Josh, etc, and had the pleasure of being able to pick their brains on some of the questions and thoughts that I've had around DI and IoC. In the end, Chad confirmed some of my current thoughts and helped me put into a metaphor that I find to be very useful in understanding what Dependency Inversion really is - a cloud objects that can be strung together into the necessary hierarchy, at runtime. Consider a set of classes that need to be instantiated into the correct hierarchy so that we can get the functionality needed. It's really easy to have the highest level class - the one that we really want to call method on - instantiate the class for next level down, and have that class instantiate it's next level down, and so-on, like this: This creates the necessary hierarchy, but breaks the core object oriented principle of loose coupling. We would not be able to use ThisClass without bringing ThatClass along with it, and we would not be able to use ThatClass without bringing AnotherClass along with it. By introducing a better abstraction for each class and putting Dependency Inversion into play, we can break the spaghetti mess apart and introduce the ability to use any of these individual classes without requiring the specific implementation of the dependent class. For starters, let's introduce an interface for ThisClass to depend on and an interface for ThatClass to depend on. Now that we have an interface that both of these classes can depend on, instead of the explicit implementation of the child object, we need to have the expected child object implement the interface in question. For example, we expect ThatClass to be used by ThisClass, so we will want ThatClass to implement the IDoSomething interface. By the same notion, we want AnotherClass to implement the IWhatever interface. This will allow us to provide AnotherClass as the dependency implementation for ThatClass. Our object model now looks like this: What we have now is not just a set of classes that all depend on each other, but a "cloud" of objects with dependencies and interface implementations that will let us build the hierarchy we need, when we need it. The real beauty of this is that we no longer have to care about the implementation specifics of IDoSomething from ThisClass. ThisClass can focus entirely on doing it's duty and calling into IDoSomething when it needs to. And, by passing in the dependency as an abstraction, we're able to replace the dependency implementation at any time - runtime, unit test time, etc. This also makes our system much easier to learn and understand, and most importantly - easier to change. Now that we have our cloud of implementations and abstractions in place, we will need to reconstruct the hierarchy that we want so we can call into ThisClass and have it perform it's operations. Here's where Dependency Inversion meets up with Inversion of Control. - To create ThisClass, we need an implementation of IDoSomething
- ThatClass implements IDoSomething, so we'll instantiate it before ThisClass
- ThatClass needs an instance of IWhatever
- AnotherClass implements IWhatever, so we'll instantiate it before ThatClass
- Once we have AnotherClass instantiated, we can pass it into ThatClass's constructor
- Once we have ThatClass instantiated, we can pass it into ThisClass's constructor
We end up with a hierarchy of objects that is instantiated in reverse order, like this: We have now successfully inverted our system's construction - each implementation detail is created and passed into the the object that depends on it, re-creating our hierarchy from the bottom up. In the end, we have an instance of ThisClass that we can call into, with the same basic hierarchy of classes that we started with. The real difference is that now we can change this hierarchy at any time without worrying about breaking the functionality of the system. Once we have our Dependency Inversion and Inversion of Control in place, we can start utilizing the existing IoC frameworks to automatically create our hierarchy of objects based on the advertised dependencies (an advertised dependency is a dependency that is specified as a constructor parameter of a class). Tools like StructureMap, Spring.net, Windsor, Ninject, and others, all provide automagic ways of creating each dependency of the object that is requested, all the way up/down the hierarchy. Utilizing one of these IoC containers can greatly simplify our code base and eliminate the many object instantiations that would start to liter our code. As I said in my previous post, I know all about what not to do with IoC containers. Good IoC usage, though, is another subject for another post.
It's official - I'm now a member of Los Techies. I will continue to post here, at DerickBailey.com, and will be cross-posting over at Los Techies once I figure out how to do that.  Thanks to Joe, Chad, and everyone else in the Los Techies crew, for the vote of confidence in adding me!
At some point, you will need to put a timer into your C# code. Hopefully you're doing Test Driven Development, or at least unit testing, to cover your need for a timer with a unit test. If you are - I'm betting you ran into some really ugly problems like tests that would not pass without having 'Thread.Sleep(1000)' calls in them. Worse yet - last week, I put a 3 second timer into a class that was being unit tested. This one mistake cause my CruiseControl build to go from 2 minutes, to timing out at 90 minutes because NUnit was keeping the app domain alive while the timer was alive, so it never closed the test run. Oops. To fix this problem, we decided we needed to eliminate the use of an actual timer and use an abstraction that could be mocked/controlled in our unit tests. Unfortunately, the .NET Framework does not have an actual abstraction for a timer. So, if you need to use a timer in your code - and at some point in time, you will - you'll want to create a very simple ITimer interface that would let you control when the timer elapses and fires its registered action. Here's the core of the abstraction that we came up with, initially. public interface ITimer { void Start(Action timerAction); }
With such a simple interface in place, we can now mock it out in our unit tests (I like Rhino Mocks) and set up an expectation on the Start method to capture the timerAction parameter, then simulate the timer elapsing by calling the timer action from our unit test. Here's an example test and 'system under test' to illustrate how we use this interface.
[Test] public void DemonstratingHowToUnitTestATimerElapsing() { Action timerElaspedAction; ITimer timer = MockRepository.GenerateMock<ITimer>(); timer.Expect(t => t.Start(null)).IgnoreArguments().Callback( delegate(Action timerAction) { timerElapsedAction = timerAction; return true; }); MySystemUnderTest sut = new MySystemUnderTest(); sut.StartMonitoringStuff(timer); //here's where we simulate the timer elapsing timerElapsedAction(); Assert.IsTrue(sut.TheTimerActionWasCalled); } public class MySystemUnderTest() { public bool TheTimerActionWasCalled { get; set; } public MySystemUnderTest() { TheTimerActionWasCalled = false; } public StartMonitoringStuff(ITimer timer) { timer.Start(() => TheTimerActionWasCalled = true); } }
There is a bit more detail to the actual ITimer interface, and the implementation, though. We ran into issues where we needed to stop the timer, prevent it from firing after we close the SUT, etc. So, all said and done, here's the full ITimer interface and MyTimer implementation that we ended up with.
public interface ITimer { void Start(Action action); void Stop(); } public class MyTimer : ITimer, IDisposable { private TimeSpan _timerInterval; private Timer _timer; private Action _timerAction; private bool IsRunning { get; set; } public MyTimer(TimeSpan timerInterval) { _timerInterval = timerInterval; } public void Dispose() { StopTimer(); } public void Start(Action action) { _timerAction = action; IsRunning = true; StartTimer(); } public void Stop() { IsRunning = false; StopTimer(); } private void StartTimer() { _timer = new Timer(o => Timer_Execute(), null, 0, Convert.ToInt32(_timerInterval.TotalMilliseconds)); } private void StopTimer() { if (_timer != null) { _timer.Change(Timeout.Infinite, Timeout.Infinite); _timer.Dispose(); _timer = null; } } private void Timer_Execute() { try { StopTimer(); _timerAction(); } finally { if (IsRunning) StartTimer(); } } }
This has worked out very well for us, so far. It lets us put a timer in place when we need one, but not worry about thread racing issues, long running tests, etc.
I've seen this question a lot recently, and Scott Bellware asks it again in response to a post by Jimmy Bogard. "Ok, but why are "contracts" important? I can write concrete classes that interact with each other just fine without interfaces. And as Roy has already demonstrated, you don't need interfaces for test-focused SoC. To wit, any concrete class's signature is a contract with its user." -- Scott Bellware First - a small psychology lesson in Cognitive Load theory and Chunking. A human brain can only hold so much information in it's short term memory. The "magic number" of 7 (+/- 2) has often been touted as the average number of concepts that a person can hold in short term memory, and still understand what's going on. ... and we need to recognize this in our code. If a developer who is reading the code has more than 7 (+/- 2) concepts, then that developer is not likely to understand the code they are reading. If you can't understand the code, you can't maintain the code. It's as simple as that. So why are contracts important? An intention-revealing interface, as a contract, can significantly reduce the cognitive load that is required to understand the code in question. Abstraction and dependency inversion via interfaces help us achieve this understandability by letting a developer's mind chunk a process into what's really important - the "when" and "what" of the process, ignoring the "how". If you eliminated all abstractions and interfaces - even the interfaces that have only one implementation - you are telling a developer that they need to know the details of "how", not just the abstraction of "when" and "what". This puts an additional load on any persons' brain, and can quickly overload the person reading the code. These theories go so far beyond just code, in software. When was the last time you saw a web site that had more than 8 or 9 buttons in it's navigation/menu, and you thought it was an intuitive and easy to use site? I'd be willing to bet that you thought the site was poorly organized and difficult to navigate. Interaction design is usually the first place that people apply cognitive load and chunking theories. Unfortunately, it's also usually the last. We need to break this cycle of overloading ourselves and our coworkers, and create proper abstractions in our code that fit easily within our own cognitive load, but more importantly in the cognitive load of other developers who have to read/maintain the code.
|