Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Technorati Profile

Real Life Single Responsibility Principle

S.O.L.I.D. principles seem to be a hot topic.  The guys over at LosTechies.com explored it last year in March as their topic of the month and did a great job of it. I know when I read blogs I enjoy when different authors post on similar topics.  I find that often the different examples and explanations paint a clearer picture than can be had with only one example.  I'd like to share an area where we use the Single Responsibility Principle (SRP) in our application

Note: The "aha" moment won't be some thrilling display of how we averted some disastrous bug or how we eliminated some thousands of lines of code.  It will be much more subtle but that's ok.  A good design should strive for an element of simplicity.  Great design is asking to hear the answer to a riddle and then thinking, "duh!  of course"  When you hear the answer you realize how "obvious" it was.

Background

In our application we queue all emails to be handled by a different process since sending email is a blocking call which slows your response times (Note to BCL junkies: yes I know there is a SendAsync method).  There are a few instances in our application where we want email to be sent right away and not queued. An example of this would be a confirmation email for a new account or a password reset request.

The Fix

We already had a QueuedEmailService class so adhering to SRP, I built a RealTimeEmailService class whose job, and only job, it is to send the email right away.  Thinking of responsibility driven design, classes:

  • Know things
  • Do things
  • Make decisions

With that in mind I needed another class to make the decision to when to send the email through the RealTimeEmailService or when to use the QueuedEmailService:

(At this point some of you might be reading thinking how easy of a problem this would be to solve and you're quite right.  What I want to point out is not the problem, but how one solves the problem.  Nearly anyone could've gone into the QueuedEmailService and added an if statement and sent emails real-time if that is what is needed, thus ignoring SRP.  By lumping all of the work together you aren't building object oriented software...sorry.  And while you might be okay with that and you're software WILL work, you run the risk of more maintenance issues and modularity problems).

Here's what a quick summary of what I've got:

   1: public QueuedEmailService : IEmailService
   2: {
   3:     public void Send(...)
   4:     {
   5:         // add to some queue
   6:     }
   7: }
   8:  
   9: public RealTimeEmailService : IEmailService
  10: {
  11:     public void Send(...)
  12:     {
  13:         // send right now
  14:     }
  15: }
  16:  
  17: public PriorityBasedEmailService : IEmailService
  18: {
  19:     public void Send(...)
  20:     {
  21:         if (priority == MailPriority.High)
  22:             // send using realtime service
  23:         else
  24:             // send using queued service
  25:     }
  26: }
  27:  
  28:  

I know many people who would look at the code above and think it is possibly overkill.  I would disagree for a few reasons:

  • Each class does only one thing.  If we have a problem with some piece of functionality it is much easier to debug.  Each of the three classes above in their full implementation will fit on your screen without the need for scrolling.  It's quite refreshing.
  • Modular design - since the application only knows that it's dealing with an IEmailService I can easily swap out implementations.  For example, if we decide that we want all emails to be sent real-time, I just change how I've configured Windsor (my IoC container) and it works, because I have a concrete class which sends real-time.  If you were to combine all of your code into one class, you'd have to go back and change your code and go through the pain of deployment.
  • Open-Closed principle - since each of the classes only have only one thing they do, I can more easily say they are closed for modification, reducing the chance that I introduce a bug later on.  If you put this code into one big method, you can change the code to meet your new needs, but each change introduces the possibility of introducing a bug.

There are cases when a design can go overboard, but for the vast majority of cases this simply isn't the case.  I'd rather see a solution where someone has gone too far than what I typically see in classes that do it all, with no clear responsibility.

I hope this helps augment your knowledge of SRP.  If you're still a little fuzzy on SRP and what it is, let me know, I'd love to discuss it with you.

Language Envy - hash literals

It's easy to let a small language feature go unnoticed. The more I spend time writing JavaScript and Ruby, the more one little detail shows itself loud and clear when I go back to my trusty C# (well, it shows itself by not being absent, if that makes any sense.)

The little language detail I'm writing about today is the literal syntax for hashes. Especially in JavaScript, because all objects are just hashes on steroids, which makes the literal object syntax become one and the same with the hash literals.

In JavaScript it's easy as 1-2-3. It's not surprising so many libraries are adopting hash parameters.

//Prototype.js sample
var elements = { success: 'myDiv', failure: 'errorDiv' };
var ajax = new Ajax.Updater(
	elements, 
	'getData.aspx', 
	{ method: 'get', onFailure: reportError }
	);
//jQuery sample (jQuery UI)
$('#fromDate').datepicker({rangeSelect: true, firstDay: 1});
$("#search").autocomplete("/product/find",
	{ autoFill: true, delay: 10, minChars: 3 }
	);

Now, I understand that part of the popularity of hashes in JavaScript and Ruby is due to the loose typing of these languages. But if the syntax wasn't light, APIs like the above ones would be much more painful to use.

C# 3 does have a hash syntax (or, more accurately, a dictionary one.) Unfortunately, dictionary initializers, although being a step forward, still leave noise to be removed.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new Dictionary<string,object>
              {
                {"Category", Category.Books},
                {"MinPrice", 33.45},
                {"MaxPrice", 50.00},
                {"Contains", "asp.net"}
              });

Hmmm, no, thanks. Maybe that's the reason we are starting to see some APIs that use (abuse?) anonymous objects and reflection to create hashes.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new { 
                Category = Category.Books,  
                MinPrice = 33.45,
                MaxPrice = 50.00, 
                Contains = "asp.net" 
              });

This last one doesn't look so bad on the surface, but we know what is going on under the covers so it's like putting lipstick on a pig. If, instead of using reflection at run-time, the compiler had support for converting the above anonymous object into a IDictionary<string,object>, then we would have a more convenient and efficient way of creating hashes. Maybe it's too late to introduce a feature like that while maintaining backwards compatibility.

I believe when you add a language feature that is elegantly designed (i.e. clean and unnoticeable,) it becomes popular more quickly — just like what is happening with lambdas . The existing alternatives for creating hashes in C# 3 are still too noisy or inefficient to be integrated in our code without reducing the readability or incurring a performance penalty.

NH Prof Public Beta

Christoper and I have had the privelage of helping Ayende to build the UI for his NHibernate Profiler over the last couple months.  Yesterday evening he released the public beta with a 30 day trial version.  If you are using NHibernate, get over to the product site and download the beta.  This is going to be an invaluable tool for developers using NHibernate and you can get it at a special price if you purchase during the beta period.

As a developer on this project, I had the unique opportunity to watch a master at his craft.  The architecture of the product is clean and Ayende has managed to jam pack this version with a ton of NHibernate smarts.  Just working on it, I gained a deeper understanding of the types of problems one can run into while using an ORM.  I would not want to do another project without it.

Another exciting aspect of this application is that we are using the latest version of Caliburn in the UI architecture.  Generally speaking, the UI architecture is composed of a very rich Presentation Model (MVVM) with a splash of MVP for good measure.  There is almost no code-behind in the views.  All communication is handled by Caliburn's action message mechanism.  We were also able to use Caliburn's new testability features to cover all our views with data binding validation tests and do basic property change notification testing.

MVP Goodness!

Congratulations to Christopher Bennage for receiving a 2009 MVP for Client App Dev!  Microsoft was also gracious enough to award me with an MVP in the same area!  Let the good times roll...

Playing with Ruby 1.9 - named parameters (sort of)

I just installed Ruby 1.9.1 RC1 alongside my stable 1.8.6 installation. I'm planning to experiment with the changes and new language features for both using them in new code and upgrade old code (or at least protect old code from potential breaking changes.)

In light of the upcoming changes in C# 4, more specifically the addition of named and optional parameters, one of the new Ruby 1.9 features called my attention immediately.

Ruby, even 1.9, doesn't support named parameters in method calls. Instead, a common pattern is to provide a Hash parameter and call it something like options. Any optional argument is passed as an item of this hash, normally using a Symbol for the key. It helps that Ruby has special support for hash arguments, making the call look much cleaner:

def my_method(arg1, arg2, options)
  opt1 = options[:option1] || "default value for opt1"
  opt2 = options[:option2] || "default value for opt2"
  # ... etc ...
end

#calling the method:
my_method(val1, val2, { :option2 => "opt val 2", :something => "whatever"})
# simplified syntax
my_method(val1, val2, :option2 => "opt val 2", :something => "whatever")

In a way this is the poor man's version of named parameters, but it seems to do the job.

This is a very popular Ruby idiom (you can see that a lot in JavaScript as well,) so truly popular that the syntax was further simplified in 1.9. We can now ditch the arrow thingy and write the same exact code as follows:

#calling the method:
my_method(val1, val2, { option2: "opt val 2", something: "whatever"} )
# simplified syntax
my_method(val1, val2, option2: "opt val 2", something: "whatever")

The first syntax is identical to what you'd use in JavaScript. The second one is the same of named parameters in C# 4. I thought this was a welcome coincidence. See the C# 4 version below.

//NOTE: C# 4 code
void my_method(string arg1, string arg2, 
      string option1 = "default 1", string option2 = "default 2",
      string something = "")
{
  // ... method body here ...
}

//calling the method:
my_method(val1, val2, option2: "opt val 2", something: "whatever");

Teaching someone to test using an Isolation Framework

Part of my job at work is to teach and mentor other developers on our team.  Right now I am in the process of teaching two of our developers how to create unit tests (notice I did NOT say integration tests because most anyone can do those).  We are also learning how to create our tests by utilizing an Isolation Framework (aka mocking framework).

I am really excited for this opportunity because I firmly believe that you create better software when you do it by creating tests to prove your code works.  I am also excited because both of the developer buy into the idea of testing and are extremely eager to learn how to to better test their code.

Because we had a few days of downtime because of the Christmas holiday before our 1st sprint on our project we thought it would be a good time to do some pairing (guess it would be better called tri-pairing).  Our plan of attack was to start to flush out some of the features in our system but do it in a total TDD manor.  We were also going to be utilizing the Rhino Mock Isolation framework in our tests.

So over the next 2 days we spent about 12 hours or so working building out our code.  Over this time we actually were able to create an complete end to end 'version' (I say version because we did not fill in all the functionality of the code but were able to get all the major pieces stubbed out) which allowed us to flush out many, many more business requirement and build a simple, yet flexible code base.

I hope both of my co-workers learned a ton from this exercise, I know I did.  This was the first time where I had actually spent any significant amount of time teaching someone who was new to testing how to do so.  Sure I had spent an hour here or an hour there, but nothing like this. 

What I really wanted to share with everyone is what I learned form this experience.

Slowdown, slowdown, slowdown
The first thing you should do when teaching something how to do anything is SLOWDOWN.  You have to remember that if you are talking/teaching to someone who is new to this they have to not only try to process the information so they can understand it, they also have to try to remember it.

Make NO assumptions, teach as if they know nothing
This one was the most important thing I learned.  You cannot make assumptions on anything.  Anytime you say anything make sure you fully explain it.  If you use an acronym EXPLAIN IT.  Any time you mention a buzz word EXPLAIN IT.  Plan and simple EXPLAIN EVERYTHING

Have them drive
During the teaching part it is critical that you have then code, have them tell you what to do.  It is ok for you to 'lead' them in the right direction, but you must not always drive.  This will really help to drive home the concepts.

Provide examples both with and without the Isolation framework
In our case because I was trying to teach them testing using an Isolation framework it really helped when I would create a test (aka integration) with no mocks and then re-create it with mocks.  Doing this really helped to explain to them how using the Isolation framework removed dependencies.

Don't let them skate by
Don't let them simply nod their head as if they understand.  Make sure you keep asking them if there is anything you can clear up or explain better.  At first they are going to simply say no, they are good.  But as you keep asking and start having them drive they WILL start to ask more questions, I promise.

Turn off any coding tools such as ReSharper (or the likes) and do NOT use shortcuts
This may have been the biggest issue for us at first.  I am pretty good with ReSharper (if I can toot my own horn here) and I was coding with it as I would do if I were by myself.  On more than one occasion the would look at me cross-eyed and ask 'what the hell just happened'.  Finally I simply stopped using it for the first day.  On the second day I went back to using R#, but I turned on Keyboard Jedi so they could see what was going on.  Even though I turned on Keyboard Jedi, I tried my best to make sure to explain what just happened when used R#.

Anyway, I have rambled on long enough and I think I have pretty much gotten my thoughts out there.  I really enjoyed working with these guys and I am looking forward to doing so again when we get back from break.

Hope this helps,

Till next time,

The benefit of writing mapping files by hand

(This post is a followup to a post on EF vs NHibernate )

As discussed in the post referenced above, my team's task was was a rework of a previous project we were all somewhat new to, and we were dealing with a database that could not be substantially changed.  It's not an ideal situation, but a pretty common one in brownfield projects.  When we had experimented with Entity Framework on this project, we just pulled in the tables through to the model and started working. (not for long, as it happened) When we decided to instead go with NHibernate, we decided to map by hand.

Starting out, we thought the initial hand-mapping would be a lot of extra time over the EF method of auto-building classes-time we were willing to put in since at least it would be straightforward compared to the problems we'd had with Entity Framework.  We had a fair number of classes with pretty complex relationships, so hand-mapping was going to take a bit of time.  Anyway, we dove in and started mapping.  As we started mapping out our relationships, we ran across some oddities-WHY were things set up as they were? We started questioning why certain relationships were in place, and why they were set up as they were (in some cases, there were extraneous foreign keys and duplication).  Other tables didn't seem to be contributing anything at all except complexity.  After seeing these things, we took a closer look at how the tables were actually used, and found that some things were not mapped well based on actual usage.  This started team discussion on what the objects were creating really *were*, if the existing naming made any sense at all, then followed and spirited talk on how we should really set up our classes, and what we could do about it given our constraints.  To save some time with all of this analysis, one of the team members also ended up writing some scripts to help do a rough initial pull of simple properties (string, dates, etc) through the mapping files to the classes-they didn't merit the same level of study at this time, and helped us finish the sprint on time.

The result of studying the tables was a compromise of tweaking some table relationships in backwards-compatible ways, renaming classes, (if not tables, since that was not available to us) creating views on top of existing tables, and in some places, simply we made note of some inconsistencies that simply could not be dealt with on the current project.  In the end, we had a much deeper, nuanced understanding of the current work, and a much better idea of  how we would deal with it going forward then we would have had otherwise.  Best of all, we gained that understanding right at the beginning of the project when it could do the most good.  To be fair, the understanding we gained wasn't a result of NHibernate itself, it was more an artifact of the way we ended up working-essentially, we ended up going through a rough exercise in building a model for ourselves that we would not have done otherwise.  But had we succeeded with Entity Framework, I don't know when or if we ever would have understood the project in that way, and I'm certain that that lack of knowledge would have burned us.

More Posts Next page »

Our Sponsors

Proudly Partnered With



What's New

The Devlicio.us Crew

Tim Barcz
36 Posts | 228 Comments | 73 Trackbacks
Sergio Pereira
84 Posts | 227 Comments | 138 Trackbacks
.NET & Funky Fresh
56 Posts | 211 Comments | 205 Trackbacks
Derik Whittaker
379 Posts | 1,583 Comments | 467 Trackbacks
Anne Epstein
1 Posts | 1 Comments | 1 Trackbacks
Chris Sutton
0 Posts | 0 Comments | 0 Trackbacks
Casey Charlton - Insane World
52 Posts | 176 Comments | 92 Trackbacks
Mike Nichols - Son Of Nun Technology
32 Posts | 121 Comments | 35 Trackbacks
Javier Lozano
0 Posts | 0 Comments | 0 Trackbacks
Christopher Bennage
69 Posts | 213 Comments | 106 Trackbacks
Billy McCafferty
75 Posts | 675 Comments | 127 Trackbacks
Lazy Developer
51 Posts | 143 Comments | 24 Trackbacks
ViNull, Off the Record
18 Posts | 35 Comments | 24 Trackbacks
Brendan Tompkins
17 Posts | 140 Comments | 20 Trackbacks
Jeff Perrin - Sexier Than You Are
13 Posts | 80 Comments | 11 Trackbacks
The Bolla Blog
11 Posts | 56 Comments | 14 Trackbacks
Alan Northam
13 Posts | 69 Comments | 22 Trackbacks
Stephen Wright
12 Posts | 50 Comments | 10 Trackbacks

Devlicio.us Alumni

Marcin Hoppe
8 Posts | 14 Comments | 0 Trackbacks
Michal Grzegorzewski
8 Posts | 28 Comments | 1 Trackbacks
Expanding the .NET blogosphere
7 Posts | 28 Comments | 6 Trackbacks
Lou Haskett
2 Posts | 14 Comments | 0 Trackbacks
Ken Gabe
1 Posts | 2 Comments | 0 Trackbacks
The Perpetual n00b
8 Posts | 37 Comments | 2 Trackbacks
Daniel Arak
1 Posts | 51 Comments | 0 Trackbacks
IDOTNET - Further along the road...
5 Posts | 1 Comments | 1 Trackbacks