Sunday, November 1, 2015

Grocery Reminder - An Open-Source Android App

I'd like to announce that my first Android app, the Grocery Reminder, has been made Open Source, and released under the MIT License.  You can find the source on my Github account.

Why Open-Source?

Some of you are probably asking why I decided to make my first app Open-Source.  After all, I put significant time and effort into this project.  The truth of the matter is that I created the app as part of a contest with my current employer in order to learn more about Android development.  In terms of how useful the app has been, let's just say it let me scratch an itch and my wife uses it on a regular basis, which is good enough for me.  

Beyond that I learned quite a bit about Android over the six months or so that it took me to develop it, and I've been able to leverage what I've learned in order to write a series of posts on Android and Test-Driven Development.  I did this to show that TDD and Android were not water and oil, and that it is more than possible to write test-driven mobile apps.  I'll continue to use this code for examples for the remainder of the Android TDD series, which I hope will benefit Android developers in one way or another.

Releasing this app as Open-Source software is an extension of the goals I mentioned above; I'm putting this code out there in the hopes that others will learn from it.  Whether that is learning a better way of developing and test-driving Android apps or simply learning from my mistakes is up to each developer to decide. 

So there it is.  The code is out there and I encourage you to check it out, hack on it, maybe even issue a pull request or two.  I look forward to any feedback you might have, and happy hacking!

Sunday, October 18, 2015

Android TDD Series: Dagger and Mockito

Practicing craftsmanship in Android is hard.  Really hard.  The framework imposes itself in a number of ways that make it difficult to write well-crafted, testable code.  The official examples don't do anything to help this, as they weren't designed to show Android development done well, they were designed to simply show it "done".  Fear not though, as others have encountered the same difficulties you're probably now facing and they've determined that where there is a will, there is a way.  They've figured out that it is indeed possible to use good engineering principles such as Dependency Injection and Mocking in Android development.

Having said that I've made it a point to incorporate these practices into my app development and found a lot of success in doing so.  The combination of Robolectric, Dagger for dependency injection, and Mockito for mocking collaborators is powerful, but it gives you a lot of flexibility.  I'd like to share this setup with you here in the hopes that it will help you design more testable, maintainable, and flexible solutions.

I've previously written about using Robolectric to stub portions of the Android framework, so lets move on to incorporating dependency injection into our apps.

Dagger Setup

Dagger is an open-source dependency injection framework for Java applications.  It is not Android-specific, but has certainly become the leading DI framework of choice for Android.  Dagger is currently in its 2.x version, however Dagger 1.x is still dominate and it is the version I'm currently using.  The following setup will be for Dagger 1.2.

Conceptually Dagger provides Dependency Injection by organizing dependencies into modules, which are used to create an object graph.  This object graph is traversed at the time of injection to determine what dependencies should be injected, and in what order.  Let's take a look at what this means in concrete terms in your Android application, shall we?

Once we have the necessary build dependencies we can start integrating Dagger in.

In build.gradle:

dependencies {
    //Other dependencies

    //Dagger
    compile 'com.squareup:javawriter:2.5.0'
    compile ('com.squareup.dagger:dagger:1.2.2') {
        exclude module: 'javawriter'
    }
    compile ('com.squareup.dagger:dagger-compiler:1.2.2') {
        exclude module: 'javawriter'
    }
}

The next step we take is to extend the Application class and provide some scaffolding for the injection process:

In MyApplication.java:

package com.example.jameskbride;

import dagger.ObjectGraph;

public class MyApplication extends Application {

    protected ObjectGraph objectGraph;
    
    @Override
    public void onCreate() {
        super.onCreate();

        createObjectGraph(getModules());
    }

    public List<Object> getModules() {
        List<Object> modules = new ArrayList<Object>();
        
        return modules;
    }

    public void inject(Object context) {
        graph.inject(context);
    }

    public void createObjectGraph(List<Object> modules) {
        graph = ObjectGraph.create(modules.toArray());
    }
}

Let's take a moment to break down what we've set up here. First, we've introduced a protected member variable here, which is of type ObjectGraph. This variable is the key to making Dagger useful, as it provides the mechanism for actually performing the injections we need. The rest of the logic we've introduced is implementation-specific, but it should cover 99% of the use-cases we anticipate. In the onCreate() method we make a call to a method we introduced, createObjectGraph(), which takes a list of objects (nominally dependency modules, which we'll get to in a moment) and invokes the static method ObjectGraph.create() to instantiate the object graph. We've also introduced a public inject() method, which performs the actual injection via the object graph.

Before going too much further we need to satisfy Android by insuring it knows about our overridden Application class. To do this we need to modify our AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.jameskbride">
    
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <!-- snip -->
    </application>

</manifest>

This setup provides the framework we need to inject modules, which which don't actually have at the moment.  Let's fix that now.  The first thing we're going to do is to create a module to provide injection of some of our custom business logic. First, suppose we have the following interface and class:

package com.example.jameskbride;

public interface SpeakerInterface {
    public String sayHello();
}
package com.example.jameskbride;

public class Speaker implements SpeakerInterface {
    
    @Override
    public String sayHello() {
        return "Hello, world!";
    }
}

Given this class, lets create a module to provide injection for it.

package com.example.jameskbride;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module(
injects = {
        MyActivity.class
    }
)
public class MyModule {

    @Provides
    @Singleton
    public SpeakerInterface getSpeaker() {
        return new Speaker();
    }
}

In this class we have several annotations provided by by Dagger and JSR330, the Java specification for dependency injection. The @Module annotation provides a way to configure the module, and @Provides is the mechanism for telling Dagger where the dependency should be constructed when necessary.  Now that we have a module let's go back to our Application class and plug it in there.

public class MyApplication extends Application {

//Snip
public List<Object> getModules() {
        List<Object> modules = new ArrayList<Object>();
        modules.add(new MyModule());
        return modules;
    }

//Snip
}

Almost done. Now we just need to actually inject into our class where the dependency will be used. Let's create an activity which will use our dependency.
In MyActivity.java:

package com.example.jameskbride;

import android.app.Activity;
import android.os.Bundle;

import javax.inject.Inject;

public abstract class MyActivity extends Activity {

    @Inject
    SpeakerInterface speaker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((MyApplication)getApplication()).inject(this);
    }
}

Notice the @Inject annotation on our SpeakerInterface member variable, as well as the fact that the variable has package scope. The package scoping is important, as injection via Dagger will not work if the injected dependency is private. Also notice that we finally call MyApplication.inject() within the onCreate() method; this is what causes the injection to occur in the first place.

This was quite a lot of work! We should now be able to make calls to the speaker within our Activity. As you can see there is quite a bit of overhead involved in the setup of Dagger, and this is just for the production side of things.  Let's take a look at the test setup now.

Test Setup

The testing side of the Dagger setup is almost identical to the production setup.  In fact, it simply involves overriding our custom Application class and providing test doubles of our modules.  First, the Application class:

package com.example.jameskbride;

import java.util.ArrayList;
import java.util.List;

import dagger.ObjectGraph;

public class MyTestApplication extends MyApplication {

    private MyTestModule myTestModule;

    @Override
    public List<Object> getModules() {
        List<Object> modules = new ArrayList<Object>();
        modules.add(getMyTestModule());
        return modules;
    }

    public MyTestModuleModule getMyTestModule() {
        if (myTestModule == null) {
            this.myTestModule = new MyTestModule());
        }

        return myTestModule;
    }
}

Here's we've created an Application class which extends our custom application, MyApplication. Notice we are loading a test version of MyModule, shown below:


package com.example.jameskbride;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

import static org.mockito.Mockito.mock;

@Module(
injects = {
        MyActivity.class
    }
)
public class MyTestModule {

    private SpeakerInterface mockSpeaker;

    public MyTestModule() {
        mockSpeaker = mock(SpeakerInterface.class);
    }

    @Provides
    @Singleton
    public SpeakerInterface getSpeaker() {
        return mockSpeaker;
    }
}


You'll notice that the test module is almost identical to the original. In this case though we are substituting the real Speaker implementation with a Mockito mock. Don't forget to add the appropriate test dependency for Mockito in your build.gradle:
dependencies {
    // Other dependencies
    testCompile 'org.mockito:mockito-core:1.10.19'
}

Now we're ready to write tests which use our Dagger-provided dependencies. Let's write our first test to drive in some functionality.
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class MyActivityTest {

    private ActivityController<MyActivity> activityController;
    private MyActivity activity;

    @Test
    public void whenTheActivityIsCreatedThenTheTitleIsSet() {
        SpeakerInterface mockSpeaker = ((MyTestApplication)activity.getApplication()).getMyTestModule().getSpeaker();
        
        String expectedTitle = "I hate hello world examples!";
        when(mockSpeaker.sayHello()).thenReturn(expectedTitle);
        activityController = Robolectric.buildActivity(MyActivity.class);
        activity = activityController.create().start().get();

        assertEquals(expectedTitle, activity.getTitle());        

        verify(mockSpeaker).sayHello();
    }
}


Run the test and watch it fail. Once we've watched it fail correctly we can implement the code to make it pass:

package com.example.jameskbride;

import android.app.Activity;
import android.os.Bundle;

import javax.inject.Inject;

public abstract class MyActivity extends Activity {

    @Inject
    SpeakerInterface speaker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((MyApplication)getApplication()).inject(this);
        setTitle(speaker.sayHello());  //Here is the line which makes the test pass.
    }
}


The test should now pass, and we are officially configured to use Dagger in both production and test!

Again, there is obviously a lot of overhead involved in the setup of Dagger, but this will pay off in the long run as your application grows. I hope this has been useful, and feel free to send me any questions you might have! Thanks!

Saturday, September 19, 2015

Android TDD Series: Test-Driving Views Part 2 - Fragments

Well, it's been more than two months since my last post in the series and I've really fallen off of this horse. The good news is that time away from the Android TDD series was well spent. I have just published my first Android app! Now it's time to get back on and get back to some Android TDD!

We started talking about testing views in Android, specifically how to test activities. While activities are certainly a core component, we actually want to minimize how much code we put in them. This is especially true for all view-related code, such as widget-population and listener functionality. Instead, a majority of this functionality should be placed in fragments. Fragments were introduced into the Android framework when it became apparent that activities would be become bloated and difficult the maintain, with a mishmash of life-cycle management, data population, and widget management. By moving all widget-based functionality (including listeners) we are able to more cleanly delineate the responsibilities for each class. Activities should focus on their life-cycle events and populating the view-model which will be used by the fragment, which will be responsible for managing the widgets and their listeners.

To Test Fragments...


You actually need activities.  This is unfortunate because when we unit test we strive to test classes in isolation as much as possible.  That being said it isn't too onerous to unit test fragments; we simply need an activity when we start the fragment.

For now, let's take a look at how to start a fragment test (src/test/java/com/jameskbride/TextFragmentTest.java):


package com.jameskbride;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.TextView;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.util.ActivityController;

import static org.junit.Assert.assertEquals;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class TextFragmentTest {

    private ActivityController activityController;
    private MainActivity activity;

    @Before
    public void setUp() {
        activityController = Robolectric.buildActivity(MainActivity.class);
        activity = activityController.create().start().visible().get();
    }

    @After
    public void tearDown() {
        activityController.pause().stop().destroy();
    }

    public void startFragment(FragmentActivity parentActivity, Fragment fragment) {
        FragmentManager fragmentManager = parentActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();
    }

    @Test
    public void whenTheFragmentViewIsCreatedThenTheViewShouldBePopulated() {
        TextFragment textFragment = TextFragment.newInstance();
        startFragment(activity, textFragment);

        TextView myTextView = (TextView)textFragment.getView().findViewById(R.id.my_text_view);
        assertEquals("Hello world!", myTextView.getText());
    }
}

This code is obviously simplified from what you would normally see.  The first thing we do is in the setUp() method, which is to build an Activity and get it into the correct life-cycle event (see my previous post).  Once we are into the actual test itself we have another required step: starting the Fragment.  We accomplish this by getting ahold of the FragmentManager (in this case we're using the SupportFragmentManager, which is actually recommended).  Once we have the FragmentManager we start a new FragmentTransaction and commit that transaction.

Now we have performed enough setup to perform the actual test.  In this case we are simply checking that the text in a TextView widget has been set when the Fragment is created. After we add enough code to get it to compile (create the TextFragment, add the factory method, newInstance(), and create a view which contains an id of "my_text_view" we can run the test via "./gradlew testDebug". This leaves with a failing test which is expecting "Hello world!". Let's get this test passing.

First, our view (src/main/res/layout/text_fragment_layout.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_text_view"/>
</LinearLayout>


Next, the Fragment code (src/main/java/com/jameskbride/TextFragment.java):
package com.jameskbride;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class TextFragment extends Fragment{
    public static TextFragment newInstance() {
        return new TextFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.text_fragment_layout, container, false);

        return root;
    }
}


Let's break this down. First, in our newInstance() method we have returned a TextFragment. Second, in the onCreateView method we inflate our view, text_fragment_layout.xml, which contains the TextView with our "Hello world!" string. The test should now pass.  This is just a basic example of how to unit test fragments in Android.

One thing to keep in mind is that just as activities can be tested in their various life-cycle events, so too can fragments.  If we need to to test code in onAttach() method we can simply call it directly.   The technique for testing Fragments is essentially the same as testing activities. 

Hopefully this has been a useful starting point, though one which has been a long while coming!



Saturday, September 12, 2015

Broken Windows and How to Fix Them

It's your first day on the job at a new client and you're excited and ready to get started.  They've got some cool problems they are trying to solve, the tech stack sounds interesting, and you've got work lined up for your team.  You get there and immediately notice that the build board is red.  Not just a little red, but bleeding red.  "Maybe it's just a single bad build" you think to yourself. "I'm sure it will get fixed right away."  

You try not to about it too much while you get settled in and start pulling down the code to build it locally.  It compiles, but there are a number of failing tests.  You notice a number of other details about the code; domain logic is spread throughout, there is bleed-over between the different layers of abstraction, and A LOT of untested code.  Code duplication abounds, and some of the tests are flaky.
You check the build board again, and notice that not only is it still red, but someone has pushed on top with more changes.  When you ask one of the other developers about it they chuckle and reply that it has been red for a while, but it's OK, it's just some of the tests.  No one seems too bothered by this.  You start wondering if you've walked into some parallel universe where a red build is acceptable, or even expected.  How did it get this way? Doesn't this bother anyone? You realize you have your work cut out for you.

Broken Window Theory

So what happened?  How did the state of the project get to this point?  How can a build get into a red state and stay that way?  Unfortunately it is entirely too easy for this to happen.  It only takes one bad changeset and zero developers who care about fixing it.  This happens in software development with maddening frequency, and is an example of the Broken Window Theory.

Broken Window Theory goes like this:

Given a building with one or more broken windows which are not quickly repaired, the tendency is for more windows to be broken and for other acts of vandalism to occur.  People notice that no one cares about the building, and there is no social pressure to prevent the vandalism.  The building quickly falls into disrepair and stays that way.

In software development lots of little changes can contribute to creating an environment which tolerates a continually broken build.  The addition of code which is difficult to test leads to fewer tests. Flaky tests can degrade confidence in the build ("Oh yeah, that build is red because of known flaky test, go ahead and push anyway!"). Just plain broken functionality is allowed to be pushed, and a general lack of design and maintenance can cause the codebase to be become chaotic and difficult to work with.  Maybe there are developers on the team who simply don't know how to write tests, or how to refactor properly.

All of this together can make it disheartening to try to do the right thing, it becomes easy to fall into the trap of "Well, this is just how the codebase is, we should just learn how to live with it." Obviously this is not the answer.

Fixing Broken Windows

So the windows have been broken and the build is red.  How do you fix the situation?  How do you get the build back to a green state and keep it that way?  The answer is simple, if not easy: get the team to care about the build.  Obviously this is easier said than done in many cases.  Often the team has been beaten down by the long-standing degradation of the build, so simply shouting about the problems in the codebase won't solve anything.  Concrete steps must be taken.

Stop Further Damage

To begin with, cordon off the building, draw a line in the sand, stop the bleeding (pick your metaphor here, there are a lot of them), but whatever you do stop the code from getting any worse than it already is.

Take your lead from this guy.

Be prepared to put the breaks on and play the bad guy, because you're about the rock the boat and upset a lot of people who have become comfortable with The Way Things Are.

Your first order of business should be to get the build back to green as quickly as possible.  If that means no one pushes code until that happens then so be it.  Implement an Evergreen Policy which states that if a build goes red it is either fixed immediately, or the changeset is backed out.

The build is an indication of the health of the project, and ultimately it should tell you whether you are ready to deliver or not, so it should become a priority to get it green and keep it green.  The code should compile and all tests should pass every single time.

Make "Done" Include a Healthy Build

For a given unit of work (user story, task, whatever you want to call it) there should be a Definition of Done.  This definition should describe the requirements to be met before that unit of work can be considered complete, and the next unit of work is begun.  Whatever those requirements currently are, they should be updated to include a clean bill of health for the build.  Appropriate tests should be added and the entire build should complete successfully.  Nobody gets to pick up another piece of work until this happens.  Refuse to allow breaking changes into the build.

Increase Confidence

By now you've hopefully gotten the build green, and laid out a plan to keep it green.  Even so, there may be tests which you can't always trust.  These tests might flap occasionally, leaving developers unsure if they've broken something or not.  If you can't trust the build you can't be sure of the quality of the software you're building.  Investigate the root cause of the flapping tests and address it as quickly as possible.  In the meantime take steps to fix the tests themselves as well.  Maybe they need to be rewritten, or moved into another, more stable layer.  Maybe there are timing issues which can solved by increasing the timeout values.  Maybe they should just be eliminated, as flapping tests are useless in terms of confidence in the build. Whatever the case, do whatever you have to create a reliable and consistent build.

Spread the Pain

Don't try to take on the world on your own. Instead, enlist everyone else to your cause.


Make everyone responsible for keeping the build green.  Chances are good you're going to need backing from the technical leadership to get everyone in line, as behavior doesn't change overnight and some developers will need an incentive to change.  Maybe this means a rotating responsibility in the beginning, but the goal is to make everyone responsible for the entire codebase, and at the very least responsible for the code they are pushing.

Educate and Train

A major cause of headache-inducing codebases is that many developers simply don't know how to do better than they already are.  They may not know how to properly unit test, or maybe they haven't been introduced to Test-Driven Development before.  Maybe they are simply inexperienced and need to be educated on common engineering practices and principles, such as SOLID, DRY, and the concepts of clean code.  Take this opportunity to help everyone step up their game.  Start holding a regular code club to practice these principles away from the production code.  Start a programming book club and encourage everyone to participate.  Do something to help everyone improve, as this will pay out for everyone, both in the short term and in the long term.

Communicate

It's amazing how often problems can be solved by simply talking about them.  Encourage the team to communicate about the issues they're having, especially when it concerns a broken build.  Often, simply acknowledging that the build is broken is enough to start a conversation about how to fix it.  Also encourage communication even when the build is not broken; make it a point to regularly get together and talk about what could be improved, both within the code and without.  It doesn't have to be an hour long meeting, it could just as easily be 15 minutes or less, which is enough time to get the team thinking about the problem at hand.

Give It Time

Change doesn't happen immediately, but if you keep at it and keep everyone on their toes it will happen sooner or later.  Eventually you'll notice a difference; instead of the build being red and people just shrugging it off you'll start overhearing conversations about how to get it fixed and fast.  Just as people got used to the build being broken all the time they'll become used to the build being green all the time.  They won't tolerate broken windows, and they'll make an effort to fix them as soon as they happen.



Saturday, September 5, 2015

Android Dev and API Keys - Keep It Secret, Keep It Safe

The Problem

You have an external API you must call which requires an API key.  This key must not be checked into source control.  Maybe you have other values which are different depending what environment you're in. Either way, you don't want these hard-coded into your source code.

The Solution

Disclaimer: The following solution was synthesized from a couple of disparate StackOverflow answers which I am now unable to find.

1. Create a properties file in which to store your sensitive security/environment values.  Properties in this file follow the standard format of key=value.  Lines may be commented out by prefixing them with the "#" symbol.  You'll want to create a properties file for each environment you'll be working in (e.g. debug, release, etc).

IMPORTANT: Add each of these files to your .gitignore file (or your version control equivalent).

Example properties file:
key.password=somepassword
#key.alias=somekeyalias This line is commented out
store.file=/home/jim/keystores/mykeystore.store
api.key=myapikey
store.password=mystorepassword

2. Update your build.gradle file pull the values out of your property file for each environment.

In app/build.gradle:
android {
    //Lots of other configuration stuff not shown here.
    buildTypes {
        debug {
            Properties properties = new Properties()
            properties.load(project.rootProject.file('local.properties').newDataInputStream())
            def apiKey = properties.getProperty('api.key')
            resValue "string", "api_key", apiKey
            // other debug config stuff not shown here            
        }
        release {
            Properties properties = new Properties()
            properties.load(project.rootProject.file('release.properties').newDataInputStream())
            def apiKey = properties.getProperty('api.key')
            resValue "string", "api_key", apiKey            
            // other release config stuff not shown here
        }
    }
}

Notice the lines where we are calling 'resValue "string, "api_key", apiKey'? This is essentially telling the build to replace the resource value "api_key" anywhere it is used with the value in the variable apiKey.

3. Add a string value to your res/values/strings.xml file to refer to your value.
In res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>    
    <string name="api_key_string">@string/api_key</string>
    <!-- Other values not shown here -->
</resources>

4. Update your AndroidManifest.xml file to make your values available to the application via meta-data.

In app/src/main/AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.yourpackage">
    <!-- Other configuration not shown here -->
    <application
        android:name=".some.applicationName"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
            <!-- Other configuration not shown here -->
        <meta-data android:name="api-key"
            tools:replace="android:value"
            android:value="@string/api_key_string"></meta-data>
            <!-- Other configuration not shown here -->
    </application>
</manifest>

Notice that on our <meta-data> tag we have defined an android:name attribute with the value "api-key", and we are using tools:replace="android:value".  This allows us to point to the value being held in our strings.xml file, referred to as "@string/api_key_string".

5. Finally, we can now refer to our value in the production code by accessing it via a Bundle.

Production Code:

        //You'll need to get a hold of your ApplicationContext for this step.  
        String apiKey;
        try {
            ApplicationInfo applicationInfo = yourApplicationContext.getPackageManager()
                    .getApplicationInfo(yourApplicationContext.getPackageName(),
                            PackageManager.GET_META_DATA);
            Bundle bundle = applicationInfo.metaData;
            apiKey = bundle.getString("api-key");
            Log.d(TAG, "api key: " + apiKey);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();  //Do something more useful here!
        }

That's it! By having your production code access this value via Bundle you've effectively abstracted away any environment-specific concerns; neither do you need to hard-code values anywhere in your source tree. This allows you to safely develop code which is portable to any environment, and frees you from worrying about someone getting access to your security-sensitive values simply by checking out your code.

Thursday, June 18, 2015

Android TDD Series: Test-Driving Views Part 1 - Activities


In my previous post we walked through the initial project setup necessary for test-driving in Android.  In that post we also wrote our first test to show that Robolectric was configured correctly, and I mentioned that we would go into more detail about what that test was doing we got to testing in activities.

A Deeper Dive into Activities

So, here we are.  Let's revisit that test and go into detail about what it is actually doing.

package com.jameskbride;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;

import static org.junit.Assert.assertEquals;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class MainActivityTest {

    private MainActivity activity;

    @Before
    public void setUp() {
        activity = Robolectric.setupActivity(MainActivity.class);
    }

    @Test
    public void whenTheActivityIsCreatedThenTheContentViewShouldBeSet() {
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);
        assertEquals(R.id.main, shadowActivity.getContentView().getId());
    }
}

Lets break this down.

Notice we have a member variable in the test for our MainActivity, activity, and a setUp() method, with this interesting line:

activity = Robolectric.setupActivity(MainActivity.class);

This line is performing some Robolectric magic, but lets take some of the mystique out of it and make it apparent what is happening.  First, if we dig into Robolectric.setupActivity() we discover what we're really doing is the following:

public static <T extends Activity> setupActivity(Class<T> activityClass) {
    return ActivityController.of(shadowsAdapter, activityClass).setup().get();
  }

The ActivityController is getting a handle on our Activity, and calling setup().get(). This is similar to the builder pattern, and get() is simply returning the Activity back to us. Let's take a look at the more interesting ActivityController.setup():

/**
   * Calls the same lifecycle methods on the Activity called by Android the first time the Activity is created.
   *
   * @return Activity controller instance.
   */
  public ActivityController<T> setup() {
    return create().start().postCreate(null).resume().visible();
  }

Now the magic has been revealed. All we are really doing here is walking through the lifecycle methods, in this case create(), start(), and resume() of the Activity to get it into the desired state (Note that "postCreate()" and "visible()" are not lifecycle events, but Robolectric helper methods.).

The example I showed earlier used Robolectric.setUpActivity(), however this does not give you very fine-grained control, as it always sets the activity in the onResume() event. However most of the testing you'll do around activities will be life-cycle based, or related to when Fragments are created, displayed or replaced (more on Fragments in the next installment). As such you'll want to use the ActivityController instead, as it gives you the ability to put your Activity in the correct state for the event that you care about.  Testing in this manner will look something like this:

    
    private ActivityController<Mainactivity> activityController;
    private MainActivity activity;

    @Before
    public void setUp() {
        activityController = Robolectric.buildActivity(MainActivity.class);
        activity = activityController.create().start().postCreate(null).resume().visible().get();
    }

    @After
    public void tearDown() {
        activityController.pause().stop().destroy();
    }

With this level of control you'll be able to use the ActivityController to put the activity in any state you need.  If you have functionality you need to test in Activity.onPause() simply chain calls to the ActivityController and perform a get() at the end:

        
     activityController = Robolectric.buildActivity(MainActivity.class);
     activity = activityController.create().start().postCreate(null).resume().visible().pause().get();

You may have noticed in the tearDown() method above that we are using the ActivityController to walk the activity through additional life-cycle events. This is important, as it insures that any clean-up you may need to do is performed.

Starting Activities and Services


Beyond life-cycle events, two other common task you'll need to perform include starting other activities or services.  Using Robolectic these are trivial to write tests for.  Let's look at starting an activity first.  Here is an example test you might write:

    
    private ActivityController<MainActivity> activityController;
    private MainActivity activity;

    @Before
    public void setUp() {
        activityController = Robolectric.buildActivity(MainActivity.class);
        activity = activityController.create().start().postCreate(null).resume().visible().get();
    }

    @Test
    public void whenTheActionBarButtonIsPressedThenTheSecondActivityIsStarted() {
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);

        shadowActivity.clickMenuItem(R.id.action_button);

        Intent startedIntent = shadowActivity.peekNextStartedActivity();
        assertEquals(SecondActivity.class.getName(), startedIntent.getComponent().getClassName());
    }

In this test we perform a click on an action bar button to fire another activity and use Robolectric to peek at the next started activity. Let's take a look at the production code:
    //Here we are in the MainActivity
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        switch(id) {
            case R.id.action_button:                
                startActivity(new Intent(this, SecondActivity.class));
                break;
            default:
        }

        return super.onOptionsItemSelected(item);
    }

Pretty simple, right? Similarly, we can test that a service has been started from our activity as well:
    @Test
    public void whenTheActionBarButtonIsPressedThenCustomServiceIsStarted() {
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);

        shadowActivity.clickMenuItem(R.id.action_button);

        Intent startedIntent = shadowActivity.peekNextStartedService();
        assertEquals(CustomService.class.getName(), startedIntent.getComponent().getClassName());
    }

Again, we're using this very basic pattern, only this time with a service. Here is the production code:
//Here we are in the MainActivity
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        switch(id) {
            case R.id.action_button:                
                startService(new Intent(this, CustomService.class));
                break;
            default:
        }

        return super.onOptionsItemSelected(item);
    }



This is obviously just a brief introduction into testing activities in Android. As you can see though, most of the activity functionality centers around testing the life-cycle events. Next time I'll go into detail about testing Fragments, and showing their interactions with activities and how to test for that as well.

As usual if you have any questions don't hesitate to ask, and I'm always looking for feedback. Thanks!

Thursday, May 28, 2015

Android TDD Series: The Setup

Previously I spoke about the challenges in following Test-Driven Development in Android.  Armed with the fore-knowledge of what we're getting ourselves into we're now ready to dive into the first serious attempt at test-driving some functionality in.

The App


To make this series a little more light-hearted I'm going to develop an app I'll call the "Business Unit Estimator".  This app will let the user take a picture of someone or someplace and assign how many "Units of Business" can be accomplished by that person or place.  For example, take the gentleman in the meme image below:

Via Quickmeme

This fellow is wearing a tie (+5 units of business right there), as well as a business jacket (+3 units of business), his hair is immaculate (+1 units of business), and he's on a cell phone (+2 units of business, as obviously more work gets done when you're on a phone).  That's a grand total of 11 units of business.  This guy means business!  Silliness aside this will provide an app we can work on to demonstrate TDD in Android.



Pre-Reqs

I'm going to make a number of assumptions before we get going.  First, I'm going to assume you have the following installed on your system:

  • Android Studio 1.1+
  • The latest Android SDK (the previous link will get this for you as well)
  • Java 7 (note: we don't want 8 here, as Android is not compatible with 8)
  • Gradle (preferably installed via GVM)
I'm also going to assume that you know how to create an Android project in Android Studio via the usual File -> New -> New Project with a "Blank Activity".  If you'd like a shortcut on creating the project feel free to check out the demo app on my Github page.

Setup

This entry in the series will focus on your environment setup to allow Test-Driving to occur via unit tests and Robolectric.

Robolectric is an Android unit testing framework that allows you to write tests which will run on the JVM, rather than on the emulator.  This has several benefits.  First, it will greatly shorten your feedback loop, as tests which run on the JVM run extremely fast.  Compare this with the out-of-the-box tools provided by Google which by and large require you to deploy code to emulator, wait for it to load, and finally wait for the test to run and you'll see a huge difference.  A secondary benefit here is that running on the JVM allows you to use a mocking framework such as Mockito to control the behavior of your dependencies.

Throughout this series I'll be using Robolectric 3.  Let's add the dependencies we need in our app/build.gradle file:


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.1'

    testCompile 'org.hamcrest:hamcrest-integration:1.3'
    testCompile 'org.hamcrest:hamcrest-core:1.3'
    testCompile 'org.hamcrest:hamcrest-library:1.3'
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:1.+'
    testCompile 'org.robolectric:robolectric:3.0-SNAPSHOT'
    testCompile 'org.robolectric:shadows-support-v4:3.0-SNAPSHOT'
}

This block should pull in everything we need to write unit tests.  While we won't be using Mockito just yet, we'll need it soon enough.  The shadows-support dependency will provide additional support for accessing parts of the Android SDK in the test environment.  We're also going to use the 3.0-SNAPSHOT versions here as Robolectric 3 is still in RC at the moment; fear not, the API solid despite that.

Next we need to add the app/src/test/java folder in our project structure, as it is not added for us when the project is generated:

Adding the app/src/test/java folder.

Our First Test

Once this is completed we can add our first test:


package com.jameskbride;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;

import static org.junit.Assert.assertEquals;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class MainActivityTest {

    private MainActivity activity;

    @Before
    public void setUp() {
        activity = Robolectric.setupActivity(MainActivity.class);
    }

    @Test
    public void whenTheActivityIsCreatedThenTheContentViewShouldBeSet() {
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);
        assertEquals(R.id.main, shadowActivity.getContentView().getId());
    }
}

There is a lot going on here which we're going to cover in more depth later on, but for now you need to know that the @RunWith and @Config annotations are required to run the Robolectric test. You should also be aware that there are multiple versions of BuildConfig.class, and you'll need to use the one which is generated for your project and not the android.support.v4 or android.support.v7.appcompat versions. Using these versions will cause errors. I'm going to skip over the setup for the moment (we'll cover this in the next entry in the series) and jump straight to the test. When we generated the project a MainActivity class was generated for us under app/src/main/java.

package com.jameskbride;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
Unfortunately (from a TDD perspective) it also added some logic to set the content view. Our first test is going to add coverage for this functionality.
    @Test
    public void whenTheActivityIsCreatedThenTheContentViewShouldBeSet() {
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);
        assertEquals(R.id.main, shadowActivity.getContentView().getId());
    }
As you can see we are using a ShadowActivity, and asserting that the content view ID has been set.  Let's execute the test. From the root of our project we'll run:
./gradlew testDebug

This causes a compilation error, as the id for main doesn't exist yet.
/home/jim/projects/BusinessUnitEstimator/app/src/test/java/com/jameskbride/MainActivityTest.java:28: error: cannot find symbol
        assertEquals(R.id.main, shadowActivity.getContentView().getId());
                         ^
  symbol:   variable main
  location: class id
1 error
:app:compileDebugUnitTestJava FAILED
Let's make this test pass by adding the id field which will allow us to verify that it is set as the content view.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
    android:id="@+id/main">

    <TextView android:text="@string/hello_world" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

The test is passing now and we've successfully demonstrated how to setup and run a Robolectric test. If you'd like to get hands-on with the example code at this point you can check out out from Github.  Join me next time when we'll go more into depth on test-driving Activities.  Also, I'm always looking for feedback, so please leave comments.  Thank you!

Tuesday, May 19, 2015

Code, Creativity, and Beauty

Earlier today I was teaching a class on scrum and XP practices.  During the course of a conversation on Test-Driven Development I made a statement to the effect of “I want to let my tests drive out my design, and not the other way around”.  One of the individuals in the class protested against this. Not against TDD mind you, but against the idea of simply following the narrow path and narrow design that the test was going to cause.  His position was that this method pays no heed to the “creative nature” of software development.  There was further conversation regarding the nature and implementation of TDD that isn’t pertinent here, but his statement stuck with me.

Is there an inherent creativity to software development?

This thought stayed with me for the rest of the day, and as I was washing the dishes just minutes ago I had a sudden dialog in my head on the subject.  You might say (ironically) that my muse visited me, and I was inspired to do something creative.  I rushed to finish the dishes and feverishly started writing out these thoughts before I lost them.

In my daily practice I do not typically stop to consider if, while test-driving a feature, what I’m doing is creative in nature.  I’m building useful things.  These things are going to be employed by someone for a purpose.  Their nature is that of tools, albeit sophisticated tools which are capable of great feats. I know what the thing should do, and I’m writing test code in a way to force the behavior of the code.  Is that creative?  Obviously the simple act of putting syntax to electrons is creative in the sense that you literally just created form and structure where none were before, just as putting these words together for you to read is a creative act.  The question I’m asking is whether there is anything inherently creative (aside from the act itself) in writing code beyond fulfilling a purpose?

Another thought: Can code be considered “beautiful”?

The individual in question also made a comparison of code to music score which I honestly can’t remember now.  I wish I could, but again, this got me thinking.  From my point of view, music and code come from two very different worlds.  Music is creative and beautiful and simply is.  It has not been written to serve a purpose beyond mere entertainment, while software development in general and code in particular was very specifically created to be utilitarian.

There is certainly code which is written purely to be creative and beautiful.  One need search no further than Perl Poetry for examples.  However, ask the average developer if the code that they are working on is beautiful and see how they respond.  They may surprise me, but I think my chances are more than just good that they would describe what they were doing as creating tools to serve a purpose, and beauty and creativity be damned.

Having said this I certainly don’t believe that the act of creating something is in any way at odds with imbuing it utility and purpose.  As a software developer I’ve seen (and endeavored to create, successfully or not) code which is elegant in its simplicity and utilitarian in its application.

Supposing code can be beautiful, how it its beauty derived?  Is is beautiful because it serves a purpose?  Or can it be beautiful simply in its own right?  Can a shovel be called beautiful?  After all, code and shovels are tools which both serve a purpose, though the shovel is infinitely more simple (elegant?).  There is the old saying that beauty is in the eye of the beholder, and that may be so.  If it is, then all code, regardless of its function (or non-functioning nature as the case may be!), could potentially be called beautiful.  This is a concept that is beyond my normal thought processes.  If a thing created for a purpose fails in its purpose can it still be considered beautiful?  If I can’t use the shovel to move material from one location to another can it, as a tool, still be considered beautiful?

To use a metaphor which is probably more familiar to most software developers, can a brick in a cathedral be considered to be beautiful?  Yes, the brick might be used to build a cathedral, and I believe it is a safe thing to say that most people consider cathedrals to be quite beautiful, but is the brick itself beautiful? To take the metaphor further people often point to cathedrals in awe, stating how incredibly beautiful and inspiring they are.  They point to elegant arches, flying buttresses, and columns, and remark at the feelings they invoke in the onlooker.  In deed, part of the purpose (see what I did there?) of cathedrals is to cause a sense of awe and grandeur in worshippers.  The church and its architects, purposely designed it that way.  They also, by the way, designed the arches, flying buttresses, and columns for specific purposes as well.  All of them in their own way support the system of the cathedral, that is they keep the building from collapsing in on itself.  Can they be considered beautiful?  Certainly, as history and wide opinion shows us. However, at the same time they are far more *useful* in purpose than many people realize.  Were they created to be intentionally beautiful while at the same time serving important purposes, or were they simply created to fulfill a purpose?

As software developers is the act of writing software inherently creative, and is the code inherently beautiful, or is it simply the act of building a tool for a utilitarian purpose?

Thursday, May 14, 2015

Android TDD Series: The Challenges

Six months ago I embarked on a journey to write my first Android app.  I'm still on that journey, and though I haven't released yet (soon!) I've learned a number of hard lessons that I'd like to share with those who are on the same path in the hopes that it will make their own journey a little easier.

Before I get to those lessons though I want to talk about some of the challenges I faced when I first approached Android development. First among them is the fact that...


You're Developing Against A Moving Target

Mobile is hot right now, and Android is constantly being updated to keep pace.  When I first started working on the my app KitKat was the latest and greatest.  Lollipop was released a month later, and at the time of this writing it already has close to 10% of the Android market share.  The build tools and support libraries are also constantly being updated, as well as the Gradle plugin and the most popular Android IDE, Android Studio.  As such, the API and your development environment can shift quickly, and library developers have to scramble to keep up.  Information that was accurate a couple of months ago can now be completely out of date.  Libraries that were compatible last week may suddenly stop working.  It's a fast-paced environment, and if you're going to be an Android developer you should be prepared to keep up.  This means following the latest Android news, keeping an eye on third-party tools, and being ready to update on a moment's notice.

As if hitting a moving target wasn't hard enough....



The Framework Is Not Designed For Maintainability


Android was written by people who were attempting to anticipate the varied needs of future app developers, and it's quite obvious that some needs were prioritized over others.  It's also quite obvious that these people (naturally) brought their own biases and schools of thought into the project.  As such, things like testable, maintainable designs and the application of well-understood principles such as Dependency Injection took a backseat to performance.

Reading the Android documentation on managing your memory usage is like reading a diatribe against every good practice you've ever used.  Thinking of decomposing your code into smaller, more focused, more maintainable classes?  Don't do that, think of the overhead!  Want to pull in a known library that meets your needs?  Heavens no, who knows what that library is doing. You should just write your own!  Google even goes so far as to suggest in their documentation that you shouldn't design apps to use the aspects of the framework they themselves provided.  All of these things we do to make our code easier to maintain and test (much less useful!) are flat-out discouraged in the official docs and maddeningly apparent in the implementation.

Admittedly these are some easy potshots to take at Google's expense, and they certainly bring up some interesting data points in regards to their design recommendations.  However, I'm of the opinion that the state of the art for Android has advanced far beyond the point that these recommendations make any sense any more.  This is true in just about every respect; the hardware has improved in leaps and bounds in the space of just a few short years, the ecosystem around Android has grown tremendously, the tooling has been steadily improving, and a thriving community provides an endless number of useful libraries.

Yes, we should eat our vegetables, brush our teeth, and keep performance in mind, but this in no way means we should simply roll over and forget all of the lessons we learned outside of mobile arena.  Gone are the days in which it was acceptable to write monster methods simply to save a few bytes instead of writing new classes and methods.  Gone are the days in which it was acceptable to new-up every dependency inline and call it good enough.   These days there is simply no excuse to not apply the same level of craftsmanship to Android applications as we would to any other project, which leads me to my next point...


TDD Is Hard (But Not Impossible)

There's no two ways about it, Test-Driven Development in Android is daunting.  Coupling the issues with maintainability I mentioned above with the fact that out of the box there are little to no testing tools available makes getting started with TDD a difficult proposition.  Luckily, the Android community has risen to this challenge, and Google has responded to the need for test support with updates to the build tools and other improvements.  Testing tools such as Robolectric used in conjunction with dependency injection frameworks such as Dagger and a healthy dose of mocks (via Mockito or similar) go a long way towards making testing a much less frustrating experience. Functional testing is now simplified as well, as frameworks such as Espresso and Robotium provide easier and more reliable UI interactions than the standard ActivityInstrumentationTestCase2 style tests.  

Even with these tools though testing is still not easy if you're not careful to design your app to be testable.  It is all too easy to simply succumb to the framework if you don't take the time to become intimately familiar with its ins and outs, and to learn when you can and should ignore a design recommendation.  Inline, anonymous listener classes?  As Dikembe Mutombo would say, "Not in my house!"  Business logic embedded in a framework class?  Nope!  It takes diligence and a critical eye for every design decision if you're going to test-drive your code in Android.  Be ready to go off the beaten path.  By the way....


If the Path Doesn't Exist, You Might Have to Build It

As I said earlier, Android is a moving target, and library developers have to scramble to keep up.  Often the pace of advancement is quick enough that the support you're looking for might simply not be there yet.  I've already had to contribute to more than one project in order to remove roadblocks for development, and chances are good that if you're reading this as an aspiring Android developer you might have to as well.  If you're using Robolectric be ready to extend Shadow classes when it becomes necessary.  Also, don't be afraid of cloning a project and pulling down the source to research a bug in your third party libraries, or of figuring out a fix to contribute back. 


These are just a few of the challenges I've encountered while developing my first Android app, and I've outlined them here to give other developers an idea of what to expect when they enter this arena. Over the course of the next several months I'll be writing an Android TDD Series, in which I'll try to provide concrete examples of how to test-drive various pieces of functionality in an example app.  I hope you'll join me here, and I look forward to your feedback.  Thanks and happy app dev'ing!

Thursday, April 9, 2015

Velocity Multipliers


I'd like you pause for a moment and think about the project you're currently working on.  What is the longest, most painful process in your workflow?  What is the step that, when you reach it, you say to yourself "Well, now I have to stop being productive while I do this."?

Really think about it.

All done?  Did you think you of some manual, repetitive step?  Did you think of your build?  Is it testing?  Is it your deployment process?  Is it an organizational process?  Did you think of more than one thing?  

Now, think about how your could reduce the amount of time it takes to accomplish this task. What impact would that have?  How much time could you save?  A few seconds? A few minutes? A few hours?  How much money could you save?  How much faster could you deliver value if you didn't have so many yaks to shave?

Whatever method you just thought of to reduce the required time for that task, that is a velocity multiplier.  Put another way, velocity multipliers are any practices, actions or processes that can be used to shorten the development feedback cycle.  They are the little hacks that have a big impact on productivity and the major practices that keep the project rolling along smoothly.  They are the tools that, after you start using them, make you wonder why you hadn't been using them all along.

Examples of Velocity Multipliers


Know Your Tools: If you are working with a particular set of tools then you should take the time to become intimately familiar with them.  Working in Linux?  Get to know Bash inside and out.  Using Intellij?  Learn all the shortcuts.  No matter what programming language you're working with take the time to learn everything you can about it.  Do these things not to simply know them for the sake of knowing, but to know how to use them well and how to use them quickly.

Maintain A Toolbox: Every craftsman has a toolbox that they maintain in order to let them do their job more efficiently.  This is just as true in software development as it is in any other trade. These tools often start out as one-off scripts that might one day become full-fledged applications and they end up paying dividends in the amount of time you save by re-using them.

For example, as a technical interviewer I'm often asked to conduct a pair-programming interview with candidates in which the candidate is asked to come prepared to write code in the language of their choice.  Frequently, and despite the candidates' best efforts, their environment is misconfigured and not in a state to write code.  I've come to expect this problem, and I now maintain a number of skeleton projects in my github account.  If a problem is encountered I simply pull down the appropriately skeleton on my machine and set up a new project so we can begin the coding exercise without further adieu.

Automate Repetitive Manual Tasks: How many times have you had to type the same long command or set of commands to accomplish a task?  Why not just write a script to do it for you?  This will 1.) save you time, and 2.) reduce the number of mistakes when performing the task.

As an example, in a previous role I was frequently asked to generate ad-hoc reports for my project manager.  I quickly discovered it was more efficient to keep the SQL scripts around for re-use later than to rewrite the scripts by hand every time the request came through.  These scripts saved me a ton of time and made my project manager very happy.

Optimize Your Build: This may take some work if you're dealing with a large codebase, but it is in the large codebases that you'll see the most gains.  First things first: kill the monolithic build.  If you have to build the entire codebase just to run a subset of tests your feedback loop is too long.  You should be able to run your unit tests almost instantly, and your integration tests nearly as fast.

A modularized build will not only allow you to build a subset of your code quickly, but it will also open the door to other optimizations, such as distributing the build across multiple nodes and running your tests in parallel.  Modularization will also help you to tease out dependencies, and to eventually starting breaking the codebase into several smaller, more manageable pieces.  Once this occurs it becomes much easier to have multiple teams working on the code at the same time without stepping on each other's toes.


These are just a few examples of how you can use velocity multipliers to reduce your feedback loops.  Each project is unique, and I'm sure that if you were to examine your workflow you could find optimizations just waiting to happen.  Often these optimizations are not realized because we think to ourselves "Sure, I could write a script to do that, but it would take a while to do and in the meantime X won't get done."  To this I reply with Nike's old stand-by: "Just do it." Whatever time you spend to save yourself time for the next N-infinity times doing it will be worth it.  Don't waste another minute, save yourself and your team hours.

Wednesday, April 1, 2015

Software Craftsmanship Vs The Iron Triangle: Cut Scope, Not Quality

"You can have it fast, cheap, or good.  Pick two."

This phrase is all too familiar to anyone who's spent any amount of time in software development.  For those who might not have heard of this phrase, it's a layperson's way of talking about the Iron Triangle of project management, which describes the constraints that every project must operate under.  These constraints are scope, schedule and cost, where scope is the requested functionality and features the system should provide, and schedule and cost are time and money, which are obviously not unlimited.

The Iron Triangle

Creating balance between these three constraints can make or break any given project, and while literal reams of articles and books have been written on the subject not much has been said regarding how software craftsmanship fits in (hint: often poorly).  This is unfortunate because life in this modern age is increasingly dependent on technology and the software that is directing it. Making decisions which allow low-quality, defect-ridden code out into the wild will have an equally increasingly costly and dramatic effect on an increasingly large number of people.  It follows then that software craftsmanship will become increasingly important to insure that high-quality, defect-free code is released instead.

Having said this I believe it is important to reflect on where software craftsmanship fits into the Iron Triangle.  As a craftsman I don't believe that quality should be sacrificed simply for the sake of expediency.  I believe that if code is to be written it should be written well.  It should be well-tested (Test-Driven!), follow good design principles, and be maintainable among other things.

This stance is not unreasonable, it is in fact the only truly reasonable approach in an industry which can have such a tremendous impact on millions of lives.

To take it out of the terminology of software development and into construction, no one ever goes to the general contractor and says "I can't afford a well-built mansion.  How about you still build me the mansion and just use cheap materials and work overtime to get the job done?"  If they did they the contractor would discretely laugh at the would-be mansion owner and suggest that they instead build a smaller house.

Unfortunately, if you find yourself in a situation where craftsmanship is at odds with the (ever-shifting) constraints of scope, schedule and cost you'll quickly find that the organization's appreciation for well-crafted, maintainable and incrementally delivered code will often take a backseat to cost-cutting, corner-cutting and a "Just ship it!" approach.

Knowing how organizations react when confronted with the choice between supporting well-crafted code and the need to simply ship something we, as craftspeople, should strive to truly understand what the organizations goals and constraints for a project are, and be ready offer approaches which don't call on us to sacrifice the quality of the software.

Let's get back to the "fast, good, cheap" quote I first mentioned and see how craftsmanship fits into each of the scenarios.

Fast and Good

Under the right conditions craftsmanship can thrive in this category.  If the scope is reasonable and the organization has the budget to support a team of knowledgeable craftspeople then a lot can get done quickly.  Obviously there are a lot more factors involved in the success for any project, but a highly motivated and experienced team can crank through an amazing amount of features.

On the other hand, if the scope is outrageous (which, lets be honest, is the more common case) or the budget can't support a team of experienced developers then the level of craftsmanship on the project is at risk.  The business may be tempted to say "All that unit testing you're doing is taking too long, can't we just skip that?", or simple budgetary concerns may cause them to under-staff the project.  Countering these two possibilities from the craftsmanship angle may involve suggesting cutting scope to deliver value while staying within budget, and delivering incrementally to give them something to get their hands on early in the process. 

Fast and Cheap

This is is dangerous territory for a craftsperson.  If the organization wants it done now and they don't want to pay a lot for it then by default they're not really concerned with the quality of the software.  They're concerned with ramming through the project and delivering something. High cost doesn't necessarily equate to a high degree of craftsmanship, but they often go hand-in-hand.  Again, as craftspeople we shouldn't be willing to sacrifice quality just to ship something.  The play here is to cut scope again if possible, and if that doesn't work then you may need to consider walking away from the project (a difficult decision to make in many cases).

Cheap and Good

This is an odd scenario to be in, as it implies that the organization wants it done well and inexpensively, but that it's OK for the project to take longer.  The "taking longer" part doesn't normally equate to inexpensive, as the longer the project runs the more expensive it will be.  If the timeline is fixed (as most projects are), then this scenario implies that the organization can't afford a team of craftspeople to tackle the problem, which places us squarely back in "Fast and Cheap" category.  Again, cutting scope, not quality, and delivering incrementally should be explored as options.


Convincing the organization to accept a reduced scope on a realistic timeline with a realistic budget is hardly ever an easy sell.  Often organizations are unable to fathom why what they're asking for is nigh-impossible and will instead push to either rush the project or ask that it be done on a shoestring budget.  Nevertheless, it is up to craftspeople to offer alternative solutions and to refuse to sacrifice quality in the face of adversity.  To those craftspeople who are facing this dilemma I say this: Good luck and stand firm!



Wednesday, March 25, 2015

What Is A Good Tech Lead?

Tech leads come in a variety of shapes and sizes, and there has been a lot written on the subject of just what constitutes a "good" tech lead.  A bad tech lead can break a team, but a good one can keep the team running smoothly.  Not everyone can fill this role, and though it takes some care to find the right person it isn't as hard as some may think. As someone who has been in this role more than once (including my current role) I have some opinions on what makes a good tech lead, including what personality traits and behavior one should look for.

What Is A Tech Lead?

Before getting into what a "good" tech lead is lets talk about the role itself.  In general a tech lead is a member of the software development team who helps to coordinate the team's efforts.  They help to insure that the team's momentum is of the forward variety.  Among other things they are also responsible for communicating up and outside of the team with various other project members, including the project manager, delivery lead, product owners, architects, etc.  As the name suggests tech leads are expected to have a high degree of technical competency, and to be able to more than hold their own in a technical conversation on the project.  They should be able to make technical decisions about the project, and have a high degree of domain knowledge to make sure the decisions are well-informed.

This is a pretty cut and dry explanation of the role, making it easy to identify who should fill the role, right?  Riiight.  Let's give it a little more nuance, shall we?


What A Tech Lead Isn't

Tech lead isn't just a title.  It turns out you can't just point to a random developer on the team and appoint them to be the tech lead.  Someone either is or is not a a tech lead, based on their personality and the behavior they exhibit.  The tech lead on the team is the individual other developers go to when there is a problem that they can't solve themselves, regardless of whether that person actually fills that role in an official capacity. They're also the one who willingly takes on extra responsibilities in the interest of helping the team to complete the project.

A tech lead is not simply the strongest technical member of the team.  A lot (most?) of developers are perfectly happy to be heads-down and working on the code which is right in front of them.  They'd rather not deal with anything outside of their immediate codebase, much less deal with the politics of the project.  This is actually a very good thing, as having strong developers on the team who only have to focus on implementing features and fixing bugs keeps the project rolling. Moreover, taking a strong developer and putting them into the tech lead role based solely on the fact that they can crank out user story after user story is a great way to kill their motivation.  A tech lead may be strong technically, but they'll have the ability to communicate and demonstrate a willingness to put up with the additional hassles of being a lead.

A tech lead is also not a manager.  If the "tech lead" is spending all of their time in meetings coordinating "resources" and zero time with their hands in the code with the rest of the team then guess what, that person is not the tech lead.  They're a manager, or well on their way to becoming one.

Having gotten all things Not Tech Lead-y out of the way lets move on to what a good tech lead.

Personality Traits

There are a number of personality traits that a good tech lead should exhibit (this isn't a comprehensive list):
  • Decisiveness - My all-time favorite quote is "He who hesitates is lost."  Above all a tech lead should be able to make a decision when no one else can.  In essence they should lead.  This doesn't mean charging in blindly when there isn't enough information, but it does mean that for given a situation the tech lead should find a way forward for the team.
  • Impatience - A good tech should be impatient to solve the business' problems.  They should be chomping at the bit to tackle the technical challenge.  Moreover they should be impatient to remove blockers for the team, and intolerant of processes and practices which slow or stop the team's ability to deliver business value.  
  • Bravery - A good tech lead should be brave enough to challenge the status quo and to push for continuous improvement.  If existing processes are a hindrance to delivering value than the tech lead should be brave enough to step up and point out their flaws and suggest improvements.  They should also be brave enough to speak painful truths if they need to be heard, both within and without the team.
  • Humility - By the nature of the role they are in very little that the tech lead accomplishes is actually directly attributable to them.  In fact, it is the team itself that achieves the goals of the project.  A good tech lead should recognize this.  The tech lead might help to coordinate the work, and may even have some excellent technical insight to share, but at the end of the day they are just another member of the team (or should be!).
  • Can-Do Mindset - When given a difficult project, or a particularly complex technical problem to solve the tech lead should be approach these issues with the mindset that they are problems that can be be solved, and they should encourage the team to approach the problem in the same way.  They should be the one to point out that a two meter exhaust port can in fact be hit with a proton torpedo (After all, they used to bullseye Wamp Rats back home with their T-16, and they weren't much bigger than two meters!).  

Exhibited Behaviors

Beyond personality traits there are also certain behaviors that a good tech lead should be exhibiting.  Again, this isn't a comprehensive list by any means.  
  • Technically Excellent - Tech leads should more than just competent developers.  They should be technically adept in the project tech stack, and should be able to quickly learn new new technology and adapt to new techniques and practices.
  • Delegates to the Team - A good tech lead doesn't try to tackle every problem themselves.  They can let go and trust the team to do their jobs and complete the work.  The tech lead should not be the hero who saves the day.  If they are then they're not doing their job to grow the team.
  • Knows the Strengths and Weaknesses of Their Team - Every team is made of different personalities, and developers all have their own individual strengths and weaknesses.  A good tech lead should understand what each developer's strengths are (to be played on), their weaknesses (to be nurtured into strengths), and what makes each member of the team tick.
  • Aggressively Defends the Team - This is important. There will be times when unreasonable demands may be made of member of the team, such as requests to do work that is not related to the project, or to stay late for an arbitrary reason.  There may also be times in which outside entities come into conflict with the team for one reason or another.  It is the good tech lead's job to defend the team from these unreasonable demands for their time, and to intervene between the outside entity and the rest of the team in order to keep them focused on the project work.
  • In the Business of Building People Up - Another big one.  A good tech builds his or her people up.  Not just for the project, but for the team members themselves.  A good tech lead encourages their teammates to continue to learn and grow, and supports them in these activities. More selfishly the tech lead should also be looking for a replacement, someone who will eventually take their place.  After all, as tech lead you don't want to stay on the same project forever do you? 
  • Able to Occupy the Nether Realm Between Technical and Non-Technical Communication - A good tech lead is capable of not just speaking the tech lingo, but also of speaking the business lingo.  They should be able to communicate with non-technical individuals who have a stake in the project.  A good tech lead is able to explain technical issues in non-technical terms when the times call for it. 


As a tech lead myself I've had to learn the hard way how to be effective in the role.  I've been fortunate to have a lot of good role models, as well as a number of not so great role models to learn from.  I've made plenty of mistakes, but I try to learn from them whenever that happens.  I don't believe anyone can simply jump into the tech lead role and instantly be good at it.  It is a role that demands that you attend the school of hard knocks, no shortcuts allowed.  The trick is finding someone who doesn't mind that kind of higher education, and who can thrive in adverse situations and come out the better for it, all the while keeping the team together and advancing forward in their goals.

I hope these insights are useful to anyone looking to find a tech lead, or who might be interested in becoming one themselves some day.  Thanks for your time, and if you have any of your own insights to share please leave them in the comment section.