Jon Kruger -
  • About Me
  • Blog
  • Values
  • Presentations
About Me
Blog
Values
Presentations
  • About Me
  • Blog
  • Values
  • Presentations
Jon Kruger
Agile

Adapting Agile to the real world

Pick up a book on Agile practices and you might find a wonderful, yet often unrealistic view of a perfect world where everyone buys into Agile practices throughout the business and you glide gracefully down the road to success.

The problem is that for most of us, that perfect environment doesn’t (and will probably never) exist, and that’s OK.

Maybe your team isn’t staffed the way that it needs to be. Maybe the people on your team don’t have the right skillset (yet). Maybe you have to integrate with lots of other systems, so you have to do a lot of up front planning and design so that you can make sure everything gets done on time.

The point is not to implement 100% of Scrum or XP or Kanban or some other methodology. I like to boil Agile down to this:

Do more of what works and less of what doesn’t.

Implementing 100% of XP may not be the best thing for you, or it may not be feasible. That’s not XP’s fault, they’re just giving you a set of best practices to work with that have proven to work well for some people. It’s up to you to make it work for you. Frankly, I don’t think it matters if something you do falls in the category of “Agile”. I just want to find ways to improve the development process, regardless of what you call it.

One practical thing that we all can do (whether we’re in charge of a team or not) is to try to improve our development process every day. Try to find ways to do more of what works and less of what doesn’t, improve processes and communication, and help your team succeed. Set your sights on the end goal and start taking steps in that direction.

January 5, 2011by Jon Kruger
QA

Developing a testing strategy

As soon as you write code, bad things can happen. Your code can be defective, and it can break existing code. It’s our job to make sure that we don’t break things.

Not breaking things is not easy. You might end up with only one bug that sneaks through into production but that can be one too many.

The team I’m on is currently trying to figure out what our plan is for testing and QA. We have two concerns:

  • How can we wrote code without defects?
  • How can we make sure that our code changes don’t break existing code?

The second one is proving to be the difficult one. Our application is 4 years old, and a good chunk of the code was written by people who are no longer on the team. It’s really difficult at times to not break something when you don’t know enough about the system to know the ramifications of what you’re about to do.

When I develop new code, I try to figure out how we can validate that everything is working and complete. When possible, I want to write automated tests. In the Ruby world, I’m using Rspec and Cucumber to do this. I want to make sure that all of the code that I write is covered by a test if possible. Thankfully Rspec and Cucumber do not make this very hard at all, and we tend to test the crap out of things as a result.

But some things are hard to validate. For example, if you’re pulling a subset of data from an external database using an SQL query, how do you know that you’re pulling back the correct data? It’s hard (if not impossible) to write an automated test for this, and in some cases you have to coordinate with someone on the team that owns the database in order to test it. It’s really important not to ignore these tests and just say that it’s going to be too hard to test. Unless you’re OK with it being broken, you have to validate it.

As a developer, don’t think that this is just the responsibility of your QA team to figure out how to test things. Certainly your QA team should be involved in coming up with the plan for testing, but you might know of edge cases that a QA person wouldn’t know about, and you might know of technical constraints that might make testing hard. Too many defects are created because developers put the onus on QA to find everything. Remember, we’re all on the same team.

So now you go into production and you move on to something else, but you’ve created a lot of features that will need to be regression tested. Here is where I think it’s really difficult. How do you keep these regression tests up to date? For example:

  • When you add a new security role to the system, do you update old test plans to test whether or not the new security role should be able to do something?
  • If you change a validation rule, do you update old test plans that could be affected by the new validation rule? (This could mean adding new tests to an old test plan because you might now have two paths through something where you might’ve only had one test before.)
  • When things change like this, how do you even know where you might need to update test plans?

I’d be interested in hearing how you all handle these situations. This is a situation where I’m really glad that I have automated tests (yesterday I was doing a big refactoring and my Cucumber tests pointed out a whole bunch of things that I had broken). But automated tests only solve the problem when you have a test for something. If you create new paths through the code that now don’t have a test, you need a way to find those scenarios and write tests for them.

December 15, 2010by Jon Kruger
BDD, Cucumber, Ruby, TDD, unit testing

Using Cucumber for unit tests… why not?

It seems that the accepted way to test in Ruby is to use Rspec for unit tests and to use Cucumber for acceptance tests (higher level functional testing). After doing a little bit of Cucumber, I’ve started to fall in love with the format of Cucumber tests.

Most Rubyists would probably agree that behavior-driven development is good (in other words, writing tests in a Given/When/Then format). We obviously do this in Cucumber (there isn’t much choice), but I’ve also written tests in this format in Rspec and in .NET.

I like BDD for two main reasons. First, I believe that software development is a series of translations. I want to translate business requirements into readable, executable specifications, then translate that into tests, then translate that into implementation code. Second, before I implement a feature and even before I write my tests, I try to write out what I want the code to do in English. If I can’t write out what I want to do in English, how and I supposed to know what I’m supposed to write in code?

Here’s my theory: if we agree that BDD is good, why don’t we write our unit tests in a format that is more amenable to BDD, that being the Cucumber format of tests? I’m not saying that we write acceptance level tests instead of unit tests, I’m saying that maybe we should write unit tests in a different format. Not only that, Cucumber tables give us a nice way to write more readable, data-driven tests. Here are a couple examples from the supermarket pricing kata (in Rspec and Cucumber).

Cucumber:

Feature: Checkout

  Scenario Outline: Checking out individual items
    Given that I have not checked anything out
    When I check out item 
    Then the total price should be the  of that item

  Examples:
    | item | unit price |
    | "A"  | 50         |
    | "B"  | 30         |
    | "C"  | 20         |
    | "D"  | 15         |

  Scenario Outline: Checking out multiple items
    Given that I have not checked anything out
    When I check out 
    Then the total price should be the  of those items

  Examples:
    | multiple items | expected total price | notes                |
    | "AAA"          | 130                  | 3 for 130            |
    | "BB"           | 45                   | 2 for 45             |
    | "CCC"          | 60                   |                      |
    | "DDD"          | 45                   |                      |
    | "BBB"          | 75                   | (2 for 45) + 30      |
    | "BABBAA"       | 205                  | order doesn't matter |
    | ""             | 0                    |                      |

  Scenario Outline: Rounding money
    When rounding "" to the nearest penny
    Then it should round it using midpoint rounding to ""

    Examples:
      | amount | rounded amount |
      | 1      | 1              |
      | 1.225  | 1.23           |
      | 1.2251 | 1.23           |
      | 1.2249 | 1.22           |
      | 1.22   | 1.22           |

Rspec:

require 'spec_helper'

describe "Given that I have not checked anything out" do
  before :each do
    @check_out = CheckOut.new
  end

  [["A", 50], ["B", 30], ["C", 20], ["D", 15]].each do |item, unit_price|
  describe "When I check out an invididual item" do
    it "The total price should be the unit price of that item" do
      @check_out.scan(item)
      @check_out.total.should == unit_price
    end
  end
end

  [["AAA", 130], # 3 for 130
    ["BB", 45],  # 2 for 45
    ["CCC", 60],
    ["DDD", 45],
    ["BBB", 75], # (2 for 45) + 30
    ["BABBAA", 205], # order doesn't matter
    ["", 0]].each do |items, expected_total_price|
    describe "When I check out multiple items" do
      it "The total price should be the expected total price of those items" do
        individual_items = items.split(//)
        individual_items.each { |item| @check_out.scan(item) }
        @check_out.total.should == expected_total_price
      end
    end
  end
end

class RoundingTester
  include Rounding
end

[[1, 1],
  [1.225, 1.23],
  [1.2251, 1.23],
  [1.2249, 1.22],
  [1.22, 1.22]].each do |amount, rounded_amount|
  describe "When rounding an amount of money to the nearest penny" do
    it "Should round the amount using midpoint rounding" do
      RoundingTester.new.round_money(amount).should == rounded_amount
    end
  end
end

A couple things stand out to me when you compare these two. First, if I want to run data-driven tests with different values, the Cucumber syntax is so much cleaner and more descriptive. Second, the “Given I have not checked anything out” section in the Rspec version is really long and contains two nested “describe” sections (many times you end up with many more than this). When you nest sections like this, it’s really hard to see the context of things or read the tests because the “Given” text is nowhere near the nested “When” sections in the code.

Rspec follows in the footsteps of previous unit testing frameworks that write test methods in test classes (or in the case of Rspec, something that resembles test classes and methods. But is this the best way, or just the way that we’re used to? We have been writing unit tests this way for years and years because we had no other choice. But that doesn’t mean that it’s the best way.

Here are the benefits I see of using the Cucumber syntax over Rspec:

  • The tests are much easier to read (especially when doing data-driven “scenario outline” tests).
  • The Given/When/Then text is all in one place (as opposed to spread out and mixed in with code).
  • It forces me to be able to write out in English what I want the code to do.
  • Any step definition that I write can easily be reused anywhere in any other Cucumber test.
  • The code just looks cleaner. I’ve seen a lot of messy Rspec tests.
  • Rspec doesn’t have a method that corresponds to the “When” step (unless I’m missing something), so you have to shoehorn it into before(:each) or the “it” method. (I’m not sure why this is, we figured this out in the .NET world long ago.)

To be fair, there are more BDD-friendly flavors of Rspec (like rspec-given). This helps you write tests in Given/When/Then format, but I still feel like all of the underscores and symbols and syntax is getting in the way of the actual test verbiage.

Favoring Cucumber is my personal preference and I know that there are some people that would probably disagree with my opinion on this, and that’s fine. But I’m really enjoying what Cucumber brings to the table, both in terms of functionality and the syntax.

December 13, 2010by Jon Kruger
productivity

The productivity gain that everyone ignores

Your team can become much more productive today! And the cost is very small relative to the cost of your developers!

You think that managers would be very interested in this sales pitch, yet almost none of them will buy it.

What am I talking about? Buying your development team new hardware. This especially applies if you’re developing in a language in .NET or Java where you have to compile your project.

I was excited to read this post today because this team gets it. One of their big improvements was to get solid-state drives for their code.

I’m trying to figure out how this doesn’t make sense. If you’re paying your developers $70-90k a year, why wouldn’t you spend a couple hundred dollars for a solid-state drive to help them get things done faster? If your team needs a profiler or ReSharper or some other software package, that request is almost always approved.

Compilation time on big .NET projects (even medium-sized .NET projects) is brutal. It totally slows down your momentum. There really isn’t much else you can do during this time (most developers check email, check Twitter, surf the web, etc.). Wouldn’t you like that to be productive time?

December 6, 2010by Jon Kruger
productivity

Go faster

Go to a software conference near you and you will probably hear talks on new languages, new frameworks, how to design code better, how to test better, and the like. What no one ever seems to talk about is how you can go faster.

We need to get faster at what we do, because it just takes too long. Why do you think companies and managers are always pressuring people to get things done faster? This is a tricky situation though — the challenge is to find ways to get faster without cutting corners, ignoring unit testing, and writing poorly designed code. Anyone can get things done faster by deciding to not write tests or not think about how to design code well, but that’s cheating. That just leads to more bugs and more work down the road.

Don’t ignore the importance of getting things done in a timely manner. I got to be a project manager on a project once, and every day I was looking at our feature wall to see how we were doing and if we were on schedule. I guarantee that your manager or project manager is doing the same thing. That experience and awareness helps keep me from not wasting time adding non-essential features or spending too much time over-analyzing things (be especially careful of this one if you’re pairing). I try to work with a sense of urgency, as if I’m competing with someone else who is trying to complete the same project faster than I can (without cutting corners).

One way to get faster at something is to practice. Find a simple coding problem, like the ones mentioned here. Pick an easy one (nothing with crazy math algorithms, complicated recursion, etc.), or maybe take a complicated one and simplify it. Try and find something that you can do in 15 minutes or less, but still involves writing tests and creating multiple files.

The first time through, go through it like you normally would. Think about design, write good tests, and make sure you understand all the nuances. Then go back and do it again and time yourself. Do it over and over, and try to beat your previous time. At this point, you’ll know how to design the code pretty well, and in order to get faster you’ll have get faster at moving around your IDE, find ways to generate code, or learn new tricks. This is what you’re trying to learn. Remember, you’re not allowed to cut corners! You still have to write tests and write well-designed, readable, clean code. Check your code each time you’re done and make sure you didn’t compromise in these areas.

In sports, there are the teams that are good on paper and there are those who execute during crunch time. You may be good at writing well-designed, well-tested code, but if you can’t get it done on time, no one is going to care. So take time to hone your skills and become a faster developer.

November 10, 2010by Jon Kruger
JavaScript, TDD

JSView: Readable, object-oriented JavaScript TDD

UPDATE: this was written before the advent of the new wave of JavaScript frameworks (Angular, Backbone, Ember, etc.). While I have moved on from using my home grown framework to these other more robust frameworks, I still agree with the concepts here, specifically that I should be able to test as much of the behavior of my UI by having a thin layer between my code and the DOM.

If you’ve tried to write JavaScript using TDD and your JavaScript deals with DOM elements, I’m guessing you’ve felt some pain. The toughest thing about writing tests against JavaScript is separating the HTML elements and the page from the JavaScript code. In the past when I’ve done this, I’ve created JavaScript classes and either passed UI elements into the constructor or by calling a method. So in the real page, I’ll have code that looks like this:

$(document).ready(function()
{
    var myClass = new MyClass(document.getElementById('blah'));
});

Then in my test class, I do something like this:

module("MyClass tests");

test("Test something", function()
{
    var element = new Object();
    var myClass = new MyClass(element);
});

This works fine since JavaScript is a dynamic language, I can put any property on the “element” variable and then write tests against it, checking various properties that I know will get set on the real element (like “innerHTML”, for example).

Here’s the problem with this: if you’re writing tests first, you’re not sure what kind of elements you are going to have in the UI. Maybe “innerHTML” will get set on my element, or maybe “value”, or maybe something else. I just don’t know because I haven’t written the UI yet.

What I need it something that wraps the HTML element so that I can just call a function like getValue() and get the value, which may come from “value” in some cases, “innerHTML” in other cases, etc., depending on what kind of UI element I have.

jQuery to the rescue!

It turns out that we already have something that will wrap UI elements — jQuery. Using jQuery, we can search for elements by type (e.g. DIV, A, TR, etc.), class, or id. This works something like this:

var elements = $(‘.MyCssClass’);

This returns all elements that have the MyCssClass class applied to them. But it doesn’t return the actual elements, it returns a wrapper around the HTML element. It also turns out that said wrapper has functions like val(), html(), and text() that I can use to get the values! Just what I needed.

But I still have a problem. If I’m trying to test code that deals with 20 different UI elements, that means that I am going to have to inject 20 UI elements or test doubles into my JavaScript code. This is both ugly and painful.

A simpler abstraction

JSView is an abstraction layer that sits between your JavaScript code and jQuery/HTML so that you can write tests for your JavaScript code without having the actual page and the DOM available in a test. Instead of calling jQuery methods directly, you will call methods that will interact with jQuery in your app, but will interact with a fake replacement for jQuery in your tests. Not only that, JSView will generate methods for you so that you can easily access values and events in a readable fashion. This will allow you to truly TDD your object-oriented JavaScript before the actual page even exists!

Now I can write object-oriented JavaScript classes that look something like this:

function Calculator(element, view)
{
    if (view == null)
        view = new jQueryView('Calculator', element);

    registerObjectProperties(this, view, ['FirstValue', 'SecondValue', 'Result', 'AddButton']);

    this.whenAddButtonIsClicked(function()
    {
        this.addValues();
    });

    this.addValues = function()
    {
        this.setResult(Number(this.getFirstValue()) + Number(this.getSecondValue()));
    }
}

Now I can write JavaScript unit tests that look like this (and without the DOM in place!):

module('When the Add button is clicked',
{
    setup: function()
    {
        calculator = new Calculator(null, new ViewTestDouble());
        calculator.setFirstValue(2);
        calculator.setSecondValue(3.5);
        calculator.clickAddButton();
    }
});

test('Then it should add the values in the first two textboxes and put the result in the third textbox', function()
{
    equals(calculator.getResult(), 5.5);
});

More details can be found here. The source code is up on github. I’ve been using and refining this for two years and I’m really liking how it’s turned out. I’m very interested in any feedback that you all might have, I’ve done a lot of JavaScript over the years but I’m not quite the JavaScript ninja that some other people are.

So get busy and write some tests!

October 25, 2010by Jon Kruger
.NET, Ruby

Ruby on Rails vs. .NET: Don’t take it personally

As I’ve written these Ruby on Rails vs. .NET posts, I was not expecting some of the comments that I got. Not that the comments I got were not bringing up valid points, but I felt a tension in some of them. The same is true about other similar RoR/.NET posts (like this one — read the comments).

I feel like this is disintegrating into a religious us vs. them debate. I had no intention of it ever being this way, nor should it be in my opinion. I’ve just been stating my preference and explaining the reasons why.

If you prefer .NET over Ruby on Rails, I have no problem with that! If you’re better at .NET or it’s a better fit than RoR for what you’re doing, I’m not saying you’re wrong. I personally think that RoR is a better web development platform than ASP.NET, but that’s just my opinion. I also don’t think that ASP.NET MVC sucks or anything like that, I’ve had a lot of success with it and it’s still getting better.

I think as software developers we need to at least consider other languages and platforms that we don’t use regularly because there might be something better out there. If anything, you’ll learn something that you can take back to your platform and make it better. You might not like what you find, and that’s fine, at least you can know that you checked it out. Not everything you try will be worth using.

You are not your language or development platform. You are a software developer who happens to have expertise in a certain language or platform. If someone even were to deride your platform (which I have no intention of doing), don’t take that as a personal attack. There are a lot of ignorant people out there in all walks of life, don’t let them ruin your day. Just because someone likes Ruby on Rails doesn’t mean that you are any less of a developer for choosing .NET.

At the same time, I’ve found a platform I like and I’m going to talk about why I like it, because on this blog I talk about things I like. Some people find this “proselytizing” to be annoying, and I’m sorry that you feel that way. I’m only doing the same thing that .NET developers did when they proclaimed that Silverlight is better than Flash and that Windows Phone 7 is the next big thing. There is nothing wrong with being excited about a platform, technology, or framework that you like. That doesn’t mean that you have to think the same as me or agree with me, and I welcome the discussion. But let’s try and be polite about it.

October 22, 2010by Jon Kruger
.NET, Ruby

Ruby on Rails vs. NET: The Active Record Pattern, is it OK?

Persistence in Ruby on Rails is done by most people through the ActiveRecord ORM, which follows and is named after the Active Record pattern. There are other Ruby ORMs (like DataMapper) that don’t follow the Active Record pattern, but they aren’t used nearly as much.

Some .NET people seem to sneer at Ruby’s use of Active Record. There is a .NET implementation of the Active Record pattern (Castle ActiveRecord, which is a layer on top of NHibernate). In .NET and Java, the Active Record pattern is somewhat frowned upon and is usually considered not as good as a more robust, flexible ORM like NHibernate or the Entity Framework where your database tables don’t have to look just like your objects.

Some people would say that the Active Record pattern violates separation of concerns because the entity objects know how to load and save themselves. One big problem in the .NET world is that since an entity object can load itself, it has to do so with static methods (e.g. User.Load(3)), which means that now you can’t stub that out in a test (if you’re in a static-typed language). In a dynamic language like Ruby you don’t have the testability problem because you can stub out class methods (analogous to static methods in .NET).

There are still more concerns posed about the Active Record pattern. Is it maintainable in the long term? What if you don’t want your database tables to look like your objects? What if I would rather have separate domain service classes to do the persistence? What about the repository pattern?

If you’re a .NET person, you have to think about life in a truly dynamic world, where you don’t have the testability issues. Are any of those other things really a concern? If you’re starting a new app, what are the chances that your database tables won’t look like your objects? In most cases, I would say slim to none! If you have an application where you have some data concerns that would require to make your data model have a different shape than your objects, then you can’t use ActiveRecord. If you want to use an object database like MongoDB, then you use an ORM that works with MongoDB (like Mongoid). If you’re building a new app on top of an existing database, you may need something that will allow you to do different kinds of custom mappings (although you might be able to shoehorn it somewhat). But for the large majority of everyone else, what is the real concern?

The added flexibility that something like NHibernate or DataMapper gives you comes with a price — added complexity. Fluent NHibernate and some of the new Entity Framework stuff allow you to do convention based mapping so that it takes away a lot of this pain. If your domain model objects have a different shape than your database tables, you could have performance concerns (although not always).

What you get from ActiveRecord is simplicity, and simplicity is worth something. When you use ActiveRecord, you are essentially saying that your database and codebase are under your control, so you can have your database tables match the domain model objects using certain conventions. Your database becomes a very thin layer that does nothing more than store and retrieve data, and all of the business logic is in the business layer (where it should be in my opinion, regardless of your ORM). If you have to change your domain model objects for some reason, you change the database too. So I’m not constrained by my database because all of my logic is in the business layer, which allows me to easily change either layer whenever I need to. The benefit to this is that you don’t need to write any code to map your objects to your database and you don’t need as much hand-rolled SQL (you’re always going to have hand-written SQL for some queries no matter what).

The Rails project that I’m currently on is four years old. We use ActiveRecord as our ORM. I don’t see any situations where it really constrains us at all or makes our code less maintainable. I think it makes things simpler because it is assumed that the database tables and domain model objects look the same (you can override some of that if you need to). I feel like there is a lot of fear and uncertainty in the .NET world over ActiveRecord because the pattern isn’t really accepted in the .NET world (for good reasons). But that doesn’t mean that it doesn’t fit well in a dynamic language like Ruby, where I think it works quite well.

So if you’re a .NET person who is skeptical about ActiveRecord in Ruby, I would encourage you to have an open mind. There are other alternatives if it doesn’t fit your application, but in most cases I think it gets the job done quite well.

October 21, 2010by Jon Kruger
.NET, Design, Ruby

Ruby on Rails and the Single Responsibility Principle

Several people took issue with my last post about Ruby on Rails saying that my example violates the Single Responsibility Principle. Here’s where I stand on this.

The SOLID principles are principles, not hard and fast laws of software development. When applying the SOLID principles, common sense should rule. There are times when violating the textbook definition of the principles is OK (regardless of what language you are using). The ultimate goal of all design principles should be reducing the cost of change. Reducing the cost of change comes in many forms:

  • Being able to get things done faster because you have to write less code
  • Being able to get things done faster because it’s easier to figure out code and what you need to change
  • Being able to get things done faster because code is wrapped in tests so you can change it and not worry about breaking things
  • Being able to get things done faster because you have automated tests which decrease the amount of manual testing that you or your QA team needs to do
  • Being able to get things done safer by having abstraction layers in place so that changing code in one place doesn’t break something else
  • Having well defined requirements so that you don’t waste time on rework
  • Having business sponsors available to answer questions quickly
  • Many more reasons that I’m not thinking of

With this in mind, all of my design decisions, including how I apply the SOLID principles, need to reduce the cost of change.

Also, keep in mind that the SOLID principles were written with static-typed languages in mind (C++, Java, .NET). While a lot of the same principles apply in dynamic languages, you can’t assume that everything is the same. In fact, the “I” and “D” of the SOLID principles arguably don’t apply to dynamic languages at all.

Several people said that my Ruby class violated SRP because it mixed class behavior, database mapping, and validation all in one class. Again, this is where I would take issue with your application of SRP. Here is the Ruby class in question:

class User < ActiveRecord::Base
  belongs_to :user_status
  has_many :roles, :through => :user_roles
  validates_length_of :name, :maximum => 100
  named_scope :active, :conditions => ["user_status.id = ?", UserStatus::ACTIVE]
end

On my last .NET project, I had domain model classes like this:

public class User : Entity
{
    public virtual long Id { get; set; }
    [Required("Name"), Length(50)]
    public virtual string Name { get; set; }
    public virtual IList UserRoles { get; set; }

    public virtual bool IsInRole(string role)
    {
        // code here
    }
}

I was using Fluent NHibernate as my ORM on this project, so I had a database table that looked like this object. So in this case, I have class behavior (IsInRole method), validation (the attributes on the Name property), and implied database mapping (using Fluent NHibernate conventions). How is this any different than my Ruby class?

Some people might argue that the textbook definition of SRP would say that I shouldn’t put validation attributes on properties like that. What is your other alternative? Write a line of custom code in an IsValid method or in another validator class, I assume. Is that reducing the cost of change? If I write custom code, I have to write a test for it. If I write boilerplate stuff like “[Required(“Name”)]” or “validates_presence_of :name”, that is so simple that I’m not going to write a test for it because I don’t think I gain anything from doing so. If I can add a whole bunch of behavior in just one line of code, then potentially violating the textbook definition of SRP is OK with me because it’s way easier to do it that way and it just makes sense.

Back to my Ruby class. My class knows how to load, save, and delete itself. In .NET, I would say this is a bad thing. First of all, I wouldn’t be able to stub out the database in a test (which I can in Ruby because I can stub out anything). Second, if you have multiple entities that do things a certain way (e.g. multiple entities that need to be cached when loading, saving, or deleting them), you would have no easy way to do that without duplicating some code (in Ruby, I can create a module and include it in a class, and in that way I could override a method like “save”). Third, I would have a direct dependence on the database, which violates the Dependency Inversion Principle (which doesn’t apply in Ruby, because all I’m depending on is some class out there with a method with a certain name, as opposed to .NET where I’m depending on a method in a class in an assembly in a .dll with a specific version). So as you can see, your domain model takes on a much different shape in Ruby vs. .NET. Both ways have their pluses and minuses, but each way is the best way for the language that you’re using.

There is one area where I see an interesting clash of Ruby and SRP. Because I don’t have to use dependency injection and because I can stub out any method in a test, it makes sense to put all methods relating to an entity object into the entity class itself. This just makes sense, and TDD would lead you in that direction. Doing this will lead you into having some really big domain model classes though.

Would this violate the textbook definition of SRP? I would say yes. You run into some of the issues that you have with big classes (harder to read). In .NET, we would argue that we should move a lot of this behavior into domain service classes, which would be smaller and easier to use in other classes (by taking the interface into the constructor of the class that was going to use it). In .NET, you have to pull things out of the entity object in order to be able to stub it out in a test, so at that point you might as well go the rest of the way and make small classes. But if you had the flexibility of being able to stub out anything in a test and you had Ruby-style mixins in .NET, would you really do it this way? One could argue that the .NET way of doing things in domain services is an example of Martin Fowler’s anemic domain model anti-pattern.

In both languages, you are making a tradeoff. In .NET, we are saying that testability is more important that potentially having an anemic domain model and having model behavior scattered around in domain services. In Ruby, we are saying that we would rather have all of the behavior in the entity class itself because it makes sense to have it there (we don’t have to worry about testability because everything is testable), even though we could end up with some big classes. Neither way is necessarily wrong, it just depends on the language you’re working in. In some cases, the .NET and Ruby communities have generally agreed on their own “best practices” and ways of doing things, and that’s just how people do things in those languages, often because the languages and frameworks make it easier to do it that way.

In summary, it depends, and use common sense. Remember what your goal is — to deliver working software. Your architecture is not the deliverable, and it’s not what makes money for the business. Flexibility, design patterns, abstraction layers, and the like often come at varying levels of cost. It’s up to you decide if it’s worth it in your situation.

October 19, 2010by Jon Kruger
.NET, Ruby

Ruby on Rails vs. .NET: Doing more with less

One thing that I quickly noticed about Ruby on Rails is that you can do a lot more with less code. This is one of the benefits of working in a dynamic language like Ruby that does not have as many restrictions as a static typed language. The end result is that you have smaller methods, more descriptive code, fewer chances to create bugs, and it becomes easier to get things done. Let me show you what I mean.

Let’s say that I have a database table that looks like this:

create table Users
(
    id int,
    name varchar(100),
    user_status_id int,
    created_at datetime,
    updated_at datetime
)

My Ruby class looks like this:

class User < ActiveRecord::Base
  belongs_to :user_status
  has_many :roles, :through => :user_roles
  validates_length_of :name, :maximum => 100
  named_scope :active, :conditions => ["user_status.id = ?", UserStatus::ACTIVE]
end

My class only has 6 lines, but it does an awful lot. Let’s go through it line by line:

class User < ActiveRecord::Base

Because I have a table in the database called "Users", I now have the following methods on my User class:

  • id, id=, name, name=, user_status_id, user_status_id=, created_at, created_at=, updated_at, updated_at=
  • find, find_by_id, find_by_name, find_by_user_status_id, find_by_name_and_user_status_id, find_by_id_and_name_and_user_status_id, and any other combination of columns I might want to query on

Because I derive from ActiveRecord::Base, I inherit a lot of data access methods like save, delete, destroy, and many more.

All I've done so far is made my class declaration! Look at everything I'm getting for free.

belongs_to :user_status

My User object has a many-to-one relationship to the User_Status table (and it's corresponding UserStatus object). I now have the "user_status" and "user_status=" methods on my object. The user status will be lazy loaded, so it won't do any database queries to get the user status until I actually need it.

has_many :roles, :through => :user_roles

My User object has a many-to-many relationship with the roles table, and in the database there is a user_roles table that serves as a mapping table. I now have a "roles" method on my User class that will give me the list of roles, and I can add new roles to the collection without having to worry about creating anything for the mapping table.

validates_length_of :name, :maximum => 100

Name is required and cannot be longer than 100 characters.

named_scope :active, :conditions => ["user_status.id = ?", UserStatus::ACTIVE]

Now I can write "User.active", which will return all active users. This is equivalent to User.find_by_user_status_id(UserStatus::ACTIVE), but now I've abstracted away that concept of an active user so that other classes don't have to know how the internals work.

end

OK, well, every language has to have some ceremony.

I haven't created any methods yet! Already my object has all of the data access methods that it needs, it will validate the object before it saves, it knows about related objects, and I abstracted away the concept of an active user.

Note that not only have I been able to do all of this with very few lines of code, the code that I did write was very simple and readable. Since the code is so simple, I'm not going to write unit tests for it either (the tests would basically be the same one line of code as the implementation code in most cases).

All of this means that I can do things much easier than before. In .NET, I would've had to create finder methods by hand. I would've had to add all of the properties that match up to my database columns by hand. I don't know how I would duplicate named_scope in a .NET ORM, maybe it's possible somehow. I've never found a way to do it. Maybe I would have to write a stored procedure.

To sum it up, all of the boring crap is done for me and I can pretty much immediately start writing code that provides business value, which is what we're getting paid to do. No ADO.NET, no more mapping my database table to my entity object, no more modifying several files just to create the same kinds of methods that I have to create for every new entity object that I create.

All of this is helping me to achieve what I've always wanted in software development: the ability to write code that says what I want to do and does it without having to do lots of typing.

October 19, 2010by Jon Kruger
Page 13 of 24« First...10«12131415»20...Last »

About Me

I am a technical leader and software developer in Columbus, OH. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...