Sunday, 22 March 2015

Wormholes through code

We have been using Jade to render our HTML pages. It's a neat templating engine for Node that values concise syntax above all else.

One of the benefits of using Node for your web backend is that you can literally reuse the exact same code verbatim on the both the server and in the browser. The first time it happens to you you might feel like you just took a wormhole through the coding space time continuum.

I had a seemingly simple problem that I was reading the most frustrated advice for. All I wanted to do was to use my Javascript object in Node in the browser.

On the server we had an object that looked like this:
module.exports.countries = {
    'CA': {
        name: 'CANADA',
        regions: {
            "AB": "ALBERTA",
            "BC": "BRITISH COLUMBIA",
            "LB": "LABRADOR",
            // Skip a few...
            "YU": "YUKON"
        }
    },
    'US': {
        name: 'UNITED STATES',
        regions: {
            'AL': 'ALABAMA',
            'AK': 'ALASKA',
            'AR': 'ARKANSAS',
            // Skip a few...
            'WY': 'WYOMING'
        }
    }
};
And I wanted to use this exact same data structure on browser. Ideally the the client side javascript would like like this:
var countries = { /* same as above */ }

/**
 * Update region based on selected country.
 */
$('#country').change(function () {
    var country = $('#country').val();
    var regions = countries[country].regions;
    // Populate dropdown with regions...
});
Here's a well asked question in which it was collectively decided to make an Ajax call to get the data. This just seems wrong. Why would you make a second network request to get data that you already had?

All the Ajax call is doing is converting an Javascript object in node to a string on the server, and then an HTTP response to a Javascript object in the browser. We can do that ourselves by calling JSON.stringify or util.inspect and render the Javascript object as is:

// We render in Node as usual.
res.render('my_page', {countries: geo.countries});
//- In Jade, lines beginning with dash (-) are run on the server.
- var countriesJson = JSON.stringify(countries)
// Exclamation point (!) tells Jade not to escape output. Otherwise the quote is escaped as " which is definitely not going to compile in the browser.
var countries = !{countriesJson};
Viola, problem solved.

Wednesday, 11 February 2015

Sleuthing for Padding

Anyone who has done UI polish has had moments where they just can't figure out where some extra padding is coming from.

So I am looking at the action bar and the icons look too far down. I've checked everywhere can can't figure out where the offset or padding is coming from. It's probably because recently I switched to using a Toolbar in the layout instead of the regular action bar, but I can't go back even if I wanted to.

After checking all the padding, margins, translations on the toolbar and coming up empty, I bring up the "now I mean business tool": the hierarchy viewer.

Sure enough I can see that the icons have some kind of offset.


The hamburger icon is too low. What about the action bar itself?


Nope, action bar is right on. What about the menus?


Yep, their too low too.

My options are looking dim. Either I add an offset myself to compensate for the mysterious extra padding or I throw out the Toolbar all together. I know that the answer has to be somewhere so I start checking the Android source as a Hail Mary. I guess that the only other thing that could be doing it would be the Toolbars onLayout().

Something is suspicious about the getChildTop:
private int getChildTop(View child, int alignmentHeight) {
    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    final int childHeight = child.getMeasuredHeight();
    final int alignmentOffset = alignmentHeight > 0 ? (childHeight - alignmentHeight) / 2 : 0;
    switch (getChildVerticalGravity(lp.gravity)) {
    case Gravity.TOP:
        return getPaddingTop() - alignmentOffset;
    // ...
Where is that alignmentHeight coming from? It turns out it's coming from Toolbar.minHeight. Now that code looks like a bug. It shouldn't be trying to center the icon when the gravity is TOP and it's already greater than minHeight.

Android being open source really comes in handy. I can see that to bypass the bug I just need to set minHeight to 0.
// There is a bug in Toolbar where minHeight is being used incorrectly to create an offset when
// laying out the children. So we use 0 for minHeight so that the bug is not exposed.
mActionBarToolbar.setMinimumHeight(0);
Let's see the results.


The icons look better centered.


And in fact are.


Looks like it's going to be a great day after all.

Wednesday, 4 February 2015

Programming Without Ifs

This is a Lunch & Learn I had fun presenting.

Most programmers started from a structured programming background. Moving to a more objective orientated approach often never occurs to developers. Learn a simple technique that can change the way you think about your next coding solutions!

Programming without Ifs - Slides

Programming without Ifs - Notes

I was sure many people would get the Monty Python air speed velocity of an unladen swallow joke. Actually, the audience was too young, only a couple people got the reference.

Wednesday, 28 January 2015

Passing Errors to Async Threads

A common listener pattern is to have two methods: one for success and one for errors.
/**
 * Listener for an async event. 
 * Sometimes you will see many similar listeners rather than templates.
 */
interface AsyncListener<T> {
    /**
     * Everything went okay and you use the result.
     * You may not include the request object as a parameter, 
     * although I have found that it makes the API easier to use if you do.
     */
    onSuccess(Object request, T result);
    /**
     * The async call failed for some reason.
     * What type of class should ErrorInfo be?
     */
    onError(Object request, ErrorInfo error);
}
Typically you will add this as a parameter to an async call, or you will have addListener() method for some kind of request object.
// As a parameter to an async call
void execute(AsyncListener<Result> listener);

// Using an addListener() method
void addListener(AsyncListener<Result> listener);
void execute();
What kind of class should ErrorInfo be? You are going to use this class a lot so you are going to want to it to be robust and easy to understand. You are going to want to preserve all the information you need for logging and responding programmatically to different types of errors.

The following class is small and simple, yet has had a few iterations and is battle hardened from many projects.

A Favorite Story

/**
 * An error that occurred that has to be reported to a listener or on another thread.
 */
public class ErrorInfo implements Parcelable {

    private int mErrorCode = 0;
    private String mDebugMessage;
    private String mUserMessage;
    private Bundle mContextData;
    private Throwable mException;

    /**
     * Use Builder.
     */
    protected ErrorInfo() {
    }

    /**
     * @return Code that can be used for custom logic flow.
     *         0 means no code has been set.
     *         Should be from an id defined in XML to avoid clashes.
     */
    public int getErrorCode() {
        return mErrorCode;
    }

    public String getDebugMessage() {
        return mDebugMessage;
    }

    /**
     * @return Message to be displayed to the user. This might be a special message from the server via an HTTP error
     *         response.
     */
    public String getUserMessage() {
        return mUserMessage;
    }

    public Bundle getContextData() {
        return mContextData;
    }

    public Throwable getException() {
        return mException;
    }

    @Override
    public String toString() {
        // Note: do not use reflectionToString() because we want these names kept after obfuscation.
        ToStringBuilder builder = new ToStringBuilder(this, new ShortToStringStyle());
        if (mErrorCode != 0) {
            builder.append("errorCode", mErrorCode);
        }
        builder.append("debugMessage", mDebugMessage)
                .append("userMessage", mUserMessage);
        if (mContextData != null) {
            // output the contextData keys individually so even if there is a really long key we will get a chance to
            // see some of the other keys.
            for (String key : new TreeSet<String>(mContextData.keySet())) {
                String value = String.valueOf(mContextData.get(key));
                builder.append("contextData:"+key, StringUtils.abbreviate(value, 1000));
            }
        }
        if (mException != null) {
            builder.append("exception", ExceptionUtils.getStackTrace(mException));
        }
        return builder.build();
    }

    /**
     * Parcelable constructor.
     */
    private ErrorInfo(Parcel in) {
        mErrorCode = in.readInt();
        mDebugMessage = in.readString();
        mUserMessage = in.readString();
        mContextData = in.readBundle();
        mException = (Throwable) in.readSerializable();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mErrorCode);
        out.writeString(mDebugMessage);
        out.writeString(mUserMessage);
        out.writeBundle(mContextData);
        out.writeSerializable(mException);
    }

    public static final Creator<ErrorInfo> CREATOR = new Creator<ErrorInfo>() {

        @Override
        public ErrorInfo createFromParcel(Parcel in) {
            return new ErrorInfo(in);
        }

        @Override
        public ErrorInfo[] newArray(int size) {
            return new ErrorInfo[size];
        }
    };

    public static class Builder {

        private ErrorInfo mError = new ErrorInfo();

        public Builder setErrorCode(int errorCode) {
            mError.mErrorCode = errorCode;
            return this;
        }

        public Builder setDebugMessage(String debugMessage) {
            mError.mDebugMessage = debugMessage;
            return this;
        }

        public Builder setUserMessage(String userMessage) {
            mError.mUserMessage = userMessage;
            return this;
        }

        public Builder setContextData(Bundle contextData) {
            mError.mContextData = contextData;
            return this;
        }

        /**
         * Convenience method for creating a bundle and adding a serializable to it.
         */
        public Builder setContextData(Serializable contextData) {
            if (mError.mContextData == null) {
                mError.mContextData = new Bundle();
            }
            mError.mContextData.putSerializable("data", contextData);
            return this;
        }

        /**
         * Convenience method for creating a bundle and adding a serializable to it.
         */
        public Builder setContextData(Parcelable contextData) {
            if (mError.mContextData == null) {
                mError.mContextData = new Bundle();
            }
            mError.mContextData.putParcelable("data", contextData);
            return this;
        }

        /**
         * Chains ErrorInfo using contextData. Copies debugMessage and userMessage if it has not been set yet.
         */
        public Builder setContextData(ErrorInfo contextData) {
            if (mError.mContextData == null) {
                mError.mContextData = new Bundle();
            }
            mError.mContextData.putParcelable("caused_by", contextData);
            if (mError.mErrorCode == 0) {
                mError.mErrorCode = contextData.mErrorCode;
            }
            if (mError.mDebugMessage == null) {
                mError.mDebugMessage = contextData.mDebugMessage;
            }
            if (mError.mUserMessage == null) {
                mError.mUserMessage = contextData.mUserMessage;
            }
            return this;
        }

        public Builder setException(Throwable exception) {
            mError.mException = exception;
            return this;
        }

        public ErrorInfo build() {
            if (mError.mException == null) {
                mError.mException = new Exception("ErrorInfo built here");
            }
            return mError;
        }
    }
}

Usage

// When catching an exception
try {
    Result result = calculateResult();
    listener.onSuccess(this, result);
} catch (Exception ex) {
    listener.onError(new ErrorInfo.Builder()
                          .setException(ex)
                          .build());
}

Wednesday, 21 January 2015

Sign Android APK with iOS Key

I was given what looked like an iOS signing key for our nice new Android app. Based on the instructions they asked for I was expecting a jks keystore file as created by keytool. Before I sent them a reply saying I could not use the iOS key, I figured I would try to make it work first.

The Magic


First we need to convert the key into something that keytool can import into our keystore. It turns out that keytool can import a private key by using a work around that uses two different features: using a PKCS12 formatted key as a keystore and merging keystores.

A Quick Read


# Convert PEM to PKCS12 format.
openssl pkcs12 -export -out certificate.pfx -in certificate.pem

# Import into our keystore
keytool -importkeystore -destkeystore my-keystore.jks -srckeystore certificate.pfx -srcstoretype PKCS12 -alias 1

# The openssl export does not preserve the alias name, it uses "1", so rename it.
keytool -changealias -alias "1" -destalias "my_signing_key" -keystore my-keystore.jks

Wednesday, 14 January 2015

Implementing Thread Yield in Javascript

I had a problem developing for the Samsung Smart TV where there was a lot of data coming back from an Ajax request. The time it took to process the data from the Ajax request was halting UI responsiveness. Basically the UI would stop reacting to the user while this data was being processed, which on the TVs limited CPU power took about 20 seconds.

Normally with a language that supports multithreaded processing you would just run the process in a background thread. What can we do in Javascript where we only have one thread?

The Magic


There is a concept in threading called Yield that halts the current thread and allows another threads to run. We could do the same thing by turning what is normally a loop with a Thread.Yield call into tail recursion using setTimeout.

The Novelty

var processWithYield = function(total, chunkSize, processData, onComplete) {

 var processNextChunk = function(begin) {
  
  if (begin < total) {
   
   var end = begin + chunkSize;
   if (end > total) {
    end = total;
   }
  
   console.log("begin "+begin+", end "+end);
   processData(begin, end);
   
   console.log("Done processing, now we are setting next timeout beginning at "+end);
   // Yield the thread by processing the next chunk in 100 milliseconds instead of right away.
   setTimeout(function() {
    processNextChunk(end);
   }, 100);
  } else {
   console.log("All processing completed");
   onComplete();
  }
 };
 processNextChunk(0);
};

Variability


I would tweak the timeout length and the chunkSize until I had the desired data processing time vs. UI responsiveness ratio I wanted.

Further Research


Rather than using a chunkSize and a timeout length the time could be used to determine when a yield should be done. The time could be checked each iteration, then the processData function would only take one row at a time. If checking the time itself was costly in terms of CPU it could only be done once every 2 or more iterations depending on the time it takes to perform one iteration.