Lately I see a lot of talk about Code Coverage even at some places where managers just want to get the job done however messy it is. Personally I think that Code Coverage like many other alike tools (style guidelines, code metrics etc) are only Manager's Gimmicks allowing them to put a check mark on an item and if checked they can feel good about them.
Let's face it developing Software is a complex, difficult and time consuming endeavor that needs excellent developers to make it work. And because of that many Managers feel to be out of control and so they want to be more in control by measuring the software because they are not able to evaluate the code by themselves and they don't want to rely on their staff.
Unfortunately tools are not able to understand an entire project and so their measurement is a close up view rather than a birds eye view. Even I don't know how good code is until I evaluated pieces of it or ran into severe problems. That does not mean that I don't have a gut feeling pretty early on about it and so far that feeling was quite often right on the money. When I design and write code I don't know if that code is good or not because there are so many inside and outside factors which I can't control. That said I follow my personal principles, I am not afraid to ripe code apart to clean it up and will write some test cases. My design and code is in my view validated when requests for changes can be implemented easily and without a lot of side effects.
Now my personal principles are (in no particular order):
Let me elaborate a little bit on these items. The layering is important to make sure that we humans can manage code and can rearrange code if necessary. For example in a project developers added DAO classes inside the Entities in order to create rich domain models. I don't mind the rich domain model but I don't like to have them inside an Entity which purposes is to map to a DB table record. This makes it impossible to extract the Entities into their own modules because they are going to be used in multiple modules. This also makes the code more complicated because a method call to an Entity can lead to a slur of other DAO and Entities calls and maybe even more calls because DAO may call other classes as well. Finally it also makes it difficult to deal with multiple Entities on the same table to deal with the amount of data retrieved.
KISS means that developers should not outsmart themselves and others. When code gets to complicated it is time to refactor and to make sure that method represent a particular task. For example I had to deal with a method that used dynamic HQL generation in order to search for certain records which is called by many different places in the code. A slight change made it necessary to test half of the application. That piece was soft badly written that it even contained dead code.
Refactoring should be a constant task of every developer. If code grows it becomes more and more difficult to do so it should be tackled right away.
Enclosing data in meaningful object makes it possible to keep changes localized rather than have to change many method signatures and algorithms. For example I created a criteria object for entity searches. Any change in the how searches where done was localized to where the object was created and when it was used. If I would have used Query by Example then I would have to change many classes and method signatures.
Well, a big part of my daily tasks is to look at other people's code and try to understand and then fix it. Inside that code I see fairly easily the history on how the code came about and why it ended up this way. More often than not developers who had to fix a bug or enhance it just made what they were asked to making the code a little bit uglier in the process. When I have to fix a problem is use the invested time to refactor and simplify the code in the process so that I and other can profit in the future. Quite often a bug is merely a symptom rather than the actual cause and fixing just the bug will not elevate the underlying cause.
Unit tests are great if they cover a lot of code. Therefore they should perform a high level task rather than just testing a single method. Any developer which needs a unit test for a simple method should look for another job. This will also increase the chance to catch a regression bug because it tests also the interaction of various methods and classes.
Finally my most dearest point which leads to a lot of heated discussion and dismissals but over and over I am vindicated in the long haul. Laziness is great but only if done with respect on the long haul. Short term gain have to be paid in the long haul, always. For example the Query by Example mentioned above is nice but it will cause troubles and should not be used in production code. An Entity just contains the attributes and so it cannot cover stuff like search parts of a string, between values, search values outside the entity and so on. But even if you can make it work it is hard to read because the method signature is not expressive. For example MyEntity do( MyEntity entity ) is not the same as MyEntity search( MyEntityCriteria criteria ). No we could change the naming but if the code has to be decompiled that info is gone. Another thing is Spring's Autowired annotation. There are several things that I don't like. First it makes testing uglier because the linking is already done and the only way to fix it is to write your own test spring configuration which may lead to problems if that one is not keep in sync with the regular one. In addition it does not show the dependencies in the spring configuration file leading to many runtime failures because of missing or duplicate dependencies.
I am pretty sure that I follow more principles but these are the one that pop up in my head first and are the ones that lead to the most problems. In any case quality is not achieve easily and Manager should invest in their developers rather than tools and processes.
Don't forget: Great Software is developer by a handful of Great Developers
-Andy