Friday, October 10, 2008

.Net Developers Get It

.Net programmers get it - Instantly Become a Better Programmer (then worry about learning TDD).   The provocative title of this blog ignores the potential TDD has as one tool for learning good design but I think few would argue with the point that good code and good design are easier to test.

This blog points to Robert Martin's articles which identify the basic principles of OO design.   I've read and reread these articles.   Most were written in 1996 for C++ Magazine.   These articles will be important to developers as long as we are doing object oriented development.

Here are the principles Bob Martin wrote about -

The Single Responsibility Principle

The Open-Closed Principle

Liskov Substitution Principle

Interface Segregation Principle

Dependency Inversion Principle

DRY and Single Level of Abstraction (SLAP) should also be on this list.   You can have a lot of fun learning about SLAP watching this video,

Unfactoring From Patterns: Job Security Through Code Obscurity.


The .Net blog also links to Glenn Vanderburg's Tactical Design presentation.   Glenn quotes 'The Mythical Man Month' - good design can be taught and later in his talk he clarifies this and states that mentoring is the only way he has found to teach design.   He also makes an excellent point about good design - it is only from good design that deeper, essential domain problems become apparent.


Per page six of the Dependency Inversion Principle article, with DI, the strucure of a well designed object oriented program is "inverted" with respect to the dependency structure of traditional procedural methods. Figure 2 shows a seemingly decoupled solution but, note that the construction of the components is ignored in this figure. When a naive developer adds component construction to these classes, the coupling returns, again making the business logic dependent on lower level components!


The clearest discussion of the two contexts in which coupling rears its head is in the first two drawings and accompanying text of this blog.   Collaboration coupling is often necessary and good.   For instance, in a Sales application, a Customer should know about his Order and his Payment.   Constructor coupling is a cross-cutting concern that complicates software development. Continuing the previous example, I, as a customer, am not asked to create my order history but, within the application, the Customer class often is. The discussions of Dependency Inversion and Dependency Injection address both Collaborator and Constructor coupling.


When Robert Martin's article focuses on the lamp design, the business logic he is so keen on making reusable is harder to identify.   Locating the business logic is easier in the Copy program, the reuse of which Martin identifies as the goal of his efforts in that domain - see page 4. After reading the article, go back and try to arrive at a decoupled solution that includes object construction for the Copy Program with just the components shown.   It can't be done. If constructing components adds coupling that would otherwise not be there, what are we to do? Cue dependency injection.


Martin Fowler's article on DI is focused on the use of dependency injection (not inversion) to eliminate coupling that would develop from code that constructs components. As I understand what Fowler is saying, to fully benefit from dependency inversion involves both using interfaces (per DIP article) and having an assembler that performs object construction and injection.


The basic principles listed in the .Net post are essential.   Unless you learn to recognize what is good code and what is bad code you risk being stuck in a horrible twilight zone. The two paragraphs on page six of Martin's article beginning with "Consider the implications of high level modules that depend upon low level modules" and "This predicament is absurd!" really impressed me. Structured Design as I learned it in the 80s got it completely wrong. Structured top-down design is like the waterfall methodology for code. Dependency inversion can be applied to RPG and COBOL to decouple high level modules from low level modules. So, avoid 1980s style Structured Design when writing Java and please use Spring DI for your Java.


Here's a well stated arguement - http://googletesting.blogspot.com/2008/10/to-new-or-not-to-new.html.