It happened quickly, I didn't even notice.
One day I was merrily strncpy'ing and the next it was immutable.
We joke about languages of old while new shinny languages are paraded in front of us, but in the end they all teach us something and make us forget other things.
Today I came across the first serious change that the Java world thrust upon my weak mind. I am working a Ruby project, a great new shinny language which is lots of fun to learn and work with.
When working in Java I use the usual Agile development process; write your test, write some code and repeat. As I progress, my code, and indeed the API design, evolve into a nice usable, stable set of libraries.
Working in Java, with Eclipse, the simplest technique is to start by writing your test, reference a public method, press a key to create it and flush out the implementation. As you go, you will naturally refactor pieces of code into new methods to keep it simple.
Well, this is where things get a little too easy for Java developers in Eclipse. To refactor a block of code into a new method just select it, press a couple of keys and Eclipse creates the new method for you. A new private method in the same class.
Sounds good right? Well it is, except, that you have now learned to not thing about the scoping your your methods when you create them. Your first is always public or protected because your test is driving it and subsequent methods are private by default as created by the IDE. It's a beautiful system.
Now you switch to Ruby.
You write your test and implement your public method, you refactor with the cut/paste/rename/suffle and low and behold, because you have learned not to think about it, you have loads of public methods in your class.
The project I am working on takes it one step further and has tests for every method, examining all its nuances, mocking all its dependencies and going to town making the implementation as couple to the test as possible. It's easy to do, they are all public, what else is a programmer to do?
Unit testing philosophy does vary depending on who you talk to but my basic goal is to:
- Test all public methods,
- Test all protected methods,
- If a private method is particularly complex make it protected and test it,
- If I have loads of "untested" private methods I need to move some to new classes and make them public. I leave it to you to quantify "loads".
- Trust your coverage tool to tell you the private code you never use and delete it.
So, starting tomorrow, I change my Ruby development process and consider all new methods private unless part of a test driven process. This will do lots of things to improve the final product:
- Simplify the test/code dependencies making the tests less brittle.
- Prevent call sequence bugs where you have to call one method before another or it all falls over. Too many publics will do that you know.
- Make the calling conventions exposed by the class easier to grok by new programmers reading the code.
- Improve Class API design which is one of the primary benefits of TDD, lost to the lazy public manic people like me.
Oh, yes, an stop putting java semicolons in Ruby code. That really upsets the Ruby people.