Skip to content

Refactoring to remove code duplication using the strategy pattern

October 29, 2014

The strategy pattern‘s main benefit is often stated as being that it provides the ability to essentially swap out parts of an algorithm’s behaviour at runtime. There is another use however that may be deemed overkill and that is simply to get rid of duplicate code.

Consider the following two methods, each with DO A STUFF and DO B STUFF as identical lines of code.

public void foo() {
  // do A stuff
  fooSpecificSection();
  // do B stuff
}
public void bar() {
  // do A stuff
  barSpecificSection();
  // do B stuff
}

How can we refactor the offending abomination to get rid of the duplication? There are a number of techniques, one way is simply to use simple control flow statements (switch, if) as suggested in the following excellent overview of the strategy pattern. So we would have the following for example.

enum Action {FOO, BAR}
public void fooBar(Action action) {
  // do A stuff
  switch(action) {
    case FOO:
      fooSpecificSection();
      break;
    case BAR:
      barSpecificSection();
      break;
    default:
      throw new IllegalArgumentException();
      break;
   }
   // do B stuff
}

As you can see from the above, depending on the number of lines of code in DO A STUFF and DO B STUFF we might not actually have reduced our total lines of code (TLOC) but we would almost certainly have made maintenance easier and less error-prone since our two cited sections of potentially intentionally identical code are no longer duplicated.

If we where to use the strategy pattern to get rid of the duplication in Java 7 we would end up defining a one method interface and an anonymous inner class as has been neatly illustrated here. In the simplest possible case our interface will effectively just be a function pointer, as is shown below.

interface Action {
  void execute();
}
private template(Action action) {
  // do A stuff
  action.execute();
  // do B stuff
}
public void foo() {
  template(new Action() {
    @Override
    public void execute() {
      fooSpecificSection();
    }});
}
public void bar() {
  template(new Action() {
    @Override
    public void execute() {
      barSpecificSection();
    }});
}

Arguably the solution shown directly above is more convoluted, however consider that the main reason for this is because of Java 7’s poor support for function pointers in the foo() and bar() methods.   This may no longer be an issue with Java 8 with the introduction of method references.

Berkeley DB Java Edition – Gotcha Log

October 17, 2014
tags:

This post is simply a log of Berkeley DB burns or gotchas written as rules to be remembered. The post will be updated as time goes by.

1. Don’t just change your enum constants willy-nilly and deploy

If you are in development mode, running your app on your local lightweight container, then this one is easy to forget. Its good to get into the habit of having a staging environment with Berkeley DB in write-to-disk mode, even on your local, so that you can occasionally get burnt by Exceptions such as this one and so remember it.

java.lang.IllegalArgumentException: Deletion and renaming of enum values is not supported: STANDARD

at com.sleepycat.persist.impl.EnumFormat.initValues(EnumFormat.java:93)

Software Vendor Marketecture – Ruling The Roost?

October 10, 2014

Skyscrapers don’t get built with one pagers, and neither should software, no wonder our software skyscrapers often degrade to sprawling horizontal shanty towns.

If you are a stakeholders in a large scale enterprise development project, and all you have in terms the presented software architecture viewpoint documentation is the one page Marketecture diagram used to sell the solution you are in deep trouble.

This is one of the fundamental problems with the software industry, projects often kick off with specifications that are nothing but Marketecture and so nothing close to a Software Architecture Document (SAD). Marketecture is without a doubt valuable, but it is not the same thing as a SAD and not the hallmark of an engineering discipline. Skyscrapers don’t get built with one pagers, and neither should software, no wonder our software skyscrapers often degrade to sprawling horizontal shanty towns.

Amazon Web Services (AWS) Customer Service Agreement: Easy Come, Easy Go

March 16, 2014

Having read the 17 page Customer Agreement I would sum it up with Easy Come, Easy Go.

By that I mean that if I where to start a business using AWS I would operate under the assumption that the AWS leg of my business could be replaced and immediately disabled with no disruption to my end-users and also my responsibilities to them. In a way this flies in the face of being mesmerized by for example the advertised resiliency of services such as S3. I regard this as common sense, but also the AWS Customer Service Agreement is quite forthright in the sense that it reminds their clients, in effect, that it must comply with governmental requests to for example move your data from one AWS region to another (e.g. move all your data from say Australia to the US).

3.2 Data Privacy. We participate in the safe harbor programs described in the
Privacy Policy. You may specify the AWS regions in which Your Content will
be stored and accessible by End Users. We will not move Your Content from
your selected AWS regions without notifying you, unless required to comply
with the law or requests of governmental entities. You consent to our
collection, use and disclosure of information associated with the Service
Offerings in accordance with our Privacy Policy, and to the processing of
Your Content in, and the transfer of Your Content into, the AWS regions you
select.

They can also as per Section 7.2 immediately terminate the agreement under a variety of conditions.

Its not worth spending too much time on the AWS Customer Service Agreement in my mind as long as one’s software architecture and promises to end-users caters for the scenario where AWS is a gonner, for whatever reason.

The Async Retry Pattern: A Great Tutorial

March 3, 2014

Seemingly simple “green path” code can quickly get complex when one considers all that can go wrong. Good old error handling and retries, its all been done before and in so many different ways.

Consider retries for transient errors, one can either re-invent the wheel (done more often than not), or use appropriate library code from Spring Batch (now Spring Retry) in a synchronous fashion, or hand the potential lengthy operation off for asynchronous handling.

When it comes to asynchronous handling, Tomasz Nurkiewicz has done the hard yards and written an informative post along with GitHub code that serves as an excellent tutorial in itself. Kudos to Tomasz!

I’m left wondering what the correlation is between the Java Active Object Pattern and the Async Retry Pattern, the Async part is seemingly the only correlation.

Column-Family Databases (DynamoDB): The Key Trade Off

February 11, 2014

I had some random fortune come may way last year in the form of a four month stint to finish off and deliver on a DynamoDB based project.  The project was handed over to me just as the requirements of the project had changed enough, in retrospect, for a column-family database such as DynamoDB to serve as a painful reminder of a key reason why we use RDBMSs; SQL. Fowler and Sadalage [1] say it best below Section 10.4 When Not To Use.

RDBMS impose high cost on schema change, which is traded off for a low cost of query change; in Cassandra [Column-Family Databases], the cost may be higher for query change as compared to schema change.

As you can gather, the requirements of the project I completed, albeit with the power of SQL sorely missed, was a prime When Not To Use example. But the experience gained is priceless, as is the trade off quote below for future software architecture specifications.

It is worth noting one more thing that Fowler and Sadalage say in the same cited Section, which matches my experience exactly. In essence they do not recommend using Cassandra, and this also goes for DynamoDB in my mind, for prototypes or tech spikes since during the early stages it is unlikely that one will know how query patterns will change. As query patterns change, with DynamoDB, my experience was that the column family design had to change. The effect of such family column design change is summed up by Fowler and Sadalage succinctly yet again [1] below.

This causes friction for the product innovation team and slows down developer productivity.

Yep, I was at the receiving end of the query pattern change burn, but am still grateful for the experience.

[1] Fowler, Martin; Sadalage, Pramod J. (2012-08-08). NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence (p. 109). Pearson Education (US). Kindle Edition.

Business Quote to Set The Tone for 2014

January 1, 2014

Some had emerged from the ordeal; others had perished. All had burned brightly in their lives.

This is from the book No Way Down – Life and Death on K2 by Graham Bowley and its the final sentences in the Epilogue. I added the bold font. You may wonder what mountaineering tragedies have to do with business? In my mind I draw parallels between mountaineers and entrepreneurs – regardless of the outcome of a venture trying is a form of success in itself.

Follow

Get every new post delivered to your Inbox.