Tuesday, August 11, 2009

Software projects are like sailing voyages

I have been reading Greg Smith's new Becoming Agile book and was struck by the false analogy that is often applied to software projects, which compares them to construction projects, where Smith points out you typically "gather requirements, create a design, excavate, lay the foundation, and then build the walls."

Smith points out two problems with applying this analogy:

"1. Additional requirements will be discovered during design, coding, demonstration, and testing.
2. Software development does not require completion of each step before the following step can be initiated. You can start design and coding based on a few initial requirements. You can iteratively build out the system, revisiting it and going deeper on requirements, design, and code as you make discoveries and refine the vision for the project."

Analogies are dangerous because they build in these sorts of inaccuracies, and that can lead to dangerous assumptions and attitudes later on. However they are excellent for helping non-experts in a field understand complex topics. I dearly want a better analogy for software projects and I have never heard a really satisfactory one, so I got the mental juices going and looked for one that makes sense to me. This is what I found ...

Software Projects are Sailing Voyages

Software projects, at least the ones I have been involved in, feel more like ocean voyages in small yachts than anything else. Like any sailing voyage you will have an idea of where you want to get to, and if you are smart you will have checked the weather forecast and planned your route - even calculating what you average speed should be and when you will reach your destination.

3100906233_d9fa131d23_b

from: http://www.flickr.com/photos/14132971@N05/3100906233/ 

This is reasonably similar to the planning and preparation for a software project where a goal will be set, the estimated time to reach it mapped out and the current environment and conditions researched.

However, in sailing you can expect to find a number of things changing your plans. Perhaps the wind changes in unexpected ways, or your plan failed to take into account the wind shadow of a particularly large island, or the strength of local currents or tides. The helmsman may have neglected to keep his eye on where you were headed, being distracted by a pretty sight, or other crew may not have kept the sails properly trimmed or closed the bilge valve.

2791384256_cb84d28653_b

from: http://www.flickr.com/photos/flasporty/2791384256/ 

Mishaps can occur, such as equipment failure, collisions with other vessels or even crew sickness or injury. Your destination port might be closed, and you find that you need to make landfall either sooner or later than planned. Even the captain's intent may change as it becomes apparent that the passengers would prefer a leisurely cruise around the coast to a deep ocean adventure.

2691809503_bd8ec4d118_b

from: http://www.flickr.com/photos/wili/2691809503/ 

Very similar changes can be expected in software projects. Your tools vendor may bring out a new release that opens up new development options, business goals can change or be re-assessed, leading to changes in requirements. Staff changes can cause a change in vision, or highlight mistakes or negligence in the work previously performed. Individuals' performance may fall short or exceed expectations for their role, and unexpected leave or changes in priorities may derail timelines.

These problems occur on construction projects too, but they have a real, physical object they have been developing with building approvals already acquired so it is far more likely that they will simply continue to the end (even then, you might end up with a project like Sydney's World Square, where it was just a huge hole in the ground with some cement in it for years).

Hole-in-the-ground

from: City of Sydney 

With software it always seems easier to throw it all away and start again (and indeed this is sometimes the best course to take). Simply having a shared analogy with the customer that makes more sense than a building will help them understand that while we can give up the voyage now, we can't avoid the fact that we have sailed this far, and perhaps we should take that learning and make use of it.

Agile software development in this case can be seen as a series of small hops around the coast, rather than the usual grand exploratory voyage undertaken by many traditional software projects. Each hop allows us to review where we have gotten to, and lets passengers get off if they so desire.

Of course analogies have their limitations, and using them to model a complex system by comparing it to another simpler, or more familiar, system does not guarantee success. It just makes client meetings shorter (which by some definitions is success!).

Friday, May 29, 2009

Half of TEDx Sydney 2009

Thanks to Josh Anstey's generosity I was able to attend TEDx Sydney last night. Whilst it was enjoyable, I ended up leaving at the half-time break and spending the evening with my family instead. Nevertheless if you're interested in TED then I would recommend giving an event like this a go, if nothing else there were some great people there like Mark Cohen, Jodie Miner and Brian Maguire.

Some background: TED is an event that focuses on thought leadership in the Technology, Entertainment and Design fields every year and has as its catch-cry "Ideas worth spreading". The TED conference sells out quickly every year (despite some unusual conditions) and attracts all sorts of luminaries and leaders. A TED event is the place to meet movers and shakers and has been the birthplace of some wonderful ideas over the years. They make the videos of each event available online during the year, and part of the focus of a TEDx event is to create that same buzz in a local venue by mixing TED videos with local speakers.

So without further ado here is my thoughts on TEDx Sydney 2009:

Venue

The Australian Technology Park hosted the event, and as that is where Elcom is based that proved convenient for me. The theatre used was a great venue for watching TED videos and live speakers alike and I think it did a good job of providing some atmosphere - although I wonder whether other venues could have made a bigger impression? (e.g. Darling Harbour Convention Centre)

MC/Host (Nils Vesk)

I don't think a Gen-Y host was the right choice for an event like this - I think less entertainment and more credibility was needed (although it was Mark Cohen who blew Nils' credibility for me). However, Nils got the job done, and managed to do the more cheesy sales aspects of his role without making it seem too cheesy (more about that later).

Craig Rispin (Futurist)

I have heard of Craig Rispin, and indeed knew someone who he'd invited to the event. Unfortunately his recursive telling of the history of futurists who tell the history of the future left me bored and dual-tweeting with Mark Cohen.

I'm not sure Craig had an idea worth spreading, perhaps he intended it to be that we are all futurists, but it felt more like he was telling us that we were smart and forward-thinking people - which was nice of him, but didn't give me a reason to care about his talk. He also pointed out the prophetic nature of speculative/science-fiction in a way that might have impacted those who didn't yet care about it - but I've known about that for most of my life so it was wasted on me.

Patti Maes (Video, MIT Media Lab)

Patti Maes is from the MIT Media Lab and demonstrated a form of augmented reality where her students had cobbled together a wearable apparatus that linked a camera, phone and some software so that you could make any surface around you into a computer work area, and interact with your environment in ways that could both instruct the computer/camera to do something (e.g. take a photo by holding your hands up in a rectangle) or could bring digital information to you based on your context (e.g. talking to a person, reading a book, looking at a product label).

She pointed out that the technology could be cobbled together for a few hundred dollars easily enough, but their point was that they were investigating what were reasonable ways to augment reality. Some of this has been done before with for example the head-up displays (HUD) that Boeing engineers use when wiring plane bodies.

This was the most exciting talk, but hardly surprising to anyone who has been following technology for the last 15 years or so.

Peter Baines (Hands Across the Water)

Peter Baines was one of the forensic specialists sent to Thailand in the aftermath of the recent Boxing Day Tsunami. He gave us a fairly somber account of that, especially dealing with the human side when giving bodies back to relatives. He went on to show how this created a desire in him and his colleagues to do more than they were for the Thais - out of that desire was birthed Hands Across the Water.

I think that Peter's idea worth spreading was that if you just focus on the results, and not the obstacles, then you can achieve your dreams - whatever they are, whoever you are. I think this was a great message, and Peter is obviously a good example of this in action. Focus, and the single-minded pursuit of an idea, is too often given lip-service as a reason for success, when I believe it might just be the major factor in it.

A large part of Peter's story was a dig at the international aid agencies that quickly went into Thailand and then just as quickly pulled out around a year later. One of his ideas is that charities should be forced to put some stats on every piece of marketing literature telling the reader how much money they spent on admin versus aid in the last financial year. The idea (much like the MIT Media guys) being to give people information to make informed decisions about where to give their money. I think this ignores part of the bigger picture, which is a question of how much admin is required to run an international charity that coordinates volunteers from many nations into situations that are often not as attractively packaged as the Thai one was. However that discussion can't happen without making the information available, and so I would welcome it form that point of view.

Bill Gates (Video, Curing Malaria and Making Teachers Better)

I had seen this one before, but hung around to watch it on the big screen. Bill and Melinda Gates' foundation is really trying to focus money and attention onto big issues that the market and governments are ignoring.

The first issue he covered was curing malaria, which seems both an achievable aim and one that has been largely ignored now that wealthy nations are free of it. His idea here was that if we focus on eradicating it then a relatively modest effort will see it gone, whilst if we tackle it half-heartedly we only make things worse.

The second issue was about how do you make teachers great, and he gave a long analysis of why this mattered, which seemed obvious, but I guess the hard numbers he pulled out showed people that it was an issue worth focusing on. I think his idea here was that we should care about the quality of teaching - mainly because in the US at least, the quality of a teacher is not easily discovered or rewarded.

Event

Overall the event had a good vibe, seemed interesting, and was a good way to share the watching of a TED video with people you knew. I think I missed too much of the schmoozing part of it to know whether that worked - but I was happy catching up with who I did see there.

There was a cheesy side to the event which was the blatant pushing of wares for the main sponsors, especially the silent auction of the Thought Leaders' services (with some fairly suspicious dollar figures on their market value). I understand that some of this is necessary to get the event paid for - but I do wonder if this could have been handled in a more subtle and positive way.

Thursday, May 14, 2009

Top 5 classic programmer folly projects

Back in the day when the British Empire was still new, wealthy landowners who had heard about great places elsewhere (usually ones where it didn't rain all the time) started a trend of re-creating these great places on their own land - often right down to the current decrepit state of said places.

Sometimes they didn't have a specific place in mind, but wanted a "ruined Greek temple" or similar stereotypical "interesting" structure (sometimes they were just plain strange). The point seemed to be to prove that a) you were interesting, b) you could pay for a spurious building for the sake of it, and c) foreign travel was all so unnecessary. These were known, rather aptly, as follies (presumably because they represented the folly of spending your children's inheritance on an expensive monument when investing it might have proven more prudent).

142697575_46dc01af64_b
From: Xerones 

Programmers it turns out are no less susceptible to follies, although they might not realise it, and they are not deliberate fakeries. There are several classic programmer follies which tend to get repeated by each generation, with ever-increasing zeal and lack of awareness of their futility.

Now, don't get me wrong, these are all fine examples of throwaway projects that you might play around with and practice on, but for some reason programmers can't seem to leave them stay as just throwaway projects - they always want to upgrade them to the status of "next big thing".

Without any further ado, here they are.

Top 5 classic programmer folly projects

1. Bug tracking

Every software program has bugs, and most programmers find they need a good system to track said bugs. Some companies, Atlassian and Fog Creek Software have made their living providing great, simple yet powerful solutions for exactly this problem.

However, there is always a temptation to take shortcuts, customise the bug tracking, or get a cheaper solution, and so inevitably every programmer gets tempted to build their own bug tracking application.

It's a folly because ...
This is actually a fairly complicated domain, especially once you add in the bug resolution workflow, web interface and email integration that even free, open-source applications have. Of course there is also the problem of what to do when your bugs are in your bug tracking software ... evil recursion in the real world!

2. To do list

I just want to track what I need to do ... and what I want is to improve this to do list. Remember the Milk has the best free implementation I've seen of this type of application, but BaseCamp, your mobile phone and even GMail are worth mentioning (not to mention trusty old pen and paper).

It's a folly because ...
You really don't need to waste brain cycles re-inventing something this simple, and when you look at the sophistication of Remember the Milk (web, offline Google Gears, Twitter, email and mobile integration) anything you do yourself looks kinda ... sad.

3. Website/blog engine

I want to use something I built myself, and it's a good chance to try my hand at content management ... except it isn't. If you are blogging then do your readers and yourself a favour and use an existing blogging application. You will have a more consistent user interface and will never find yourself not posting because the build is broken after that last refactor and you can't be bothered fixing it yet.

It's a folly because ...
The free alternatives are great, the cheap ones are even better and frankly it's not that great a domain for learning how to code, especially web stuff.

4. Hobby management

My hobby (roleplaying games, model robots, high performance cars, salsa dancing, etc) is out of control and I need a way of managing it. Actually no you don't, you probably just need to get out and live more.

It's a folly because ...

You don't really want to mix up your hobby and your work, it just makes one less fun and the other less professional. it is also an area where you will never really be satisfied with the result because it's your hobby. Finally, when you show it to other people they are likely to go "Ummm ... very nice. What is it?" Hugh MacLeod defines a geek as "Somebody who socializes via objects" and congratulations, that's exactly what you've just become!

5. Application Building Applications

This is the one where you build an application that uses meta-data to build an application. It seems this is the purvey of the very smart and the very dumb. The really smart guys believe they can be the ones to break through and nail this problem, the really dumb ones just don't realise how hard it is.

It's a folly because ...

It's possible to do this in theory, but in practice you only ever get around 80% of the way there, and it turns out the other 20% is the bit that an application really needs to live and breathe. Really, really smart guys manage to push that 80% up to the giddy heights of 81.63%, but hey, it still doesn't do what you really wanted it to.

Bonus! Installer software

OK, here is number six. What do you do when you want to distribute your application to clients? Use the MSI installer for Visual Studio? Heck, no! You go ahead and create your own installer software, complete with license number check, built-in unzipper and some cross-platform nastiness.

It's a folly because ...

You already know you shouldn't be doing this. Go use something someone else created and love the fact that you don't need to do it by hand!

 

OK, time for confession time, I've been guilty of each of these (at least through to the design stage). What about you, what were your follies?

Friday, February 20, 2009

Loading objects' fields/properties automagically

There is a very nice function in the new ASP.NET MVC code that allows a Controller to load an object from values passed in from a HttpRequest (UPDATE: called UpdateFrom, see ScottGu's post). It did a best guess on matching values to object properties, but most (99%?) of the time that is all you need. Well, when I started using Domain-Driven Design (DDD) and Test-Driven Development (TDD) on the latest additions to our Community Manager.NET product I wanted to find something similar - but I couldn't find anything as terse and useful.

So I did what any good dev would, I read the sourcecode and derived my own functions to do something similar, but with the SqlDataReaders that my repositories would be getting out of SQL Server (it almost feels like the ActiveRecord pattern ...). Below are the result, two LoadToObject() functions (and a PopulateTypeException class) in my BaseRepository class that give me the functionality I need. I'm putting these out there in case someone else needs this, and in the hope that any glaringly obvious errors might get picked up by others!

One issue I had with the Microsoft version of this function was they only load public properties of an object, not public fields. Now I know that in C# you can setup properties as easily as fields, but in VB it's still a hassle. I personally like using fields for simple value storing because it is clearer to see what they do in the code and leave more space for real method calls.

The final problem I ran into was that my custom Html data type needed to implement it's own TypeConverter so that the HTML in the SQL Server ntext field could be converted to a strongly typed Html type. But that can go into another blog post if people are interested.

    ''' <summary>
''' Populates an object's public fields and properties with values from a SqlDataReader.
'''
</summary>
''' <param name="readerToLoad">The SqlDataReader that needs to be loaded into the object.</param>
''' <param name="obj">The object we want to populate.</param>
''' <param name="objectPrefix">A prefix to the object field/property names. Tries to match using "." and "_".</param>
''' <returns>The object passed in with fields/properties loaded.</returns>
''' <remarks>
''' Does a best guess as to how to match names from the SqlDataReader to the object.
'''
</remarks>
Protected Function LoadToObject(ByVal readerToLoad As SqlDataReader, ByVal obj As Object, ByVal objectPrefix As String) As Object
Dim
newColl As New System.Collections.Specialized.NameValueCollection()
Dim x As Integer

If
obj Is Nothing Then
Throw New
ArgumentNullException("obj", "Object must have a value in order to be loaded to.")
End If

For
x = 0 To (readerToLoad.FieldCount - 1)
newColl.Add(readerToLoad.GetName(x), readerToLoad.GetValue(x))
Next

Return
LoadToObject(newColl, obj, objectPrefix)
End Function

''' <summary>
''' Populates an object's public fields and properties with values from a NameValueCollection.
'''
</summary>
''' <param name="valueCollectionToLoad">The NameValueCollection that needs to be loaded into the object.</param>
''' <param name="obj">The object we want to populate.</param>
''' <param name="objectPrefix">A prefix to the object field/property names. Tries to match using "." and "_".</param>
''' <returns>The object passed in with fields/properties loaded.</returns>
''' <remarks>
''' Does a best guess as to how to match names from the NameValueCollection to the object.
'''
</remarks>
Protected Function LoadToObject(ByVal valueCollectionToLoad As System.Collections.Specialized.NameValueCollection, ByVal obj As Object, ByVal objectPrefix As String) As Object
Dim
objType As Type = obj.GetType()
Dim objName As String = objType.Name
Dim exceptionList As New StringBuilder()
Dim props As PropertyInfo() = objType.GetProperties()
Dim fields As FieldInfo() = objType.GetFields()
Dim ex As PopulateTypeException = Nothing
Dim
prop As PropertyInfo
Dim field As FieldInfo

' try writing to the object's properties
For Each prop In props
'check the key, going to be forgiving here, allowing for full declaration or just propname
Dim key As String = prop.Name

If objectPrefix <> String.Empty Then
key = objectPrefix + key
End If

If
valueCollectionToLoad(key) = Nothing Then
key = objName + "." + prop.Name
End If

If
valueCollectionToLoad(key) = Nothing Then
key = objName + "_" + prop.Name
End If

If
valueCollectionToLoad(key) <> Nothing Then
Dim
conv As TypeConverter = TypeDescriptor.GetConverter(prop.PropertyType)
Dim value As Object = valueCollectionToLoad(key)

If conv.CanConvertFrom(System.Type.GetType("System.String", True, True)) Then
Try
value = conv.ConvertFrom(valueCollectionToLoad(key))
prop.SetValue(obj, value, Nothing)
Catch e As Exception
Dim message As String = prop.Name + " is not a valid " + prop.PropertyType.Name + "; " + e.Message

If ex Is Nothing Then
ex = New PopulateTypeException("Errors occurred during object binding - review the LoadExceptions property of this exception for more details")
End If

Dim
info As New PopulateTypeException.ExceptionInfo()

info.AttemptedValue = value
info
.PropertyName = prop.Name
info
.ErrorMessage = message

ex
.LoadExceptions.Add(info)
End Try
Else
Throw New
Exception(String.Format("No type converter available for type: {0}", prop.PropertyType))
End If
End If
Next

' now try writing to the object's public fields
For Each field In fields
'check the key, going to be forgiving here, allowing for full declaration or just fieldname
Dim key As String = field.Name

If objectPrefix <> String.Empty Then
key = objectPrefix + key
End If

If
valueCollectionToLoad(key) = Nothing Then
key = objName + "." + field.Name
End If

If
valueCollectionToLoad(key) = Nothing Then
key = objName + "_" + field.Name
End If

If
valueCollectionToLoad(key) <> Nothing Then
Dim
conv As TypeConverter = TypeDescriptor.GetConverter(field.FieldType)
Dim value As Object = valueCollectionToLoad(key)

If conv.CanConvertFrom(System.Type.GetType("System.String", True, True)) Then
Try
value = conv.ConvertFrom(valueCollectionToLoad(key))
field.SetValue(obj, value)
Catch e As Exception
Dim message As String = field.Name + " is not a valid " + field.FieldType.Name + "; " + e.Message

If ex Is Nothing Then
ex = New PopulateTypeException("Errors occurred during object binding - review the LoadExceptions property of this exception for more details")
End If

Dim
info As New PopulateTypeException.ExceptionInfo()

info.AttemptedValue = value
info
.PropertyName = field.Name
info
.ErrorMessage = message

ex
.LoadExceptions.Add(info)
End Try
Else
Throw New
Exception(String.Format("No type converter available for type: {0}", field.FieldType))
End If
End If
Next

If Not
(ex Is Nothing) Then
Throw
ex
Else
Return
obj
End If
End Function

''' <summary>
''' Contains exceptions that arise during the populating of an object by the LoadToObject() method.
'''
</summary>
<Global.System.Serializable()> Public Class PopulateTypeException
Inherits Exception

Public Class ExceptionInfo
Public PropertyName As String
Public
AttemptedValue As Object
Public
ErrorMessage As String
End Class

Public
LoadExceptions As New List(Of ExceptionInfo)
Private PopulateTypeException()

Public Sub New(ByVal message As String)
MyBase.new(message)
End Sub

Public Sub New
(ByVal message As String, ByVal inner As Exception)
MyBase.new(message, inner)
End Sub

Protected Sub New
(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
End Sub

End Class

Tuesday, February 10, 2009

Challenging software development blogs

I am not hugely keen on top 100 lists or similar trite listings of people, blogs or posts, however sometimes I notice that I have too many tabs open in Chrome (hello, 58?!) and need to itemise some of them. Many of the ones I keep open are blogs that challenge me enough that I want to read them frequently (I know ... I should be using an RSS reader, so call me old-school! ;).

I think these are some of the more challenging blogs* out there with regards to software development - read these and you will find your brain, assumptions and dealer-held beliefs under high-voltage attack.

* OK, so I am going to miss a couple of fantastic ones - what is important is that you check out the ones I do mention!

59459065_0ed25c902e_o

Joel on Software (visit)

Joel Spolsky of Fog Creek Software and Stack Overflow fame has had one of the most well-read and discussed software development blogs on the planet for years now. He is an original thinker in a market filled with duplicates, he also has a deep commitment to giving his developers great office space.

The Software Simplist (visit)

Udi Dahan's blog specialises in Service Oriented Architecture (SOA), but I read him for his refreshing view of domain-driven design (DDD). I got a new insight into DDD from his DDD & Many to Many Object Relational Mapping post.

Scott Bellware's Blog (visit)

Scott Bellware is probably the most hated/respected .NET rebel on the planet. His abrasive manner and obvious chip on his shoulder with Microsoft and the ALT.NET mainstream put some people off, but he has a deep insight into what Agile development is meant to be all about and a straightforward manner in sharing what he knows. He also seems pretty sure that most developers are learning impaired. A good example of his (more positive) thinking is Productivity: It Comes from Software Design Rather than Software Tools.

Noop.nl (visit)

Jurgen Appelo's software development management blog has some of the most pragmatic and interesting advice available for functional managers of developers. His company's situation is similar to Elcom's, so I appreciate his honest and smart insight into how to make Scrum work with large teams working on many disparate projects. He has useful posts like How to Handle Many Simultaneous Projects which apply Lean/Scrum principles to the real world of custom software development.

You'd think with all my video game experience that I'd be more prepared for this (visit)

Jason Yip from ThoughtWorks focuses his blog on lean manufacturing principles and how they apply to the reality of software development. A challenging thinker and opinionated professional, he manages to stay as radical as someone like Scott Bellware with a more pleasant demeanour. A typical (longer) post from him would be No matter how many times you say it, we still don't need a QA on the team.

Greg Young's Blog (visit)

Greg Young is a Microsoft MVP who has some very interesting opinions on domain-driven design, namely that the domain model is only there for write operations. Check out his DDDD: Master-Detail Question post for more details on this and how he uses a thin DTO layer to power his read-only UI pages.

Chad Myers' Blog (visit)

I first found out about Chad from a talk he and Jeremy Miller gave on Opinionated MVC (see videos here and here). Jeremy Miller developed StructureMap, which is a Dependency Injection/Inversion of Control framework. Chad is also the driving force behind the Virtual ALT.NET (VAN) group which has helped developers connect from places as far afield as Texas and Australia!

James Bach's Blog (visit)

Interested in software testing? Then you need to quickly head over to James Bach's blog and check out his controversial, but smart and honest posts on the topic. To understand where he is coming from, check out his Schools of Testing ... Here to Stay blog post.

So ...

Who did I miss? Leave a comment and let me know!

Thursday, February 05, 2009

The Fat Controller must die!

As most parents with little boys know the Fat Controller is a key figure in the Thomas the Tank Engine TV series (and books, toys, clothing, linen, bags, crockery, snacks, etc.). he is a cheery fellow, unfortunately prone to angrily shouting at train engines, but equally kindly and caring about his beloved vehicles (especially steam powered ones like Elizabeth the lorry). For the sake of my children I must point out that I have no problem with this jolly fellow.

fat controller

There is another domain where fat controllers exist, and that is the world of the MVC (Model-View-Controller) pattern. The pattern has experienced a renaissance recently in web applications, particularly because of Ruby on Rails, and now Microsoft's ASP.NET MVC offering.

Now these Ruby on Rails guys have been doing this for a little while longer than the ASP.NET guys, and one key paradigm became clear fairly early on:

"Try to keep your controller actions and views as slim as possible."

This was most clearly explained by Jamis Buck in his excellent Skinny Controller, Fat Model post back in 2006, which is still worth reading even if you don't use Ruby on Rails. More recently Ian Cooper has pointed out this is the same problem webforms had:

"This is the good old problem of domain-logic in code-behind that we had in ASP.NET webforms. Indeed Webforms are just another type of controller, a page controller, and switching to an application controller model does not remove the need for us to watch for domain logic creeping into the controller. There can be a temptation to believe that just because the controller is easier to test it is now safe to put domain logic in there. Do not fall into that trap."

In his book, Domain-Driven Design, Eric Evans identifies this as the Smart UI Anti-Pattern.

“Put all the business logic into the user interface. Chop the application into small functions and implement them as separate user interfaces, embedding the business rules into them. Use a relational database as a shared repository of the data. Use the most automated UI building and visual programming tools available.”

SmartUI
Image from David Hayden's blog

Eric is kind (and pragmatic) enough to point out when it is useful.

“A project needs to deliver simple functionality, dominated by data entry and display, with few business rules. Staff is not composed of advanced object modelers.”

Clearly ASP.NET's webforms model encouraged this sort of practice (it is just far too easy to do), but surely a controller is a safe place for this code? After all, a controller can use many views, so it is more clearly separated than code behind. The problem is that whilst application logic ("Which view do I show next?", "What domain object is handling this request?") makes perfect sense in a controller, there are too many examples of them being used as stores for business/domain logic - which is the province of the domain model.

Hang on, we probably have a (ubiquitous) language problem here. You see, the "Model" in MVC != the "domain model" in Domain-Driven Design (DDD). In fact we need to map the DDD concept of layered architecture to MVC in order to see what we truly have.

MvcMapToDdd

Instead of giving the Model layer a fully fleshed out domain and supporting infrastructure (repository and services), many ASP.NET developers seem to want to treat the Model as pure database infrastructure and DAL (like the one in the Smart UI graphic above). This leads to the problem of where to put the business logic, and the natural assumption is that it belongs in the controller ... which is like making the navigator the captain of the ship.

Ian and Jamis have much more (technical) stuff to say on this subject so I'd advise you to check their posts out if you're into .NET or Rails, respectively, but do take this message with you, the Fat Controller must die!

Wednesday, December 10, 2008

Useful URLs

Whilst at the Sydney ALT.NET meeting this week last month (this post took far too long to write) I had two divergent lines of thought crossover and mashup inside my brain ...

office-sign-brain

I have been working for some months on a large corporate extranet portal and have been steadily fighting to keep the client focused on organising the site around, not my ideas of their organisation's needs, not their ideas of their organisation chart, but rather on the information needs of their clients, the people the portal is really there for.

This can be subtle, after all we all have good reasons for liking our ideas of how to organise the site. In fact we needed to make sure that the content authors from our client in fact could publish their content in a way that made sense to them (and thus organised around their needs).

Back to the Sydney ALT.NET group, as Ali went about explaining the usual routing options with ASP.NET MVC it occurred to me that ASP/ASP.NET developers have been doing the same thing with the organisation of their application URLs. For years they have been organised around the structure of the site as it is developed, with folders in the original web projects visible on the final website URLs. Even when we have introduced user-friendly URLs, and used ASP.NET MVC's routing we still manage to come up with ideas that fit our view of the business model and not our users' needs.

Aside: Do users even care about URLs?

This is a great question because it is at the heart of what I'm talking about here. My subjective view is that they do, I know that I do and I've seen people refer to the URL when trying to work out where they are within a site. However, many sites still have complex, unfriendly URLs and I think the average user (quite rightly) doesn't trust them.

Let's look at it another way, do you care about your users? If you do then you will want to help them every way you can, including making your URLs friendly and useful.

I suspect that the real problem is that we lack a clear design language, or paradigm for helping us work these things out. After all when you can do anything with a URL, who is to say what is right? Yet, if there is one thing the growth of the web has taught us, it is that UI standards grow out of users liking websites that follow common practices (e.g. shopping carts instead of bags, boxes or orders; horizontal main navigation menus as opposed to vertical, circular, drop down boxes, etc.). See Jakob's Law of the Internet User Experience:

"Users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they already know."

Similarly we may find that websites that follow RESTful URL paradigms with particularly clear syntax are seen as much more useful than ones where you have to rely on the menu structure or search. Here is a (contrived) online shopping example:

Old School (ASP.NET Webforms):

http://domain/shop/cart/default.aspx?Method=AddCart&ProductId=123

New School (ASP.NET MVC):

http://domain/cart/add/123

Most Useful (or not):

http://domain/buy/Sony/Walkman?quantity=1

Now I'm unhappy with that last example (perhaps going against the "shopping cart" paradigm muddles things), but my point is that we should phrase things the way the user sees them and not what suits our architecture/business model. Give the URL back to the user as another useful tool and see what happens!

Contact Me