Agile Zone is brought to you in partnership with:

Ivo has posted 2 posts at DZone. View Full User Profile

Writing good code requires you to perform experiments

03.05.2009
| 11495 views |
  • submit to reddit

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.


References
Published at DZone with permission of its author, Ivo Wever. (source)

(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.

Dimitri Missoh 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.

Mladen Girazovski replied on Fri, 2009/03/06 - 4:23am

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.

 Experiment:

  • the act of conducting a controlled test or investigation

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.

 

 

Jason Kilgrow replied on Fri, 2009/03/06 - 8:22am

Huh. I do this all the time. Actually, I can't imagine doing it the other way (just whip the code you want to try into your project). If it is something that I'm not absolutely certain how to do, I write the code outside of my project or in a class with a main method or inside of a junit test or something that I can run over and over again without running my whole project. It works great!

Bobby Hargett replied on Fri, 2009/03/06 - 8:50am

Ahhh, I used to do that all the time in my younger days, I don't understand why I have moved away from it. Maybe this will renew that old fire.

Franz Wong 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.

Witold Szczerba 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.

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.

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.

Ivo Wever 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.

 

Mladen Girazovski replied on Sun, 2009/03/08 - 1:02pm in response to: Ivo Wever

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.

 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. 

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.

 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.

 

 

 

Witold Szczerba replied on Sun, 2009/03/08 - 1:03pm in response to: Ivo Wever

You misunderstand the intention of the separate class/project: it's something you throw away after you are done.

Of course this is something you throw away. How did you manage to think I misunderstood that?

Ivo Wever replied on Mon, 2009/03/09 - 3:36am in response to: Witold Szczerba

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.

 

 

john green green replied on Fri, 2009/11/27 - 12:02pm

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.
nike china shoes

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.