Saturday, August 29, 2015

Enumerated Types - Java

Coming from a long C++ background, one of my favorite constructs in Java was the simple enumerated type. I found the added full-fledged, "class-like" behavioral characteristics useful from the beginning. Just the simple ability to specify a string value in the element constructors alone almost doubles the power of a C++-like enum because it allows you to essentially make String enumerated types when coupled with a toString() method overload. Of course there is much more power to the Java enumerated type's class-like capabilities than just this. One of the first really interesting usages I found for an enum was to create a simple state machine. I no longer have the source code, but if you are interested in how to do this web search for it, there are others who have done this.

When creating API's I find the bounded nature of enums to be self-documenting when used as parameters such as keys in key-value pairs, as opposed to traditional usage of strings. Additionally it removes the possibility of bugs from a consumer of the API making a typo in a string key. However, what if you are releasing an API that has both a defined set of key values and the possibility for unknown key values. I find that sometimes you have the need for an "extensible" enumerated type. For example, in one case we were delivering an Android library for usage in client software with a server-side back-end component that could add functionality over time. I wanted to provide the capability for a customer to use new keys delivered via new server functionality even though the library itself was unaware of these keys at the time of the library creation. However, I still wanted the self-documenting, less error-prone way of specifying keys provided by an enumerated type. To get both behaviors, we introduced a simple construct that we called DynamicEnum. A DynamicEnum is a class, not a Java enum, but uses String constants to enumerate the known values.

The DynamicEnum thus has the benefit of providing a set of values for all known element types, and can also be extended by adding additional values. In an upcoming post on usage of the abstract factory pattern I will describe why this can be useful through a real-world example.

Tuesday, August 18, 2015

Use Case: Being a Code Custodian, Manual Inspections



This is the third and final post of this series. Please see the last two posts for my thoughts on what it means to be a code custodian and the application of automated inspection tools in this role.

While automated tests have a place in detecting potential bugs or maintenance issues for a code-base, I find that only manual inspection can detect issues in proper usage of the classes, methods, and design patterns in use for a particular code base. At a recent positions, some of the stylistic things that I looked for in a manual inspection relate to reducing accidental complexity, and include:
  • Crisp and clear interfaces, especially customer-facing API's
    • Well-documented API calls
      • In this case, we used Javadoc
      • Many of the developers were non-native English speakers, making this more critical for our team
    •  Well-named methods
  • Proper usage of existing design patterns within the code base
  • Avoidance of internal packages
    • In our case, we had libraries that had external and internal packages. Sometimes developers would accidentally reach down into an internal package of another library
    • A better approach would have been to find an automated approach for verifying compliance
  • Proper application of standard object-oriented practices
  • Stylistic consistency
    • At a gross-level, without being intrusive
Of course, I also checked for more substantive issues like potential threading issues and other defects, but often the stylistic issues are more noticeable.

To avoid getting behind, I would review checkins on a daily basis on average. With about 10 active developers on the team, it wasn't practical to review every line of code that was checked in. To limit the time commitment I applied a few filters to guide my engagement level:
  • Individual developer expertise
    • Does this a developer have a track record of committing high-quality software?
    • Does this developer have experience in the area of the code that is being changed?
  • Type of code under change
    • Is this a core or performance-sensitive area of the code, requiring more attention?
    • Are the modules under change complex and/or already in need of refactoring
  • Customer-facing
    • Is this a customer-facing API or an internal method that will be obfuscated away?
We had a policy whereby developers were encouraged to ask for reviews of changes to critical and/or complex sections of code. The best developers in the group used this policy judiciously, and I would seldom review checkins by them unless they requested a review.  On the flip-side, if a developer had a track record of sloppy checkins and/or was working in an area of the code with which s/he had little familiarity I was likely to take more notice.

Having a role of technical lead, does not make anyone the expert on everything. I interpret the code custodian role to mean that I should coordinate with other experts on the team to help identify areas of risk and coordinate collaboration, not try to be the sole authority on everything. It's always helpful to get another set of eyes on your code, and I would frequently solicit code reviews for trickier areas of my own code submissions from one or two other senior members of the team. Additionally, I would sometimes ask for help from these same members in performing code reviews of submissions from others on the team that I find to be in a critical portion of the code that I have less familiarity with.

Of course it is very helpful to be intimately familiar with the software before taking on these types of reviews. In this case I had designed and coded much of the initial code base, which made the job easier. Were I to drop into a new code base, I could still look for general code and styling issues, but would be less apt to give any valuable feedback relevant to fitting into existing design patterns and proper usage of libraries, etc.

In an effort to preserve developer freedom, if the issues I detected were all small or stylistic, often I wouldn't say anything, but rather lock it away in case the advice might come in handy in the future as part of more substantive feedback. If the issue is in naming of methods and/or javadoc and the user is not a native-English speaker I might make the change directly in the code base and check it in since the changes are non-controversial and straightforward. For most other types of feedback I would usually make suggestions in an email. Developer woud either follow the suggestions or provide good reasons for not following them. Lastly, I find it can be helpful to reference well-known books by experts in the field when making a point to give it more credence and make it less of a single person's opinion.

In this series of posts I discussed the role of a code custodian in maintaining a clean base. I stress that this is not always an appropriate role and there are many different approaches and techniques. I don't necessarily advocate for the approaches laid out here, but list them by way of an example that worked well in one environment. I found the manual and automated inspections to be helpful but perhaps they would be too intrusive or unnecessary in another environment. In a third environment, perhaps more stringent techniques would be appropriate.

Saturday, August 8, 2015

Use Case: Being a Code Custodian, Automated Inspections



As stated in my last post, the roles of an architect and/or team lead can vary dramatically depending on team dynamics. Being a code custodian may or may not be appropriate for your organization. On the one hand, it's hard to argue against the importance of having a cohesive code base with similar coding patterns and standards for quality. On the other hand, a heavy-handed environment can be very disabling for developers and reduce team members' feelings of empowerment. So how best to balance these competing factors?

A recent long-running project I worked on had the following team dynamics:


  • Varied developer skill levels
    • Fresh from university to senior
  • Combination of remote and local developers
    • Most remote
    • English skills that also varied in quality between team members
  • Mix of time working in the code base
Although we had some written coding guidelines, I find this to be a largely ineffective way of managing a code-base. We did have some standards, but the best standards are already available and published in books such as "Effective Java" by Joshua Bloch and "Clean Code" by Robert Martin.

Instead, I chose to rely on a mix of automated and manual inspection approaches. See my last post for a comparison between these approaches.

Perhaps the most important tenet to developing any of these strategies is to get active participation from other members of the team in their usage and application. Some of the inspections by these tools can feel intrusive and even arbitrary at times. Getting the team or a subset of senior developers on the team to buy-in to the list of checks is important to foster a feeling of ownership to the policy and to avoid tying developers down and hampering creativity. it might take a couple of iterations to refine the rules.

For this situation, we used CheckStyle, FindBugs, and lint in out suite of tools that were run on Jenkins. Checking stylistic rules can be particularly treacherous if applied too heavy-handedly. When looking at CheckStyle, the first thing I did was to immediately drop silly rules such as where semicolons or spaces are placed. There is nothing worse than breaking the build because you missed a spacing constraint. I think that it's important to maintain consistency in the code-base, especially within an individual module. But this consistency does not need to be enforced via an automated tool.

However, that doesn't make the likes of CheckStyle worthless. There are a number of checks within CheckStyle that, when enforced, aid in keeping the complexity down in the code base. We used a number of CheckStyle rules, but the following were somewhat helpful in keeping code complexity manageable:

  • FileLength
  • MethodLength
  • ParameterNumber
  • AnonInnerLength
  • AvoidNestedBlocks
  • MagicNumber
  • Nested* (various Nested rules)
Some of the other methods, like HiddenField, were also useful in avoiding bugs.

FindBugs and lint (and occasionally CheckStyle) were good at identifying potential defects and leaks. At first the tools detected a number of issues, but over time there were fewer and fewer violations.

Having good reporting mechanisms was very important. At first our reporting mechanisms were very poor, requiring a lot of digging to find the source of the build error. This was largely due to the limitations of the central build CI system we were using. When we shifted the tests to run on Jenkins, the reporting was much crisper, making for a much better experience.


Friday, August 7, 2015

An Extensible Factory Pattern - Use Case



NuanceAndroidCore (NAC) was designed to be a highly customizable library, facilitating creation of Siri-like voice assistants, without imposing constraints on the look and feel of these assistants. The platform controls the voice dialog and provides callbacks to the UI layer for displaying recognition results and status of the recording and recognition. Consumers of the library render this feedback as they see fit.

The library also performs data lookups such as calendar events and alarms within a range of dates; and actions such as launching an application, adding/deleting/changing alarms, events, and playing music. Much of the benefit of the library comes from its ability to perform all this seamlessly and automatically. However, in many cases, individual customers might have their own implementations for one or more of these applications, with their own API's, and sometimes with added functionality. The challenge was to come up with the best way to support these customizations, control and manage the intricacies of the voice dialog, and supply default behaviors for everything else.

This is where the extensible factory proved to be useful. NAC used this pattern in several places, including creation of its action and lookup handlers. NAC registered its own implementations of each handler (for example a handler for sending an SMS message). Each customer could then customize specific actions by registering a different factory to override the default implementation, should they desire different behavior. In this manner, they could leverage everything else the library provides, including everything related to the voice dialog for that action, and any actions that didn't need customizations, and only provide code for specific overrides of the default behavior.

Each of the action handler factories are chosen from a map keyed off an element of the server response (for example, an action of type "sms" would key an action handler of type SMS). Building off the sample code introduced in the last post about dynamic enums, the factory method looks like:


(Disclaimer: This snippet was hand-edited from the original code and not compiled. The possibility exists for compilation errors.) 

This technique relies on reflection to build up the handlers, but performance is not a concern because the construction of the handlers is a very small portion of the overall time to perform an action, typically dominated by the time in getting recognition results returned from the server.

The voice recognition logic  and dialog management for this system is server-side.
So the opportunity exists for new voice domains to be added and deployed to the field that NAC is not configured for, after NAC has already been released. This is where the dynamic enum class discussed in the last post became useful. With the dynamic enum, NAC could register all its known handlers with immutable keys, while also supporting key types it doesn't know about. For example, the SMS key type would be defined and used by a customer wishing to override default SMS handling, but the customer could create a new key, say "sports" on the fly should the "sports" domain be added to the server domains after the NAC library has already been released.

In the next post, I will explore an alternate approach using Dagger2 for dependency injection.