There are a few important principles to follow when writing code. The one I will talk about today is the DRY principle. DRY stands for Don’t Repeat Yourself. What does that mean in code then? Basically it means that you should never duplicate code. If you do the same thing in two different places then break that functionality out into a function.
Why you might wonder?
Consider this:
You have three places where the exact code is used and you realize that you want to do something subtly different. So you go about changing the code. But, you forget to change the code in one place. You go on coding and then the test section tells you that “the results are inconsistent, in places XXX, YYY happens but in place ZZZ, AAA happens”. This might be hard to find later. Besides, when you want to change anything you have to do it in multiple places.
A real life example of this that I quite recently encountered in a project I took over:
dateCreated.ToString("yyyy-MM-dd HH:mm")
That line was scattered all over the place. It also turned out that the hours (HH) was written as 12 hour clock in some places and 24 hour clock in others. A very simple thing, hh (12 hours) instead of HH (24 hours). It still took me a while to track that down as everything looked fine (I also didn’t catch on to the small/capital letters until after a while). What I did was breaking the string out into a function like so:
private string GetDateFormat() { return "yyyy-MM-dd HH:mm"; }
and then used like this:
dateCreated.ToString(GetDateFormat())
Yes, I realize that this could be made in a lot of other ways, this sufficed for me though.
So, the benefit here is that I can change in one place instead of a lot, it also gets easier to read.
This was a very simple example but I think it shows pretty well the point I try to make. When developing new code, always try to follow the DRY principle.
What about the DAMP principle then?
DAMP stands for “descriptive and meaningful phrases” and is the opposite of DRY, not in the sense that it says “everything should look like a trash heap and be impossible to read”, in that readability is more important than avoiding redundant code.
What does this mean and where to use it?
DAMP mostly applies when writing test code. Test code should be very easy to understand to the point that some redundancy is acceptable.
In my previous blogpost I showed how to unit test in Ruby using Test::Unit and I had the following code:
def test_2_inserted_return_true prime_generator = PrimeCalc.new actual = prime_generator.is_prime?(2) assert_equal(true, actual) end def test_7_inserted_return_true prime_generator = PrimeCalc.new actual = prime_generator.is_prime?(7) assert_equal(true, actual) end def test_13_inserted_return_true prime_generator = PrimeCalc.new actual = prime_generator.is_prime?(13) assert_equal(true, actual) end
There are a few ways of doing this that is more DRY which I’ll show you first.
def test_that_the_first_few_primes_are_detected_as_prime [2, 3, 5, 7, 11, 13, 17].each do |p| assert @primality_tester.prime?(p) end end
Since there is no real difference in what is tested (except that the input value should be different) we could do this. A loop that asserts that the values inserted are prime.
The question is which is more descriptive of the above and the below however. It depends on the number of values to be tested I’d say.
def test_that_2_is_detected_as_prime assert @primality_tester.prime?(2) end def test_that_7_is_detected_as_prime assert @primality_tester.prime?(7) end def test_that_13_is_detected_as_prime assert @primality_tester.prime?(13) end
Note: There has been a few refactorings made as you can see. The class is created in the setup part, we do the method call in the assert and since we want to check truth values assert is used instead as it passes if it receives true.
[…] Readability is more important than avoiding redundant code. […]