Writing good code requires you to perform experiments
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.
- Login or register to post comments
- 5698 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)










Comments
Artur Biesiadowski replied on Thu, 2009/03/05 - 11:42am
For me, hotswap is the most obvious and easy solution. Put the code you are not sure about in proper place, run given component in debug and hack around. In eclipse, just saving a file is enough to get it done. As an extra benefit, you already have debugger running if there is some non-obvious behaviour you want to investigate.
I'm most often using separate experiments for micro benchmarks and in few unfortunate cases where I had to run native parts on platform I had no development environment on.
dmissoh replied on Thu, 2009/03/05 - 2:53pm
Hi Ivo,
thank you for your post. I'am totally agree with you. Although writting a unit test before starting with the real implementation is a good practice, it turns out that experimenting is the best way I have to learn about the API or the programming language I currently use. I is also the best way (for me) to find alternative solution, sometimes better, sometime worst for any kind of problem. Experimenting do not necessarily leads you to write better code but has first of all a didactic effect. So be creative, keep experimenting.
mgira replied on Fri, 2009/03/06 - 4:23am
Experiment:
Whitout a proper test, you are not Experimenting.
Since you are talking about starting a Spring-Hibernate App for Unittesting you are clearly talking about Integrationtests, not Developer Unittests.
I suggest you try it with a developer test, you'll be much faster than by trying to verify your results in a non-automated way.
jkilgrow replied on Fri, 2009/03/06 - 8:22am
bhargett replied on Fri, 2009/03/06 - 8:50am
franzwong replied on Fri, 2009/03/06 - 10:23pm
I also do that. Therefore, I always open 2 instances of eclipse, 1 for performing experiment. I open new project if the experiment does not have great dependency to the original project.
May be I also have to learn how to use the "branch" feature for SVN. I am not familiar with this.
witoldsz replied on Sat, 2009/03/07 - 6:50am
Are you guys serious? You really test something using separate project or class and when it works you copy'n paste? What if one has to change it? Is he or she going to create yet another project or class, copy'n paste, change it, test and copy'n paste it back? What if his or her tests did not take the case you did and new feature works and old ones are now broken? When you test something, it has to stay in project and become a part of a test suite which can be invoked any time anyone wants to see if everything still works.
You say "unit test" but you talk about something else. Unit tests are all about running piece of code (the code under the test) in isolation. That means, when you want to write unit test to test your little, tiny piece of code, for example your regex, then there is nothing else your test should cover or execute.To make that possible you can use stubs, mocks or anything else you find useful. When your test environment is really hard to create or it is fragile or it takes many lines of code - that is the clear sign your code is a mess. If that is the case you have to find out what is wrong with your code. When you discover it and resolve the root cause, you will find writing real unit tests easy, but what is really great is the quality of your project will become much better.
Confusion09 replied on Sun, 2009/03/08 - 11:47am
@mgira
If you were already planning to write a unit test for the thing you are experimenting with, then you can indeed use the unit test. However, you usually don't have a seperate unit test that tests a regex: you have a test for a method that uses the regex. From the failure of a test, it may not be immediately clear that the regex is at fault.
Now about the difference between unit tests and integration tests: there is a grey area in between them. If I test my Hibernate DAO's, I used Spring's AbstractTransactionalSpringContextTests to make sure the database doesn't change. This requires some bootstrapping and that can take some time. Moreover, multiple tests are run in each unit test class and that again takes more time than is necessary to get your sql to be correct. Strictly speaking, it would be an integration test, but effectively, it's a unit test.
@witoldz
You misunderstand the intention of the seperate class/project: it's something you throw away after you are done.
mgira replied on Sun, 2009/03/08 - 1:02pm
in response to: Confusion09
Well, i see your point, however, it could be easier to create a test Method on the fly and have an assertXXX() in there for the regex or some other small experiment.
At the end it boils down to the same: Testing some small piece of code out of context. I prefer a unittest (developertest), but this is a matter of personal choice.
Kent Beck even suggests to learn a new framework by writing unittests (developertests) for its public API. Sounds funny in the beginning, but if you think about it, when learning a new framework/API this is exactly what you always do: You test its features, so you could as well do it as an unit test and use its buildin support for assertions.
I agree, using a DB in a test is an integrationtest rather than a developertest, but since you do not need to bring up the whole context but just the DB and the ORM instead, it's not a "full" (for whatever that means) integrationtest.
I use DBUnit for my DAO Tests in the "Backdoor Manipulation" fashion: http://xunitpatterns.com/Back%20Door%20Manipulation.html
I do not create a Spring Context for my DAO tests, because i think not nessecary and it keeps my tests simplier.
For tests in the business tier i use plain developertests, again without a Spring context.
witoldsz replied on Sun, 2009/03/08 - 1:03pm
in response to: Confusion09
Of course this is something you throw away. How did you manage to think I misunderstood that?
Confusion09 replied on Mon, 2009/03/09 - 3:36am
in response to: witoldsz
Then I do not understand your earlier comment. There is no need to copy-paste code for every change: this is about specific changes that can benefit from some quick experimentation outside of the project. Of course your code has to pass all unit tests and you have to provide new ones for it. In fact, on one occasion I even wrote the unit test in this fashion, so I wasn't delayed by the execution of the other 15 tests, where nothing was changing.
m vaganek replied on Fri, 2009/03/13 - 6:48pm
This post is absolutely correct. While unit testing is good, and testing 'in situ' (in context of the project) is good and necessary, there is a huge value in isolating a piece of logic/code and testing it and experimenting until it is well understood and correct.
One of the primary advantages of so doing is that it will make all the dependencies very explicit. Implicit and non-obvious dependencies are a major source of software instability.
Unit testing tools, ide's, frameworks, etc are all good and I use them all, but when I need to really understand how something unfamiliar works, or when I just want to be able to re-use it and rely on it, I build it as standalone as possible.
There is nothing magic about JUnit, Ecplise, Spring, or whatever. They cannot do your thinking for you. If you cannot isolate and identify the dependencies and work with something in a lightweight fashion, you are just adding entropy to your project.