Monday, November 19, 2007

Detestable long methods

Some people like long methods. Some do not like them. Personally I belong to the latter category. But that does not really matter here. Most discussions around the subject fall back on some vague aesthetic arguments. Usually it ends in some variant of “I like to see what happens” vs “I think we should build nice abstractions”. It is always nice to try to fall back onto something measurable.

Even if I might not make it all the way to strict mathematical scientific precision, I want to throw in an argument that is just a little bit less fuzzy. Let’s talk about test, baby …

Say that we have a decently long method. Probably it will take care of a few things, taking responsibility of A, B and C. This could be respectively validating some data, doing the right thing on validation error and processing it in different ways. For each of these we have a few different variants (m,n, resp p).

To test this code we need to create a test for every path through the method. As we have m alternatives for A, n alternatives for B, and p alternatives for C we will probably need about m*n*p tests. This is roughly the same as the cyclomatic complexity.

Now, let’s do some refactoring. Responsibility A is split out to a method of its own, B to a method of its own, and C likewise. What remains is of course the same old method as before, but it now just consists of a few calls to a(), b(), and c().

To test a() in isolation we will need about m different test cases. To test b() we need n, and to test c() we need p. Then we need a test that puts them all together and covers the (previously) long method. Might take a few, but say one for simplicity. In total we need m+n+p+1 tests for full coverage.

So, by separation of concerns we have limited the number of test cases for full path coverage from m*n*p to m+n+p, which probably is drastically less. Put another way: our refactoring imploded the combinatorial explosion into linear space.

Ok, agreed that the analysis is a bit rough and not really rigid; but I think the general idea holds. If someone wants to elaborate to an example and do a strict analysis, let me know.

As for “detestable” I like to give the credit to the unknown person of the Denver JUG (if I’m not misinformed) who coined the expression: darn good job.

Friday, November 16, 2007

What is wrong with public fields?

Public fields are bad for your OO. If your datafields are public anyone can do
dansaccount.balance = dansaccount.balance - 4711; which would be pretty disastrous for my private economy.

Instead we protect our data by wrapping them in getters/setters, which enable us to do
dansaccount.setBalance(dansaccount.getBalance() - 4711); which is equally as disastrous to my economy.

If we claim to encapsulate our data and provide set/get, we could equally well use public fields to me. The only difference is forcing us to a really non-intuitive syntax of assignment: security through obscurity in other words.

Of course public fields are bad OO, we just have to know why.

The interesting part is not encapsulation of data, it is encapsulation of behaviour. Let us have a look around our system and see at how many places our data is interpreted in a non-trivial way. Probably we will find a few places where a string is interpreted as an order-number and a non-trivial format is enforced. If that logic (might just be one line of code) is spread out through the system, it does not matter how well you protect your data with setters, you have bad encapsulation anyway.

What bad encapsulation leads to is most of the time duplicated functionality, i e same functionality written at several places, because the programmer did not find the first implementation. Note that this does not necessarily mean duplicated code, the order-number check might be rewritten slightly different every time.

So, public fields are bad, but not in a way that get/set solves.

Wednesday, November 14, 2007

Betawave interference

Betawaves: brainwaves related to learning, and rest

Interference: the process of someone deducing something; also patterns that that emerge when the waves from two sources meet each other; also something getting in the way, causing a disturbance

In other words betawave inference might be what happen when my thoughts are picked up by you, are put on top of your experience and new insights are born. Or perhaps I just want to disrupt your brain.