Archive for the ‘Books’ Category
The Last Lecture – Randy Pausch
I recently watched Randy Pausch's 'Last Lecture: Achieving Your Childhood Dreams' and read the corresponding book and although it's not directly related to software development I think that some of the points that he makes are really intriguing.
These were some of the parts that particularly stood out for me:
- Introduce the elephant in the room – whatever it is that people are really thinking about, put it out in the open. I think on development teams there is often a distrust of the way that other people write code because it's different to the way that we do. If we can get this out in the open more frequently and agree on a shared approach then it should result in a more consistent code base.
- Get the fundamentals down – Pausch suggests that we need to understand the fundamentals because otherwise the fancy stuff isn't going to work. In Apprenticeship Patterns Ade Oshineye and Dave Hoover suggest that we should 'Study the Classics' which is a similar idea.
While I think they're certainly right I'm not sure that learning theory before putting it into practice is the most effective way to learn. I think we need to do a bit of both at the same time alternating between the two so that we actually have a frame of reference when we're learning the fundamentals.
- The brick walls are there for a reason – Pausch describes how we'll often come across obstacles stopping or blocking us from what we want to do but that we shouldn't be discouraged, they are there so that we can see how much we really want something. I think this is just generally true and not just related to software development.
- The skill of self assessment – Pausch suggests that we need know what we don't know which I think is perhaps the best advice in the book. We need to recognise our true abilities but also have a sense of our flaws and create feedback loops to allow this to happen.
My colleague Liz Douglass has come up with the idea of Feedback Frenzies to help create this feedback loop and this is one of the best ideas I've come across for doing this.
- One of my favourite quotes from the book is the following which I believe was originally from Dan Stanford:
Experience is what you get when you didn't get what you wanted
…
It's a phrase worth considering at every brick wall we encounter, and at every disappointment. It's also a reminder that failure is not just acceptable, it's often essential.
I think we can do this much more in the software world. There sometimes seems to be a stigma with identifying things which fail but I think it's really useful for others to learn from mistakes that have been made.
The Last Lecture is one of the best presentations I've had the chance to watch – I'd certainly recommend it.
Debug It: Book Review
David Agans' 'Debugging' is the best debugging book that I've read so I was intrigued to see that there was another book being written on the subject.
Paul Butcher offered me a copy of the book to review so I was keen to see whether it was more like 'Debugging' or 'Release It' as Ted Neward suggests.
The Book
Debug It by Paul Butcher
The Review
Much like Krzysztof Kozmic I found that a lot of the ideas early on in the book were similar to what I've been taught by my ThoughtWorks colleagues over the last 3 1/2 years.
I do think it's really good seeing these ideas in words though because it's quite easy to forget about the best way to approach problems in the heat of the moment and the approaches suggested by Paul certainly aren't done everywhere in my experience.
These were some of my favourite parts of the book:
- When chasing a bug Butcher suggests that a useful technique to use is to try and disprove your theory of why the problem has happened. Too often we come up with a theory and just adapt any data to fit our thinking. This is also known as confirmation bias.
In his talk 'Pimp my architecture' Dan North suggests a similar approach more generally when working out how to tackle any problem. Each person has to take the other person's argument and then fight for that to be used instead. I quite like this idea – certainly something to try out.
- When discussing the need to refactor code as we go along, the author points out that if the code we want to change doesn't have any tests around it then we need to write some to provide us with a safety net.
Remember, however, that refactoring crucially depends upon the support of an extensive suite of automated tests. Without tests, you’re not refactoring. You’re hacking.
Hamlet D'Arcy makes a similar point but perhaps more forcibly in a really good blog post and Michael Feathers' 'Working Effectively With Legacy Code' covers the topic in much more detail.
- One tip which seems obvious but is still one I've tripped up on many times is to go through the list of changes that we've made before checking in! It's incredibly easy to forget about some seemingly insignificant change that we made before checking it in and perhaps breaking our application unexpectedly.
Somewhat tied in with this is the idea of checking in small changes more frequently and only changing one thing at a time which I wrote about previously.
- I like that Butcher puts a lot of emphasis on ensuring that we actually know what's going wrong before we attempt to fix anything.
Without first understanding the true root cause of the bug, we are outside the realms of software engineering and delving instead into voodoo programming or programming by coincidence.
This is particularly true when addressing performance problems where he rightly suggests that we should look to profile the code before making a premature optimisation.
He also suggests using the debugger so that we can get a good idea about what the code is actually doing when it's running. While I think this is useful I feel that the need to use the debugger in this way frequently might suggest that our code is difficult to reason about which could well be something to address.
- A couple of other cool suggestions are to call on team mates to help us out if we're getting stuck trying to fix a bug and if that's not possible then to either write out the problem or talk to the rubber duck.
If you don’t have someone to play the role of cardboard cutout, all is not necessarily lost. Try scribbling down a narrative of the problem on paper or perhaps composing an email to a friend. The trick is not to censor yourself — just like a writer would.
I don't think the importance of communicating with team mates can be underestimated and Butcher points out that if we notice a bad pattern in the code than it's no good just going through and changing it everywhere. We need to talk with the rest of the team to decide whether we can get an agreement on the way we'll develop code going forwards.
- The only idea I disagreed with is that of putting assertions into the code which I feel adds clutter to our code even though it makes it fail faster than would otherwise be the case. From my experience if we write good enough unit tests and have good logging in our code then the assertions aren't needed.
In Summary
The book is pretty quick to read at around 200 pages and packs a lot of useful tips into that space. I'd say it's a pretty useful book to keep by your desk to refer to now and then.
Fundamentals of Object-Oriented Design in UML: Book Review
One of my favourite recent blog posts is one written by Sammy Larbi on coupling and cohesion and while discussing it with Phil he suggested that I would probably like this book and in particular the chapter on connascence which I've previously written about.
The Book
Fundamentals of Object-Oriented Design in UML by Meilir Page-Jones
The Review
I really enjoyed reading this book and I think it's one that I could come back and read again to gain something else from in the future.
Nearly all the mistakes that I've made and seen made with respect to the design of object oriented code are outlined in one form or the other in this book.
The book is split into three sections. The first discusses some fairly basic object oriented concepts, the second covers UML as a notation for describing our designs and the final section goes more deeply into the principles of object-oriented design.
What did I learn?
- Although we don't seem to use UML much these days I was coming to the conclusion while reading those chapters that perhaps UML is useful as a design tool but the aim shouldn't be to come up with a UML diagram, but rather to drive a design in code.
This is something which Uncle Bob also touched on recently:
Is TDD a replacement for design?
No. You still need all your design skills. You still need to know design principles, and design patterns. You should know UML. And, yes, you should create lightweight models of your proposed software designs.
We actually found on a project I worked on recently that everyone had a different way of diagramming a design and it would have been useful to have a common notation between us. UML is surely the tool to solve that problem.
- I quite like the way that Page-Jones describes the different types of messages that objects can receive:
- Informative – a message telling an object about something that happened in the past.
- Interrogative – a message asking an object to reveal something about itself.
- Imperative – a message telling an object to take some action on itself.
An interrogative message is effectively a getter whereas the other two are commands being sent to the object. I've not seen the distinction between events which happened in the past and those which are going to happen in the immediate future.
- I've frequently come across the idea of information hiding when it comes to designing objects but Page-Jones introduces the idea of implementation hiding which I think is really neat.
The idea is that while some information about our object will be viewable to other objects e.g. through attributes/getters, we can still hide the implementation of that information internally so that if we we want to change it in the future then we won't have to change all its clients too.
- I found the concept of the rings of operation really interesting. The idea is that there are some methods on our objects which just make use of other methods on the same object. Those methods wouldn't touch any of the fields of an object directly but would rely on those methods in the inner rings to do so.
For example if we have a getter on an object to access a field then if other methods on that object want to access that field they should go via the getter instead of accessing the field directly.
I often find myself avoiding using getters with the hope that if don't increase their usage then it will be easier to get rid of them in the future. This approach would discourage doing that.
- I like the idea of type conformance when it comes to inheritance – we should try to ensure that any sub types adhere to the contract of their parent.
The other part of this chapter describes 'closed behaviour' – all the operations on any class that we inherit from should obey our class' invariant.
I think this can be where we go wrong when we write classes which extend a List for example. The API of a List will typically have 'Add' and "Remove' operations but on a lot of the application I work on we only want the 'Add' functionality and not the 'Remove' option. Page Jones suggests that if we want to use inheritance in this situation then we should override methods on the super class to make 'Remove' do nothing.
- I now find that I prefer Page Jones definition of cohesion:
Class cohesion is the measure of interrelatedness of the features (the attributes and operations) located in the external interface of a class
I'm inclined to believe that we might be able to tell how related the features are by looking at the clients of the class and seeing whether they are all using the class in similar ways.
He then outlines three signs that we have cohesion problems with a class:
- Mixed instance cohesion – a class has some features that are undefined for some objects of the class. I find that this typically happens when we try to make a generic data type to cover everything and then try to jam any variations on the type into the same definition. It is typically solved by pulling out another class. This is the worst type of cohesion.
- Mixed domain cohesion – a class contains an element that directly couples the class with another class that is unrelated domain wise. This typically happens when we mix infrastructure code into our domain code.
- Mixed role cohesion – a class contains an element that couples it with an unrelated class in the same domain. I think this is the most typical type of cohesion that I've seen and the main problem is that we end up with classes which have multiple roles which makes them difficult to change.
In Summary
There's way more in this book than I could ever hope to cover here but these are some of the interesting bits that stood out from this reading of it. I'm pretty sure that I'll come back to this one in the future.
While reading the book I had the feeling that some of the ideas are quite similar to those in Domain Driven Design and since this book was published it contributes to my belief that a lot of DDD is covered by just doing OOP well.
Overall this is a really good book, worth reading.
Zen Mind, Beginners Mind: Book Review
The Book
Zen Mind, Beginner's Mind by Shunryu Suzuki
The Review
I first came across the actual term beginner's mind when reading through the 'Wear The White Belt' chapter of Apprenticeship Patterns although it was often mentioned to me on one of the first projects I did at ThoughtWorks a couple of years ago that people liked teaching me things because I just took the information in pretty much without questioning.
I find nowadays that I analyse what people tell me way a lot more and then compare it against what I already know to see if it adds to my understanding. In a way this is useful but sometimes prevents me fully understanding ideas since I have already judged them.
I started researching beginner's mind a bit to see if there was anything written on the state of mind required to maximise learning and this was the book that kept being mentioned so I decided to get a copy of it.
It is fundamentally a book on Zen and a lot of the stuff around that area didn't make a lot of sense to me but I think there were some general ideas which can be applied to learning in general.
What did I learn?
- One of the early chapters sets the message for the book with the following quote:
In the beginner's mind there are many possibilities. In the experts there are few.
Straight away it gets to the point which I think describes the problem that we have in software development once we've done a few projects and accumulated a set of ideas of the best way to deliver software – we often stick to those ideas and aren't open to the idea of better ideas being out there.
On the other hand as Fred Brooks points out there is no silver bullet so perhaps this also explains why there is often skepticism when new ideas are described since its quite likely that potential negative points of these approaches have either not been described or not yet discovered.
- The author raises some interesting ideas around how to get the best out of people by suggesting that the best way to do this is to let them do what they want but to watch them. Although he then went out to reference this back as a metaphor for controlling our own thoughts I was reminded of the Netflix culture slide show which I came across lately in terms of how they give employees freedom but expect them to act in the organisation's best interest rather than expecting employees to follow a lot of rules.
- One thing I really liked was the emphasis on listening to what someone says 'without having your own idea [in mind]…forgot what you have in your mind and just listen to what he says'. I think one problem we can run into when listening to other people is that we extract the bits of what they say which fit in with what we believe – something known as the confirmation bias.
I actually found an old post of mine which lists some mistakes we commonly make when listening to others speak. It makes quite interesting reading.
Another quote from the book sums up a more useful approach:
See things as they are, observe things as they are, let everything go as it goes
- He goes on to suggest that we should have no negative or positive feelings towards what someone says to us and that we should give up our preconceived ideas and subjective opinions which I didn't think made much sense in the software development game since a lot of what we do is about assessing the merits of different approaches.
The beginner's mind entry on the C2 wiki makes more sense by describing Ward Cunningham's approach:
You can generally tell when you're dealing with someone who really knows their stuff by the amount of reference they make to the way it has always been done. Folk like our own WardCunningham seem able to ditch all that stuff and approach each problem as if it were completely new and they had never done anything like it before.
Then, when they have a solution, they'll either recognize it as a Pattern in the standard lexicon, and leverage readymade tools, or not. But they never come in armed for bear when all the customer needs to catch is clams.
It seems like we only initially need to have an empty mind while we are taking in the new information and then we can make use of the knowledge that we already have later on.
- The author suggests that 'when you do something just to do it should be your purpose' which seems somewhat similar to the idea of focusing on the process in Agile instead of always on the outcome of what we're doing.
While a result focus can be helpful I often notice that important things like the quality of what we're making get dropped by the wayside if we focus too much just on completion.
I do think there is some need to focus on whether what we're doing is actually improving us (although the book advises against this) and I recently came across Chad Fowler's idea of always asking 'Am I better than yesterday?'.
- It is pointed out then when learning zaizen we cannot expect rapid progress but instead that we will progress little by little which I think is pretty much the same in software development.
With nearly all skills a lot of practice is needed – as Talent is Overrated points out – we don't just become an overnight sensation but need to work our way through the Dreyfus Model for each skill gradually improving our level.
In Summary
Although this book is about Zen I still found some interesting ideas about learning and I guess its always interesting to read something a bit different.
I'd be interested in knowing if there was a book that covered beginner's mind purely from a learning point of view instead of Zen if anyone knows of any titles!
Brownfield Application Development in .NET: Book Review
The Book
Brownfield Application Development in .NET by Kyle Baley and Donald Belcham
The Review
I asked to be sent this book to review by Manning as I was quite intrigued to see how well it would complement Michael Feather's Working Effectively with Legacy Code, the other book I'm aware of which covers approaches to dealing with non green field applications.
What did I learn?
- The authors provide a brief description of the two different approaches to unit testing – state based and behaviour based – I'm currently in favour of the latter approach and Martin Fowler has a well known article which covers pretty much anything you'd want to know about this topic area.
- I really like the section of the book which talks about 'Zero Defect Count', whereby the highest priority should be to fix any defects that are found in work done previously rather than racing ahead onto the next new piece of functionality:
Developers are geared towards driving to work on, and complete, new features and tasks. The result is that defect resolution subconsciously takes a back seat in a developer’s mind.
I think this is quite difficult to achieve when the team is getting pressure to complete new features but then again it will take longer to fix defects if we leave them until later since we need to regain the context around them which is more fresh in our mind the earlier we fix them.
- Another cool idea is that of time boxing efforts at fixing technical debt in the code base – that way we spend a certain amount of time fixing one area and when the time's up we stop. I think this will work well as an approach as often when trying to fix code we can either get into the mindset of not fixing anything at all because it will take too long to do so or ending up shaving the yak in an attempt to fix a particularly problematic area of code.
- I like the definition of abstraction that the authors give:
From the perspective of object- oriented programming, it is the method in which we simplify a complex “thing”, like an object, a set of objects, or a set of services.
I often end up over complicating code in an attempt to create 'abstractions' but by this definition I'm not really abstracting since I'm not simplifying but complicating! This seems like a useful definition to keep in mind when looking to make changes to code.
- Maintainability of code is something which is seriously undervalued – I think it's very important to write your code in such a way that the next person who works with it can actually understand what's going on. The authors have a fantastic quote from Perl Best Practices:
Always code as if the guy who ends up maintaining your code is a violent psychopath who knows where you live.
Writing code that is easy for the next person to understand is much harder than I would expect it to be although on teams which pair programmed frequently I've found the code easier to understand. I recently read a blog post by Jaibeer Malik where he claims that it is harder to read code than to write code which I think is certainly true in some cases.
- There is a discussion of some of the design patterns and whether or not we should explicitly call out their use in our code, the suggestion being that we should only do so if it makes our intent clearer.
- While describing out how to refactor some code to loosen its dependencies it's pointed out that when the responsibilities of a class are a bit fuzzy the name of the class will probably be quite fuzzy too – it seems like this would server as quite a useful indicator for refactoring code to the single responsibility principle. The authors also suggest trying not to append the suffix 'Service' to classes since it tends to be a very overloaded term and a lot of the time doesn't add much value to our code.
- It is constantly pointed out how important it is to do refactoring in small steps so that we don't break the rest of our code and to allow us to get rapid feedback on whether the refactoring is actually working or not. This is something that we've practiced in coding dojos and Kent mentions it as being one of his tools when dealing with code – I've certainly found that the overall time is much less when doing small step refactorings than trying to do everything in one go.
I'm quite interested in trying out an idea called 'Bowling Scorecards' which my former colleague Bernardo Heynemann wrote about – the idea to have a card which has a certain number of squares, each square reprsenting a task that needs to be done. These are then crossed off as members of the team do them.
- An interesting point which is made when talking about how to refactor data access code is to try and make sure that we are getting all the data from a single entry point – this is something which I noticed on a recent project where we were cluttering the controller with two calls to different repositories to retrieve some data when it probably could have been encapsulated into a single call.
- Although they are talking specifically about poor encapsulation in data access layers, I think the following section about this applies to anywhere in our code base where we expose the inner workings of classes by failing to encapsulate properly:
Poor encapsulation will lead to the code changes requiring what is known as the Shotgun Effect. Instead of being able to make one change, the code will require you to make changes in a number of scattered places, similar to how the pellets of a shotgun hit a target. The cost of performing this type of change quickly becomes prohibitive and you will see developers pushing to not have to make changes where this will occur.
- The creation of an anti corruption layer to shield us from 3rd party dependency changes is suggested and I think this is absolutely vital otherwise whenever there is a change in the 3rd party code our code breaks all over the place. The authors also adeptly point out:
The reality is that when you rely on another company's web service, you are ultimately at their mercy. It's the nature of third-party dependencies. You don't have control over them.
Even if we do recognise that we are completely reliant on a 3rd party service for our model I think there is still a need for an anti corruption layer even if it is very thin to protect us from changes.
The authors also describe run time and compile time 3rd party dependencies – I think it's preferable if we can have compile time dependencies since this gives us much quicker feedback and this is an approach we used on a recent project I worked on by making use of generated classes to interact with a SOAP service rather than using WCF message attributes which only provided us feedback at runtime.
In Summary
This book starts off with the very basics of any software development project covering things such as version control, continuous integration servers, automated testing and so on but it gets into some quite interesting areas later on which I think are applicable to any project and not necessarily just 'brownfield' ones.
There is a lot of useful advice about making use of abstractions to protect the code against change both from internal and external dependencies and I particularly like the fact that the are code examples showing the progression of the code through each of the refactoring ideas suggested by the authors.
Definitely worth reading although if you've been working on any type of agile projects then you're probably better off skim reading the first half of the book but paying more attention to the second half.
Real World Functional Programming: Book Review
The Book
Real World Functional Programming by Tomas Petricek with Jon Skeet (corresponding website)
The Review
I decided to read this book after being somewhat inspired to learn more about functional programming after talking with Phil about his experiences learning Clojure. I'm currently working on a .NET project so it seemed to make sense that F# was the language I picked to learn.
What did I learn?
- I've worked with C# 3.0 since around July 2008 so I had a bit of experience using some of the functional features in C# before picking up this book. I therefore found it very interesting to read about the history of lambda and the different functional languages and how they came into being. Having this as an opening chapter was a nice way to introduce the functional approach to programming.
- Immutable state is one of the key ideas in functional programming – this reminded me of a Joe Armstrong video I watched last year where he spoke of his reduced need to use a debugger when coding Erlang due to the fact that there was only one place where state could have been set rather than several as is the case with a more imperative approach. We have been trying to code with immutable state in mind in our coding dojos and while it takes a bit more thinking up front, the code is much easier to read when written that way.
- Separating the operations from the data is important for allowing us to write code that can be parallelised, focusing on what to do to the data rather than how to do it. Sadek Drobi has a nice illustration of what he calls mosquito programming vs functional programming on page 14 of the slides of his QCon presentation. It describes this idea quite nicely.
- A cool technique that Phil taught me when reading language related books is to have the PDF of the book on one side of the screen and the REPL (in this case F# interactive) on the other side so that you can try out the examples in real time. The book encourages this approach and all the examples follow on from previous ones which I think works quite well for gradually introducing concepts.
- Functions are types in functional programming – I have had a bit of exposure to this idea with Funcs in C# but partial function application is certainly a new concept to me. I can certainly see the value in this although it took me a while to get used to the idea. I am intrigued as to where we should use a functional approach and where an OO approach when working in C#. I think both have a place in well written code.
- F#'s implicit static typing is one of my favourite things about the language – you get safety at compile time but you don't waste a lot of code writing in type information that the compiler should be able to work out for you. It has the strongest type inference of any language that I've worked with and I thought it was quite nice that it was able to work stuff out for me instead of me having to type it all out.
- I really like the idea of option types which I first learnt about from the book. Having the ability to explicitly define when a query hasn't worked is far superior to having to do null checks in our code or the various strategies we use to get around this.
- I thought it was cool that in the early chapters the focus with the F# code is to provide examples that you can just get running straight away instead of having to worry about the need to structure your code in a maintainable way. After I had a reasonable grasp of this then the chapter about using record types to structure code in an OO way come up. I still prefer the C# style of structuring code in objects – it just feels more natural to me at the moment and manages the complexity more easily. It is quite easy to switch between the two styles using features like member augmentation so I think it's probably possible to mix the two styles quite easily.
- We can use modules to make F# functions which don't fit onto any class available from C# code. The code is not as clean as if we were writing just for it to be used by other F# code but it's not too bad:
module Tests = let WithIncome (f:Func<_, _>) client = { client with Income = f.Invoke(client.Income) }
We can then call this in our C# code like so:
Tests.WithIncome(income => income + 5000, client);
Dave Cameron has written more about this.
- Although I studied data structures at university I don't really pay a great deal of attention to them in terms of performance normally so it was interesting to see the massive performance hit that you take when appending a value to the end of an F# list compared to adding it to the beginning. F# uses linked lists so if we want to add something to the end then there is a lot of recursion involved to do that which is quite costly. In terms of big O notation we go from O(N) where N is the number of elements to append to O(N*M) in terms of performance.
- Chapter 13 is about parallel processing of data for which I found I needed to download the Microsoft Parallel Extensions to .NET Framework 3.5, June 2008 Community Technology Preview and then add a reference to 'C:\Program Files\Microsoft Parallel Extensions Jun08 CTP\System.Threading.dll' in order to make use of those features.
- The author provides a nice introduction to continuations and how you can make use of them in F# by using continuation passing style. I'm intrigued as to how we can make use of these in our code – we do a bit already by making use of callbacks which get fired at a later point in our code – but from what I've read it sounds like we should be able to do even more especially when writing web applications.
- Asynchronous workflows are also made very accessible in this book – I had previously struggled a bit with them but the author covers the various API methods available to you and then explains what is going on behind the syntactic sugar that F# provides. I have made some use of these in the little twitter appication that I've been working on now and again.
In Summary
I really enjoyed reading this book – it's my first real foray into the world of functional programming since university and I think I understand the functional approach to programming much better than I did back then from reading this book.
It takes an approach of introducing various functional programming concepts before showing examples of where that concept might come in useful when coding. It's also particularly useful that examples are shown in C# and F# as this made it much easier for me to understand what the F# code was doing by comparing it with the code in a more familiar language.
I'd certainly recommend this to any .NET developers curious about learning how to apply ideas derived from functional programming to their C# code and indeed to any developers looking to start out learning about functional programming.
97 Things Every Software Architect Should Know: Book Review
The Book
97 Things Every Software Architect Should Know by Richard Monson-Haefel
The Review
My colleague Erik Doernenburg mentioned that he had written a couple of chapters in this book a while ago and there was a copy of the book in the ThoughtWorks office so I thought I'd take a look.
I'm far from being an architect but since their decisions affect what I do I was intrigued to see what they should be doing.
The contributions in the book are also available on the 97 things wiki.
What did I learn?
This book contains a series of short essays by software architects, 97 in total, so clearly there is a lot to be learnt from this book. I'll just cover some of the ones I found most interesting.
- The first chapter in the book talks of the need to not put your resume ahead of the requirements and instead choose the right technology for the customer rather than the one that you want to use. Later on Greg Nyberg talks about how good ideas kill projects due to them getting out of hand and taking up much more time than expected to implement and affecting far more of the code than you would think. The suggestion therefore seems to be that we shouldn't upgrade frameworks and should be cautious about introducing technologies into our project.
At face value this seems to make sense but it somewhat limits our ability to improve in my opinion. If we always choose the technology based on what we currently know then how will we know when something better comes along.
I much prefer the idea of trying out several solution early on (an idea that Erik Doernenburg mentions in 'Try before choosing' using lean's idea of concurrent set based engineering. Experimentation is very important early on in a project although of course we must eventually be looking to choose the best solution and go with that at the last responsible moment.
- Another one that really stood out for me is 'Simplicity Before Generality, Use Before Reuse' written by Kevin Hennery. He speaks of how we often use general purpose infrastructure code/class libraries which don't actually help us solve our specific problem.
It's better to derive the generality of a solution later on having originally designed for what we need them for in the first place. Joe Walnes' XStream framework is often pointed out as being a library which was developed in this way – he only put in the features that he needed rather than trying to think how people might want to use it and by doing so actually did cover the way that most people would use it.
- I think my favourite essay in the book is 'Don't Be Clever' by Eben Hewitt where he talks of the importance of being 'as dumb as you possibly can and still create the appropriate design'. He goes on to add:
More developers can implement and maintain dumb solutions. In dumb solutions, each component can only do one thing. They will take less time to create, and less time to change later.
It's so easy to make clever design decisions but when there are other people on a team that need to work with these designs it is in fact pointless to be clever and creating something simple that everyone will be able to work with is a much better approach.
Dave Anderson also talks about the importance of designing our code so that it's easy for someone from a different team to work with especially if they have to make production fixes. The need for the code to be obvious, testable, correct and traceable are pointed out as being key.
- Another one which I really liked is 'The Business vs The Angry Architect' which talks about the need to listen to what the business are saying instead of always waiting to have our say and display our superior knowledge. My favourite quote from this chapter is:
Remember; when you’re talking you can only hear something you already know. Don’t ever start thinking you’re so smart that no one else has something valuable to say.
…
Don’t allow yourself to become a disgruntled genius that spends all of your time trying to impress others by making witty, condescending statements about how poorly the company is run. They won’t be impressed.This is certainly something that anyone in a software team can apply not only architects. Certainly I have learnt that it's important to accept some decisions instead of constantly pointing out how wrong they are, something which Dan North also points out in his 'Pimp My Architecture' talk.
- I really like Timothy High's idea of 'Recording Your Rationale' where he suggests keeping track of all the trade offs being made so that we know in the future why certain decisions were made. This ties in quite nicely with Dan North's idea of the project shaman who tells the stories of the project and why different decisions were made. Mark Richards also talks about the need to communicate clearly with the developers on the team and keep them informed about the big picture and the like and Timothy High goes on to talk about the importance of recording any assumptions that we make.
On every project I've worked on we have recorded assumptions related to the order of stories and the approach we are likely to take during estimation sessions and it certainly makes it easier to explain decisions in the future.
Dave Quick suggests that we could also record potential risks on projects until they are no longer a risk. They can be prioritised and reviewed when there is new information. I quite like this idea as it puts the information out in the open rather than sweeping it under the carpet.
- Paul W. Homer talks of the benefit of sharing our knowledge and experiences, an idea that I absolutely agree with and I think can be valuable within teams as well as within the industry. He points out that explaining our ideas to others helps us find the weaknesses in what we are saying – I agree, I find I learn most when trying to teach things to other people.
- Einar Landre's essay about how the architect's focus is around the boundaries and interfaces is another interesting one – I think this is the place where the messiest code ends up being so it makes sense that you would have the strongest person technically in the team involved. Creating these boundaries is certainly essential from my experience.
The author talks about making use of Domain Driven Design concepts such as bounded contexts and context mapping to handle the complexity around these areas.
Keith Braithwaite also talks about the value of having multiple overlapping representations instead of trying to have one representation for the whole system which seems along the same lines as the DDD approach.
- Scott Mcphee and Burkhardt Hufnagel both talk about the importance of paying back technical debt before it causes us problems. Scott covers it more from the angle of correcting incorrect decisions as soon as we can while Burk comes at this more from the angle of making changes the correct way later on if we can't do the first time we make them. I think this is something that we often forget to do and it's not immediately painful so we think we've got away with it until a few months later we notice how truly difficult it is to make any changes at all and then it's really hard to recover the code to a good state.
- Jeremey Mayer makes a very astute observation about reuse of code – developers need to know that code is there to reuse otherwise they will just write the functionality that they need themselves. He also notes that developers tend to prefer to solve problems themselves rather than ask for help.
Dan Bergh Johnsson also noted at QCon that developers will only wait 30 seconds to try and find a piece of code that they need before writing it themselves.
In Summary
I enjoyed reading this book and there is plenty more in this book than just what I've mentioned – I was mainly interested in the architecture advice which affects me as a developer but there's also advice which doesn't apply so much to me at the moment which is probably more interesting to architects.
The Five Dysfunctions of a Team: Book Review
The Book
The Five Dysfunctions of a Team by Patrick Lencioni
The Review
I heard about this book a while ago but I was intrigued to actually get a copy by Darren Cotterill, the Iteration Manager on the project I'm working on at the moment.
I was particularly interested in learning whether the ideas of agile and/or lean help to solve any of these dysfunctions.
What did I learn?
- The book is split into two sections. In the first section a story is told about an organisation with a dysfunctional team and the dysfunctions are gradually introduced. The second section covers them in more detail and provides ways to overcome. The dysfunctions are as follows:
- Absence of Trust – team members are unwilling to be vulnerable within the group
- Fear of Conflict – team cannot engage in unfiltered and passionate debate of ideas
- Lack of Commitment – team members rarely have buy in or commit to decisions
- Avoidance of Accountability – team members don't call their peers on actions/behaviours which hurt the team
- Inattention to Results – team members put their individual needs before those of the team
- One of the most interesting arguments the book raises is around getting everyone to be focused on the same goal whereby the collective ego gets precedence over individual egos. This requires a lack of politics which is defined as 'when people choose their words and actions based on how they want others to react rather than what they really think'. This idea also seems similar to the idea in lean thinking of favouring the big picture over local optimisations – the team as a whole succeeding is more important than any individual success.
- The other danger of individual goals being favoured over those of the collective is identified as being specialism in teams whereby everyone is responsible for their part and noone else knows anything about it. Pair programming with frequent rotation is one approach that we can use in software development teams to help avoid this specialisation as well as encouraging team members to become generalising specialists rather than expert in just one area.
- The ideas around healthy conflict are quite interesting. Meetings should have some level of conflict otherwise we probably just have false harmony. This sounds a little similar to the idea in lean that 'no problem is a problem' – i.e. we shouldn't keep things to ourself but instead get them out there and find a way to solve the problem. The author also points out that conflict is never going to feel comfortable but that doesn't mean that we shouldn't engage in it.
- I particularly liked the ideas for creating trust on a team – team members are given the opportunity to share some information about themselves including their greatest strength and weakness in relation to the team. I've not seen this explicitly done on any teams I've worked on but I think that when pair programming people do share this kind of information so maybe we do actually get some of the benefits of this approach. The idea is that team members should be 'confident that their peers intentions are good'. Reading this reminded me of the retrospective prime directive.
- An idea which I don't completely agree with is that we should look to make decisions because 'a decision is better than no decision' – the author claims that not making decisions can lead to a lack of confidence in the team and that dysfunctional teams wait until they have enough data to be certain that their decision is correct. He does then go on to point out that if the decision is wrong then we should not be afraid to change it which I do agree with. In software development teams though I question the value of making decisions too early – there is some value in following an approach such as set based concurrent engineering where we try out several approaches before converging on the actual solution later on.
In Summary
I found this book really interesting and I could definitely relate to some of the the things that were talked about.
I think lean/agile ideas do solve some of the problems but certainly not all of them and it would definitely be interesting to try out some of the exercises suggested on future teams I work on.
The Mythical Man Month: Book Review
The Book
The Mythical Man Month by Fred Brooks Junior
The Review
Pretty much since I started working at ThoughtWorks 2 1/2 years ago I've been told that this is a book I have to read and I've finally got around to doing so.
Maybe it's not that surprising but my overriding thought about the book is that just about every mistake that we make in software development today is covered in this book!
What did I learn?
- The title of the book and the second chapter of the book refers to the situation that surely everyone who has ever worked on a software development project is aware of – if a project is late then adding new people onto it will make it even later. This is due to the fact that a big part of software development is communication and adding people makes that communication more complicated than it previously was, therefore meaning it takes longer to get things done. My colleague Francisco has a nice post describing the ways that adding people can slow down a development team. The idea that a baby can't be produced any quicker by having 9 women rather than just one is a particularly common metaphor used to explain this.
- Incompleteness and inconsistencies of ideas only becomes clear during implementation – pretty much putting a dagger into the idea that we can define everything up front and then code it just like that. This is certainly the area that the agile and lean approaches look to change and certainly the earlier we can try out different ideas by using approaches such as set based concurrent engineering the more quickly we can end up with a useful solution.
- An interesting idea about creating a surgical team ,with a few very experienced people doing the majority of the coding and being assisted by other members of the team, is suggested as being a successful route to delivering software. It sounds quite different to the teams that I have worked on where everyone on the team is involved although the objectives behind it seem valid – reducing the communication points and ensuring the conceptual integrity of the solution. Uncle Bob recently wrote about this describing these teams as master craftsman teams but it sounds as if this would require quite a radical shift in the recruiting strategies of organisations. Dave Hoover also has an interesting post on this subject but he takes the angle of building apprentices on teams like this.
- This seems closely linked to another idea about team composition described later on in the book which speaks of the need for a team to have a technical director and a producer – the technical director sounds to be quite similar to Toyota's idea of the Chief Engineer and they would be technically in charge while the producer (Iteration Manager?) is in charge of everything else. The underlying idea here is that we don't just have one person in charge of a team, there are two distinct and important roles.
- Brooks says the most important aspect of the design of a system is to ensure its conceptual integrity i.e. a consistent set of design ideas. In order to achieve this Brooks suggests the need for a system architect – while I agree with this idea I think it is more a role and maybe one that can be done by the Tech Lead on a project. The Poppendieck's also talk of the need for conceptual integrity in Lean Software Development. The point here is to create a system which is easy to use both in terms of function to conceptual complexity. I am reminded of a Dan North quote at this stage: "We're done not when there's nothing more to add, but when there's nothing more to take away"
- The productivity increases gained by using high level languages are mentioned – the underlying idea being that using these allow us to avoid an entire level of exposure to error. I think this makes sense and as an example I think the introduction of functional collection parameters into C# 3.0 will lead to a reduction in the amount of time spent debugging loop constructs since we no longer have to use these so frequently.
- When talking about object oriented programming Brooks speaks of the need to design objects which describe the concepts of the client.
If we design large grained classes that address concepts our clients are already working with, they can understand and question the design as it grows, and they can cooperation in the design of test cases.
In other words…Domain Driven Design! Reading this part of the book very much reminded me of Phil Will's QCon presentation where he spoke of the way that the business and software development teams at the Guardian were able to collaborate to drive the design of the domain model for their new website.
- The idea of only performing system debugging when each individual component actually works is something which should be obvious but is often not followed. If we know a component doesn't work on its own then we can guarantee it is not going to work when we try to integrate it with other components so the exercise seems slightly pointless to me. Common sense advice I think!
- Speaking of code reuse Brooks points out that the key here is the perceived cost of finding a component to reuse that is important – this ties in nicely with an idea from Dan Bergh Johnsson's QCon presentation
Your API has 10-30 seconds to direct a programmer to the right spot before they implement it [the functionality] themselves
- Brooks talks of the need to have documentation for our projects – he uses a project workbook to do this and I think the modern day equivalent would be the project wiki. The idea of creating self documenting programs to help minimise the documentation that needs to be written is also covered. The importance of how we name concepts in our code is especially important in this area.
- The need to progressively refine the system by growing it rather than building it is suggested later on in the book – the limitations of the waterfall model are described and the approaches of agile/lean are pretty much described – building frequently, getting it working end to end, rapid prototyping and so on.
In Summary
I really enjoyed reading this book and seeing how a lot of the ideas in more modern methodologies were already known about in the 1980s and aren't in essence new ideas.
I'd certainly recommend this book.
Lean Thinking: Book Review
The Book
Lean Thinking by James P. Womack and Daniel T. Jones
The Review
This is the latest book in my lean learning after The Toyota Way, Taiichi Ohno's Workplace Management and Lean Software Development and seemed like the most logical one to read next as it came at lean from a slightly different angle.
I found this the most hard going of the books I've read on the subject so far.
What did I learn?
- The underlying themes the book points out for successfully getting an organisation to adopt a lean approach is that we must have a change agent, lean knowledge and a lever for change. Interestingly that lever for change can often be a recession when a firm needs to make changes in order to survive – when times are good there is no need to change so it's easier to just keep the status quo.
- My favourite quote from the book is the following which talks about the mindset needed for lean thinking:
Create a mindset in which temporary failure in pursuit of the right goal is acceptable but no amount of improvement is ever enough.
I like this because too often the human instinct is to take the risk free approach where we are afraid of failure and therefore miss opportunities to get better. The lean approach allows us to get past this in pursuit of a greater goal.
- One idea which really resonated with me as someone working in the industry was how Pratt & Whitney had to get past the managerial attitude of "ship on time and you'll be fine [even if you're shipping junk]" in order to make improvements. Often with software projects I have found that there appears to be a real focus on the data of promised delivery even though it would be beneficial to ship a bit later and ensure greater quality. Often there is no actual loss (except loss of face) from doing this either.
- Co-locating teams is a constant thread throughout the book and I've found this to be an important factor in successfully delivering software as well. The author also talks about the need to look at the cost across the whole life cycle of the product rather than just the cheaper production cost of offshoring operations. Around the time I read this chapter I was drinking some Ribena which said on the label that the blackcurrants were picked in New Zealand, the drink bottled in China and I was drinking it in Australia. There were quite a lot of transportation costs involved in the life cycle of that drink! In software it is the cost of communication rather than transportation that we need to consider when deciding to spread a team across different locations.
- The idea of takt time stood out for me – the idea here is to only produce at the rate at which the product is being demanded. This means that sales people shouldn't go trying to create spikes in demand which I think is quite different to the way that typical organisations operate. Software wise I suppose this would be about delivering at the pace at which the customer needs the functionality and trying to release regularly so there aren't spikes in the requirements.
- In the Wiremold case study the idea of reducing the suppliers so that there are less integration points in the whole process is described. In software having less moving parts certainly makes it easier for us to go faster.
- An interesting thing that is pointed out is that in all the firms case studied there are never any layoffs directly linked to lean improvements. This despite the fact that a lot less people will be needed once the process has been improved. It is pointed out that if people lose their jobs from lean then they're going to do their best to sabotage it. The importance of everyone being involved in the continuous improvement is also emphasised. There are endless steps of improvement, we are never done.
- The importance of having a standard language when talking about lean is emphasised, helping ensure that everyone is talking about the same things. I think the idea is fairly similar to that of the ubiquitous language from Domain Driven Design.
- One of the wishes of the author is to create lean enterprises where lean thinking is applied all along the value stream from the raw materials all the way to the customer. The difficulty of getting all the firms to work together to allow this to happen is described but I can't really see how this is going to happen for the time being.
In Summary
I found this book very heavy reading – it's taken me almost three months to complete it! The stories hold good lessons but I found The Toyota Way to be a much easier read.