Monday, 18 December 2006

Simple Design

This is such a common idea in any kind of activity that requires any kind of design.

There’s the many time quoted "Make everything as simple as possible, but not simpler." by Albert Einstein.

And at first glance this all makes perfect sense and seems quite wise. The problem is that it doesn’t make for a particularly good thinking tool. It would be great if you could look at a piece of software and go, "ok, let’s make this as simple as possible". This often doesn’t help! It can help for getting rid of some obvious crud, but often this keeps the design the same and simply cleans it up. Finding the simplest possible design out of an unbounded set of designs is a lot more complicated than it first seems.

It can be hard enough generating alternative design ideas, often ideas are constrained by various assumptions, the language your working with, the technology your working with, what you've worked on previously, you knowledge of patterns of design etc etc. How would you feel confident that you found the simplest design?

The more I look into design and see all kinds of alternative ways to design things the more I'm not sure what the exact nature of simple design looks like. Of course there's lots of ideas on how to simplify designs, and there's some great frameworks that make things that were hard to do a lot simpler. But...

I think that there is no absolute simple design. I don’t think it’s even definable given a bunch of constraints (eg, context, purpose, etc)

Not that I think anyone thinks there is an absolute but it is worth keeping in mind that simple design is more about having a "quality" of simplicity rather than being simple or not.

Friday, 15 December 2006

Pretending to have written code

This technique is all about writing code based on code you pretend you have already written. TDD uses of this technique to great effect. The idea is you write a test based on code that doesn't exist yet. So, you invent code that you need in order to express the test. Then, once you have the test, you create the real code for the stuff you pretended to have and make it do what it needs to in order to make the test pass.

Great stuff.

However, the idea of pretending that code exists extends beyond simply expressing a test. It also works well for writing the code itself. Write the body of a method assuming that the objects, methods and variables you need are already there. This allows you to play with solving the problem without worrying about having the infrastructure to actually make the code work. This is powerful.

Some of the problems you see when you don't do this....

You start solving a problem, and you figure you need a method in order to solve the problem, so you go build the method, then you go back and try to complete the problem only to find you didn't really need that method, you actually need something quite different. Basically, when your solving something at the specification perspective write the code imagining you have all the things at the implementation perspective.

You ponder a problem and start putting in a bunch of variables that you think you need in order to solve the problem. This can cause all sorts of grief. Firstly, you tend to build infrastructure that you don't necessarily need, and secondly, and probably the worst effect, you can start constraining yourself about how to solve a problem in terms of the variables you have created. This can be massively limiting and can mislead you for a long time especially if you are resistant to throwing code out. This is one of the more common mistakes I have witnessed.

There is an idea in lean manufacturing that you delay decisions to the last possible moment. Or flipping that around, you leave your options open as long as possible. You want to do this in code also, if you make your mind up too early about something it can constrain your thinking and close out alternative solutions before you need to.

By pretending you can express your thoughts faster which tends to give you quicker feedback about whether you understand an idea or there are gaps in your knowledge. ie, quicker learning. As you learn you conceptulise what you need from the implementation perspective without actually writing it till you have conceptually solved enough of the problem that you need the implementation in order to pass a test.

The counter argument I have heard for not doing this is "It's not the way I think", but I think this is a hangover from when you first start programming. When you first start programming in a language your not entirely sure what's possible and what's not. If you write a "pretend method" your often unsure whether you can build the infrastructure or not. example "I wonder if I can hold arrays of strings?" So you investigate whether you can build the infrastructure you think you need. However, once you get proficient at a language/coding you generally know what's possible and what's not. You know what concepts you can express. Sometimes you don't, so its worth going off and investigating. But in general you know.

The constraint to this idea is that you don't want to pretend for very long. You want to work in reasonably tight cycles of writing tests, writing code. And by no means is this a "rule" it's just a thinking tool that can help you write good code faster. It's possible that pretending can constrain your thinking also, so it's good to have other thinking tools you can use too.

Thursday, 14 December 2006

It's a matter of perspective

One very useful thinking tool I've used a lot when evaluating code is the concept of "Levels of Perspective". I haven't seen too many references to this concept, I orginally saw it as a simple side bar in UML distilled by Martin Fowler. There's a few people who have picked up on this idea and I find it really good. I have another blog post sitting in draft where I was going to flipantly make reference to this idea but I thought I should blog on it for those who may not of come across it. It's a fantastically useful tool because I find in a lot of peoples code these perspectives get mixed up willy nilly and its a great tool to work out how to start refactoring a tangled mess back to sensibility. When pointing out this idea in relation to code I see people going "Ah!". (hmmm, wonder if I've praised this concept enough?)

The levels of perspective are :-

Conceptual
Specification
Implementation

The conceptual perspective is to do with classes of objects in your design. What responsibility each object has and hence where methods should live. Common mistakes you can make when you get this wrong is methods on the wrong object hence some objects knowing too much about other objects. Names of classes and methods dont make too much sense when trying to explain your design. Abstract and concrete concepts are mixed together ( I'll do a blog post on this one a few posts down the track because this is one of the main causes of bad design that I've seen, but, theres a few other ideas I want to chuck out there first).

The specification perspective is the particular steps you need to take in order to fufill a responsibility. eg a Move responsibility would require a "Remove From Source" and "Add to Target"

Implementation is the actual code that achieves a particular step of the specification.

A common thing I see is that specification and implementation stuff get mixed together. Often this is done innocently at the beginning but can start making the code confusing as it evolves. Simply separating out these two perspectives can make for much simpler methods.

Once you have specification stuff separated out it then gets simpler to pull this out as an interface then you can vary the implementation by simply providing different objects that implement this interface which then allows for any kind of dependency injection (blog post to follow later....). If your using a language which has duck typing then this is even easier. The specification also helps with talking abstractly about how to solve a problem which then helps you rationalise about the closure (blog to follow later...) of the abstractions you have made. What I mean by this is that you create a language where you can fully talk about the concept your working with.

For example if you are working with a stack, the language "push", "pop", "top", "empty" provides a language to play with stacks. If you forgot to put the "empty" method in then you wouldn't have closure and it would get harder to express how you want to manipulate a stack.

So developing a good specification perspective helps you rationalise about your objects, it helps clear up abstractions, which provides good language that helps you write more understandable code.

All of this is nicely summed up with the "Open Closed Principle (OCP)" (bog to follow later...). A fundamental idea of OO deisgn but OCP is almost too simple of an idea that its often hard to appreciate the subtle influences it can have on your design. That's why I think you need a bunch of thinking tools, like levels of perspective, to help you reflect on how all these thinking tools work.

There's a lot more that could be said about levels of perspective that I could be here forever! However this idea overlaps with many other ideas and I'll refer back to this idea in other blog posts which will hopefully shed more light on all of this.

Don't burn your bridges

Just a followup on my last post and reflecting on Alexs blog about when to kill code.

There's a concept of scope that needs to be taken into account. The scope that I had in mind for my previous post is the day to day code your building. If your about to build a bridge and you dig a hole in the wrong place for the foundation. Back out of it! Don't carry on and "just make the bridge fit".

However, as in Alexs case, sometimes the whole "bridge" is in question once its build. There's fundamental changes you want to make. This can be a lot harder. There's a number of options.

1. Modify the existing bridge in a disciplined and engineered way. This often has a lot of challenges and you often have to work within some limiting constraints. But it can be a good option. It really depends on how fundamentally different you need the bridge to be.

2. Build a new bridge near the old bridge that meets all your needs, provide transitioning roads from the old bridge to the new bridge. But this also has problems, the transitioning from the old bridge to the new bridge may be quite difficult.

3. Build another bridge in another location with no transitions and just hope traffic will change over to using this bridge.

4. Burn the old bridge down and start again. This is probably the worst option, during this time no one can cross the bridge, you effectively destroy a bunch of value and take ages to get the value back.

Everything has pros and cons, there's no clean easy "right" answer. Software is a bit more flexible than concrete structures so we can exploit that to some degree, but there are always tradeoffs, especially when your creating platforms that other people build things on top of. However whatever option you take, in general, I don't think you should burn your bridges.

Wednesday, 13 December 2006

Don't throw good code after bad code

One effective technique for writing good code is chuck out code that's not working out too well. This is probablly one of the harder techniques to get to grips with. It's pretty easy to understand the idea, however, when your actually writing code and have created a bit of a mess it is easy to convince yourself to keep tinkering to get it right. Or, alternatively, you figure you can refactor your way to good code. Usually there's something in your head that tells you that the approach your taking sucks but you know you can hack it to make it work.

Don't. Cut your losses and kill the code.

The fact you realise that it sucks means you probablly understand the problem a lot better than when you first started. Thats the key thing, that's actually the hard part, writing code when you know exactly what it has to do is often reasonably trvial once your confident in a particular language.

You might salvage the unit tests, but sometimes its better to biff those out also. This gives you the chance to rethink your approach afresh.

For starters you might just comment out your code "just in case". This is especially true if the code you have generated is quite complex. Your not quite sure if you can recreate it. However this is often a big stinky code smell and most often you will find a simpler soloution when you do it again. So once you get used to backing out of code then you'll just delete it.

Tuesday, 12 December 2006

Separating Command and Query

Separating command and query is an idea that Betrand Meyer came up with. The general idea is that a method should either be for changing the state of an object or querying that object about its state. eg

widget.Add( 12 ); // command

x = widget.Sum(); // query

Calling sum won't change the state of widget. In fact it is referentially transparent, that is, the call to sum can be replaced with whatever the result of sum is without changing the behaviour of the software. ie


x = 12;

Which just means calling Sum has no side effects.

On the other hand, the command Add" can do whatever it likes to the object. There is no result from the add that represents the changed state of widget.

So why is this a good thing? It helps in separating your code into simple methods that are responsible for just one thing. This often simplifies code. One of the mistakes I have seen people make is that if you have some action that returns a value (mixing command and query). eg

int count = widget.Add(); // returns the number of items in widget

And you use this method in one place, everything seems fine. Sometime later you find you really need to know count somewhere else. But the only way to find out the the count is by adding something. Nuts. So you may end up storing the value of count somewhere for later retrieval but then this starts complicating another object with the details of widget, and worse, count may be wrong by the time you use it, or, even worse yet, you may end up doing a hack that Adds something to get the count then immediately removes it again. Where as what you really need to do is separate the command and query and simply ask the widget for its count whenever you need it. This is a bit of a simplified example and generally you fall into this trap when the objects and methods semantics are not so clear. In fact sometimes renaming a method can be all that's needed to show this confusion.

Of course, there are many examples you could come up with as to why you may not want to separate command and query. That's fine. As long as you know you're doing it. Most of the problems come when you don't realise your doing it. It's just one thinking tool that helps you evaluate code and potentially help you name a problem.

One nice thing you can do if you do with commands is return this/self as the result. This then allows you to do command chaining eg.


widget.Add(1).Add(2).Add(3);


For some, this whole command query thing may seem all too obvious and trivial, but I wanted to blog on it since I have seen people getting their code in a mess because they didn't make the clear distinction between command and query.

Monday, 11 December 2006

Award for Kiwifruit blemish

We got an award http://www.frst.govt.nz/Awards/TechCommendations.cfm for our kiwifruit blemish technology this year.

Cool technology! If anyone out there would like a job working with this kind of cool technology we are looking for some absolutely top notch developers. Preferably with some kind of background in product based technical software development. Ideally with fantastic OO, TDD / Unit testing, and C++ skills. However, we are mainly looking for really smart people who understand how to create good software.

If interested, send your CV to keithn (remove this) @ compacsort . com

Thinking Tools

One thing that I think is very important in software development is having good thinking tools. By thinking tools I mean any ideas, tips, insights, philosophies, questions, "rules", approaches, etc that helps you build software. These mental tools then need to be arranged into some kind of coherent structure so that they make sense and you can reason about them.

It is very important to have this coherent structure of all your thinking tools otherwise you can end up limiting yourself unnecessarily. for instance

C++ Macros are bad!
The law of demeter!

There is a piece of wisdom behind these ideas and this wisdom has been encoded into a very digestable rule or "ethic". However the real wisdom is not well represented by this nicely packaged idea. These ideas live in eco-system of thinking tools and should be assimilated into a coherent approach about creating software. This approach needs to be constantly re-evaluated and filtered and re-interpreted. Many perspectives need to be incorporated, experience needs to be gained, mistakes need to be made.

Philosophically speaking we need to take a somewhat post modern approach to software development ideas. The ideas of deconstructionism and hermeneutics are very useful here as we look at some of the"rigid" concepts of software development and as we read various peoples thoughts on software development.

I'm not sure how my next few posts are going to work out, but I want to discuss a bunch of thinking tools I use and also hopefully articulate some of the overall concepts I have of software development.

Saturday, 9 December 2006

Blog Refactored

Well, I used to host my own blog on my own site but I think I over estimated my interest in finding some good blog software and getting it all setup. Instead I went with a basic blogging engine, but I tended to get spamed to death, so I gave up on blogging. However, for a while now, I've wanted a place to write down a bunch of evolving thoughts I have had about creating code, designing, and the overall philosophy of creating software. This is more of a selfish interest thing, I find that if I try to write all this stuff down I have to think things through a bit more thoroughly and reflect more on the sanity of what I'm writing. So, this time round I've decieded to go with blogger. I've used it before for non software blogs and it's all nice and simple and hopefully I will make a lot more use of it!