Be inspired -> Generalize -> Specialize -> Win
May 24, 2010
You know, in software development, there is a paradigm that is called “reusability”. It’s something that I follow very strictly. The code that I write utilizes all kinds of devices that are intended to support this end.
However, what is really important is to develop a workflow for creating code that has a very high reusability ratio and as little noise as possible. I hate noisy code.
My personal workflow can be described by the words I use for the title of this article. I will explain each step of the process (yes, including the winning!).
This article is written WITHOUT an example, intentionally. I WILL give you an example, in a later post, but for now, I will try to stay as abstract as possible because I think that… I should generalize first and specialize later!
So, what about…
being inspired…
You want to accomplish something. You have your goal, you have your task, your tools and your environment.
This, actually, is a two – step process. First of all, there is the goal – and then there is the means.
The “proof of concept” – phase falls hereunder – and this is the only phase where I actually encourage you to write bad – TERRIBAD – code. It’s throw – away – code, it is only there to teach you “how stuff works”. Treat it this way! Don’t spend time commenting every statement (a practice I will talk about soon), don’t put too much effort into building a structure. Just use your unit testing framework (or write a console application if you must) and find out about the technicalities.
Now we need to…
perform a polycontextual generalisation…
Big words! But the idea behind this is that every problem we look at in software development encompasses at least two domains – the problem specific domain and the domain of general functionality for the application at hand and future developments.
The result of looking at things this way is that the amount of “throw away” – code, the amount of “noise” is reduced and that the building of the “general purpose” library is facilitated.
In other words, reducing the level of abstraction for a moment:
The problem to be solved has a context in which the code will be executed and requires a supporting framework, and if it is only the worst, the most smelly noise that I know of: boilerplate code.
So lets make a virtue of necessity and convert even the shortest bit of boilerplate code into a library function.
Another step lower on the abstraction ladder:
Use lambda expressions (“anonymous functions” if you use a substandard language) / delegates, the strategy pattern, double dispatch, dependency injection (btw, you can combine the latter two into a single pattern, I will show you that in a later post) and…
…unit test everything. Don’t write console application code at this point, don’t assemble a “button1_Click” – “GUI”. Use unit testing, be very zealous about your test cases, think about the most absurd things you are sure of being non – issues.
Also, think about “what else could I use this for in the future” and…
(this is the lowest I will go in terms of abstraction in this article!)
…”isn’t this a candidate for my ‘ComponentModel’ namespace instead of ‘ConcurrencyExtensions’ or even ‘GUIWrapper’”.
Then – and ONLY then – you get the best out of it.
And this applies to all domains the code belongs to. Put the problem specific part of the code into library methods as well – and generalize them as much as possible, you will be grateful in a few months or even years, when a similar problem turns up again.
Working with functional language elements (LINQ) and AOP (which covers crosscutting concerns mostly, but I also use it to facilitate my extreme lazyness when it comes to writing code) I became used to creating library functionality like crazy and seeing the solution of the problem as the distillate of all the work.
Now, the next step…
Specialize the general solution again…
At this point, you have created library functions, an object model, interfaces and clases. Lots of them, hopefully. You have separated the concerns, you followed the law of demeter zealously, you inverted the control and maybe you even injected some dependencies.
Now it is time to use all the assets you created to implement the problem that led to the creation of all this wonderful stuff – you specialize the solution now to solve the original problem.
If done correctly (this takes some practice and experience) you will now notice that solving the problem that inspired you in the first place is a matter of…
…a few moments!
You don’t think about “which loop goes where” and “do I call this or that method” anymore. You have a framework now that solves your problem – and you know the problem itself (and the technicalities) so well that everything works like a charm, it is like magic.
And this is the moment when you found…
the “I – win” – button for software development
A few weeks later, you find yourself in dire need of a similiar solution. A similar environment for another data handling issue that is closely related. “lol” you say to yourself… “I can do this with a few lines of code, I have a thoughly unit – tested framework for my problem. There will be no noisy copy & paste, no boilerplate code, no time wasted on code that I have already written. Now I have become a developer with a code base at my fingertips.”
Congratulations.