Thursday, September 24, 2009

Four Bits of Advice: Another Bit

This is the third post in a short series of post about developper adivce ([1], [2], [4]). The first one listed 16 pieces of advices in the form of headlines. The second post briefly explained the first 4, and this post is about the next 4:


0100: Consider infrastructure orientation
Where should infrastructure code go? Well, what is infrastructure code? It's code enabling domain objects to be used by the infrastructure parts of an application, like data persistence parts, the serialization parts, or the remoting parts. Often such code is added to domain objects in a vertical manner via inheritance, resulting in something along the lines of:















This works fine in a lot of cases, but there is the alternative of having the domain objects contain references to infrastructure objects, and letting them delegate to the infrastructure code when needed. That alternative results in a horizontal arrangement of domain and infrastructure code, which looks something like this:


The point is not that orienting infrastructure code horizontally is better than vertically. The point is that it is worth evaluating both option when designing a piece of software.

0101: Use role based interfaces
Interfaces, as in C# or Java interfaces, should define a single role an object can play. An object, on the other hand, can play several roles, and therefore it is perfectly all right for a class to implement several interfaces. This opposes a style of programming often seen in both C# and Java: Given a class called Foo, there is an interface called IFoo. The only class that implements IFoo is Foo, and all the public methods of Foo are implemtations of IFoo methods. An interface like IFoo does not add much value: It does not express or define anything that the public interface of Foo does not already express and define. The only thing IFoo adds is a test seam. Granted test seams are important and valuable, the same seam and more seams are available if Foo implements a number interfaces each defining a role. These roles make sense in terms of the application and its domain. Therefore they make the software easier to read, and with any luck more flexible.
For more on this I recommend Martin Fowlers post about role interfaces.

0110: Be economic
Do waste resources unnecessarily. Specifically: Do not make interfaces larger than they need to be. Do not add extra features to interfaces "just in case", or "because I can". The same goes for larger designs. Adding that extra stuff is wasteful, because you have to spend time writing it, because other programmers have to spend time reading and understanding it, and because it needs to be tested. Furthermore the shorter more concise implementation is usually the more elegant.
For more on this read through Kevlin Henneys slides on economy and elegance.

0111: Prefer code over comments
Comments can and do lie. Comments become obsolete and out of date. Comments are overlooked by programmers. By contrast, code is actually read by programmers, code is and stays current, and code with good naming can often express what would otherwise have been written in comments.
Thats it for now.

Sunday, September 20, 2009

97 Things Every Programmer Should Know

I have contributed a piece to the 97 Things Every Programmer Should Know wiki, which is a wiki containing a long list of good advice for programmers. The plan is that the wiki will turn into a book, by the same name as the wiki. There are well over 100 pieces on the wiki by now, and it's well worth the read; there are a lot really good tidbits.
The piece I contributed is about preferring declarative code over imperative code. It's at http://programmer.97things.oreilly.com/wiki/index.php/Declarative_over_imperative, if you go read it I would appreciate your feedback.

Sunday, September 13, 2009

Build automation with psake

I finally got a chance to take a proper look at psake, a build tool using PowerShell for the build scripts. Below is a psake script I did for a propject. It can compile the code by using MSBuild, clean up binaries, run NUnit tests, measure test coverage, and show the coverage results in the NCover gui. To do so a few paths are setup in the propoerties section, and it is assumed that tests reside in projects with names that end with Test:
properties {
 $base_dir = Resolve-Path .
 $testAssemblies = (Get-ChildItem "$base_dir" -Recurse -Include *Test.dll -Name | Select-String "bin")
 $buildartifacts_dir = (Get-ChildItem "$base_dir\src\" -Recurse -Include bin)
 $src_dir = "$base_dir\src"
 $tools_dir = "$base_dir\tools"
 $nunit_dir = "$tools_dir\NUnit-2.5.2.9222\bin\net-2.0"
 $ncover_dir = "$tools_dir\ncover"
 $db_script_dir = "$src_dir\Database"
 
 $env:Path += ";$ncover_dir;$nunit_dir"
 
 $test_result_file_postfix=".test-result.xml"
}

task default -depends Compile

task Compile {
 exec msbuild "$src_dir\DummyNameToProtectTheInnocent.sln"
}

task Test -depends Compile {
 foreach($test_asm_name in $testAssemblies) {
  $file_name =  [System.IO.Path]::GetFileName($test_asm_name.ToString())
  exec nunit-console.exe $test_asm_name /nodots
 }
}

task Coverage -depends Compile {
 $old_dir = pwd

 foreach($test_asm_name in $testAssemblies) {
  $file_name =  [System.IO.Path]::GetFileName($test_asm_name.ToString())
  $working_dir = [System.IO.Path]::GetDirectoryName($test_asm_name.ToString())
  $out_file_name = "$base_dir\$file_name".ToString().Replace(".dll", "") + ".coverage.xml"
  
  cd $working_dir
  NCover.Console.exe nunit-console.exe $file_name /nodots //x $out_file_name
  cd $old_dir
 } 
}

task Coverage_Gui -depends Coverage {
 foreach($xml in (Get-ChildItem . -Name -Include *.coverage.xml)) {
  tools\ncoverexplorer\NCoverExplorer.exe $xml
 }
}


task SetupDB {
 ."$base_dir\execute-sqlfile.ps1"

 Execute-SqlFile "$db_script_dir\RestoreBaseLineDB.sql" ".\SQLExpress" "master"
 Execute-SqlFile "$db_script_dir\SQL_CreateLoginAndPermissions.sql" ".\SQLExpress" "ConnectPortal"
 Execute-SqlFile "$db_script_dir\AddCompanyIDsToModul.sql" ".\SQLExpress" "ConnectPortal"
 Execute-SqlFile "$db_script_dir\UpdateOrder.sql" ".\SQLExpress" "ConnectPortal"
}

task Clean { 
 remove-item -force -recurse $buildartifacts_dir -ErrorAction SilentlyContinue 
}

I like the idea of using PowerShell for automation in projects targeting Windows for two reasons: One, its a real programming language (as opposed to xml), two, more and more things on Windows boxes can be set up and controlled through PowerShell. I want a real language for my build automation becuase it tends to become complicated over time, so sooner or later it I need the power of a programming language. And if the project only targets Windows, then PowerShell is good choice because its simply the Windows command line, and things like IIS, Exchange, SQL Server and so on provide PowerShell interfacfes.