Monday, April 26, 2010

View-Model design question

Here's a design question for you!

Lets say you are working in ASP.NET MVC 2 (or your favorite MVC web framework).  Lets also say you have a nice rich model.  Your controllers have to fetch the model objects and get that data to your view.  How do you do that?

There are a bunch of ways:
  1. Pass the model directly to the view
  2. Create a "View-Model" class and put a property on it that exposes the model
  3. Create a "View-Model" that completely hides the model behind properties of its own
And there are a bunch of variations on those too.  But those are the main options.

The best thing about #1 is it's as simple as can be.
#2 is almost as simple as #1 but adds the ability for you to create other custom properties on the "View-Model" object that can perform various operations for the view.  For example, you might format values, or retrieve the latest object from a list, etc.

The downside to these two options is your View is directly coupled to your Model.  This might become a problem if you end up with lots of Views that depend on the same Model, or if the Model keeps evolving and being refactored over time.

That's where #3 comes in.  By creating all new properties on the View-Model, you're basically applying the Dependency Inversion Principle and saying, "This view needs this data, I don't care where it comes from as long as someone provides it."  You will now need some form of mapping layer to get the data from the Model to the properties of the View-Model.  This is more work, but it's also nice.  When the Model changes, you only need to update the mapping, which is dramatically easier than digging into lots of HTML and finding what could be many references to your properties.

Now, that said, there are still lots of changes that will require you to make changes to the Model, View-Model, and View.  Any change that is a change in the *meaning* of the Model will cascade this way.  But there is a whole set of changes that won't cause this update cascade.  Like any refactoring of the Model for example.

The obvious downside with #3 is more code and more work (Though tools like AutoMapper certainly help).

So, how do you know when to apply which pattern?  Is one pattern always better than the others, or does it depend.  And if it depends, on what?  And how do you know when it's time to switch from one to the other?

Thoughts?  Experiences?

Monday, April 19, 2010

SRP and complexity

The Single Responsibility Principle (SRP) is probably the most important concept of good design.  But even once you know about it, and have read up on it, and seen countless blog articles describe and reference it, you may find yourself hesitant to actually follow it in real life.

The usual argument against it is that it seems like it might increase the complexity of your code.  Lets look at an example of applying SRP to a method.

public void UpdatePrimaryThingStatus( string status )
{
  Thing primaryThing = null;
  foreach( Thing t in something.AllThings )
  {
    if ( t.IsPrimary )
    {
      primaryThing = t;
      break;
    }
  }

  if ( primaryThing != null )
    primaryThing.Status = status;
}
There's nothing _wrong_ with this code, but it doesn't really follow SRP because the method is updating the primary thing's status, as advertised, but it's also finding the primary thing.  Lets factor out the finding of the primary thing into its own method:

public void UpdatePrimaryThingStatus( string status )
{
  var t = GetPrimaryThing();
  if ( t != null )
    t.Status = status;
}

public Thing GetPrimaryThing()
{
  foreach( Thing t in something.AllThings )
  {
    if ( t.IsPrimary )
      return t;
  }
  return null;
}
Notice how much code actually disappeared here.  And notice how simple each method is.  But, we did add a new method to the class.  Do we intended to reuse this method?  That depends, it IS a useful method that could easily be reused, but since we didn't have it already, lets assume we don't need to reuse it right now.  So yes, we simplified the code in the individual methods, but by adding a new method we've increased the complexity of the class.

We should probably ask why adding a new method is a problem.  It's only one new method!  It's well defined with a single responsibility, with an intention revealing interface, and simple code to boot.  Why would we think this is going to increase the complexity of the class?  Probably because we're used to working with classes that are thousands of lines long with lots and lots and lots of methods!  So yes, if you're applying SRP to your methods, but not to your classes, things might get a little complex.  But make sure your classes have a single responsibility, and you'll find that this wont be the case anymore.

OK, so if our classes are following SRP, then we'll be breaking large classes into more smaller classes.  But now we have lots of classes!  Doesn't that make our code more complex?

This same pattern will follow right up the chain through namespaces and assemblies...  is this getting out of control?  What's the solution?

The solution is cohesion!  You can add lots of small classes as long as they are all part of a cohesive whole.  This is actually a really beautiful thing.  If your classes are well organized, and obviously form a cohesive unit, you get an amazing benefit.  Lets say you need to go into the code and find a bug.  You know what area the bug is in, even if you don't know exactly what it is.  There may be 20 files that make up your code, but you'll probably only need to crack open 3 or 4 of them to find and fix the bug.  And each file you do open will be understandable, dare I say, easily understandable.

You may think there is still a problem in understanding the WHOLE.  To understand how it all works, don't you now need to open all these little classes and figure out how they all work together?  Yes and No.  Again, I think the fact that each class has a clear single responsibility (and therefore an intention revealing interface) means you can actually understand the WHOLE and read less code than if you had it all squished into a single class.

So, whatever you do, don't let fear of complexity drive you away from SRP.

Monday, April 12, 2010

Framework Disease

A lot of software engineers have a Computer Science background.  My college education, for example, included  the standard things like Data Structures and "Operating Systems."  It also included some cool things like Artificial Intelligence, Peer to Peer, Automata Theory, and Evolutionary Computation.  I was also fortunate enough to have the opportunity to participate in some research projects as well which included Mobile Agents, Evolutionary Computation, and Swarm computing.

These things are cool.

But now I spend my time figuring out how to get data from a UI into a database and back again.  That's basically the bottom line of "Enterprise Application Development".  Surprisingly, there are enough challenges in this space to keep you busy for a very long time.  And while the topic itself doesn't have a lot of sex appeal, the work is actually amazingly broad, even just from a technical standpoint.  And once you add the "business" concerns in, it has the potential to become very interesting indeed.

But still I'm a computer scientist, and I'm inexorably drawn by computer science-y problems.  In the Enterprise space, the most computer science-y problems tend to be those of building "frameworks."  And what I mean by framework, is re-usable code bases that developers use to avoid having to write the same (or similar) code over and over again.

Frameworks are to some people as cat nip is to cats, or street lights are to moths, drugs to drug addicts, or cigarettes to smokers, or...  Some people loooooooove building frameworks.  They are always on the look out for an opportunity to build a framework.  At the first sign of duplication, or recurring pattern, you can see the light in their eye... framework!

I call this Framework Disease.  Frameworks are tricky.  They can be huge time savers.  And they certainly are fun to work on, since they're so computer science-y.  But at the same time, they can be real time wasters.

Sometimes the problem you are trying to solve with a framework simply isn't worth the time it takes to build the framework.  This could be because all the framework does is replace some standard boilerplate code that could easily be copied and pasted or generated.  In these cases, centralizing the boilerplate can actually be a bad thing because you're forcing every use to be identical forever.  Just because they are the same now doesn't mean they always will be, or always should be.

Other times the framework ends up being written in such a way that it actually becomes a problem.  This can happen when the framework starts limiting what you can do, or when it continues to grow and grow and grow, or when the complexity of the framework obscures the simplicity of the problem being solved.  When this happens you're spending more time working on and fighting with your framework than you are on actually getting things done.

Another problem with frameworks is the tendency to build them too soon.  If you set out to write a framework without having seen plenty of examples of what your framework will be replacing, your framework is probably doomed.  To be really successful, you have to write the code your framework will replace in a number of different places.  If you don't, you'r just guessing about what should be abstracted into the framework.  This means you really don't know what should go in the framework, nor where the framework should be flexible or where it should be rigid.

I have personally fallen into all these traps many times, and just about everyone I know has suffered from a bit of Framework Disease at one time or another.  It is very contagious.

I think Framework Disease is a symptom of not being connected enough with the goals of the development effort.  At Codemash, Mary Poppendieck told a little parable that went something like this:
A philosopher walked into a quarry and saw three people working with pickaxes.  He walked up to the first man and asked him, "What are you doing?"  The man irritably looked up and said, "I'm cutting stone, what the hell does it look like?!"  The philosopher moved on to the second man, asking the same question.  "I'm making a living for my family."  Finally the philosopher asked the third man, who responded, "I'm building a Cathedral!"
The third guy clearly understood the context of his work.  I think a lack of understanding of the context of work is frequently what leads to Framework Disease.  Passionate people in particular are susceptible to this.  Without a broad understanding of why you are doing what you are doing every day, how can you possibly stay focused on the important things?  How can you possibly stay energized?

So if you find yourself exhibiting the symptoms of Framework Disease, step back and ask yourself, "If I'm not building a Cathedral, what am I building?  And does this framework really further that goal?"

Monday, April 5, 2010

Passion

I think there are two qualities that set really great developers apart:
  1. Technical competence
  2. Passion
Pretty much in that order.  If Bob has strong tech skills, it means he can solve complicated problems to a reasonable level of quality independently.  But if he is lacking passion, it means he wont be looking for opportunities to improve, or to push the envelope on issues like code quality, cleanliness, productivity, etc.

If Bill has a lot of passion, it means he'll be on the lookout for ways to improve.  Both in his own work, and his team's work.  But if Bill doesn't have the technical competence to back it up it means he's simply unreliable.  The impression will be that he pays lots of lip service to quality and improvement but never manages to actually deliver any.

Bennie, on the other hand, might have both of these qualities.  This makes him reliable and constantly improving. And not just improving himself, but improving those around him.  Bennie is the guy who's likely to not only complain about some "policy" his office has that he feels is hurting more than helping, but to actually work on getting that policy changed.  Effectively, Bennie is a leader.

I think people with passion naturally end up leading, regardless of whether they are in "leadership" roles.  You don't have to be the boss to influence how your company works.  And you don't have to be the team lead to influence what technologies get used and how.

However it is this fact that makes passion a double edged sword.

Passionate people are more likely to challenge the status quo.  Which is good.  Unless they are challenging it in ways that actually hurt their team or hurt their company.  This runs along the same lines as some issues I discussed in an earlier post called Engaged Employees.  In a nut shell, if the priorities of the passionate people don't line up with the priorities of the business, you've got trouble ("With a capital T.  And that rhymes with P and that stands for..." Passion?).

When the passionate people become dis-engaged, there are two likely outcomes.  They might start "farting around" with "improvements" that don't actually help the team or the business accomplish any of its goals.  It is probably still true that these "improvements" are "good" in their own context.  But in the context of the business, they might actually be "bad," or possibly just unimportant (and therefore a waste of time).  On the other hand, the passionate people might decide to simply checkout.  They might decide to put in the minimal amount of effort possible, with an attitude of "screw those guys."  If just one person was acting in either of these ways, it wouldn't be that big of a deal.  But when it's your passionate people, it can lead to much more trouble.  These are your leaders after all, and their attitude and behavior rubs off on everyone else.

A company plagued with dis-engaged passionate individuals (like Bennie) would probably like to trade them all for simply technically compete people (like Bob).  The Bobs would stop causing so many problems and stop challenging everything and stop being in such a bad mood all the time and just get their work done.

But we have to ask, what has led the passionate people to be so removed from the goals of the business?  I think there is always a simple one word answer to that question: Management.  The book First Break All The Rules makes the case that a managers job is simply to bring out the best in his people.  And not the best out of context.  If you're an amazing yo-yo player but you program for a living it's not your manager's job to bring our your best yo-yoing.  Obviously.  It's his job to bring out your best in the context of the goals of the business (What a Programmer Wants in a Manager).  If your passionate people don't know what the priorities of the business are, or if they can't figure out what they could do today to have the biggest impact on the company, then management has messed up somehow.

But just because management has messed up doesn't mean we get to blame them and call it a day.  It doesn't mean we can just give up, stop trying, decide not to care, or adopt a bad attitude.  That is the path to the dark side.  As Bobbies, we have to do what we've always done: Fix it!  This is going to be harder for us than, say, designing a better data layer.  This is now a people problem.  And as technical nerds, we are probably not the best suited individuals to address people problems.  But sometimes we have to embrace the circumstances life throws at us, however uncomfortable they may be, and we have to grow up, step up, and fix it!