Tuesday, December 20, 2011

Constant Pain with Non-Constant Constants

This thought has crossed my mind before... since it is on my mind now I thought I might share. Perhaps it will help someone on their software development career path... or perhaps it is just me venting...

The Art of Coding


One of the greatest challenges of coding is being able to understand it. Skill in coding is being able to understand the problem well enough to create a solution (otherwise known as coding). Great Skill is being able to write a solution so that someone else (including the future you) can read and understand what it is they are looking at. This concept isn't new, but yet we seem to be either challenged with the concept... or distracted. Even back in 1952 (yes 1952!!), in the computer history archive a set of lecture notes which in them states: "It is quite difficult to decipher coded programs even with notes and even if you yourself made the program several months ago." It also states: "I think the answer is simple: to make it easy one must make coding comprehensible". Well said!

The Point of Constants


One area that seems to be a constant :) struggle is constants. There are at least a couple of justifications for using constants I can think of: 1) a point of reference for tools (autocomplete with intellisense in IDEs and refactoring), 2) A common holder of value for which if it changes will be realized across the system. The main point of a constant isn't DRY or reuse... a common point of confusion for some reason.

IMO the stronger argument is point 2. if you were coding in VI or emacs, point 1 may not be of value, but point 2 certainly would be. If you name the reference of a constant the same name as the value of the constant... then you lose any the value of point 2.
It must also be said that constants, although they add value, they make code less readable (see examples below). If your constants have no value, they don't achieve points 1 and 2, then they need to be whacked!


Examples of Losing with Constants


This is real production code... some variables changed to obscure identify.


// example 1 Really?? where does this end?
String EMPTY_STRING = "";

// this isn't readable... it takes minutes (instead of seconds) to understand its value
// example 2
String ADVERTISE_PROPERTY_PREFIX = OUR_PROPERTY_PREFIX + "advertise.";
String ADVERTISE_TRADER_ADDRESS_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "host";
String ADVERTISE_CONTEXT_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "context";
String ADVERTISE_TYPE_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "type";

// example 3
// here's a common one
static final String TABLE_NAME = "email";

// Column names for all the fields in the email table
static final String ID = TABLE_NAME + ".email_id";
static final String CUSTOMER_ID = TABLE_NAME + ".customer_id";
static final String ADDRESS = TABLE_NAME + ".address";
// ...
static final String FIELDS = ID + ", " + CUSTOMER_ID + ", " + ADDRESS + ", " + CREATED_BY + ", " + LAST_MOD_BY
+ ", " + CREATE_DATE + ", " + LAST_MOD_DATE + ", " + TERM_DATE + ", " + WEB_USER_ID;

// List of fields names with formatting used for select statements
static final String SELECT_FIELDS = ID + ", " + CUSTOMER_ID + ", " + ADDRESS + ", " + CREATED_BY + ", "
+ LAST_MOD_BY + ", " + "TO_CHAR(" + CREATE_DATE + ",'" + DATE_TIME_FORMAT + "')," + "TO_CHAR("
+ LAST_MOD_DATE + ",'" + DATE_TIME_FORMAT + "')," + "TO_CHAR(" + TERM_DATE + ",'" + DATE_TIME_FORMAT
+ "')," + WEB_USER_ID;

// SQL used to create a new EMAIL record
static final String CREATE_SQL = "INSERT INTO " + TABLE_NAME + " (" + FIELDS
+ ") VALUES (?,?,?,?,?,SYSDATE,SYSDATE,NULL,?)";

// SQL used to retrieve an email record by id
static final String RETRIEVE_BY_ID_SQL = "SELECT " + SELECT_FIELDS + " FROM " + TABLE_NAME + " WHERE " + TERM_DATE
+ " IS NULL AND " + ID + "=?";


For example 1... where does it end? would you create a constant A = "A"? When can EMPTY_STRING not be an empty string or ""? In this case, we get no value and less readability.

Example 2 is the chaining of constants, commonly found when there are a large number of property values being retrieved from a file or sys env. While not as bad as example 1, it is less readable. Having a prefix constant may be of value, but rarely is the chaining of constants of value. It isn't worth trading the potential for a company name change or something similar for readability. Or put another way, it isn't worth trading something that is unlikely to happen for something else which is more likely to be needed (that being the readability of the code)

Example 3 I see all the time... argghhhhh... please... just stop!

Examples of good constants would include, urls and database connections strings or a project defined standard date format.

May your constants always be final!

Wednesday, December 14, 2011

Advanced Spock Techniques



In recent years there have been a couple of tools that stand out when it comes to helping me be productive. One of those is the groovy test framework Spock. It is worthy of an introductory blog post... but that isn't this post. One of the challenges to Spock is the documentation isn't a complete as one would hope. The Spock Basics is fantastic when getting started but it is what it claims to be basics. I've been speaking with NFJS on the subject of Spock for the last half of 2011. On 2 occasions I've had the look our red shirted friend in the picture has when asked about controlling aspects of mocks in spock... meaning I didn't have the answer. In this case, google didn't discover it either... a quick email to the Peter Niederwieser reveals the previously undocumented solution. (at least that's my understanding)... and thanks Peter!



Here we will discuss 2 advanced aspects of mocking with spock. If you need more details on mocking in general hit the Spock site... or wait patiently for a future post:)

Problem Setup:

When mocking with Groovy we get 2 benefits from the verification of the mock. 1) order of execution, 2) failure if another method on the mock was executed but was not setup in the demand configuration.



void testDeposit() {

Account account = new Account(TEST_ACCOUNT_NO, 100)

def mock = new MockFor(AccountDao)
mock.demand.findAccount(TEST_ACCOUNT_NO) { account }
mock.demand.updateAccount(account) { assertEquals 150, account.balance }

def dao = mock.proxyDelegateInstance()
def service = new AccountServiceImpl(dao)

service.deposit TEST_ACCOUNT_NO, 50
mock.verify dao
}


Spock Cleanup


A similar solution in Spock might look like this:

def "deposit into account test refactor"() {

def mock = Mock(AccountDao)
def service = new AccountServiceImpl(mock)

when:
service.deposit nmr, amt

then:
mock.findAccount(_) >> account
1 * mock.updateAccount(_)
0 * mock.createAccount(_)

and:
account.balance == total

where:
nmr | account | amt | total
"101" | new Account("101", 100) | 50 | 150
"101" | new Account("101", 0) | 50 | 50
}


However this solution doesn't guarantee order nor do we want to use the 0 * mock. on all possible methods.

Spock Mock Solution


It turns out that we can repeatedly use the then: dsl to determine the order of events. So we can modify the Spock code above with the following changes.


then:
1 * mock.findAccount("1234") >> account

then:
_ * mock.updateAccount(_)

In this case we are saying that the findAccount() method will be called exactly once and return the account object and "then" the updateAccount will be call any number of times with any type of argument. The test will fail if the updateAccount is ever called prior to the findAccount being invoked first.

We can use this same technique to solve the strictness concern we have as well by adding one more then: block of code as outlined below:

then:
1 * mock.findAccount("1234") >> account

then:
_ * mock.updateAccount(_)

then:
0 * mock._

In this case the last 0 * mock._ says to expect nothing else. Ahhh.. the beauties of a dynamic language:)

Happy Coding... may your builds never fail and your tests always green bar!