Wednesday, March 25, 2009

TDD in MVC applications

When developing a web application using MVC there are some components of the application that are not easily tested and can't be tested using automated unit tests. Since automated unit tests are the TDD bread and butter it follows that you can't use Test Driven Development for every aspect of your application. Our team has mentioned that it is difficult to know when to use TDD so I'm hoping to provide some guidance to help in this area. Any comments or suggestions about other methods are welcome.

Libraries: "That code should be in the Model!"

I think it's pretty simple really. Basically anything that will be used as a library function should have a unit test written for it and anything that should have a unit test written could be developed using TDD. In MVC, you would use TDD to develop Model code. If there is any code in the controller that contains some business logic that could be pulled out and made into a library function then that code should be in the model.

Any other aspect of the application would need to be tested using acceptance testing methods.

Monday, March 23, 2009

Are You Invested?

We use Scrum and have weekly sprints. I had someone asking me about a piece of the application that had been developed in a sprint a couple weeks prior. The developer asking the question had not worked on that piece during that previous sprint and was now working on something that involved refactoring a portion of that code. During the discussion, when asked about how certain pieces of it worked, the developer brought up the fact that the piece of code was not written by him, as if to say, "Well, that's not MY piece of code". I was more than a little surprised by this comment and not only because in Agile development there is collective code ownership but also because it shows a lack of investment in the project. These obviously go hand in hand. The more invested a developer feels in a project the greater his sense of ownership.

Even so, the concept of collective code ownership means that all team members are responsible for the code that is developed. That doesn't mean that you have to know every detail about the application or about what your team members are working on but it does mean that you should at least know what they are working on and how it impacts the rest of the application. If they are applying a new technology you should at the very least have an idea of some of the issues that can come up while doing so simply from the daily stand up meetings. The point of collective code ownership is that any member of the team can work on any piece of it. A single piece of the code is not dependant on a single developer. This is also a benefit of occasional pair programming and having other team members test your code/tasks because it allows for another pair of eyes to look at the problem even if it is done as more of an overview.

So if a developer comes across a task that requires them to work on a piece of the code that they haven't worked on before they should be doing all they can to learn what they can about this piece of code. Whether they turn around and talk to the developer who first wrote it, read through the code (which would probably be my first step) or start researching on their own by looking online, in books or other documentation, they should be invested enough that the fact that they did not write it in the first place should never even come up.

Friday, March 20, 2009

TDD Adoption

I've been doing a lot of reading about Test Driven Development and how to use and apply it and found some of the most revealing material while reading about Behaviour Driven Development. I was reading this Introduction to BDD and the TDD Adoption Profile mentioned at the top of the article was the catalyst for this post. This will make sense to anyone who knows anything about BDD since BDD is basically an attempt to relabel TDD to help people use it more appropriately.

What I hope to do here is highlight some of the key areas that seem to cause developers to fail while using TDD or fail to adopt TDD. I get the impression that development teams attempting TDD often end up not using it properly or consistently or else quitting.

Developer Buy In

This could be a failing point of any development technique but I think it affects TDD more so because of the requirement to write tests first. If the developers don't buy in, they won't write tests and will continue to just develop in whatever way they are accustomed to.

Focus on Testing

Of course there is a focus on testing in TDD! The T stands for Test, doesn't it? This was one of the biggest realizations for me while reading the BDD Introduction mentioned above. They mentioned that most developers get to step 4 in the TDD adoption profile and stop there missing the benefits of steps 5-7. I think this was a big realization for me since I was probably still at step 4 in my own acceptance of TDD. After reading steps 5, 6 and 7 and reading about how BDD is basically TDD with less focus on testing and instead a focus on behaviour I began to see the real benefits of TDD. So to oversimplify things, the BDD folks are basically rebranding TDD to focus attention where the the real gains in TDD can be made. This leads me to wonder then if a developer would gain more by first being taught about TDD with this emphasis in mind rather than having to get there on his own, making these realizations as he goes. I can see how the personal realizations would carry more weight than just being told about these things in advance but wouldn't foreknowledge at least increase the likelihood of the realizations occurring?

Learning TDD on the Wrong Project
I don't mean to suggest that TDD only works with certain types of projects but I'm convinced that there will be a greater chance of adoption if the selected project is a new one or has had very little work done on it. The reason I say this is because the first step in TDD is to write tests first and not to write code you don't have to. So writing tests for existing code can at times seem pointless or at least more work than it's worth when you already have a working application (although there is merit in having thorough unit test coverage) and writing tests for new code requires the team to develop using new techniques on an application they've likely already spent a lot of time on and are fairly adept at debugging. I'm not suggesting Unit tests shouldn't be written or that TDD can't be used on an existing project, I'm just pointing out areas where I have seen resistance to TDD adoption. For a team new to TDD it may be better to start fresh. Starting fresh may also help the team feel more inclined to experiment with this new method whereas an existing project will already have set expectations the team is accustomed to. I appreciate that step 1 in the TDD adoption profile is about starting by writing unit tests around their code so perhaps a first foray into TDD is best done on an existing project but I would argue that it would be better to not refer to it as TDD at this point in time because it is actually not yet TDD. Instead I would call it what it is and that is writing unit tests to help improve the quality of the code being tested. It is not yet TDD because TDD requires that you first add a test for the feature you want to add and then after seeing the test fail you implement the feature.

Poorly Designed Code is Hard to Test


One of the realizations while learning TDD occurs when the developer discovers that TDD is in fact a design process that helps them define the application's API. Developing in this way will likely produce better code than was previously being produced and of course have tests written for but my point here is that if attention is also given to applying best practices like proper object oriented techniques and design patterns then TDD adoption is smoother and the TDD process itself becomes easier. Take MVC for example. When followed correctly all business logic should end up in the Model which makes things much easier to test, especially if the model was created using object oriented design principles.

I know some of what I've said are problems that are addressed by using TDD and in realizing that it hopefully increases the value of TDD in the eyes of those trying to use it.

Kent Beck has written a great book called Test-Driven Development: by Example that I would recommend as a great starting point for anyone trying to learn TDD.

Some might ask, why not just use BDD? My response at this point would be, I don't know, why not? Perhaps frameworks for BDD are not yet as established as those used in TDD. Maybe we should all switch to BDD. Or maybe, TDD works just fine provided we shed light on more than just the testing aspect of it.

Wednesday, March 4, 2009

Design Patterns vs. Architectural Patterns

After discussing MVC and it's use (or non-use, actually) in some of our apps it became apparent that a bigger problem existed in the design of these applications. Now most of our apps are used in house and were developed initially by a group of bygone developers and as part of the ongoing task of trying to enhance and adapt them we are reminded of the benefits of a strong attention and adherence to good design.

Despite being written in an Object Oriented language, much of the functionality in these applications is accessed through static methods and the model classes are nothing more than containers. When model objects tend to be simple containers we get this confusion about what the controller actually is. If all appropriate code were actually in the model classes the division would be a little clearer. LINQ makes things a little easier because it creates a bunch of your model for you and you can build on it using partial classes and such. The problem persists in LINQ apps though where if developers don't follw good OO design we can have all these static methods adding another layer of complexity to everything.

There is an article on implementing MVC in ASP.Net that outlines it pretty well. The part I don't like is that the model is not object oriented but uses static methods. It is still a good reference though. So in the context of ASP.NET, the way I see it is that the code behind is the controller and basically everything else that is not an aspx page is the model.

Both Design Patterns and Architectural Patterns will improve the quality of code when applied. It follows that using them together will yield even better results.

Subversion Best Practices: Branching and Merging (because we've been doing it wrong all along)

Despite having read the chapter on branching and merging in the svn book, and spent a lot of time thinking about how it should be done, the subversion repository structure at both my current job as well as my previous one have left something to be desired. Branching and Merging never quite worked as nicely or smoothly as it was supposed to. Eventually we just looked at how the Apache project did it and the correct method became clear to us and although we are not suggesting exactly what they're doing (they have active development happening in several branches) it took looking at their project to make the light go on.


The Old Way

  1. Trunk was supposed to mirror what was in production, although we were never actually able to achieve this which sparked the many discussions about how else we could do it.
  2. All Development happened in a numbered branch and a new branch was created for development every time we wanted to push to testing in preparation for staging (which made for messy SVN logs and much difficulty with Merging caused by confusing ancestry).
  3. Bug fixes would be made to the old development branch which would then require us to either make the same bug fix to the new branch or merge the old branch up and then back down into the new branch or even a merge directly across between the 2 branches, all of which added to the mess in some way causing conflicts or ambiguous ancestry.
  4. Tags were made when something was pushed to staging/production but it was unclear how/when these tags should be created.
  5. It was confusing to explain the branching procedures to new people and difficult to enforce/maintain.

The New Way
  1. Development occurs in the trunk. Trunk is ultimately the development branch itself. The majority of development will occur in the trunk.
  2. Branching occurs when:
    1. We want to create a release of current feature set. This can be done as a Tag, or a branch and a Tag. The latter method would create a branch for doing bug fixes and new tags would need to be created for that branch every time a set of bug fixes are pushed as a release.
    2. Development of a new feature would seriously disrupt normal development
  3. Release branches will be pushed to Testing, then to Staging and finally production. Bug fixes to these branches will be done within the branch and then merged up into the trunk. This way bug fixes are always included in the trunk (dev) and there is no messy merging across or down from trunk into a current dev branch.
  4. Every set of fixes/changes made to the old branch are tagged so we know which version contains which set of fixes.
  5. Easy to explain to new people.
  6. Easy to maintain.

Code Slinging

I've thought for a while that I should start a development related blog where I can drop bits of development related goodness. The name Code Slinging came to me while reading the Contrasted with "cowboy coding" section in the wikipedia article on Agile Software Development. It was the first time I'd heard the term but thought it very apt and it prompted me to go ahead with creating this blog.

The interesting thing is that anyone who has ever written code would more or less have had experience with the Cowboy Coding methodology, if we can really call it a methodology since it lacks structured methods and procedures.

Like I said, it was the first time I had heard the term but as I read it's definition it all seemed very reminiscent of anything I had done on my own or even most group work while at university. The initial reaction is that it has a negative connotation (especially after having worked on an agile team for the past year and on a modified RUP team previous to that) but on further thought I can see merit in actually choosing it as a development methodology in certain circumstances. These circumstance, rare as they may be, would require a small, skilled team of individuals who trust one another and their abilities and who have near complete autonomy in the decision making process. However, I think these circumstances are so rare and the conditions for successful execution so difficult to achieve that it renders Cowboy Coding a viable option only when the decision maker is the sole developer on a project. Basically one man jobs or personal projects.

Cowboy Coding can in many cases very much resemble agile methods because they both have working software as a measure of success, they are both adaptive methods and they both require trust between developers (to be successful). However, without a focus on some integral agile principles (like specific timeblocks that are in themselves complete development cycles) it cannot be classified as such.