Moin Moin,
in an earlier post (PHPUnit - testing PHP apps) I was posting the assumption, that I am a bad programmer. The reasons therefor has been the fact, that I don’t (unit) test the software I write. Is it still true? … Kind of!
Actually I did some steps in the direction to improve the quality of the code I write. The best thing to do at first is to ask people from whom I think they can help. The topic was “Testing”. I was speaking with Arne Blankerts about that and he offered his help during some nice evenings eating Tapas, drinking beer and speaking theoretically about OOP and Testing.
The decision was clear on one hand. I have to test my software / my code. On the other side - what does it help if I am the only one who is doing it while working on an app. And how do I convince my co-worker, that we have to test. I knew that it will become a challenge. And now, after some weeks … I am the only one who is testing. Hey wtf! But step by step.
How testing does not work
I like to make little jokes about Java. And yes I will continue. Not only because of the fact, that other people are making jokes about PHP. I think the programming language is at a minimum responsible for bad written code. It is the pressure to get a project as fast as possible done, the money aspect and finally the hacker who is coding the software. You can write real bad code in PHP - but you can also do that in Java, C, Perl, Ruby, Python and so on. So let’s go on with making jokes because it’s just a game and makes the day funny.
In our company, we have some guys programming a real cool e-marketing software in Java. Markus Wolf is the team leader and knows a lot about testing. I asked him if he would write some slides for an in house training about testing. Some days later we sat together and he explained the principles about testing. Afterwards we went over to the practical part and ‘tried’ to write the first tests for our software eUNIQUE. We are using ZEND Framework and it’s features - e.g the Registry pattern. Uhu - first mistake because hard to test. So we sat together for about three hours with the result of writing one test for one method. We were (and I am still) using PHPUnit. That’s testing? Simulating millions of objects (mock objects), including a whole framework, writing many lines to be able to write one $this->assertEquals(blabla, blub)? C’mon!
So what went wrong? Nothing at all! Really! Because the result, and more important the conclusion of our efforts were simple: the code is written as it is not easily testable. That means - the code is bad! And I am a bad programmer! That was what I was feeling. I had to change that.
First step to be able to test
I don’t like if others think I am a bad programmer. Would you like that? No! But what is even worse - I don’t like that I think I am a bad programmer. I had to change that. I had to change this situation not being happy and satisfied with my work. So my decision was to learn how to write better (cleaner) code.
When we were having holidays with friends in Denmark, I was reading Martin Fowlers book “Refactoring”. This is a real good book. During reading I often thought - yeah - this is the way it should be and man, you did stuff like that already without really knowing, that it is called refactoring. Maybe because of that fact, it was fun to read the book.
Beside that book I was reading Kent Becks “Test Driven Development” what was good also, but not that what I will be able to do. One aspect not being able to develop in TDD mode is the fact, that learning TDD is a bigger effort than writing Unit Tests after the production code is written (I come to that point later) and that a lot of code I work with is already written. But anyway - the book showed a real good concept and brought a lot of ideas. I will surely read it again.
And a third one: Robert C. Martin’s “Clean Code”. This book rocks! Everything you ever wanted to read about how to write a give names to variables, functions, classes, how to write functions and classes, how to comment your code, how to built a system and so on - it’s in this book. Maybe I like this one most.
The essence of these books (and the list is by no means finished) is the following:
How do I write code which is clean, well structured and testable?
Believe me - it’s a challange to reach that goal. A lot of experience is needed to be able to say: I can write clean code (the authors of the books have decades of experience). I am in the process of starting to write clean code (to all my future entrepreneur’s: this is a sign for a good programmer: interest of becoming better and willing to work on it!). And it’s a lot of fun and gives a lot of secureness.
The first step to be able to test code is refactoring. The situation I was speaking of a little before is a good example. The problems in our code are coupling and dependencies. One big target of refactoring is decoupling and less dependencies (if needed you want to use dependency injection). But shall I now write everything new or leave it like it is? Both is wrong! There are some examples in software history that companys died because they thought the only way to get better code is to write everything new. The problem: all the experience, the bugs and their fixes are gone. Writing the software means new bugs and no experience.
Leaving the code like it is also a bad idea. So in this situation I like Martin Fowlers view: refactor all the time in little steps. If looking to older code to understand what the code is doing (this is over 70% of what a programmer is doing each day) and if finding stuff which could be written better, do it. The idea is to find a good tradeoff between effort/time for doing it and the things you have been inteded to do when you hit this part of your code. If you have the feeling that it will take too long and it is too complicated to refactor the code part now, don’t do it right now.
More important is what to do with new code. I decided to make a cut. Now if I write code for a specific functionality:
- I check if the object(s) I created are well designed
- I check if the methods are doing only one thing and are small enough
- If not I refactor
- If the object (or some dependent objects) are finished I write tests for them
- If tests fail or code (a method) is not testable, I refactor until I can run the test and I have a green bar (or no errors on the shell)
It’s as simple as this. Since I do this, the results are tremendous! I feel much more comfortable because the code is much better readable, easier and at least better.
So my conclusion and learning process was to understand, that reliable and good software needs to be unit tested. This is for sure not the only point to reach the target of good software but a fundamental one. I want to encourage every hacker to follow this target and tell im: fuckin’ test your code!
(this post is two months old and was not published because I wanted edit it later. After reading it I thought it’s worth publishing it …)