Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

Saturday, July 25, 2015

Being a Code Custodian



The roles of a team lead can vary dramatically depending on the team dynamics. Being a code custodian may or may not be appropriate for your organization. I have found it valuable in some situations. There are automated and manual approaches to monitoring the integrity of software. I like to apply both when appropriate. Each has pros and cons:

  • Automated Approach - Usage of software tools to detect potential defects and/or style violations
    • Advantages
      • Can check for a large number of potential defects and/or design smells
      • No ongoing time investment after initial investment to setup and configure
      • Can be tied into CI environments like Jenkins to guarantee adherance
    • Disadvantages
      • Not good at catching the most important issues
      • If rules are configured too restrictively, becomes more of a hindrance than a benefit
  • Manual Approach - Human review of checkins or some subset of checkins
    • Advantages
      • Only way to catch many types of issues
      • Keeps the reviewer abreast of new development
      • Leads to mentoring opportunities for the reviewer
      • Good way for the reviewer to learn from other approaches and pickup new techniques
    • Disadvantages
      • Difficult and important to be completely objective and remove opinion from feedback
      • If applied heavy-handedly 
        • Kills developer empowerment
        • Can be disastrous to morale
      • Time-intensive
      • Spotty
        • Usually unrealistic to fully check everything
I would further decompose automated approaches into 2 categories.
  • Category 1: Surface Analysis - Static-analysis tools including lint, checkstyle, and findbugs
    • Advantages
      • Customizable
      • Rules-based
      • File-driven
      • Easily integrated into many modern IDE's
      • Easily integrated into build or CI environments via a CLI
      • Many free or open-source
      • Often mature and robust
    • Disadvantage
      • While they can catch many "surface" issues, they don't always dig very deeply
  • Category 2: Deep Analysis - Tools that looks more deeply into aspects such as cyclomatic complexity, memory usage, and performance. 
    • Advantage
      • Tend to be higher value 
    • Disadvantages
      • Difficult to automate
        • Some intended more as an aid for manual test and debug
        • Some produce results that should be inspected and interpreted
      • Can be difficult or impossible to quantify rules for
      • Less typically free or open-source

In the next two posts I will delve into how I applied these tools in recent projects.

Saturday, June 27, 2015

Balancing Performance with Code Readability

Image result for balance

This is a topic much discussed in the industry and the position I take is a common one: Code first for readability and support, refactor for performance as necessary. There are notable exceptions to the wisdom of taking a readability-first approach. In general you will know if your code is one of these exceptions. It could be graphics-intensive operations, operations widely used and distributed in libraries, and similar situations where you know critical paths through the code a priori. For the 90% case, where squeaking out every nanosecond of performance is not critical I like to use the following steps:
  1. Write code to be as readable and supportable as possible
  2. Validate that the performance is acceptable
  3. If performance is not acceptable, profile to find the hot spots
  4. Identify techniques for improving performance of these hot spots
  5. Using the Strategy Pattern
    1. Extract each module to  be refactored into a separate component and introduce a simple factory to serve up the existing implementation
    2. Introduce a higher performing implementation and update the factory to use this new strategy
    3. Add comments as necessary to the new strategy implementation
The factory gives us much more flexibility. It allows us to restore the original strategy if we later find that we really don't gain enough overall performance to warrant the new version. It also allows us to experiment with different strategies for improving the performance before deciding on one.

I am of the school of thought that a lot of comments in code is a design smell that the code wasn't as well thought out and decomposed as it should be. I think that most code should be written to be self-documenting with appropriately named methods with small scope. There are certain exceptions to this. Writing for performance is a common way of adding unintentional complexity. Often this added complexity is unavoidable. We should add sufficient comments to explain the code and the reasoning behind the extra complexity so that someone further down the road does not reverse our decisions (perhaps for readability) without understanding the implications of that reversal.

Next week I will push into a use-case where I opted for readability over performance in conflict with published performance recommendations from the platform vendor.