Writing good code requires you to perform experiments

By Confusion on donderdag 5 maart 2009 07:52 - Comments (19)
Categories: Java, Software engineering, Views: 21.016

How often do you have to solve a small problem that is a part of a larger project and decide to take the time to perform some seperate experiments to solve the problem, before adding the partial solution to the whole? In the past, I hardly ever did that and everytime I encounter such a situation, I still have to resist the temptation to take the route that seems to be the shortest, but that has long proven to be the longest road to the solution.

As an example, suppose you need to extract some information from a string and decide the best way is to use a regular expression. You know that the problem isn't trivial and that you probably need a few attempts to get it right. Still, your initial inclination is to just put the regex in there and go through the motions of compiling the code, performing the steps required to invoke the code (click a button, enter some text, etc), find out that the regex doesn't work, modify it and go through the motions again and again and again, probably while making some other modifications. Because the cycles take relatively long, progress is slow and you start cursing every typo. If you recognize this, then I think you can become faster and happier at your problem solving by reading on.

The advantage of the 'intuitive' approach is that, if the solution is right, you have immediately come closer to solving the larger problem. However, if the solution fails, the iterations to be informed of your failure and to verify subsequent modifications may soon take more time than developing a seperate solution to the subproblem would have taken. For some reason, we always seem to underestimate the amount of work it takes to get it right and consequently we opt for the small change that we will have the correct solution the first time around.

Some of you may now be thinking that the obvious solution is to write a proper unit test and run that unit test after every modification, until the code passes the test. I agree that goes a long way, but usually the test is part of a larger number of classes and running all those tests takes times, especially if it bootstraps an entire Spring-Hibernate application or something of the like. In such as case, it still takes more time than is needed.

My solution is not to be afraid to experiment. It seems to cost too much time to create a new script or class, seperate from the larger project, provide the correct libraries, run this small project multiple times to get feedback on your solution and finally copy-paste the solution back into the project your are working on. However, my experience is that it is well worth the time you need to do this, because it prevents the endless cycles of building-deploying the entire application and getting it to provide feedback. I hardly write a regular expression or SQL query without first testing it seperately from the application. Now these example are given at the smallest level, but it also holds for somewhat larger design issues and even for issues people call 'software architecture'.

Another thing about these small experiments that I find a major advantage, is that it gives you the freedom to explore some avenues that you wouldn't dare put into the actual project. You can't just start switching libraries or refactoring relatively large parts of the code and changing too much is risky and frowned upon, even if you can easily revert your changes (assuming you are using a versioning system. If you aren't, stop reading, install Subversion and commit your code before continuining this article).

A third advantage of experimenting is that it encourages you to rewrite and polish the code that you are writing. You can go through more iterations in experiments 'outside' of the project, because you have a clear overview over the code involved. Modifications of code inside a larger project are less inviting to proper refactoring to do 'the right thing'.

Painters, writers, craftsmen, even philosophers: if famous ones are asked for the secret of their succes, they always advise exercise and experimentation. I hope I have explained that it also simply makes sense. If you don't want to take it from them, take it from rationale.

Volgende: The ability to predict a decision does not disprove free will 03-'09 The ability to predict a decision does not disprove free will
Volgende: Why functional programming doesn't catch on 02-'09 Why functional programming doesn't catch on


By Tweakers user Floort, donderdag 5 maart 2009 01:30

That's how I like to write most of my code.
First write a working piece of code that solves your problem, then do a complete rewrite. The second version of the code is almost always more elegant, better to understand and faster than the first draft.

Languages with an interactive interpreter are also a huge advantage when you want to play around or experiment with your code. No need to create boilerplate classes, compile etc. before you can even (re)run a single test on your code.

By Tweakers user RobIII, donderdag 5 maart 2009 01:39

Nice and oh-so-true article. What you just explained is what I've been doing the past 10 years; I create test-cases, 'empty projects/solutions' and 'stripped down versions' for every brainfart all the way through the project I'm working on. And though to me and you this might seem natural, I know for a fact a lot of people in the business that don't or even won't use this approach. I never understand why; it makes your life oh-so-much easier. It takes some time to 'get used to' this approach but it almost always pays off.

Just today I created a blank C# solution because I needed to implement a "Left()"-alike function from VB.Net. Just to make sure behaviour was the same I created a console-app, wrote my code, called the function with all possible 'edge cases' and 'monkey proofed' it and pasted the..what...6 lines of code back in the main project :Y)

Even though, I work with Visual Studio Team System now and must admit I am slowly drifting away from this path. Very slowly, but I am. That is because of the awesome test-projects with unit tests VS allows you to set up; this also saves you a lot of time creating blank/new projects and allows one to blackbox test every aspect of a function.

By Tweakers user Niek.NET, donderdag 5 maart 2009 10:58

I've found that linqpad is an excellent addition to my dev environment. It is ideal for the workflow you're describing above.

Despite what the name implies, the application allows you to test any amount of code, not just dlinq statements.

By Tweakers user PrisonerOfPain, donderdag 5 maart 2009 15:27

I tend not to use these techniques for lower level development such as regular expressions or SQL statements, because most of the time I tend to get them right (due to the lack of complexity in most regular expressions I write) and I haven't used them that much recently.

However, larger more high level parts of the applications I work on are generally tested first outside of the project because it's easier and faster to debug (due to low overhead).

The most recent example was a cooperative multi-tasking scheduler; due to the nature of the beast it was quite difficult to debug within the original project. Other examples include file parsers and fooling around with floating point notation to perform mip-map level selection.

Most of the time I just create a simple new project in my IDE which end up getting named 'Foo1', 'Foo2' et cetera. There are specific tools available to assist in these kinds of things such as RegexBuddy and SnippetCompiler. Other things are the command-line applications for your database, or simply the command-line regular expression tools such as sed/awk.

[Comment edited on donderdag 5 maart 2009 15:28]

By Paul Krause, donderdag 5 maart 2009 18:22

Confusion, you seem to be somewhat unclear about what experimentation actually is. The techniques you describe in this posting cover a wide range of practices, which if undertaken all at once amount to no more than fiddling.

Experimentation requires a disciplined approach, where you change one thing at a time and then test it. That absolutely requires unit tests. And what's this garbage about unit tests requiring external frameworks? A unit test does not require any external frameworks. Any test that does is, by definition, not a unit test.

If your unit tests take too long to run, then they are worthless. Drop everything else and fix that first. If you don't, the dragon of complexity will overwhelm you sooner or later.

By Jeff Tucker, maandag 17 augustus 2009 20:34

This is an approach that I call "brute force and refactor." Just the act of coming up with the quickest, dirtiest solution tends to enable me to better visualize the problem and the solution and as I'm iterating through 12 nested loops, I start to see things that are unnecessary or just plain stupid. After that solution compiles, runs, and solves the problem, then I start removing things and "optimizing" the code (it's not really optimizing in most cases but it feels like it sometimes). Occasionally, I'll realize a better way to do something as I'm implementing my brute-force approach and I'll just scrap what I'm doing and re-write it. I usually do this within the app though so I like the approach of running through this process separately. If your code is well-written and losely coupled, isolating a particular part for a re-write usually isn't difficult. Also, when you mention unit tests that bootstrap all of spring and hibernate, those wouldn't be unit tests. Spring handles dependencies for you so when you're unit testing you should be either faking out those dependencies manually or mocking them somehow (as appropriate) or, best yet, eliminate them entirely. If you do have a test that needs to fire up hibernate and spring, it's an integration test and not a unit test. My definition of a unit test is something that tests a single part of the code in isolation to ensure that it correctly implements its side of the contract. An integration test tests a part of the system as a whole and ensures that the contracts themselves are correct and that the assumptions made by all sides of the contract are valid. Also, usually if an integration test fails, it will have a corresponding unit test failure.

By calvin, maandag 17 augustus 2009 22:02

this is exactly why I abandoned java long ago for python. experimentation in python is easy. easy experimentation means easier software iterations. ideas can be tested and explored and implemented much faster.

By Jerky, dinsdag 18 augustus 2009 00:42

In Eclipse I just set a debug breakpoint and evaluate snippets of experimental code in the "Display" view (or edit + re-save the class and let hotswap make the new version active). This gives you most of the "dynamic interpreted language" fast turnaround advantages.

By Funka!, dinsdag 18 augustus 2009 01:18

While I agree with the gist of this article, I do my "experimentation" for regexes in a wonderful program called RegExBuddy (a commercial product, but well worth the pittance of $) and for SQL, in either SSMS or linqpad (which was already mentioned in a comment above). These tools are even easier and faster to work with, in my opinion, than creating separate projects/programs... For anything/everything else, I'll put it into a Unit Test file, where it can remain a part of the project for longer than something "temporary." (But still lends itself to "experimentation" as needed.) I also use NUnit, which can be used to just run one single test if you like; doesn't require you to run the entire suite at once and can thus be very quick to use...

By Abhijith, dinsdag 18 augustus 2009 10:02

>If you aren't, stop reading, install Subversion and commit your code before continuining this article).
Your advice for using version control is a good one but the choice of version control is not.
Git is a better choice especially if you are developing individual pieces and integrating it with the rest of the code.

By Peter, dinsdag 18 augustus 2009 11:49

I will occasionally get carried away in Ruby finding out how few lines of code I can put a certain bit into, when I had just started out trying to find a method that wasn't incredibly lengthy. It can get pretty ridiculous, because most things can be done in one line if you REALLY try.

By René, dinsdag 18 augustus 2009 18:56

Strongly agree with calvin, specially having an interactive mode (just firing up the python interpreter and typing stuff in command line) is a great thing!

This might apply to a bunch of similar tools (with interactive and batch like mode). It does make a big difference against a complex setup like in only using a 'full' (code to .exe) compiler tool.

This makes my code great quality since I start... wanting to test a regular expression? No problem, use the interactive interpreter.

Want to test a module? No problem, run the module in 'stand alone', as main module, then then the 'if __name__ == '__main__' quick test code will test your functions.

By Tom, woensdag 19 augustus 2009 19:49

Offcourse using test driven design, you can formalize the whole experiment-process. Using a good test framework you can test just the things under consideration. (Your sql query, regex, etc)

In the end you have much added value from your experiments in the future, because as a test they verify the correctness of your changes. (My changes did not break anything else etc...)


By tayab, dinsdag 13 maart 2012 16:44

You got a really useful blog I have been here reading for about an hour. I am a newbie and your success is very much an inspiration for me.Shop Vac

By shona628, dinsdag 13 maart 2012 22:47

Hi, just wanted to say I attended this conference last year, and found it by far the best of about 8 conferences that I attended in the field. Full of professional insight based on testing by experts that knew what they were talking about. I would certainly go again and recommend it to anyone operating in this field.
free vectors

By tayyba, donderdag 15 maart 2012 15:05

Hello, great job! I did not expect this on Wednesday. This is agreat post. Thanks!
keylogger hardware

By shona628, dinsdag 20 maart 2012 18:05

I am taken appropriate good I came upon this web page.
search engine optimization az

By ddddd, vrijdag 23 maart 2012 15:29

great to get some tactics on how to prevent this from happening.
Escorts Paris

By hfkhgl., zondag 25 maart 2012 12:40

Great job. Well with your permission allow me to grab your rss feed to keep up to date with incoming post. Thanks a million and please keep up the delightful work.
Garrett Metal Detectors

Comments are closed