Wednesday, October 10, 2007

Testability and Design

As Michael Feathers notes, 'The Deep Synergy Between Testability and Good Design', there is a lot of discussion about how to test private methods. I think he's absolutely correct that the need to test a private method is a hint about the design. I've been reviewing a class that I was never completely happy with because it exposes private methods for testing. Looking at it today I'm sure it would be possible to extract a class that would improve the design and fix the problem. It would have been much easier to clean this up when I was writing the code than to find the time to fix it now. I wish I had listened closer to the hint that my test was giving me.

It's pretty amazing how much we learn about the goodness of a design when try to test it. In the past I used to write fewer and larger classes than I do today. Most of the reason for the change is for better unit tests.

Wednesday, October 3, 2007

The Discipline of Agile

An article by Scott Ambler at Dr. Dobb's does a nice job refuting the idea that agile development is not disciplined. I think some of this might come from the lack of ceremony on agile development projects. Things get done and no one makes a big deal of it. Software is normally usable (and very likely releasable) at the end of every iteration, so the actual release can be anti-climatic. Contrast that with traditional methods where every phase or milestone is a big deal and release is often an earth shaking event. Maybe the traditionalists are just mistaking all their ceremony for real discipline.

Friday, September 28, 2007

Never Start With the Data Model

My bias is for object oriented design and domain modeling. I am convinced that you don't build great software by starting design with a data model. I think starting with the data model is just about the worst idea and pretty much guarantees mediocre software. The best systems start with a domain model and work through the various layers of the system down to the database, not the other way around.

The database should be left until as late in development as possible. Experience shows this is not the case because creating the database is usually one of the first things on a project task list. Instead we should be asking how soon do we really need a database? The unit tests will be better and faster when they don't need a database. You know that data access should be encapsulated behind an interface. Why not leave the database until we know what the data requirements of an at least partially working system are?

Honestly, I can't think of a harder way to try to conceptualize a system than through a data model. Do your users understand a database schema? Is a database schema the model of your system you want to carry around in your head? Great software requires a model that can be used to communicate with users, developers, product owners, and domain experts. I don't think a data model is how any business person conceptualizes their business processes. What you need is a consistent coherent domain model that can can be used to make sense of a system at any level. You must be able to "peel the onion" to discover details as needed. Design by data model immediately forces all the nasty gnarly implementation details front and center. It is a well understood user interface design principle that bad designs expose details of the data model via data entry screens. The worst designs percolate the data model from top to bottom.

The best software solutions model a problem in the problem domain. A data model is a solution in the database domain not the problem domain. So why is the database schema where design so often starts? Maybe it's the mainframe mentality in big corporations, or naive developers who don't really understand object orientation, or just a general ignorance of object oriented design and domain modeling. Eric Evans wrote great book on domain driven design that is not as widely read as it deserves to be. In that book he talks about the "ubiquitous language" of a software project -
"A domain model can be the core of a common language for a software project. The model is a set of concepts built up in the heads of people on the project, with terms and relationships that reflect domain insight. These terms and interrelationships provide the semantics of a language that is tailored to the domain ..."
I don't see such a language ever coming from a data model.

What prompted me to write this was a post touting the new release of an "active record" object relational mapping framework for Java and some controversy it generated in this post. As you can probably guess, I'm not really a fan of the active record design pattern. But reading the posts and the comments, and knowing how popular Ruby on Rails is, it's clear that lot's of developers are very big fans.

I don't get it. Maybe it's because active record is so easy to understand. I suppose active record might work for small systems. But I would never want to use it on any even moderately sized enterprise software project. I see enough ugly code, highly coupled, tangled classes, and mangled hierarchies without database access code mixed into my business classes and immediately coupling my design to the database. I shudder to imagine the maintenance headaches it would cause. At least I'm in good company -
"Another argument against Active Record is the fact that it couples the object design to the database design. This makes it more difficult to refactor either design as a project goes forward."

Martin Fowler, Patterns of Enterprise Application Integration
"In an object oriented program, UI, database, and other support code often gets written directly into the business objects. Additional business logic is embedded in the behavior of the UI widgets and database scripts. This happens because it is the easiest way to make things work, in the short run.

When the domain-related code is diffused through such a large amount of code, it becomes extremely difficult to see and to reason about. Superficial changes to the UI can actually change business logic. To change a business rule may require require meticulous tracing of UI code, database code, or other program elements."


Eric Evans, Domain Driven Design

I hope the fans of active record know what they could be getting themselves into, but as usual I doubt that is the case.

Wednesday, September 19, 2007

There Aren't Any Rules

I know a lot of programmers won't agree but there are few, if any, "rules" for writing good code. It doesn't matter what platform or language or type of software you are writing. If you think someone can hand you a set of rules that you can follow to write good code you are mistaken. I try not to call anything a rule anymore. Now I call them guidelines or principles. The difference is that a guideline needs to be interpreted and judged to know when it should be applied. A guideline might also apply to more than one case.

Sorry, but I reserve the right to change my mind tomorrow about what I told you today was the right thing. This profession is too young, changes too fast, and is too much of a craft for rules written in stone. I've been doing this long enough to know that many things we consider best practices today are likely to change tomorrow. Remember hungarian notation? At one point you would have flunked a code review if you didn't use it, now you'd be more likely to flunk if you did. How about object oriented design? I remember when inheritance and polymorphism were going to save the world. Now too much inheritance is a sure sign of bad design. How about unit testing? We're still discovering the best techniques for things like mock objects.

Much of what makes good code depends on situation and context. Michaels Feathers says it very clearly -
"Good programming is contextual. Practice is contextual. We can articulate rules about how to use language constructs correctly, but they're just guidelines. Context is king."

When Good Code Looks Bad, Michael Feathers
I'd like to add that it is also about having the knowledge and judgment to know which guideline to apply when. There aren't any shortcuts, it takes judgment, practice, and study to write good code. Becoming a good programmer is hard work and you won't be one by following a set of rules. But you might become one if you practice and study the art of programming.


Wednesday, September 5, 2007

Metrics To Improve Unit Testing

At Test Often Joe Ponczak lists seven metrics that you can use to make your methods more testable, "Seven Metrics to Improve Your Unit Testing". Experienced unit testers will probably be familiar with the metrics but it never hurts to review. I mainly mention this because it is the blog for CODIGN Software which makes some nice reasonably priced Eclipse plug-ins for writing JUnit tests and analyzing code coverage.

p.s. I sure don't like the white on black color scheme on the blog though.