Blog

Finding and fixing complicated code

It's hard to beat lines of code as a complexity metric: the subjective complexity of a piece of code seems to correlate very well with its length. Over the years, many other metrics have been devised and explored, but they tend to be more complicated yet less effective than the simple old lines-of-code.

One exception to the rule is McCabe Cyclomatic Complexity, a metric almost exactly as old as I am. McCabe can often find methods that aren't that many lines of long, but that nonetheless a typical maintainer would identify as being complicated and difficult to maintain. Small wonder that GNU Complexity puts so much emphasis on it.

What McCabe does is count the number of independent paths are needed to cover a method from beginning to end. The way McCabe described it, in his delightfully readable paper on the subject, is that it's the number of test cases you need to get statement coverage for a given method. It sounds like something that would be impractically hard to calculate--you are minimizing over arbitrary test cases!--but it's not complicated at all. He proved that, with a few extra assumptions, all you really have to do is count the number of branching options in a given body of code.

McCabe complexity is very effective in my experience. A method with complexity 10 is usually a dense, gnarly tangle of code, even if it's only 20 lines long. Yet, 20 lines of code is not enough to reliably be complicated just by its number of lines of code. If it's a simple linear sequence of non-branching code, it's usually reasonable to leave it alone. McCabe Complexity is therefore a real coup.

Even better, there's usually a straightforward way to act on code that has a poor McCabe complexity measure. If you see a method with a lot of branches in it, you can usually make the code more maintainable by factoring out some of the clusters of branches to their own smaller methods. The main method gets easier to understand, and if you do it tastefully, the smaller factored-out methods will also be easier to understand.

One place McCabe complexity falls down, though, is large switch statements. If you write network code that receives a message and dispatches it, it's perfectly fine style to write a switch statement for the dispatch with one case for each kind of message. This is especially true if each case simply calls a method that does the real work. Such a switch statement will easily have a dozen cases, one for each message type, but what alternative would be any more maintainable? Factoring out methods for subsets of the cases doesn't seem obviously better, and reducing the number of cases is often impossible.

McCabe is even worse for switch statements that consider pairs of types that are each drawn from some enum. To see some typical examples, look at Cast.scala in the Apache Spark source code. All the big switch statements in there are enumerating pairs of types, and they strike me as a very reasonable way to manage a problem that is just fundamentally complicated. This organizational style reminds me of how people organize definitions on paper when they are studying and explaining language semantics. Such people will typically define their relations and functions using a dozen or so cases, each of which has a number of assumptions (x is a class type, y is a class type, and x inherits from y), and a conclusion you can draw if all of the assumptions hold (x is a subtype of y). If this style is reasonable for theory papers, where people are expending enormous time and energy to bring a complicated subject within the reach of the human mind, it seems only reasonable to write such definitions in code when possible.

Overall, McCabe complexity is excellent and has stood the test of time. I wonder, though, if "number of branching statements" might be even more useful for anyone trying to simplify their code. "Number of branching statements" is the same as McCabe for if statements and while loops, but for switch statements, it only adds 1. Such a measure seems like it would better focus on code that is not merely complicated, but also possible to simplify.

Posted in Blogroll

Finding and fixing complicated code

It's hard to beat lines of code as a complexity metric: the subjective complexity of a piece of code seems to correlate very well with its length. Over the years, many other metrics have been devised and explored, but they tend to be more complicated yet less effective than the simple old lines-of-code.

One exception to the rule is McCabe Cyclomatic Complexity, a metric almost exactly as old as I am. McCabe can often find methods that aren't that many lines of long, but that nonetheless a typical maintainer would identify as being complicated and difficult to maintain. Small wonder that GNU Complexity puts so much emphasis on it.

What McCabe does is count the number of independent paths are needed to cover a method from beginning to end. The way McCabe described it, in his delightfully readable paper on the subject, is that it's the number of test cases you need to get statement coverage for a given method. It sounds like something that would be impractically hard to calculate--you are minimizing over arbitrary test cases!--but it's not complicated at all. He proved that, with a few extra assumptions, all you really have to do is count the number of branching options in a given body of code.

McCabe complexity is very effective in my experience. A method with complexity 10 is usually a dense, gnarly tangle of code, even if it's only 20 lines long. Yet, 20 lines of code is not enough to reliably be complicated just by its number of lines of code. If it's a simple linear sequence of non-branching code, it's usually reasonable to leave it alone. McCabe Complexity is therefore a real coup.

Even better, there's usually a straightforward way to act on code that has a poor McCabe complexity measure. If you see a method with a lot of branches in it, you can usually make the code more maintainable by factoring out some of the clusters of branches to their own smaller methods. The main method gets easier to understand, and if you do it tastefully, the smaller factored-out methods will also be easier to understand.

One place McCabe complexity falls down, though, is large switch statements. If you write network code that receives a message and dispatches it, it's perfectly fine style to write a switch statement for the dispatch with one case for each kind of message. This is especially true if each case simply calls a method that does the real work. Such a switch statement will easily have a dozen cases, one for each message type, but what alternative would be any more maintainable? Factoring out methods for subsets of the cases doesn't seem obviously better, and reducing the number of cases is often impossible.

McCabe is even worse for switch statements that consider pairs of types that are each drawn from some enum. To see some typical examples, look at Cast.scala in the Apache Spark source code. All the big switch statements in there are enumerating pairs of types, and they strike me as a very reasonable way to manage a problem that is just fundamentally complicated. This organizational style reminds me of how people organize definitions on paper when they are studying and explaining language semantics. Such people will typically define their relations and functions using a dozen or so cases, each of which has a number of assumptions (x is a class type, y is a class type, and x inherits from y), and a conclusion you can draw if all of the assumptions hold (x is a subtype of y). If this style is reasonable for theory papers, where people are expending enormous time and energy to bring a complicated subject within the reach of the human mind, it seems only reasonable to write such definitions in code when possible.

Overall, McCabe complexity is excellent and has stood the test of time. I wonder, though, if "number of branching statements" might be even more useful for anyone trying to simplify their code. "Number of branching statements" is the same as McCabe for if statements and while loops, but for switch statements, it only adds 1. Such a measure seems like it would better focus on code that is not merely complicated, but also possible to simplify.

Posted in Blogroll

Picasso and Keycloak

So over the weekend I was trying to use Picasso to cleanly load images served by a server secured using KeyCloak. This was surprisingly easy using AeroGear’s authz library.

I needed the following dependencies in my apps build.gradle file

    //AGDroid deps
    compile 'org.jboss.aerogear:aerogear-android-core:2.1.0'
    compile 'org.jboss.aerogear:aerogear-android-security:2.1.0'
    compile 'org.jboss.aerogear:aerogear-android-store:2.1.0'
    compile 'org.jboss.aerogear:aerogear-android-authz:2.1.0'
    //Picasso deps
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.squareup.okhttp:okhttp:2.4.+'
    compile 'com.squareup.okio:okio:1.5.0'

And I configure Picasso with the following

OkHttpClient picassoClient = new OkHttpClient();

        picassoClient.interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                ModuleFields fields = AuthorizationManager.getModule("KeyCloakAuthz").loadModule(null, null, null);
                Pair<String, String> header = fields.getHeaders().get(0);
                Request newRequest = chain.request().newBuilder()
                        .addHeader(header.first, header.second)
                        .build();
                return chain.proceed(newRequest);
            }
        });

        picasso = new Picasso.Builder(appContext).downloader(new OkHttpDownloader(picassoClient)).build();

*KeyCloakAuthz* is a AuthzModule protecting my server. You can find out more about them on the AeroGear website.

Posted in Blogroll

How to open Finder from the Terminal in OSX

 open .  

This came in handy this morning.
Posted in Blogroll

How to open Finder from the Terminal in OSX

 open .  

This came in handy this morning.
Posted in Blogroll

How to find a Java class file in your Maven repository (or any other directory full of jar files)


find . -name "*.jar" | xargs grep -r [CLASS NAME]

In case you are ever wondering why your builds aren't working.
Posted in Blogroll

How to find a Java class file in your Maven repository (or any other directory full of jar files)


find . -name "*.jar" | xargs grep -r [CLASS NAME]

In case you are ever wondering why your builds aren't working.
Posted in Blogroll

The Grapefruit Buck

I have had the pleasure of discovering The Grapefruit Buck, my drink of choice when I need a serious break from the code. Give it a try, it helps to brink clarity to the world ;)

  • A generous portion of ice
  • 2 shots Absolute Ruby Red Vodka
  • ½ shot St. Germain's Elderflower liqueur
  • a splash Campari Bitters
  • a splash Lime Juice
  • fill the rest with Ginger Beer
  • drop a slice of grapefruit on top
Shake it all up and enjoy!


Posted in Blogroll

The Grapefruit Buck

I have had the pleasure of discovering The Grapefruit Buck, my drink of choice when I need a serious break from the code. Give it a try, it helps to brink clarity to the world ;)

  • A generous portion of ice
  • 2 shots Absolute Ruby Red Vodka
  • ½ shot St. Germain's Elderflower liqueur
  • a splash Campari Bitters
  • a splash Lime Juice
  • fill the rest with Ginger Beer
  • drop a slice of grapefruit on top
Shake it all up and enjoy!


Posted in Blogroll

Aerogear Android 2.1 Released

AeroGear 2.1

What’s New

Sync Alpha

AeroGear has released the first alpha of our data sync technology. This includes the AeroGear Sync Server and libraries for iOS, JavaScript, and of course Android. This technology allows for cross platform data synchronization as seen here :

AeroGear SyncDemo from Christos Vasilakis on Vimeo.

If you followed the development of the Android library you will remember that we originally tried to use Google’s XMPP services as the medium for data sync. Because of technical limitations we dropped this idea and moved to wrapping the Netty client provided with AeroGear Sync Server in an Android service instead.

To activate the service you need to add it to you AndroidManifest.xml file. You will also need to provide properties for serverHost, serverPort, and serverPath. These properties are defined by where you have deployed the sync server. Here is an example connecting to the sync server running on the host of an emulated Android device:

 <service android:name="org.jboss.aerogear.android.sync.SyncService">
  <meta -data
  android:name="serverHost"
  android:value="10.0.2.2" />
  <meta -data
  android:name="serverPort"
  android:value="7777" />
  <meta -data
  android:name="serverPath"
  android:value="/sync" />
</service>

Any Activty you want to receive sync events needs to implement the SyncServerConnectionListener interface, bind itself to the SyncService instance, and then subscribe to events on connections.

Binding and subscribing example :

@Override
protected void onStart() {
 super.onStart();
 serviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   final SyncService syncService = ((SyncService.SyncServiceBinder) service).getService();
   SyncActivity.this.service = syncService;
   syncService.subscribe(SyncActivity.this);
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   finish();
  }
 };
}

@Override
protected void onResume() {
 super.onResume();
 Intent syncServiceIntent = new Intent(this, SyncService.class);
 bindService(syncServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}

SyncServerConnectionListener implementation Example :

@Override
//Called when the SyncService instance is connected to the Sync server AND the Activity is subscribe to the service after binding.
public void onConnected() {
 /*clientId is a unique identifier which identifies the device connection*/
 clientId = getSyncService().getClientId();

 /*a client document is a document the sync APIs know how to synchronize and is managed by the sync libraries*/ 
 final ClientDocument<jsonnode> clientDocument = clientDoc(documentId, clientId, JsonUtil.toJsonNode(content));

 /*adding a document to the service causes it to send and receive updates*/
 getSyncService().addDocument(clientDocument);
}

@Override
//Called when the document is updated by an external source
public void patched(final ClientDocument data) {
 runOnUiThread(new Runnable() {
  @Override
  public void run() {
   final ClientDocument</jsonnode><jsonnode> document = (ClientDocument</jsonnode><jsonnode>) data;
   final Info updates = JsonUtil.fromJsonNode(document.content());
   //handle your updates here.
  }
 });
}

For a full implementation demo look at our cookbook.

Minor Changes

Pipe improvements

After nearly two years we have implemented AGDROID-7 by adding Pipe.read(String id, Callback<t> callback). Now fetching by id is as simple as the following:

private void retrieveData() {
  LoaderPipe<data> pipe = application.getPipe(this);
  pipe.reset();
  pipe.read(String.valueOf(15), new MyCallback());
}

GCM Push Configuration

We’ve added some extra validation to the GCM Push Registrar. Now if you leave off properties such as variantId the library will throw an exception when you try to build the PushRegistrar as opposed to the registration method failing with an error callback.

GCM Unregistration

Now the library will check to see if you have a registered client before it attempts unregistration. Previously it would always make a call to the Push Server which would fail with a HTTP 404 error if you were not registered. Now the method immediately fails without a network call.

Demo Improvements

We’ve added a few demos to the official cookbook.
* Sync Demo This is the demo for our sync libraries.
* Two Factor This is an example of a Two-Factor One Time Password app using AeroGear.
* Password Manager This demonstrates using encryption to secure a password store behind a passcode.

We’ve also fixed some bugs in the Shoot and Share app as well as the AGReddit app.

What’s Next

For 2.2 and the future we are looking at improvements to our authz libraries as well as better offline resource management. As per usual you can watch our JIRA

About AeroGear

If you would like to learn more about AeroGear’s Android libraries a great place to start is our Android landing page. If you would like to participate in development, have questions, or want to chat with us our community section has all of our contact information.

Changelog

  • AGDROID-362 Migrate AeroDoc example to Gradle and move to cookbook repo
  • AGDROID-156 Update aerogear-crypto-android-demo and move to cookbook repo
  • AGDROID-343 AeroGearGCMPushConfiguration#buildRegistrar needs more validation
  • AGDROID-361 AGReddit should say Bad Password when you fail at logging in.
  • AGDROID-7 add pipe functionality to retrieve data by ID
  • AGDROID-312 Implement Android Client Sync Engine
  • AGDROID-369 Sync Android Demo app
  • AGDROID-313 Implement Android Sync Client
  • AGDROID-368 unregister fails with server returned the error code 405 android
  • AGDROID-385 Update AeroGear Sync README
  • AGDROID-377 Move DiffSync client into a android.app.Service
  • AGDROID-386 Deprecate and remove client-xmpp
  • AGDROID-370 XMPP Client NPE @ DiffSyncClientHandler.java:45
  • AGDROID-364 Package XMPP Sync Client to not include duplicate files
  • AGDROID-363 Refactor XMPP Sync Client to get below the 65k method limit
  • AGDROID-371 XMPP sync client should support json patch
  • AGDROID-367 Shoot-n-Share 401 error (invalid_client) on Google Drive upload
  • AGDROID-366 Shoot-n-Share does not offer keyboard for Keycloak redirected login screen
  • AGDROID-365 XMPP Sync Client does not handle multiple documents correctly
Posted in Blogroll

AJUG Tweets

Follow @atlantajug on twitter.

Recent Jobs

    AJUG Meetup

    An Enterprise Developer’s Journey to the IoT

    Tuesday, July 21, 2015

    The current hype around the Internet of Things (IoT) has led to a substantial amount of innovation thanks to open source software, open hardware, open standards, and community inspiration. In this session, we will explore how you can use open source software to incorporate the physical world (the “Things”) into your traditional enterprise IT infrastructure. We will walk the path from a typical enterprise developer’s current focus on web desktop applications to mobile and devices, specifically developer prototyping platforms like Raspberry Pi, Intel Edison, Arduino, Spark Core, and several others. Learn how to connect the physical world to your enterprise backbone via sensors and actuators with MQTT and Apache ActiveMQ.

    Location:


    Holiday Inn Atlanta-Perimeter/Dunwoody

    4386 Chamblee Dunwoody Road,
    Atlanta, GA (map)