Archive

Author Archive

Why I choose to invest in clean code

September 21st, 2009 erik lebel posts profile No comments

Lately there is a lot of talk about “Clean Code”. This is in part due to Robert Martin’s recent book by the same name. I’ve heard people come up with idealistic reasons to embrace clean code practices. That all well and good, but when you’re face with a team who does not share your conviction, this can be difficult.

Why should I invest in clean up code if I cannot keep the whole of the code pristine?

Well I continue to write clean code and to re-pass the broom over the same floors I have previously swept because if I dont it will deteriorate into a real bordello.

I continue to clean up because every effort I make to figure some tangled mess out is an effort I do not want to repeat later. The two hours I spend trying to figure out the purpose of a dozen poorly-named classes are hours I do not want to re-live. The next time I pass through this code I want my previous insights to jump out at me, not hide behind the same mess I dug through last time.

I continue to clean up along my path because I hope that the next person (however clean-conscience they may or may not be) does not get slowed down by the previous mess. This person is my team-mate, and the success of my current commitments is dependent on them. Anything I can do to save them wasted time benefits me.

I continue to write clean code and clean up the problems that cross my path because that same team-mate may waste my precious time asking me questions that I could otherwise have answered directly in the code.

This seemingly futile exercise in clean up is all geared at saving me wasted time on a daily basis.

Why do I chose to invest in clean code? Because I’m lazy.

  • Share/Bookmark
Categories: Développement logiciel Tags:

Abstracting out static contexts

September 3rd, 2009 erik lebel posts profile 3 comments

Any test favoring developer will tell you singletons are the bane of testability. Static contexts make testing difficult. When dealing with legacy code, we are often faced with the problem of testing around such problematic coupling. I’ve had enough opportunity to dable in such code to have developed some strategies in dealing with coupling. In this post I’ll present a strategy I refer to as abstracting out singletons.

For the purpose of discussion I present the following code fragment:


public class TightlyCoupled {
	public void quickPurchase(String customerReferenceNumber,
				int productCode, int quantity) {
		CustomerCatalog customers = CustomerCatalog.getInstance();
		Customer purchaser = customers.find(customerReferenceNumber);
		if (purchaser == null)
			throw new UnknownCustomerException(customerReferenceNumber);
		OrderItem requestedItems = Inventory.getInstance().take(productCode, quantity);
		Order quickOrder = new Order(purchaser);
		quickOrder.add(requestedItems);
		// ...
	}
}

This code is displays the symptoms of coupling that clearly make testing difficult. Can the inventory and customer catalog be easly programmed to behave in a predictable and testable manner? Your answer will be contextual, but often they cannot. In most enterprise application such singletons will bootstrap the initialization of other singletons as well as database connections. Can these services be easily mocked? Doubtful.

I have seen cases where programmers will allow themselves to override the singleton before the test scenario. This works, but does not help to move away from the current programming model. What we want is to be able to provide an alternate implementation of these services to a constructed instance of the class under test (CUT). The problem with using a dependency injection approach to testing is that most applications developed with singleton spread are rarely blessed with an IoC container to facilitate object construction. Consequently we can rarely allow ourselves to remove the default constructor of the CUT.

So the first thing that I propose is that we consider using a DI approach, and in order to support this we provide two constructors for our CUT: one that allows for the injection of the dependencies, an a default constructor that wires the class with the default dependencies. This quickly leads us to something like this:

public class LessCoupledThroughConstructor {
	private CustomerCatalog customers;
	private Inventory inventory;

	public LessCoupledThroughConstructor(
			CustomerCatalog customers,
			Inventory inventory) {
		this.customers = customers;
		this.inventory = inventory;
	}

	public LessCoupledThroughConstructor() {
		this(CustomerCatalog.getInstance(), Inventory.getInstance());
	}

	public void quickPurchase(
		String customerReferenceNumber,
		int productCode, int quantity) {
		Customer purchaser = customers.find(customerReferenceNumber);
		if (purchaser == null)
			throw new UnknownCustomerException(customerReferenceNumber);
		OrderItem requestedItems = inventory.take(productCode, quantity);
		Order quickOrder = new Order(purchaser);
		quickOrder.add(requestedItems);
		// ...
	}
}

So now our CUT can be passed a test friendly set of dependencies with a minimal impact on existing code. What’s more, if the CUT is normally treated as a singleton also, its default constructor can become private, and its instance accessor would not take any dependencies. The test friendly constructor would remain public.

This approach has one drawback. When working on a legacy system that relied heavily on singleton accessors to initialize its services, I quickly discovered that many of these services had developed a kind of magical initialization order. No one knew for certain what that order was, but many bugs in the system were to to it. This minor adjustment I proposed broke the initialization order: the dependency services where initialized in the constructor, and not on first use in the using method. Ka-boom!

No problem. The solution is to introduce a minimal amount of abstraction. I decided to creation some wrapper services. These services delegated operations to the static context on a per-call basis, but where not singletons or static instances themselves. This produces the code bellow:

public class LessCoupledThroughWraping {
	private CustomerCatalog customers;
	private Inventory inventory;

	public LessCoupledThroughWraping(
			CustomerCatalogService customers,
			InventoryService inventory) {
		this.customers = customers;
		this.inventory = inventory;
	}

	public LessCoupledThroughWraping() {
		this(new GlobalCustomerCatalogService(), new GlobalInventoryService());
	}

	public void quickPurchase(
			String customerReferenceNumber,
			int productCode, int quantity) {
		// as previous example
	}
}

To give you an idea of what the wraper services look like:

public class GlobalInventoryService implements InventoryService {
	public OrderItem take(int productCode, int quantity) {
		return Inventory.getInstance().take(productCode, quantity);
	}
}

This approached allows the CUT to define a default set of dependencies, but still provides the possibility to inject dependencies.

These approaches are clearly not good examples of applied TDD, but on large systems that have a great deal of code coupling it is often necessary to introduce such test seams. Gradually a large system becomes split into an IoC container friendly design with well tested components.

Other areas where such a strategies work include all static data, static third party APIs, as well as static platform functinality.

An example that I used recently involves the .NET runtime’s “DateTime.Now” which can make testing time dependent behavior unpredictable. My goal was to test that after 10 minutes some condition expired. Obviously I didn’t want a test that ran for ten minutes. I abstract out a date and time service and at test
time I substitute a date time service on which I can set the desired date and time. This makes testing cleaner and more reliable, and in this last case I only needed to redefine the date/time service’s time to jump ahead ten minutes.

What do you think? Have you encountered similar problems? What did you do to work around them?

  • Share/Bookmark
Categories: Développement logiciel Tags:

Using metaphore in the application domain

August 27th, 2009 erik lebel posts profile No comments

Tuesday I caught the presentation “System metaphore revisted” by Joshua Kerievsky and Brian Foote. The presentation was interesting, but left me with some mixed feelings.

Firstly let me say that I was not previously familiar with XP’s metaphore. I will not attempt an exmplanation, I may get some important points wrong, and in any case there is already existing liturature on the subject.

Their presentation brought up various example of metaphores applied to entire systems, and the continual reflection that goes into finding an appropriate metaphore. A good metaphore can facilitate understanding of the system and generate insight into new ideas. This is inded a powerful tool.

Metaphore is already present in much of our common, every-day software landscape, and helps express the behaviour of many of its components. Some plaform examples include pipes and streams, some system examples include folders and files and desktops. These metaphores provoke clues as to what is being described and the kind of behaviour that can be expected.

A few questions in the room were raised about how the metaphore relates to the use of the ubiquitous domain language advocated in DDD. The answers did not resolve the uneasyiness that I felt at the idea of mixing metaphore in the domain language or in replacing the domain language with a metaphore.

The idea of metaphore appears to work well in a context where you are developing YOUR application and you are your own client. I really dont see the interest in using a metaphore to describe an application in a context where the domain is already well defined and provides a wealth of terms to describ it. Better yet, the domain language does not need translating between developers and users. It seems wastfull and dangerous to add potential confusion to an already difficult process.

A side disscussion after the presentation with Rebecca Wirfs-Brock and Michel Feathers (I hate plugging names, but the insight is not my own), lead to the suggestion that the value of the metaphore arises from providing a parallel for a behavior we can relate to. A given metaphore provides an insight for a kind of problem. Perphaps we need a catalog of metaphores that can help to simplify the expression of common subsystems.

So in order to simplify the expressing of something with assembly line charactersistics the assembly line metaphore is appropriate. Certainly a small body of metaphores could easily cover a good number of underlying application behaviors. These start to tend towards patterns and frameworks: “if faced with such and such a situation, apply this kind of solution”.

A cautionary note is due here: it is impossible to expect a catalog of metaphores to meet high-level application needs, if this was possible a handfull of applications would have dominated the world’s business world. Alas things are not that simple.

I think these guys have done some cool stuff with the idea of the metaphore, and I can see an interest in exploring it when the domain is mine to choose. I’m relatively certain that the overhead of model to domain translation required to communicate with clients is unnecessay and unjustifiable on a project with a pre-defined domain language.

  • Share/Bookmark
Categories: Agile 2009 Tags:

Agile2009 – Jour 1 – Integration Tests Are A Scam – J. B. Rainsberger

August 25th, 2009 erik lebel posts profile 1 comment

I went to see J.B. Rainsberger’s “Integration tests are a scam” today at Agile 2009.

A good portion of the presentation focused on the sheer numbers of tests required to tests the combined complexity of many classes integrated together. His argument being that the gap between the actual coverage of integration tests and adequate coverage is largely unmeasurable, but makes for such uncertainty in test coverage as to make integration tests mostly meaningless. In fact worse, they lead to a false sense of security.

His solution to this is one of separating dependencies (notably services) with interfaces (see the dependency inversion principle) and using these interfaces to:

  1. test the client object using mocks
  2. test the server object via its interface to ensure contract (interface) compliance

This will allow a great deal of confidence in the successful integration of components because their interactions have been validate sufficiently with incurring the cost of integration tests. In fact he recommends putting integration tests aside, only bringing them in to find specific bugs, but throw them away once the bug is solved and unit tested.

Another important advantage of this approach is the increased test execution speed. This goes without saying.

Past experimentation with this led me to the conclusion that some of the pain you feel when using mocks to test each class in isolation is tied directly to the design of the code being tested or mocked. Consequently the cure for this pain is a modeling one. Breaking down objects into smaller ones with fewer dependencies helps to reduce the complexity of the individual components (see the single responsibility principle).

Applications go from small model/large objects to large model/small objects.

This poses a new problem for teams. Breaking objects down into smaller ones can be a challenge, especially for developers less comfortable object modeling concepts. This often leads to a clutter of very poorly named objects that are unnavigable. Great attention must be put into ensuring navigable namespaces and classes.

The presentation did not state that acceptance, stress and other types of tests should be dismissed, but ultimately that interaction testing with integration tests was unjustifiably costly for its poor ROI.

All in all a well presented, if a controversial subject. I agree that favoring unit and interaction tests is a great way to develop with code confidence. I’m not sure I’m ready to throw away integration testing, but maybe I’ll give it a try for a bit. Who knows, maybe I’ll like it.

What do you think?

  • Share/Bookmark
Categories: Agile, Agile 2009 Tags: