Jon Kruger -
  • About Me
  • Blog
  • Values
  • Presentations
About Me
Blog
Values
Presentations
  • About Me
  • Blog
  • Values
  • Presentations
Jon Kruger
.NET, Uncategorized

We’re flushing money down the toilet and no one is talking about it

Every business cares about making money and reducing costs. Yet every day I press a button and sit idly while I watch a little progress bar move. This happens every time I want to run an application or run a test.

compiling

Compiling code is something we’ve just gotten used to. Maybe that’s not the right phrase — we’ve learned how to put up with it. Granted, things are a lot better than they used to be. My first job after college was working on a C++ application where changing some of the foundational header files meant 30 minutes of compiling just to rebuild the application!

When .NET came out, they said that it compiled so fast that you would wonder if it actually did anything. That was true on demo apps that only had a few source files, but as your application grows and grows over time, those compilation times are quite noticeable. Certainly it was better than it was in C++, but that only makes you feel good for so long.

Let’s compare this to working with a dynamic language like JavaScript. When I’m coding JavaScript, it runs my tests in less than a second whenever I save a file!! No compiling, no loss of momentum, and oddly enough, dynamic languages don’t run noticeably slower than compiled languages for the kinds of applications that most of us are building.

Scary math

How much is compiling costing you? I decided to find out. The application that I’m in is 5 years old and has a fairly sizable codebase. Rebuilding the entire solution takes about 2 minutes, but usually I don’t need to rebuild everything. If I change a test file and run the tests, it still takes 30 seconds to compile what it needs to run the test. My machine is a year or two old, but it’s a pretty solid development machine with plenty of RAM and everything running on SSD. Your codebase may be smaller (or larger) than mine, so the compile times will vary. If you codebase is smaller because you app is younger, think about what it might be when your app is 5 years old.

There is a Visual Studio extension called Build Monitor that will record the compilation time every time you compile and then dump it to a json file. We all installed this and we recorded compile times from several different developers over a couple weeks, and here’s how it came out:

99 hours of dev time
5.4 hours spent compiling

… which means that 5.45% of our time was spent waiting for the code to compile.

Let’s put this in perspective:

If I code for 8 hours, I lose 26 minutes to compiling each day.

If I code 6 hours a day on a 6 month project, I lose a whole week to compiling.

Spread that across your entire team and multiply that by the average hourly rate of your employees.

5 days lost x 6 hours of coding time per day x 5 devs x $60/hr = $9,000

That’s real money!

Note that we haven’t taken into account that I can’t take advantage of my tests as much when the cost to run them is higher, so I’ll write a bunch of code before I run the tests, which makes diagnosing problems harder.

We also aren’t taking into account the slowdown that comes from having to stop for 30 seconds and go find something else to do like check email while I wait.

We also aren’t taking into account the lost business value because we can’t deliver features faster.

We also aren’t taking into account that someone out there is writing code that is trying to take away your market share, and if they can do it faster than you, they have an advantage.

What can we do about this?

Here are some things you can try to reduce compile times.

Get an SSD

There’s absolutely no reason why you should not be using a solid state drive at this point. When I switched to an SSD, my code compiled 3 times faster. You can get a 128GB SSD on Amazon for under $50. If your company won’t buy one for you, buy it yourself.

Get a faster machine

A new machine isn’t as cheap as an SSD, but if you can get a faster machine and speed up compilation time, the machine is going to pay for itself very quickly. At least make sure that your current machine isn’t strapped for RAM (which is really cheap).

Check your build settings

Once you download your nuget packages, you don’t need to check for them on every build! I like to leave this box unchecked.

nuget

Make sure the number of parallel project builds matches the number of threads your machine can run at one time. Also, when you run your code, you should only be building the projects that you need to run the code.

buildandrun

Split up your solution

If your solution contains a bunch of projects that you don’t ever edit, they’re just taking up memory and compile time. I like having one solution that has everything, but it can’t hurt to make smaller solutions that only have subsets of the code that you need in certain circumstances.

Unload projects

If you don’t split up your big solution, you can unload projects by right-clicking on the project in the Solution Explorer and selecting Unload Project. This will essentially remove the project from the solution that you have open without actually removing it (unloading is a user-level thing, so you can unload what you want without affecting your other team members).

Consolidate projects

I see lots of solutions where there’s a project for the data layer, a project for the business layer, a web project, and many more. The problem with this approach is that every time you compile, it has to copy .DLLs around to all of those different bin\debug folders, which takes time.

I would recommend consolidating projects whenever you can. Yeah, this might allow someone to reference the data layer from a controller instead of going through the business layer, but we all should know what you should or shouldn’t do in a codebase without having to have project boundaries enforcing it.

There is one caveat here… if you consolidate projects, then you can’t unload them anymore and you’ll have to compile them all the time. So while you might save time by consolidating projects, in some cases you could increase people’s compile time because you force them to compile code that they might otherwise unload.

Rethink your language choice

If you’re using a dynamic language like Ruby or Python or JavaScript and you’re still reading this, you may be mocking .NET developers right now. People that use dynamic languages can run their tests anytime they save a file. They can deploy changes to code by just deploying a single code file instead of compiling all of the code and deploying it. They can change a line of code, hit F5 in the browser, and immediately see what will happen. They don’t have to spend $500 for their IDE. They don’t absolutely need to have super high end machines to do development. And oh by the way, they aren’t spending 5% of their day watching their code compile.

(Yes, I know there’s a free version of Visual Studio, but how many of you are using that at work?)

I did Ruby on Rails for a year, and not only was it nice to not have to compile, I just loved the language. You really can do a lot more with less code. I felt like someone took off the training wheels and I could just write code that did what I wanted to do without all of the ceremony.

I realize that it doesn’t make sense for most teams to rewrite an existing codebase in another language just to avoid compilation. However, I will say this – someone else is competing against your company, and by using another language, they could have a 5% (or more) advantage. Ruby on Rails is very widely used by startups, and no one is more pressed for time and money than a startup.

C’mon .NET

I’m sure there are reasons that .NET can’t become an interpreted language like Ruby, but why can’t it? You can already make dynamic method calls in .NET using reflection, and at runtime it will attempt to call the method that you specified and will throw an exception if it can’t find the method. So why can’t everything work that way? Compilation may still have value as a sort of test to make sure that everything does link up, and it probably makes runtime faster if I can compile my code before I deploy it. But the real win will come when I can write .NET code and run it without having to check every method call and check every line for syntax errors when I’m only going to execute a few lines of code in a test.

Yeah, I know, now there’s ASP.NET Dynamic Compilation, but when I read about it, it just sounds like moving the slow compilation to the web server, which is convenient but isn’t going to save a lot of time when developing from what I can tell. But I haven’t actually tried it, so I suppose I could be wrong (I hope I am).

What else am I missing?

Do you have any ideas, tips, or tricks for how you’ve reduced compilation time on your team? I’d love to hear your thoughts! We’re all tired of watching progress bars.

November 11, 2015by Jon Kruger
.NET

A lesson in LINQ deferred execution

I learned something interesting about LINQ today, and I’m surprised that it took me this long to run into this.

Do you think this test would pass?

public class Account
{
    public int AccountId { get; set; }
    public string Status { get; set; }
}

[TestClass]
public class Test
{
    [TestMethod]
    public void Deferred_execution_test()
    {
        var accountIds = new[] {1, 2, 3};
        IEnumerable list = accountIds.Select(accountId => new Account {AccountId = accountId});
        
        foreach (var account in list)
            account.Status = "Active";

        foreach (var account in list)
            Assert.IsTrue(account.Status == "Active");
    }
}

It actually fails.

I'm sure when you've been debugging code you've at some point seem something like this:

The key is the "Expanding the Results View will enumerate the IEnumerable". This means that it hasn't yet executed the code in the Select() clause. So every time you access the IEnumerable<T>, it's going to execute the Select() statement, which means that it will new up new Account objects every time.

This test will pass:

public class Account
{
    public int AccountId { get; set; }
    public string Status { get; set; }
}

[TestClass]
public class Test
{
    [TestMethod]
    public void Deferred_execution_test()
    {
        var accountIds = new[] {1, 2, 3};
        IEnumerable list = accountIds.Select(accountId => new Account {AccountId = accountId}).ToList();
        
        foreach (var account in list)
            account.Status = "Active";

        foreach (var account in list)
            Assert.IsTrue(account.Status == "Active");
    }
}

All I did was add .ToList() to the end of the statement after the Select(). This executes the Select() statements and stores and actual List<T> in the "list" variable instead of a WhereSelectArrayIterator (which has deferred execution).

Just something to keep in mind if you're using Select() to new up some objects.

March 28, 2015by Jon Kruger
.NET, TDD, unit testing

Changing how I structure unit tests

When I write unit tests, I use the BDD-style GIven/When/Then format so that the tests are descriptive and explain the business functionality that is being implemented. But I’ve recently changed the way that I do it.

Let’s say that I’m implementing bank account functionality and I am writing code to implement the following:

Given a bank account
When I deposit money into the account
Then the balance should increase by the amount of the deposit

The old way

I used to write them like this:

[TestFixture]
public class When_I_deposit_money_into_the_account : Specification
{
    private Account _account;

    public void Establish_context()
    {
        _account = Given_a_bank_account();
    }

    public void Because_of()
    {
        _account.Deposit(10m);
    }

    [Test]
    public void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

    private Account Given_a_bank_account()
    {
        return new Account();
    }
}

This style is used by RSpec and many people in the .NET community. I’ve had a lot of success doing it this way, but I’ve always had some complaints.

  • The Given/When/Then phrases are spread out and aren’t in order.
  • We have the Specification base class, which isn’t bad but I think it might confuse new people who know NUnit but don’t know my special base class.
  • If you have a lot of “given” statements, you’re tempted to use inheritance or nested contexts, each with their own level of setup, virtual properties and methods, etc. This is very unreadable and gets unwieldy very quickly.

The new way

This isn’t really a new way, but it’s new to me. I’ve seen it before over the years but I didn’t really start doing it until I joined my current team where they did it this way and I’ve come to like it a lot better than the old way.

[TestFixture]
public class Bank_account_tests
{
    [Test]
    public void Deposit()
    {
        Given_a_bank_account();
        When_I_deposit_money_into_the_account();
        Then_the_balance_should_increase_by_the_amount_of_the_deposit();
    }

#region Helper methods  

    private void Given_a_bank_account()
    {
        _account = new Account();
    }

    private void When_I_deposit_money_into_the_account()
    {
        _account.Deposit(10m);
    }

    private void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

#endregion
}

The best thing about doing it this way is that the business functionality is clearly specified at the top of the class and the Given/When/Then statements aren’t spread out all over the place. There are no crazy inheritance hierarchies, base classes, or big setup methods. When I write tests, I just write out the Given/When/Then scenarios in plain text and then use Specs2Tests to generate the test code for me. Then all I have to do is fill in the private helper methods. This is really easy, like filling in the blanks.

Also, I typically hate regions but in this case I find that they work quite well because they hide the helper methods that I typically don’t want to see when I open the class file.

It depends

Obviously there are situations where this is all overkill and you can just write simple tests without Given/When/Then methods all over the place. Just do whatever makes sense. I’ve found that this new-to-me way leads to very readable and easy to maintain tests.

January 18, 2012by Jon Kruger
.NET, Ruby

Retrospective – a year as a Ruby on Rails developer

I spent the last year or so working on a Ruby on Rails project and now I’m back in the .NET realm again. I’ve been asked to write about what that year working on a new platform taught me and how I’m applying it to .NET, so here goes.

I love the Ruby language

I really really like Ruby as a language. You can write good code in Ruby and you can write good code in .NET. But I can write much cleaner, succinct code in Ruby because the language has fewer restrictions. I can do all of the same things in .NET, but it might require factories, dependency injection, code generators, etc. The code ends up getting the job done, but there is a lot more code and it’s more complex. The best example I can think of is a set of factories that create objects for unit tests. I’ve seen many implementations of this in .NET, but none have approached the simplicity of factory_girl in Ruby.

UNIX command line

UNIX is very command-line driven and it’s designed to be that way, so you can do a lot from the command line. You can do a lot with the Windows command line too (certainly with Powershell), but for the first time I really mastered the command line, and I really liked it. Now when I’m in Windows I pretty much use the bash shell that gets installed with Git for almost everything.

On switching from .NET to Rails

I really like Rails, but Rails is different from .NET in a lot of ways. I had no trouble coming into an existing Rails team and picking things up quickly. There are a lot of similarities between Rails and ASP.NET MVC. But if you want to take an existing .NET team and all start doing Rails, you definitely are going to want to bring someone with Rails experience to help you. You have to learn a whole new stack (because Rails runs on UNIX). The patterns and techniques are the same, but learning a new toolset will take time.

This doesn’t mean that teams shouldn’t consider switching to Rails. I’m just saying that while that might be a worthwhile idea, it’s going to take some work. But now that I’ve gone through the exercise, if I had to start a new project and was either working on my own or could choose a team to work with me, I would go with Rails because I feel it’s easier to do things.

Ever changing frameworks

Rails is open source, and there literally is a gem for everything. The problem is that all of it is constantly being updated. So if you decide to use the latest version of Rails, there is a chance that all gems won’t work in the new version. The same problem happens when you try to upgrade to a newer version of Rails – now certain gems won’t work, so you upgrade those, and now other gems don’t work. It’s not a showstopper, but it gets annoying at times. At the same time, I’d rather have this problem than having to write more things by hand myself.

Your process will determine your effectiveness, not your language

It may be true that it’s faster to develop in Rails than .NET. But what has much more impact is how you develop software. You can write good code in .NET and Rails and you can write bad code in .NET and Rails. If you have shoddy requirements, if you are relying solely on manual testing, if your business users can’t tell you what they want, if your team is not writing high quality code, or if there are other impediments that keep you from getting things done, your effectiveness will be limited. Regardless of what platform you’re on, working on improving your development process because that is ultimately what will determine your success.

October 25, 2011by Jon Kruger
.NET, BDD, Cucumber, Ruby, TDD, unit testing

Why do we group our tests by file?

Most people I know put their unit tests in files that mirror the folder structure and filename of the actual class that is being tested. So if I have app/models/order.rb, I’ll have spec/models/order_spec.rb. The tests in the order_spec.rb file will test the code in the order.rb file. Every project I have been on, whether Ruby or .NET, has done it this way.

But have you ever thought about why we do it this way?

We do it this way on our project and I keep running into two problems. The first problem is when I am about to modify some existing code and I want to know what tests will test that portion of the code. The first place I look is the corresponding test file (based on the folder structure or filename), but that doesn’t always give me all of the tests for that functionality.

The second problem is when I refactor some existing code and the refactoring spans multiple classes. Now I have broken tests all over the place and it’s hard to reconstruct the tests so that they test the same business concepts that they were testing before. Often times the tests were testing a portion of the system of classes that I am refactoring, but were not as encompassing as they should’ve been.

Here’s the thing — when I write tests, I’m typically using the Given/When/Then style of writing tests, even in unit tests using frameworks like RSpec. I’ll have test code that looks like this:

describe "When completing an order" do
  it "should set the status to In Process" do
     # test code here
  end
end

That code tests functionality having to do with orders and is going to help me ensure that my code performs some business function correctly. But if you look at that code snippet, you don’t know what classes I’m testing. Yeah I know, it’s just an example and I left out those details. But the point is that it doesn’t matter what classes I’m testing. What matters is that my tests are testing that my code performs a certain business function.

That being said, why are we grouping our tests by file? Wouldn’t it make much more sense to group our tests by business function instead?

I already have ways to find tests for a given class. I can search my code for the class name, or if I’m in .NET I can do Find Usages and have a little window pop up that tells me everywhere a class (or method) is used.

If my classes were grouped in folders by business function instead, I get the following benefits:

  • I can see what tests exist for a given business function
  • It encourages me to write tests that test business functionality, not test data structures (classes, methods, etc.)
  • I can put all kinds of tests in there (unit tests, Cucumber tests, even manual test plans) — all in one place, all checked into source control
  • My tests document business functionality instead of documenting a class

Remember, code constructs like classes and methods are just a means to an end, our goal is to write software that provides business value and performs specific functions. So I might as well organize my tests accordingly.

(Disclaimer: I have never actually tried organizing tests this way. It makes sense to me and I think it would work great, but I might try it and find out that it doesn’t work. But if anything, maybe I’ll start a good discussion.)

June 27, 2011by Jon Kruger
.NET, Speaking, TDD

I’m speaking on TDD at CONDG on 1/27

I’ll be speaking on test-driven development at CONDG on Thursday, Jan. 27 at 6pm. I’ll show you some live TDD coding and explain how TDD can help you write awesome code and eliminate defects. Hope to see you there!

January 18, 2011by 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 1 of 3123»

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...