When good enough is (or isn’t) good enough

Posted on January 16th, 2012 in Uncategorized by Jon Kruger

I came across this post the other day that went on and on railing on things that the author found unacceptable in today’s web frameworks, specifically Rails and ASP.NET MVC. It covered the whole gamut of issues, from abstract base classes in ASP.NET MVC to mega-controllers in MVC frameworks.

I’ve thought a lot of the same things too, to various extents. For example, I’ve never understood why controllers existed. Why can’t we just define routes that are handled by route handler classes that use conventions and REST and things like that? Yet I continue to use controllers in web apps. It made me think, at what point is something bad enough to do something about it and when do I just live with it?

This is the kind of question that makes software development so difficult, but at the same time a lot of fun. Today we were looking at a piece of code that needed to be refactored. We couldn’t figure out what the right way was to implement it, nor could we decide if it was worth the time to even do anything about it.

How do you decide what to do in this situation? The way I see it, you have to look at the return on investment on everything you do. In my controller example, I could invest the time to implement some non-controller solution. On a large enough project, I would probably get a good return on investment compared to using controllers.

But then again, you could argue that since controllers are towards the outer layers of the stack, maybe you can live with it. I care much more about the sanctity of the domain model because that’s the heart of my application. So is it really worth the time or not?

But it gets more complicated than that. Let’s say it takes me a week to implement the non-controller solution. During that time I’m not delivering any client facing features, and that might not sit too well with the people paying for your project. I was in this situation once, and the project almost got cancelled. Thankfully I pulled it out and was on the project for a year and a half and my framework investments more than paid off. But those first few weeks were nerve racking.

So what’s the answer to my original question? I guess it depends. As does pretty much everything else in software development. Which means that you don’t get an easy way out and you are going to have to use your head.

I still think I’m right about the return on investment thing. But at the same time you need to be shrewd about it.

Making a dent in the universe

Posted on December 2nd, 2011 in Uncategorized by Jon Kruger

A recent post on a local user group message board set off a firestorm of reaction. The gist of the post was that developers in Columbus “seem to focus on life in their work/life balance”, aren’t interested in working long hours, “check out at 5pm”, and that “the drive to put a dent in the universe doesn’t seem as strong here.”

Steve Jobs is the poster child for the startup/work hard lifestyle. Steve Jobs worked really hard, made a lot of money, and invented technology that changed the way that many of us doing things. When he died, scores of people were proclaiming his greatness and praising him for his contributions to society. According to many people, Steve Jobs made a large dent in the universe.

I hope I’m making a dent in the universe. But if I am, it’s not going to be because I write code. I’m thankful that I get paid to do something that I really enjoy doing. But at the end of the day, what difference does it make if I write some code that helps a company make more money?

I really love software development. I enjoy hacking on Ruby code at night and talking with people about which JavaScript framework is going to win. But while I sit here and watch my plasma TV and type on my high-end MacBook Pro while my iPhone beeps at me, people out there are struggling to get food for their kids to eat tonight, living in fear of disease or wars or corrupt governments, or sitting at home alone feeling lonely.

Obviously I’m not living in Africa running an orphanage and digging wells for poor people, but doesn’t mean that my time spent writing software is meaningless. I’m reminded of the scene in Chariots of Fire when Eric Liddell is talking about how he feels when he runs.

I believe God made me for a purpose, but he also made me fast. And when I run I feel His pleasure.

Eric was a missionary to China at times in his life, but he also found a lot of meaning in training and running in the Olympics. Some people said that running wasn’t as important as being a missionary, but running was a means to an end for him, that end being finding God’s pleasure in whatever he was doing.

We’ve all been given talents, and many of us use them every day at work. I hope that my ability to write software will give me opportunities to make a difference in lives of people that I encounter in the process. I hope that I can install confidence in the people I work with and that we can build camaraderie while we work together towards a common goal. I hope that people are energized and excited to come to work and that we can experience that good feeling that comes with working together to be successful. And while we’re at it, we’ll develop some software that will help a business be more profitable.

While I enjoy what I do at work, to me there’s a lot more out there for me than my job. I’m just not willing to line up for 80 hour weeks, multiple side projects, and lots of weekends away from home. I have a wife and two kids and to me, those things are much more important than software development. This doesn’t mean that I’m not dedicated or that I don’t care about my craft or that I’m any less of a developer than the hero programmer working 80 hours. I just have some other priorities in life that I also find important.

Many people out there work long hours (particularly people who are single). Many doing it willingly because they enjoy doing it or they find it challenging and exciting. I don’t really have a problem with that, because we’re all entitled to spend our time doing what we want.

If you could promise me that if I worked as hard as Steve Jobs that I would have the level of success that he had, I wouldn’t take you up on it. I guess I just have a different view of what success is. I would rather be a good husband, father, and friend to other people and try to use my job and career to further those goals. I may not appear to be as “driven” or “motivated” to people in the startup world, but I beg to differ. I have a passion for what I do, and software development is just one piece of that puzzle. Go on vacation away from your computer and your job for a week and you’ll notice how it doesn’t seem so important by the end of the week.

We are fortunate as developers to work in a fun and exciting industry where we get paid to do something that many of us would enjoy doing for free. My challenge to you is to look past that and see the big picture. Some day my working days will be done and when that time comes, I have a feeling that I will care more about the friendships I made and the people I helped than I will about whether I followed the Single Responsibility Principle or how many user groups I spoke at. But that day is still a long way off, so for the time being I’m going to use all the passions and abilities that I’ve been given to make the world a better place.

UPDATE: Apparently someone else was thinking the same as me… and it’s worth the read.

Reestablishing the employer/employee relationship

Posted on June 21st, 2011 in Uncategorized by Jon Kruger

DISCLAIMER: Nothing said in this post should be taken as a reflection of my relationship with any of my employers or clients, current or in the past. Thankfully the ones I’ve had have been pretty good.

How do you view your relationship with your employer? More specifically, what is your response to your employer’s requests and demands?

I feel that many people view the relationship with their employer like a sort of indentured servitude where you also collect a paycheck. When I say that, I don’t mean that in a negative way, because most people don’t think of their manager or employer in a bad light. But I feel that most employees feel like they should do whatever their employer asks them do without raising a fuss (unless something they are asked to do is unethical). Again, I’ve thought this way in the past, and I never really thought of my employers negatively (in fact, I really liked them).

The Business Of You

Today I would argue that this is not the correct way for you as an employee to view this relationship in most cases. (Yes, I am an independent consultant, so I don’t really have an employer, but I still work for and report to clients.)

Business have all kinds of relationships without outside vendors. For example, a business may have preferred hardware vendors, vendors that provide hosting services, vendors that provide janitorial services, and so on. These relationships are all mutually beneficial partnerships, where each side of the partnership has something to gain from the relationship. Businesses also have partnerships with software developers like you.

Whether you think of it this way or not, you are running a business. Your business sells your software development services. You have a business plan, goals, a balance sheet, and things that you value (you might not have these things written out, but you still have them). Your values for your business might be to make a certain amount of money, to work using a technology you enjoy, to feel like you’re making an impact on the company you work for, have time for whatever hobbies you like to do, and have ample time to spend with your family. Your family is also a part of your business because they are something that you value, and what happens at your place of work affects them too (either directly because you’re gone at work or indirectly because you’re stressed out when you get home).

I think you might view your relationship with your employer differently when you view it as a partnership between businesses. Businesses and vendors negotiate all the time on any number of issues (and not always related to money). If you think of it this way, instead of your employer unilaterally deciding the path for your business, it should be something that you both agree upon that is mutually beneficial for both sides.

Protect Your Business Interests

Like I said, I’ve had the good fortune of working for good people throughout my career, but unfortunately there are employers and managers out there who will try to coerce you into do things that are not in your best interest. For example, maybe you’re heard things like these from your manager:

  • “We have a lot to get done this release and we can’t afford to hire anyone else right now, so you all are going to have to work a little extra to get this done.”
  • “I know that I told you to build the feature that way, but actually it needs to work this way… but I still need it done by the same date.”
  • (a few days before a release) “This feature just came up and we really need to get this in, I’m going to need you all to stay late to get this done.”

Overtime, while not ideal, is a part of what we do. There are going to be deadlines, server outages, and things like that. But there’s a difference between normal overtime (server outages happen and someone needs to fix them) and someone taking advantage of you either for their own benefit or because they don’t have the guts to say no to their superiors.

Every situation is different, and maybe you’re OK with these sorts of requests. Maybe you get paid overtime and you like the extra money. Maybe you are willing to go the extra mile to get ahead or get a promotion, or maybe you don’t have many other job opportunities out there so you have to stay and deal with it. Maybe you’re in a job where overtime is expected and you knew that going in.

The important thing is to think of your career like a business. If you’re employer is trying to get you do something that isn’t good for you, don’t just sit there and let their decisions drive your business. This also applies if you want to work with a certain technology or skill set and your company doesn’t have that kind of work for you. Be willing to say no, or even be willing to go find another job. Your career should be something that benefits you and benefits the people that you work for, and as soon as one side isn’t getting any benefit, then something needs to be done.

Change doesn’t come without desire and awareness

Posted on June 1st, 2011 in Uncategorized by Jon Kruger

I spent my lunch hour at the Path to Agility conference talking with a friend of mine who is in the middle of trying to get his team to embrace some agile practices, particularly around automated testing. Some of the changes that he’s trying to implement are causing some friction with the team who are not embracing the change.

People not wanting to change is nothing new. But what is the reason behind that unwillingness? It’s real easy to blame the team members and just say that they don’t care, they’re lazy, they like technology X instead of the new thing, etc.

Instead of just blaming others, maybe we should look at how we (as the change facilitators) are helping to create a desire to change and an awareness that there is even a need for change. If you’ve been doing your job a certain way for the last 10 years at the same company and you’ve been getting praised for your work or getting good performance reviews and raises, why should you change? After all, your company has been telling you that you have been doing an exceptional job. And now you’re being told that the way that you’ve been doing it is wrong?

This is what makes situations like this particularly challenging. Before we can even expect people to change, we need to show them that although they have been doing a good job in the past, we have an idea of how they can do their job even better. For some teams, having 50 bugs in production each month might seem good to them if last year they had 80 bugs in production each month, when for some teams having 5 bugs a month in production is a lot.

Unfortunately there is no easy answer to this problem. In fact, I can’t even say that I really know how to effectively handle these things. What I am learning is that the people side of software development is probably the most difficult part, and it’s probably where we all need the most work.

A matter of perspective

Posted on October 18th, 2010 in Uncategorized by Jon Kruger

There are lots of difficult situations in life. However, it is up to you to decide how difficult they are going to be.

As of last Thursday I have a newborn living in my house. While this is awesome, it will probably be several months until I can sleep all the way through the night again and I’m often awake at 2:00 AM rocking a baby to (hopefully) sleep. There are more or less two ways that I can deal with this:

  • Stupid kid, why won’t he just go to sleep??!?!??
  • God has blessed me with this cute little addition to our family and I get the honor and privilege of teaching him how to sleep, eat, play, and live.

Regardless of which of those two viewpoints I take, the reality doesn’t change: he’s going to keep me up at night. There’s really nothing I can do to change that, that’s just how newborns are. But I can change the way I look at it and the attitude that I take towards the situation. As a result, I’m now smiling at 2:00 AM as I look at our little youngster instead of being bitter about having to roll out of bed yet again in the middle of the night.

The same idea can apply to any difficult situation in life, including your career. Maybe you’re stuck doing boring maintenance work, working with less than stimulating technologies, or just not doing what you’d really like to do. While this can certainly be draining, try and take a new approach to it: in the morning when you get to work, choose to strive to be the best that you can be with whatever technology you’re using. Try and find new ways to get better and faster at it. Turn those hindrances and constraints into a challenge. Don’t let the situation determine your happiness or your motivation.

Every day you have a choice to be awesome at what you do or to find ways to be negative and let things tear you down. It’s much more fun to be awesome!

Planning for success

Posted on September 8th, 2010 in Uncategorized by Jon Kruger

We all want to succeed at something, whether it’s your career, a sport, being a good parent, or whatever else you’re working at. But do you have a plan for succeeding?

The fact of the matter is that if you just hope that you’re going to succeed without doing something to make sure that you actually do succeed, it’s unlikely that you will achieve your goals. Most people do not succeed accidentally, they do it through many small decisions and actions over the course of time that lead them to success.

First, think about your personal mission statement in life. What are your priorities, and what is most important to you? Consider everything — your family, God, friends, activities, work, etc. This way when you set goals for yourself, you can make sure that they line up with your priorities. For example, maybe your work goals involve spending 20 hours a week doing something and as a result you don’t have any time to spend with your kids. If your list of priorities says that your family is more important than work, maybe you need to think about the goals that you’re setting to make sure that it’s the right thing to do.

Once you write out your personal mission statement and your priorities, it’s time to think about your goals. Do you want to learn how to do mobile development? Be a better spouse? Get to know your kids better? Be able to run a half-marathon? Lose 20 pounds? Brainstorm and write down a bunch of ideas.

Now that you have your ideas, evaluate them all and figure out which ones are most important. Think of your life and career like a business. What adds the most value to your life at this point in time? You can have different goals for different areas of your life (e.g. your marriage, your kids, your career).

Once you have your goals, think about the steps that you need to take to get there. Write them down and share them with someone else so that they can help you stay on track.

Now you have to execute. When you have to make a decision about what to do with your time, remember your goals and priorities and make the decision based on that. You certainly don’t want to make decisions solely based on things like feelings, what others might think, or what others say you should do.

This is what I do to make sure that I’m making the most of my life and it’s really helped me keep my priorities straight and be a better husband, father, and software developer.

I’m doing the “grok talk” at CONDG on Thursday

Posted on July 20th, 2010 in Uncategorized by Jon Kruger

I’m doing a quick little “grok talk” at the CONDG meeting this Thursday, July 22. I’ll be talking about some simple productivity tips that have helped me to get things done faster and become more productive and effective. While this does not sound very exciting and sexy as hearing Tim Wingfield talk about IronRuby, finding ways to become faster and more productive is something that we all could use.

And if I end up boring you to death (which I don’t plan on doing), you can stay and listen to Tim talk about IronRuby.

I’m ready for a new kind of conference

Posted on May 7th, 2010 in Uncategorized by Jon Kruger

During the last week I was able to go to two software development conferences, the Ann Arbor Day of .NET and Stir Trek. I love these events because I get to see a lot of people that I don’t get to see on a regular basis.

On the other hand, I don’t feel like I get much out of the sessions anymore. It’s not that the sessions are bad, but I feel like I’ve heard a 100/200 level talk on pretty much everything I want to hear about. At each of these conferences there have been some talks that I have really enjoyed, but a lot that I don’t have a real interest in hearing again.

Granted, I’ve been to more of these events than a lot of people. I remember the first time I went to events like this and they were awesome. I was learning a ton of stuff and it was new and exciting.

I miss that feeling. I certainly don’t know it all. I know there is a lot that I could learn. But I guess I’m ready for a new kind of conference. Some ideas floating around in my head:

  • A conference featuring mostly 300-400 level talks
  • A BarCamp style event where anyone can sign up and show code
  • An all open space conference

I know there are conferences like this. I know I’m not the only person who thinks this because I’ve talked to other people feeling the same way. I’ve heard of some of these conferences, but they’ve been other places other than Central Ohio. For example, look at the session list for the most recent ALT.NET Seattle event and notice the difference between this event and the various Day of .NET events. Granted, the target audience is different. But I’m a part of that target audience. I don’t always have the time and money to travel to these events.

I think part of the problem is the wide breadth of technologies in the .NET space. In the last year Microsoft has released Silverlight 4, Windows Mobile 7, .NET 4, ASP.NET MVC 2, OData, and probably other stuff that I can’t remember off the top of my head. So it’s really easy to come up with an “Intro to <insert new MS tech here>” because there are so many choices. Often times these are compelling topics, don’t get me wrong. But every day I go to work and I’m working on plain old web apps or Winforms apps or WPF apps like the rest of you. I want someone to come talk about how I can do better at what I’m doing every day. Show me how to better implement design patterns, or how to test my code better, or how you structure your MVC app to take advantage of jQuery validation, or how to use some ORM, etc. Those things will help me do a better job on the projects that I’m working on today. Sure, I’m curious about Windows Mobile 7 and Silverlight and OData, but my first priority is to get better at the stuff I’m using at work right now.

I feel like I’m getting a lot of talks that might pique my curiosity about new technology, but not a whole lot about how I can improve at the stuff I already know. I’m talking about talks like Nate Kohari’s talk at MIX about how he built Agile Zen with ASP.NET MVC and jQuery. When I watched this talk, I got some ideas on how to do some things, but I also realized that Nate is doing some crazy stuff with jQuery and JavaScript that I would’ve never thought of. It showed me some things that I need to go learn that could really help me on my current ASP.NET MVC project.

Please don’t think I’m criticizing conferences like Stir Trek or the Ann Arbor Day of .NET, because they’re good events put on by volunteers who spend their own time to put it on without any compensation, and I’m really thankful that people spend their time so that we can have community events like this.

I guess I’m just looking how I can take my daily work to the next level.

Improving your validation code — a refactoring exercise

Posted on March 11th, 2010 in Uncategorized by Jon Kruger

Today we’re going to talk about validation. Most people have some concept where they validate an entity object before it is saved to the database. There are many ways to implement this, and I’ve finally found my favorite way of writing validation code. But what I think is really interesting is the thought process of the many years of validation refactoring that have got me how I do validation today. A lot of this has to do with good coding practices that I’ve picked up over time and little tricks that allow me to write better code. This is a really good example of how I’ve learned to write better code, so I thought I’d walk you through it (and maybe you’ll like how I do validation too).

In the past, I would’ve created one method called something like Validate() and put all of the validation rules for that entity inside that method. It ended up looking something like this.


public class Order
{
  public Customer Customer { get; set; }
  public IList<Product> Products { get; set; }
  public string State { get; set; }
  public decimal Tax { get; set; }
  public decimal ShippingCharges { get; set; }
  public decimal Total { get; set; }
  
  public ValidationErrorsCollection Validate()
  {
    var errors = new ValidationErrorsCollection();
    if (Customer == null)
      errors.Add("Customer is required.");
    if (Products.Count == 0)
      errors.Add("You must have at least one product.");
    if (State == "OH")
    {
      if (Tax == 0)
        errors.Add("You must charge tax in Ohio.");
    }
    else
    {  
      if (ShippingCharges > 0)
        errors.Add("You cannot have free shipping outside of Ohio.");
    }
    
    return errors;
  }
}

The problem with this approach is that it’s a pain to read the Validate() method. If you have a large object, this method starts getting really cluttered really fast and you have all kinds of crazy if statements floating around that make things hard to figure out. This method may be called Validate(), but it’s not telling much about how the object is going to be validated.

So how can we make our validation classes more readable and descriptive? First, I like to do simple validation using attributes. I’m talking about whether a field is required, checking for null, checking for min/max values, etc. I know that there is a certain percentage of the population that despises attributes on entity objects. They feel like it clutters up their class. In my opinion, I like using attributes because it’s really easy, it reduces duplication, it’s less work, and I like having attributes that describe a property and give me more information about it than just its type. On my project, I’m using NHibernate.Validator to give me these attributes, and I’ve also defined several new validation attributes of my own (just open NHibernate.Validator.dll in Reflector and see how the out-of-the-box ones are written and you’ll be able to create your own attributes with no problems). Now my class looks more like this:


public class Order
{
  [Required("Customer")]
  public Customer Customer { get; set; }
  [AtLeastOneItemInList("You must have at least one product.")]
  public IList<Product> Products { get; set; }
  public string State { get; set; }
  public decimal Tax { get; set; }
  public decimal ShippingCharges { get; set; }
  public decimal Total { get; set; }
  
  public ValidationErrorsCollection Validate()
  {
    var errors = new ValidationErrorsCollection();
    if (State == "OH")
    {
      if (Tax == 0)
        errors.Add("You must charge tax in Ohio.");
    }
    else
    {  
      if (ShippingCharges > 0)
        errors.Add("You cannot have free shipping outside of Ohio.");
    }
    return errors;
  }
}

When I put these attributes on properties, I don’t write unit tests for that validation. If I was really concerned about whether or not I put an attribute on a property, I could spend 2 seconds going and actually checking to see if that attribute was on the property instead of spending 2 minutes writing a test. It’s just so easy to use an attribute that it’s hard to screw it up. I haven’t been burned by this yet. So already I’ve eliminated some validation code that was cluttering up my validation methods and I eliminated some tests that I would’ve otherwise written.

But my Validate() method still looks messy, and it’s doing a bunch of different validations. The method name sure isn’t telling me anything about the type of custom validation that is being done.

Let’s write some tests and see where our tests might lead us.


[TestFixture]
public class When_validating_whether_tax_is_charged
{
  [Test]
  public void Should_return_error_if_tax_is_0_and_state_is_Ohio()
  {
    var order = new Order {Tax = 0, State = "OH"};
    order.Validate().ShouldContain(Order.TaxValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_tax_is_greater_than_0_and_state_is_Ohio()
  {
    var order = new Order { Tax = 3, State = "OH" };
    order.Validate().ShouldNotContain(Order.TaxValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_tax_is_0_and_state_is_not_Ohio()
  {
    var order = new Order { Tax = 0, State = "MI" };
    order.Validate().ShouldNotContain(Order.TaxValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_tax_is_greater_than_0_and_state_is_not_Ohio()
  {
    var order = new Order { Tax = 3, State = "MI" };
    order.Validate().ShouldNotContain(Order.TaxValidationMessage);
  }
}
 
[TestFixture]
public class When_validating_whether_shipping_is_charged
{
  [Test]
  public void Should_return_error_if_shipping_is_0_and_state_is_not_Ohio()
  {
    var order = new Order {ShippingCharges = 0, State = "MI"};
    order.Validate().ShouldContain(Order.ShippingValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_shipping_is_0_and_state_is_Ohio()
  {
    var order = new Order { ShippingCharges = 0, State = "OH" };
    order.Validate().ShouldNotContain(Order.ShippingValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_shipping_is_greater_than_0_and_state_is_Ohio()
  {
    var order = new Order { ShippingCharges = 5, State = "OH" };
    order.Validate().ShouldNotContain(Order.ShippingValidationMessage);
  }
 
  [Test]
  public void Should_not_return_error_if_shipping_is_greater_than_0_and_state_is_not_Ohio()
  {
    var order = new Order { ShippingCharges = 5, State = "MI" };
    order.Validate().ShouldNotContain(Order.ShippingValidationMessage);
  }
}

These tests are testing all of the positive and negative possibilities of each validation rule. Notice that I’m not checking just that the object was valid, I’m testing for the presence of a specific error message. If you just try to test whether the object is valid or not, how do you really know if your code is working? If you test that the object should not be valid in a certain scenario and it comes back with some validation error, how would you know that it returned an error for the specific rule that you were testing unless you check for that validation message?

I could just leave the validation code in my implementation class as is. But I’m still not happy with the Validate() method because it has a bunch of different rules all thrown in one place, with the potential for even more to get added. If I just refactor the code in the method into smaller methods, it’ll read better. So now I have this:


public class Order
{
  public const string ShippingValidationMessage = "You cannot have free shipping outside of Ohio.";
  public const string TaxValidationMessage = "You must charge tax in Ohio.";
 
  public Customer Customer { get; set; }
  public IList<Product> Products { get; set; }
  public string State { get; set; }
  public decimal Tax { get; set; }
  public decimal ShippingCharges { get; set; }
  public decimal Total { get; set; }
 
  public ValidationErrorsCollection Validate()
  {
    var errors = new ValidationErrorsCollection();
    ValidateThatTaxIsChargedInOhio(errors);
    ValidateThatShippingIsChargedOnOrdersSentOutsideOfOhio(errors);
    return errors;
  }
 
  private void ValidateThatShippingIsChargedOnOrdersSentOutsideOfOhio(
            ValidationErrorsCollection errors)
  {
    if (State != "OH" && ShippingCharges == 0)
      errors.Add(ShippingValidationMessage);
  }
 
  private void ValidateThatTaxIsChargedInOhio(ValidationErrorsCollection errors)
  {
    if (State == "OH" && Tax == 0)
      errors.Add(TaxValidationMessage);
  }
}

That’s better. Now when you read my Validate() method, you have more details about what validation rules we are testing for. This is a more natural way of writing the code when you write your tests first because it just makes sense to create one method for each test class.

Then your boss comes to you with a new rule — an Ohio customer only gets free shipping on their first order. This is a little bit trickier to test because now I’m dealing with data outside of the object that is being validated. In order to test this, I am going to have to call out to the database in order to see if this customer has an order with free shipping. How this is done I don’t really care about in this example, I just know that I’m going to have some class that determines whether a customer has an existing order with free shipping.

One of the cardinal rules of writing unit tests is that I need to stub out external dependencies (like a database), and in order to do that, I need to use dependency injection and take in those dependencies as interface parameters in my constructor. But another rule of DI is that I can’t take dependencies into entity objects. This means that I’m going to have to split the validation code out from my entity object. I’ll move them out into a class called OrderValidator, and it’ll look like this:


public class OrderValidator : IValidator<Order>
{
  private readonly IGetOrdersForCustomerService _getOrdersForCustomerService;
  public const string ShippingValidationMessage = "You cannot have free shipping outside of Ohio.";
  public const string TaxValidationMessage = "You must charge tax in Ohio.";
  public const string CustomersDoNotHaveMoreThanOneOrderWithFreeShippingValidationMessage =
    "A customer cannot have more than one order with free shipping.";
 
  public OrderValidator(IGetOrdersForCustomerService getOrdersForCustomerService)
  {
    _getOrdersForCustomerService = getOrdersForCustomerService;
  }
 
  public ValidationErrorsCollection Validate(Order order)
  {
    var errors = new ValidationErrorsCollection();
    ValidateThatTaxIsChargedInOhio(order, errors);
    ValidateThatShippingIsChargedOnOrdersSentOutsideOfOhio(order, errors);
    ValidateThatCustomersDoNotHaveMoreThanOneOrderWithFreeShipping(order, errors);
    return errors;
  }
 
  private void ValidateThatCustomersDoNotHaveMoreThanOneOrderWithFreeShipping(Order order, ValidationErrorsCollection errors)
  {
    var ordersForCustomer = _getOrdersForCustomerService.GetOrdersForCustomer(order.Customer);
    if (order.IsNew)
      ordersForCustomer.Add(order);
    else
    {
      ordersForCustomer = ordersForCustomer.Where(o => o.Id != order.Id).ToList();
      ordersForCustomer.Add(order);
    }
    if (ordersForCustomer.Count(o => o.ShippingCharges == 0) > 1)
      errors.Add(CustomersDoNotHaveMoreThanOneOrderWithFreeShippingValidationMessage);
  }
 
  private void ValidateThatShippingIsChargedOnOrdersSentOutsideOfOhio(Order order, ValidationErrorsCollection errors)
  {
    if (order.State != "OH" && order.ShippingCharges == 0)
      errors.Add(ShippingValidationMessage);
  }
 
  private void ValidateThatTaxIsChargedInOhio(Order order, ValidationErrorsCollection errors)
  {
    if (order.State == "OH" && order.Tax == 0)
      errors.Add(TaxValidationMessage);
  }
}

Notice that the OrderValidator class implements IValidator. This interface is pretty simple and looks like this:


public interface IValidator<T>
{
    ValidationErrorsCollection Validate(T obj);
}

Now that the validation class has been moved outside of the entity object, I need to know which IValidator<T> classes I need to run when I want to validate an object of a certain type. No worries, I can just create a class that will register validator objects by type. When the application starts up, I’ll tell my registration class to go search the assemblies for classes that implement IValidator<T>. Then when it’s time to validate, I can ask this registration class for all IValidator<T> types that it found for the type of entity that I need to validate and have it do the validation.

I think we could take this one step further. Currently our OrderValidator class is doing three different validations. You could argue that this violates the Single Responsibility Principle because this class is doing three things. But you might also be able to argue that it doesn’t violate the Single Reposibility Principle because OrderValidator is only doing one type of thing. Does it really matter?

What if you got a new validation rule that says that the State property on the Order can only contain one of the lower 48 U.S. states (any state other than Alaska or Hawaii). We also want to add this rule to a bunch of other entity objects that only should use the lower 48 states for their State property. Ideally, I would like to write this validation rule once and use it for all of those objects.

In order to do this, I’m going to create an interface first:


public interface IHasLower48State
{
  public string State { get; }
}

I’ll put this interface on the Order class and all of the other classes that have this rule. Now I’ll write my validation code (after I write my tests, of course!). The only problem is that it doesn’t really fit inside OrderValidator anymore because I’m not necessarily validating an Order, I’m validating a IHasLower48State, which could be an Order, but it also could be something else.

What I really need now is a class for this one validation rule. I’m going to give it an uber-descriptive name.


public class Validate_that_state_is_one_of_the_lower_48_states : IValidator<IHasLower48State>
{
  public const string Message = "State must be one of the lower 48 states.";
  
  public ValidationErrorsCollection Validate(IHasLower48State obj)
  {
    if (obj.State == "AK" || obj.State == "HI")
      errors.Add(Message);
  }
}

Some of you are freaking out because I put underscores in the class name. I put underscores in test class names, and it just seemed natural to use a very descriptive English class name that describes exactly what validation is being performed here. If you don’t like the underscores, then call it something descriptive without using underscores.

Now I change my registration class so that when you ask for all of the validation classes for an entity, it also checks for validation classes for interfaces that the entity implements.

What’s great about is that if an entity object implements IHasLower48State, it will now pick up this validation rule for free. My registration class has auto-wired it for me, so I don’t have to configure anything. I get functionality for free with no extra work! I’m creating cross-cutting validation rules where I’m validating types of entities.

Conclusion

If you made it to this point, you’re a dedicated reader after making it through all of that (or you just skipped to the end). I wrote all of this not only to show how I do validation, but also to show you the thought process I go through and the hows and whys behind how I refactor things and find better ways to write code.

Software Engineering 101 - Sat., Feb. 27 - Nashville and online!

Posted on February 24th, 2010 in Uncategorized by Jon Kruger

Leon Gersing, Jim Holmes, and I are putting on our Software Engineering 101 event this Saturday, Februrary 27 in Nashville. If you’re not in Nashville (and you probably aren’t), you can watch the entire event online on LiveMeeting!

We’ll cover topics like object-oriented programming, the SOLID principles, and code metrics and we’ll spend the afternoon doing some hands-on test-driven development. This event was a lot of fun the first time we did it and I’m really looking forward to it.

You can register for this FREE event here (you need to register if you want to watch online to get the LiveMeeting info).

Next Page »