Microsoft Azure-Aclypse – Yet Another Quality Attribute Reminder

With Azure’s global outages impacting millions of end-users today, as a Software Architect this is just a simple reminder. Either your architecture has a quality attribute that requires resilience in the face of an apocalypse-like cloud vendor outage or it does not.

Chances are that no individual vendor will ever entertain the notion that they will suffer a global outage. SLAs are unlikely to get lost business back. It is the architect’s job to guide their client through the scenarios that may impact their business, including an Azure-Aclypse.

Maven Cobertura and JaCoCo Plugins – What Are Your Rock Bottom, Minimum Standards?

When it comes to test driven development, the best line I’ve heard is the following.

Your clients are not a distributed test environment

These wise words where uttered by my Spring Core lecturer while covering the difference between unit and integration tests in Spring parlance. On the note of unit and integration tests, after working on a vast array of projects, it has dawned on me, with some sadness, that not a single project, organization or team I’ve been on has had non negotiable standards when it comes to code coverage. Of course, most projects have had unit testing as a part of a checklist, but not a single one has made a lasting effort to both measure and enforce a minimum goal in terms of code coverage.

In this post we take a look at potential rock bottom configurations for the free cobertura-maven-plugin in particular and also visit the jacoco-maven-plugin. Finally we encounter lacking JDK 8 support and start considering paying for a commercial plugin.

Before delving into code coverage tooling it’s worth asking why it matters, to whom, and what it means. So, what does code coverage mean? Why should software engineers care? Why should project managers care? Why should project sponsors care? If a consultancy (vendor) is doing the development, why should this organisation care? These are not questions we’ll delve into here in depth other than noting that coverage reports help detect code that had not been adequately tested by automated test suites.

No Standards? Introduce a Lower Quality Gate

So what to do in a world of little to no standards? In my mind the answer is to set one’s own personal standards, starting with defining what rock bottom is. This is a personal professional line in the sand. Its also a great question, when considering joining a project or organization, to ask of your prospective employer. The question would be what unit, integration and system test code coverage standards the organization has and then crucially how they are enforced and made visible to all concerned.

In terms of motivating the need to minimum standards, the term quality gate seems apt. On a given project, even personal project, one would have two gates, the lower gate would be enabled by default and builds will fail on developer machines if this minimum standard is not met, a CI server would also independently verify using the minimum standard. If this lower quality gate has not been met, the project manager or development manager should know about it.

The Plugins

Lets move onto the plugins. The cobertura-maven-plugin is used to report on and check your unit test code coverage using the Cobertura code coverage utility. So we’ll first check if all tests are passing and then check to make sure our standards have been met. Once we move onto the integration test phase, where our beans and infrastructure is tested in concert, the jacoco-maven-plugin will report on and check our integration test code coverage. 

The importance of performing both unit testing (individual classes) and integration testing (incorporating a container such as the Spring context) cannot be overstated. Both plugins and so both types of testing must be done in a given project and this stands to reason: we want coverage standards for individual classes as well as cooperating runtime services and ordinarily we only proceed to the latter once the former has succeeded as per the Maven Build Lifecycle.

Rock Bottom – Our Lower Quality Gate

It stands to reason that there some should be some correlation between the application domain and the amount of effort one will invest in unit and integration testing. When it comes to rock bottom however the application domain is irrelevant since it represents our bare minimum standard that is domain agnostic.

In terms of the merits of a rock bottom configuration for Cobertura and JaCoCo, the following IBM developerWorks sourced statement supports such an approach.

The main thing to understand about coverage reports is that they’re best used to expose code that hasn’t been adequately tested.

Cobertura

Defining a minimum standard when it comes to Cobertura, as it turns out, takes some effort when one considers the array of options one has to consider. For example the configuration below is the usage example provided on the official plugin page.

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>cobertura-maven-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <check>
            <!-- Min branch coverage rate per class. 0 to 100. -->
            <branchRate>85</branchRate>
            <!-- Min line coverage rate per class. 0 to 100. -->
            <lineRate>85</lineRate>
            <haltOnFailure>true</haltOnFailure>
            <!-- Min branch coverage rate for project as a whole. -->
            <totalBranchRate>85</totalBranchRate>
            <!-- Min line coverage rate for project as a whole. -->
            <totalLineRate>85</totalLineRate>
            <!-- Min line coverage rate per package. -->
            <packageLineRate>85</packageLineRate>
            <!-- Min branch coverage rate per package. -->
            <packageBranchRate>85</packageBranchRate>
            <regexes>
              <!-- Package specific settings. -->
              <regex>
                <pattern>com.example.reallyimportant.*</pattern>
                <branchRate>90</branchRate>
                <lineRate>80</lineRate>
              </regex>
              <regex>
                <pattern>com.example.boringcode.*</pattern>
                <branchRate>40</branchRate>
                <lineRate>30</lineRate>
              </regex>
            </regexes>
          </check>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>clean</goal>
              <goal>check</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

The first question that comes to mind when it comes to the above is what the configuration means in the first place. The main concept we need is the difference between the line rate and branch rate, which has been neatly explained here. So, a potential starting point would be a 50% line coverage rate on a project wide basis as a rock bottom configuration with branch coverage excluded. Naturally we will halt on failure as a rule since this is our bare minimum standard and not necessarily what we will aspire to achieve.

			<plugin>
        		<groupId>org.codehaus.mojo</groupId>
        		<artifactId>cobertura-maven-plugin</artifactId>
        		<version>2.5.2</version>
        		<configuration>
        			<instrumentedDirectory>target/cobertura/instrumented-classes</instrumentedDirectory>
          			<outputDirectory>target/cobertura/report</outputDirectory>
          			<check>
            			<haltOnFailure>true</haltOnFailure>
            			<totalLineRate>50</totalLineRate>
          			</check>
        		</configuration>
        		<executions>
          			 <execution>
                        <id>cobertura-clean</id>
                        <phase>clean</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>cobertura-instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>instrument</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>cobertura-verify</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
        		</executions>
      		</plugin>

JaCoCo

When using JaCoCo to generate code coverage reports both that jacoco-maven-plugin and maven-failsafe-plugin must be configured as per this excellent resource.

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <!-- The Executions required by unit tests are omitted. -->
        <!--
            Prepares the property pointing to the JaCoCo runtime agent which
            is passed as VM argument when Maven the Failsafe plugin is executed.
        -->
        <execution>
            <id>pre-integration-test</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                <!--
                    Sets the name of the property containing the settings
                    for JaCoCo runtime agent.
                -->
                <propertyName>failsafeArgLine</propertyName>
            </configuration>
        </execution>
        <!--
            Ensures that the code coverage report for integration tests after
            integration tests have been run.
        -->
        <execution>
            <id>post-integration-test</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

JDK 8 Support Lacking – Time To Look At Altassian Clover

While producing this post I had to abondon using both cited plugins and to start looking at Altassian Clover since the two cited free plugins do not support JDK 8 at present but Altassian Clover does. The latter does come with a $300 price tag, and that should be fine, it worth spending money on good development tools.

cobertura-maven-plugin issue log

Issue 1: cobertura-maven-plugin 2.6 gave incessant error, downgraded to 2.5.2 which made the error go away. Did not have the time for analysing the reasons for the failure.

Issue 2: Tests would not run with the mvn clean verify command, got incessant exceptions and bytecode on the console with the reason being “Expected stackmap frame at this location.” As it turns out this is was due to JDK 8 not being supported. Downgrading to JDK 7 was not an option for me, neither was spending time on understanding subtle new behaviours of JDK 7 .

AWS S3 Glacier Billing Example – The Peak-Restore-Bytes-Delta Burn

There’s lots to read about S3 online, but nothing helps more with overarching service design than the burn of an actual bill.

Peak-Restore-Bytes-Delta is effectively a usage penalty and as you can see the fines can be massive and render using Glacier financially infeasible.

As expected, on the billing front there is nothing Simple about using the Amazon Simple Storage Service (S3). In fairness however 5 out of 8 line items can be attributed to using Glacier along with S3.

The costs below represent a single month of testing using the Asia Pacific (Sydney) Region (ASP2) during October 2014.

ITEM COST PER UNIT USAGE COST
EarlyDelete-ByteHrs $0.036 per GB – Glacier Early Delete 1.440 GB-Mo $0.02
Peak-Restore-Bytes-Delta $0.012 per GB – Glacier Restore Fee 16.277 GB $0.20
Requests-Tier1 $0.00 per request – PUT, COPY, POST, or LIST requests under the monthly global free tier 168 Requests $0.00
Requests-Tier2 $0.00 per request – GET and all other requests under the monthly global free tier 52 Requests $0.00
Requests-Tier3 $0.06 per 1,000 Glacier Requests 16 Requests $0.01
TimedStorage-ByteHrs $0.000 per GB – storage under the monthly global free tier 0.000022 GB-Mo $0.00
TimedStorage-GlacierByteHrs $0.0120 per GB / month of storage used – Amazon Glacier 0.181 GB-Mo $0.01
TimedStorage-RRS-ByteHrs $0.0264 per GB – first 1 TB / month of storage used – Reduced Redundancy Storage 0.003 GB-Mo $0.01

The red hot glaring line item is Peak-Restore-Bytes-Delta, note that in the given month, only 181 MB was archived costing a paltry $0.01 (this cost provides some insight into AWS’s rounding). So why the comparatively massive $0.20 for the retrievals? Peak-Restore-Bytes-Delta is effectively a usage penalty and as you can see the fines can be massive and render using Glacier financially infeasible. With Glacier only 5% of the total amount of storage used can be retrieved for free in a given month. The $0.20 is for the peak billable retrieval rate as per the Glacier FAQs (look for the question entitled “Q: How will I be charged when retrieving large amounts of data from Amazon Glacier?”) and it means a peak rate of 16.277 GB/hr worth of transfers took place – so in essence during one particular hour 16.277 GB worth of retrievals where scheduled.

It’s also worth looking at the EarlyDelete-ByteHrs. A total of 1.440 GB-Mo was deleted early (within less than 90 days). Now first off what is a GB-Mo? Presumably it means Gigabyte-Months which means Gigabytes multiplied by months which is 3 months in terms of what an early delete is defined to mean. In essence, if one looks at the rate (3 times the TimedStorage-GlacierByteHrs rate) then EarlyDelete-ByteHrs just means they will bill you for 3 months of usage no matter what.

Refactoring to remove code duplication using the strategy pattern

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

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?

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

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.