Mark Needham

Thoughts on Software Development

Archive for January, 2010

DDD8: Mixing functional and object oriented approaches to programming in C#

with 6 comments

I did a presentation titled 'Mixing functional and object oriented approaches to programming in C#' at the Developer Developer Developer conference in Reading.

The slides from the talk are below:

I've not done many technical talks so far. My only previous attempt was a talk on F# one at the Sydney Alt.NET user group last year so I'm still learning how to do this effectively.

It was quite interesting reading through some of the feedback from twitter and several people pointed out that the content was too basic which was something I was concerned about while writing the talk:

OK. 30 mins into #ddd8 talk of functional vs OO approaches and I've been told one small thing I didn't know.

#ddd8 finished @markhneedham talk… Good speaker,but but basic For me, the last 20% of the content should have been 80% of the talk

"If you want to learn more…" Er…yeah. I certainly want to learn more than I just did. #ddd8

Mark did a good job but difficulty lvl would help as it was quite basic. Missed caching bit looking at twitter. Doh!

Mark Needham's talk on functional and OO at #DDD8 was OK, but the first 2/3 was too much of a simple intro.

The feedback I got in person was that the talk worked alright and there were a couple more positive comments on twitter too:

Great day at #ddd8 – really enjoyed Mark Needham's functional programming session & testing ASP.Net with Ruby

Listening to @markneedham at #ddd8. He has a fantastic abilty to break things down and explain them :)

I think there were probably too many slides in the talk – I found myself pausing unnaturally so that I could move to the next slide which was also pointed out on twitter:

In my first session at #ddd8 on functional programming – loadsa slides – someone get the guy a remote!

I think I'll probably go with less slides the next time – some of them weren't adding much value anyway so I don't think it would hurt too much to drop them.

Overall though it was a good experience for me getting the chance to put this talk together and I think I learnt a little more about better ways to understand the way we can use functional programming in C# by having the opportunity to prepare this.

Written by Mark Needham

January 31st, 2010 at 2:05 pm

Posted in .NET

Tagged with

Book Club: Growing Object Oriented Software – Chapter 7 (Steve Freeman & Nat Pryce)

with 2 comments

My colleague David Santoro has started up a technical book club at the client we're working at in Wales and the book choice for the first session was Chapter 7 – Achieving Object Oriented Design – of Growing Object Oriented Software, guided by tests written by Steve Freeman and Nat Pryce.

In this chapter they cover various approaches for driving towards object oriented code including techniques to find new objects and a detailed description of TDD and how we can approach this in a way that allows us to drive out new behaviour effectively.

These are some of my thoughts and our discussion of the chapter:

  • I quite liked the quote that the authors open the chapter with:

    In matters of style, swim with the current; in matters of principle, stand like a rock.
    —Thomas Jefferson

    I think we often end up spending a lot of time arguing about style when a lot of the time keeping to core principles is more important if we're to keep our state in a maintainable state. I suppose it's a bit of an abstract quote but it seems a useful one to keep in mind.

  • One suggestion that the authors make is to organise our code into layers – an implementation layer where have our different objects (which Martin Fowler refers to as the push button API) and then a declarative layer on top of that i.e. a domain specific language.

    On the projects I've worked on I don't recall us doing this except for in test code where we would often end up writing DSLish code to describe how the application was supposed to work. I suppose this is just a logical next step.

  • Somewhat related to this the authors point out that following a TDD approach ensures that we have to specify the 'what' of what we want to achieve before we specify the 'how'. In this case the test describes what we want to achieve and the production code is the implementation of that.

    They also emphasise the importance of ensuring our tests are understandable by limiting their scope. From my experience we can often get away with using very minimal test data in most of our unit tests and if we need to write a lot of setup code for each test then we've probably done something wrong somewhere.

    Anwar pointed out that if we're finding it difficult to test what we want to from one level then it can make sense to try and test that from further up the stack. While this is certainly true I think we need to be careful to ensure that we're not just doing that because we don't want to work out how to make our code easier to test further down.

  • I first realised how useful value objects could be after seeing a talk by Dan Bergh Johnsson at QCon in London last year and the authors describe several ways that we can try and get more of these types of objects in our code.
    • Breaking out – if code's becoming too complicated we might split the responsibility of a large object into several smaller ones. I find that the key here is to focus on making incremental improvements to this type of code. It can often be a big job to get the design of these types of objects as we want them and since we might not get the time to do that, just making the smallest improvement we can think of repeatedly can be quite useful. Having said that I still find it quite difficult to do.
    • Budding off – to mark a domain concept in the code we might create an object that wraps a field or has no fields at all. I find this approach is the hardest to introduce as people often see it as adding pointless code when we could just use a primitive instead. This is the area of micro types and I think there's probably a measure of judgement required here to determine in which situations we get benefit from taking this approach.
    • Bundling up – if we see a group of values being used together then we might bundle them together into a type. I find that it's easier to do this when it's groups of primitives that you're bringing together. I don't find it as easy to spot when groups of objects are being used together and a concept is probably missing.
  • While I've been doing TDD for a few years now I don't think I've yet totally grasped the idea of pulling interfaces into existence to the extent that the authors describe while writing tests:

    We think of this as “on-demand” design: we “pull” interfaces and their imple- mentations into existence from the needs of the client, rather than “pushing” out the features that we think a class should provide.

    Liz Keogh refers to this as Pixie Driven Development and I think following this approach would help us to end up with meaningful interfaces containing groups of functionality rather than seemingly random groups of methods which seem somewhat related.

    It's certainly an area I need to spend more time practicing on.

Written by Mark Needham

January 28th, 2010 at 7:13 pm

Posted in Book Club

Tagged with

Automapper: Don't forget Mapper.Reset() at the start

without comments

I wrote about my first thoughts using Automapper last week and although I realised that it makes use of the static gateway pattern we ran into a problem where two consecutive calls to a method using AutoMapper always returned the same value for one of the mappings.

The code was roughly like this:

public Bar CreateNewBar(Bar originalBar, string someNewValue)
{
	Mapper.CreateMap<Baz, Baz>()
      .ForMember(x => x.Id, opts => opts.Ignore())
      .ForMember(x => x.SomeProperty, opts => opts.MapFrom(source => someNewValue));
}

In our test everything worked fine because we were only calling the method once but when testing it out we were making multiple calls to the method and always receiving the same value for 'someNewValue'.

I hadn't quite pieced together that each mapping was probably only created once for each source/destination pair. I thought it would be recreated each time but browsing through the code we can see that's what's going on:

Configuration.cs

public IMappingExpression CreateMap(Type sourceType, Type destinationType)
{
   var typeMap = CreateTypeMap(sourceType, destinationType);
 
   return new MappingExpression(typeMap, _serviceCtor);
}
public TypeMap CreateTypeMap(Type source, Type destination)
{
   TypeMap typeMap = FindExplicitlyDefinedTypeMap(source, destination);
 
   if (typeMap == null)
   {
   ...
   }
   return typeMap;
}
private TypeMap FindExplicitlyDefinedTypeMap(Type sourceType, Type destinationType)
{
   return _typeMaps.FirstOrDefault(x => x.DestinationType == destinationType && x.SourceType == sourceType);
}

We put a test which called the method 'CreateNewBar' method twice to make sure that was actually the problem and then made use of the 'Reset' method on 'Mapper' to avoid the problem:

public Bar CreateNewBar(Bar originalBar, string someNewValue)
{
    Mapper.Reset();
	Mapper.CreateMap<Baz, Baz>()
      .ForMember(x => x.Id, opts => opts.Ignore())
      .ForMember(x => x.SomeProperty, opts => opts.MapFrom(source => someNewValue));
}

Written by Mark Needham

January 27th, 2010 at 7:57 am

Posted in .NET

Tagged with

TDD: Rewriting/refactoring tests

with 2 comments

I've read several times about the dangers of the big rewrite when it comes to production code but I've recently been wondering whether or not we should apply the same rules when it comes to test code or not.

I worked with Raphael Speyer for a few weeks last year and on the code base we were working on he often spent some time rewriting tests originally written using rMock to use mockito which was the framework we were driving towards.

One of the benefits that he was able to get from doing this was that he had to understand the test in order to change it which enabled him to increase his understanding of how the code was supposed to work and identify anything that didn't seem quite right.

I quite liked this idea at the time and while spending some time recently working with some tests which required quite a lot of setup and were testing several different things in the same test.

Unfortunately a few of them were failing and it was quite difficult to work out why that was.

My initial approach was to try and work my way through the tests inlining all the test code to start with and then extracting out irrelevant details to make the tests easier to understand.

Despite those attempts I was unable to work out why the test was failing so I worked out what the main things the test was trying to verify and then wrote tests from scratch for each of those cases.

I was able to write tests covering everything the original test did in several smaller tests in less time than I had spent trying to debug the original one and with a fair degree of confidence that I'm testing exactly the same thing.

As I see it the big danger of rewriting is that we're always playing catch up with the current system which is still being worked on in production and we never quite catch up.

I'm not so sure this logic applies in this case because we're only rewriting small bits of code which means that we can replace the original test very quickly.

My main driver when working with tests is to ensure that they're easy to understand and make it easy to reason about the code so if I have to rewrite some tests to make that happen then I think it's a fair trade off.

My initial approach would nearly always be to refactor the tests that are already there. Rewriting is something I'd look to do if I was really struggling to refactor effectively.

Written by Mark Needham

January 25th, 2010 at 10:06 pm

Posted in Testing

Tagged with

TDD: Simplifying a test with a hand rolled stub

with 6 comments

I wrote a couple of weeks ago about my thoughts on hand written stubs vs framework generated stubs and I noticed an interesting situation where it helped me out while trying to simplify some test code.

The code in question was making use of several framework generated stubs/mocks and one in particular was trying to return different values depending on the value passed as a parameter.

The test was failing and I spent about half an hour unsuccessfully trying to work out why it wasn't working as expected before I decided to replace it with a hand rolled stub that did exactly what I wanted.

This is a simplified version of the test:

[Test]
public void SomeTest()
{
	var service = MockRepository.GenerateStub<IService>();
 
	service.Stub(x => x.SomeMethod("call1")).Return("aValue");
	service.Stub(x => x.SomeMethod("call2")).Return("anotherValue");
 
	// and so on
 
	new SomeObject(service).AnotherMethod();
 
       // some assertions
}

For the sake of the test I only wanted 'service' to return a value of 'aValue' the first time it was called and then 'anotherValue' for any other calls after that.

I therefore wrote the following hand rolled stub to try and simplify the test for myself and plugged it into the original test:

public class AValueOnFirstCallThenAnotherValueService : IService
{
	private int numberOfCalls = 0;
 
	public string SomeMethod(string parameter)
	{
		if(numberOfCalls == 0)
		{
			numberOfCalls++;
			return "aValue";
		}
		else
		{
			numberOfCalls++;
			return "anotherValue";
		}
	}
}
[Test]
public void SomeTest()
{
	var service = new AValueOnFirstCallThenAnotherValueService();
 
	new SomeObject(service).AnotherMethod();
 
       // some assertions
}

I've never tried this particular approach before but it made it way easier for me to identify what was going wrong and I was then able to get the test to work as expected and move onto the next one.

In retrospect it should have been possible for me to work out why the original framework generated stub wasn't working but it seemed like the right time to cut my losses and the time to write the hand generated one and get it working was an order of magnitude less.

Written by Mark Needham

January 25th, 2010 at 9:23 pm

Posted in Testing

Tagged with

TDD: Removing the clutter

with 3 comments

I got the chance to work with Phil for a couple of weeks last year and one of the most interesting things that he started teaching me was the importance of reducing the clutter in our tests and ensuring that we take some time to refactor them as well as the code as part of the 'red-green-refactor' cycle.

I'm still trying to work out the best way to do this but I came across a really interesting post by J.B. Rainsberger where he describes how he removes irrelevant details from his tests.

Since I worked with Phil I've started noticing some of the ways that we can simplify tests so that they are more useful as documentation of how our system works.

Wrapping methods around irrelevant test builders

One thing I've noticed in tests recently is that generally most of the setup code for a test is irrelevant and is just there to get the test to actually run. There's very little that's actually interesting and more often than not it ends up getting hidden amongst the other irrelevant stuff.

The test builder pattern is a really useful one for allowing us to easily setup test data but I feel that if we're not careful it contributes to the clutter.

To describe a contrived example:

[Test]
public void SomeTest() 
{
	var bar = BarBuilder.Build.WithBaz("baz").BuildBar();
	var foo = FooBuilder.Build.Bar(bar).BuildFoo();
 
	var someObject = new SomeObject();
	var result = someObject.SomeMethod(foo);
 
	Assert.That(result.Baz, Is.EqualTo("baz");
}

In this example 'Foo' is actually not important at all. What we're really interested in is Baz which happens to be accessed via Foo.

I've started refactoring tests like that into the following style:

[Test]
public void SomeTest() 
{
	var bar = BarBuilder.Build.WithBaz("baz").BuildBar();
 
	var someObject = new SomeObject();
	var result = someObject.SomeMethod(FooWith(bar));
 
	Assert.That(result.Baz, Is.EqualTo("baz");
}
 
private Foo FooWith(Bar bar)
{
	return FooBuilder.Build.Bar(bar).BuildFoo();
}

In this example it doesn't make much different in terms of readability but when there's more dependencies it works quite well for driving the test into a state where all we see are the important details that form part of the 'Arrange – Act – Assert' pattern.

New up object under test inline

Object initialisation is often not worthy of a variable in our test since it doesn't really add anything to our understanding of the test.

I only really break this rule when we need to call one method on the object under test and then need to call another method to verify whether or not the expected behaviour happened.

More often than not this is only the case when dealing with framework code. It's much easier to avoid this in our own code.

In the example that I started with we can inline the creation of 'SomeObject' without losing any of the intent of the test:

[Test]
public void SomeTest() 
{
	var bar = BarBuilder.Build.WithBaz("baz").BuildBar();
 
	var result = new SomeObject().SomeMethod(FooWith(bar));
 
	Assert.That(result.Baz, Is.EqualTo("baz");
}

The only time I don't do this is when the constructor takes in a lot of dependencies and keeping it all inlined would take the code off the right side of the screen.

In any case it's a sign that something's gone wrong and the object probably has too many dependencies so we need to try and fix that.

Pull up static dependencies into fields

Another technique I've been trying is pulling static dependencies i.e. ones whose values are not mutated in the test up into fields and initialising them there.

A typical example would be in tests that have a clock.

[Test]
public void ShouldShowFoosOlderThanToday()
{
	var clock = new ControlledClock(new DateTime(2010,1,16));
	var fooService = MockRepository.GenerateStub<IFooService>();
 
	var fooFromYesterday = new Foo { Date = 1.DayBefore(clock) });
	var aCollectionOfFoos = new List<Foo> { fooFromYesterday };
	fooService.Stub(f => f.GetFoos()).Return(aCollectionOfFoos);
 
	var oldFoos = new FooFinder(clock, fooService).GetFoosFromEarlierThanToday();
 
	Assert.That(oldFoos.Count, Is.EqualTo(1));
	// and so on
}

I would pull the clock variable up to be a field since the value we want to return for it is going to be the same for the whole test fixture.

[TestFixture]
public class TheTestFixture
{
	private readonly IClock Clock = new ControlledClock(new DateTime(2010,1,16));
 
	[Test]
	public void ShouldShowFoosOlderThanToday()
	{
		var fooService = MockRepository.GenerateStub<IFooService>();
 
		var fooFromYesterday = new Foo { Date = 1.DayBefore(clock) });
		var aCollectionOfFoos = new List<Foo> { fooFromYesterday };
		fooService.Stub(f => f.GetFoos()).Return(aCollectionOfFoos);
 
		var oldFoos = new FooFinder(Clock, fooService).GetFoosFromEarlierThanToday();
 
		Assert.That(oldFoos.Count, Is.EqualTo(1));
		// and so on
	}
}

I'm less certain what I would do with 'fooService'. I've run into problems previously by pulling these types of dependencies up into a setup method if we've also moved the corresponding 'Stub' or 'Mock' call as well. With that setup the intent of the test is now in two places which makes it more difficult to understand.

In Summary

It's really interesting to read about the way that others are trying to write better tests and Brian Marick also has a post where he describes how he is able to create even more intention revealing tests in a dynamic language.

It'd be cool to here some more ideas around this.

Written by Mark Needham

January 24th, 2010 at 1:13 am

Posted in Testing

Tagged with

Coding: The collecting parameter pattern

with one comment

The collecting parameter pattern is one of my favourite ones when used well but I've noticed recently that it can lead to quit misleading APIs as well.

One way that we used it quite effectively was when getting objects to render themselves to a ViewData container which was then used to populate the view.

public class Micro {
	private string micro;
 
	public Micro(string micro) {
		this.micro = micro;
	}
 
	public void renderTo(ViewData viewData) {
		viewData.add(micro);
	}
}

I think it's quite obvious from the method name what it does and we can easily test this method by checking on the contents of the value passed in after the method's been executed.

The problem I've noticed with this pattern is when the method isn't so explicit about what it's doing or where a method is using a collecting parameter as well as returning a value.

For example:

public SomeModel GetModel(ViewData viewData) 
{
	viewdata["someKey"] = "someValue;
	// do some other stuff
 
	return new SomeModel(...); 
}

It's not entirely obvious from reading the method signature that it would be mutating the 'ViewData' that's been passed in. I would actually expect that 'SomeModel' is being constructed from 'ViewData' if I just read the method signature in isolation. It's almost like it's following the collecting parameter pattern by accident.

In a way I find that API as misleading as ones which make use of an 'out' parameter to allow multiple values to be returned – it doesn't do what you expect, its intent is not clear.

Since I've started playing around with functional programming languages I've become more keen on the idea that functions take in inputs and return outputs and this pattern goes against that idea by encouraging mutation of state.

It seems to me that for the most part writing functions which return a value and don't do anything else reveal their intent more and for the less frequent occasions where we want to keep encapsulation but still find out some data about an object the collecting parameter pattern works pretty well. It should be used sparingly though.

Written by Mark Needham

January 23rd, 2010 at 2:45 pm

Posted in Coding

Tagged with

Automapper: First thoughts

with 4 comments

I came across Jimmy Bogard's Automapper library a while ago but hadn't had the opportunity to try it out on a project until this week.

The problem we wanted to solve was relatively simple.

We had a domain object and we wanted to create a copy of that with one of the fields changed and all of the ids cleared from the object and any objects contained within it so that we could persist the new web of objects to the database.

We had a structure a bit like this:

public class Foo 
{
	public Bar Bar { get; set; }
	public Baz Baz { get; set; }
}

And wanted to create a copy of this object while changing one of the values on Baz:

Mapper.CreateMap<Foo, Foo>().ForMember(x => x.Id, opts => opts.Ignore());
Mapper.CreateMap<Bar, Bar>().ForMember(x => x.Id, opts => opts.Ignore());
Mapper.CreateMap<Baz, Baz>()
      .ForMember(x => x.Id, opts => opts.Ignore())
      .ForMember(x => x.SomeProperty, opts => opts.MapFrom(source => someNewValue));

It works really well although it took me a little while to realise that the 'Mapper' class was keeping track of what we'd set up via its methods internally.

Jimmy refers to this as the static gateway pattern which seems a little similar to the way that Rhino Mocks keeps track of expectations from what I remember from reading some of the code.

In general though I've got more used to expression builder style DSLs so it was interesting to see one which has been done with a different approach.

The next thing we had to work out was where that mapping code should go.

Since it's completely about 'Foo' I originally thought it should go inside Foo on a static method which we could use to clone the object perhaps with an API like this:

public Foo CloneWith(string someNewValue)
{
	// mapping code in here
}

The problem with that is that it means we have a static dependency in our domain model and from reading Alistair Cockburn's Hexagonal Architecture article I've come to believe that we should try to ensure that objects in our domain model don't have dependencies on anyone else.

An alternative might be to have it on the object and then create an interface which represents the ability to clone Foo:

public Foo CloneWith(string someNewValue, ICanCloneAFoo fooCloner)
{
	return fooCloner.Clone();
}

The mapping code would then go on the implementer of 'ICanCloneAFoo'. The discussions we had around this reminded me of a post I wrote about a year ago and the solution we decided to use was the same. We put the mapping code onto a mapper object.

It's not a bad solution as it follows the convention that's been done for other mapping problems in the code although as Mike pointed out, the code to clone the object is not as discoverable as it would be if it was on the object itself.

In that mapper we're still calling the Automapper code directly which I think is fine although I'm not sure whether we're quite adhering to the idea of wrapping 3rd party libraries, as suggested in Growing Object Oriented Software, and not allowing them to bleed into our code base.

It seems like in the case doing that might lead to more problems than it would solve.

Written by Mark Needham

January 22nd, 2010 at 11:21 pm

Posted in .NET

Tagged with

Functional collectional parameters: Some thoughts

with 6 comments

I've been reading through a bit of Steve Freeman and Nat Pryce's 'Growing Object Oriented Software guided by tests' book and I found the following observation in chapter 7 quite interesting:

When starting a new area of code, we might temporarily suspend our design judgment and just write code without attempting to impose much structure.

It's interesting that they don't try and write perfect code the first time around which is actually something I thought experienced developers did until I came across Uncle Bob's Clean Code book where he suggested something similar.

One thing I've noticed when working with collections is that if we want to do something more complicated than just doing a simple map or filter then I find myself initially trying to work through the problem in an imperative hacky way.

When pairing it sometimes also seems easier to talk through the code in an imperative way and then after we've got that figured out then we can work out a way to solve the problem in a more declarative way by making use of functional collection parameters.

An example of this which we came across recently was while looking to parse a file which had data like this:

some,random,data,that,i,made,up

The file was being processed later on and the values inserted into the database in field order. The problem was that we had removed two database fields so we needed to get rid of the 2nd and 3rd values from each line.

var stringBuilder = new StringBuilder();
using (var sr = new StreamReader("c:\\test.txt"))
{
    string line;
 
    while ((line = sr.ReadLine()) != null)
    {
        var values = line.Split(',');
 
        var localBuilder = new StringBuilder();
        var count = 0;
        foreach (var value in values)
        {
            if (!(count == 1 || count == 2))
            {
                localBuilder.Append(value);
                localBuilder.Append(",");
            }
            count++;
        }
 
        stringBuilder.AppendLine(localBuilder.ToString().Remove(localBuilder.ToString().Length - 1));
    }
}
 
using(var writer = new StreamWriter("c:\\newfile.txt"))
{
    writer.Write(stringBuilder.ToString());
    writer.Flush();
}

If we wanted to refactor that to use a more declarative style then the first thing we'd look to change is the for loop populating the localBuilder.

We have a temporary 'count' variable which is keeping track of which column we're up to and suggests that we should be able to use one of the higher order functions over collection which allows us to refer to the index of the item.

In this case we can use the 'Where' function to achieve this:

...
while ((line = sr.ReadLine()) != null)
{
    var localBuilder = line.Split(',').
                        Where((_, index) => !(index == 1 || index == 2)).
                        Aggregate(new StringBuilder(), (builder, v) => builder.Append(v).Append(","));
 
    stringBuilder.AppendLine(localBuilder.ToString().Remove(localBuilder.ToString().Length - 1));
}

I've been playing around with 'Aggregate' a little bit and it seems like it's quite easy to overcomplicate code using that. It also seems that when using 'Aggregate' it makes sense if the method that we call on our seed returns itself rather than void.

I didn't realise that 'Append' did that so my original code was like this:

    var localBuilder = line.Split(',').
                        Where((_, index) => !(index == 1 || index == 2)).
                        Aggregate(new StringBuilder(), (builder, v) => {
                           builder.Append(v);
                           builder.Append(",");
                           return builder;
                        });

I think if we end up having to call functions which return void or some other type then it would probably make sense to add on an extension method which allows us to use the object in a fluent interface style.

Of course this isn't the best solution since we would ideally avoid the need to remove the last character to get rid of the trailling comma which could be done by creating an array of values and then using 'String.Join' on that.

Given that I still think the solution written using functional collection parameters is easier to follow since we've managed to get rid of two variable assignments which weren't interesting as part of what we wanted to do but were details about that specific implementation.

Written by Mark Needham

January 20th, 2010 at 10:45 pm

Posted in Coding,Hibernate

Tagged with ,

Strategic Design (Responsibility Traps) – Eric Evans

with one comment

Reading through some of Simon Harris' blog entries I came across his thoughts on a presentation Eric Evans did at QCon titled 'Strategic Design – Responsibility Traps' which seems to cover a lot of the ground from the second half of Domain Driven Design and more.

In the presentation Evans make some really insightful comments and points out a lot of mistakes that I've made on projects. It certainly serves as a reminder to go back and read part 4 of the book again and really understand the material from that section.

These were the most interesting observations for me:

  • In this talk he makes some similar points to those that he made in his 'What I've learned about DDD since the book' presentation that I had the chance to see at QCon in London last year. One of these is that there is no such thing as a "right model" – there are only models and some will help us describe our system better than others.
  • Evans suggests that we need to spend most of our time modeling in the core domain since this is the code that gives us a competitive advantage and allows us to differentiate ourselves from competitors.

    I often wonder where the best places to focus efforts on code bases is and I've typically been of the opinion that the pain points are the best place to work on since we can see an immediate reward from doing this. As I've mentioned before I quite like Fabio's technical debt quadrant as a mechanism for measuring where we should focus our efforts with this approach.

    It still seems different to what Evans suggests although I'm inclined to believe that the areas of most pain could well be the areas we need to be subtle to change and there could therefore be some correlation between those areas and the core domain.

    I've not seen a distinction between the core domain and other parts of the domain model on any projects I've worked on so it'd be interesting to hear other opinions on this.

  • A related point to this which I haven't completely grasped is that there are some areas of the code which we shouldn't bother trying to improve and instead should just work around and not worry too much about creating intricate models.

    I like this advice in a way although it seems a little dangerous to me and perhaps seems to conflict with Uncle Bob's idea of following the boy scout rule and improving the code slightly every time we touch it. As I understand it, Evans advice would be to only follow this advice when we're working in the core domain.

  • Evans points out that we should try to avoid the universal domain model, something which Dan North also points out in his article on SOA. As I see it we can either decide to explicitly mark out multiple different models in our code explicitly otherwise we'll just end up with one mediocre model being bent to fit the needs of every part of the system.

    I guess it seems intuitive to try and reduce the amount of code required in a system by just doing the modeling once but different teams in different contexts have different meanings and uses for the model that it doesn't make sense as an approach.

  • My favourite quote from the presentation is the following:

    Be truly responsible, don't just satisfy the emotional need to be responsible.

    I really like refactoring code so this is a good reminder to me to take a step back when I find myself doing that and consider whether what I'm doing is actually useful.

    Evans suggests that it's pointless being the team janitor and cleaning up the code after everyone else has rushed to get features delivered. The suggestion seems to be to get the strongest developers on the team working on the most important domain code rather than creating the infrastructure/platform for the rest of the team to work from.

At the moment I feel like watching this presentation has made me think more about the value of what I'm doing when working on a code base. I don't feel so inclined to randomly refactor code and I'm more keen to work out which bits of the system I'm working on would benefit from this kind of attention.

As I mentioned earlier I now need to finish off reading section 4 of the big blue book!

Written by Mark Needham

January 18th, 2010 at 10:52 pm