What Are You Optimising For?

Very few software designs/architectures are completely and objectively bad. Most designs optimise for something. Here’s a [probably incomplete] list of things that you could optimise for in software architecture:

  • Developer Time Now
    When we say we’re doing something “quick and dirty”, or that we are taking out “Technical Debt”, then we are optimising the development time now.
  • Developer Time Later
    This is what people traditionally mean by “good” code. A developer wants to write code that will be easy to work with several years from now. This is based on the perception that most of the hours a developer spends working, they are maintaining an existing system.
  • Product Iterations
    In simple terms this means building something that is highly flexible and is likely to meet a broad range of future (as yet unknown) requirements. By making the system flexible we reduce the number of iterations we are likely to need before the customer is happy with the product.
  • Testing Time
    While optimising for Product Iterations means making a flexible product, optimising for testing time is almost the exact opposite. The ideal system to test is one with a single button labelled “Do {Something}” which, when clicked, does exactly what it says it will. The more options, configuration, flexibility and programmability you introduce to a system the more time it will take to test to a reasonable level of satisfaction.
  • Backwards Compatibility
    This means designing a system to accommodate existing users who potentially don’t want to have to think about the new features. Or perhaps have lots of existing data in a structure that is not conducive and to the new features you want to introduce. By optimising for backwards compatibility, we’re building something in a way we wouldn’t normally like, but that will make it easier to roll out.
  • Deployment Risk
    In these days of hosted services and sand boxed apps this is becoming less of an issue. But anyone who’s had to think about rolling out an upgrade to a user community where you don’t know exactly what data they have or what the environment its running in looks like, then this will be familiar. Depending on the context you might make users go through long-winded upgrade procedures or pass up on framework upgrades and new technologies just to be sure that your next version will not fall over when it hits real world user machines.
  • Deployment Effort
    Sometimes the solution you want to build will be a nightmare to setup in production. It may require lots of servers, or perhaps a combination of services for caching, queuing, persistence, messaging and load balancing. In some cases, you may want to spend extra development effort building automated installation tools or even take a performance hit so that rolling it out is easier.
  • Support Time
    Sometimes it’s preferable to take extra developer and testing time to introduce automated installations, lots of logging and diagnostics, remote crash reporting, user friendly failure messages with troubleshooting guides, extra documentation, lots of context sensitive sensible defaults or reduced flexibility. All so that it’s less work to support once it goes out the door.
  • End User Learning Curve
    There’s often a market for an entry level version of apps that maybe don’t have all the power of the competitor products but which is easy to pick up and use. Alternatively, you could trade development and testing time and build an easy to use product that has a lot of flexibility behind the scenes for the power users.
  • End User Usage Effort
    If you’ve ever used VIM, you’ll understand what I’m getting at. VIM sacrifices End User Learning Curve in order to optimise for End User Usage Effort. Sometimes developer and tester time is taken to build hundreds of special business logic that will make the system do exactly what the user needs exactly when they need it.
  • Performance
    This often means sacrificing Developer Time Now/Later in order to make the system run faster. For example, using an off the shelf ORM tool will reduce the code you need to write and maintain, but to get that extra performance people often resort to hand crafting the database queries they need.
  • Scale
    The ability to handle millions of users or Terra bytes of data often comes at the expense of developer time, deployment effort or single user performance. If you really need to handle that scale then you’ll have to sacrifice something else on the list to do it.
  • Budget
    If you have very deep pockets then most other problems can be made to go away. If you’re willing to build your own data centre with 10,000 servers in and an army of people to keep your site running then you can defer having to think about writing scalable code or deployment effort. This    is sometime a logical approach. This is not always true though. A baby takes 9 months no matter how many women you have.

I find that conversations between engineers about the best architecture to use are always easier and less emotive when people are clear about what they’re optimising for, why, and what they’re willing to sacrifice in the process. It’s helpful to keep asking: what are you optimising for?

 

Follow People on Hacker News with hn_comment_follow

I often find the comments on Hacker News are fantastic and there are certain users who’s opinion I always value. To that end I’ve created a python script to help follow what my favourite people are saying on Hacker News: hn_comment_follow. It’s on GitHub in case others would like to fork it.

To call it, invoke the script like this:

python hn_comment_follow.py pg patio11 d4nt

The list of users should be space separated.

The output will look a bit like this:

2 days ago

pg

http://news.ycombinator.com/item?id=3435252

This sounds like a crazy plan for a startup, I realize, but this is the right sort of crazy. ;In fact, the way the Hackruiters think about Hacker School is a lot like the way we initially thought about YC: if it doesn’t make money, it will at least have been a benevolent thing to do.

patio11

http://news.ycombinator.com/item?id=3434547

Props to Microsoft, but this is actually pretty routine. ;(It was literally written policy at a previous employer of mine.)Manual exception handling at the warehouse is crazily expensive. ;It is much, much easier to write it off (as shrinkage, not charity) than to get the item back into active inventory (all the fun of chasing invoices, except the amount payable is “one XBox”, and the person doing the chasing sees their general productivity go to pot), particularly as it may have been opened. ;The charity suggestion removes many customer objections and ends the ongoing CS expense almost immediately.

patio11

http://news.ycombinator.com/item?id=3434967

Just staying, our literally written policy was “Offer DDD”: donate, destroy, or “dispose of” (a polite euphemism for “You keep it”) the misshipped item. ;I would have added the Christmas flourish if I were saying it in December, too, but the options would have been the same in July. ;(n.b. The business does not care what you do. ;We want to convey, in the politest possible way, that we both don’t want it and don’t want to talk to you about it.)

Design Notes are not Functional Specs

At my company, we don’t write Functional Specs, we write Design Notes. This post explains the differences and the thinking behind those differences.

Design Notes contain some Balsamiqs, some text, and the occasional table definition. Many people, when they see a Design Notes document think of it as a Functional Spec. They exist purely for the time before the software is written as an aid for developers and testers. Once there is software, the software is the spec. This contrasts with Functional Specs where any differences in the software and the spec should be automatically considered a bug, although it practice there are often things that got added without the spec being updated because it was too much work to update the spec.

Things change, and we want to spend our time building software, not continually updating documents about the software we’d like to build. When specs have to be kept up to date, it becomes incredibly difficult to finish the spec and actually start development. Every new idea from users, every question from developers, every clarification that testers ask for, they all require a new version of the document and every new version has to be sent out for review which triggers lots more feedback. While this is going on, it{781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f}u2019s tempting to halt development to avoid “unnecessary rework” and to allow the analysis to “complete”. Let’s get one thing straight: analysis is never complete and software will always evolve. Any process that assumes otherwise is a broken process.

The overhead of having to keep the spec 100{781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f} accurate can be so tortuous that getting to a final version of the spec often involves pressuring some stakeholders into accepting things they don’t like just so everyone can agree and move on. Having done that, it becomes politically very difficult to re-open the spec later on. So even the most obvious and important changes have to wait until “Version 2” because we can{781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f}u2019t possibly change the spec once it{781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f}u2019s been signed off.

Design Notes do present a challenge for testers. Traditionally a tester’s job was to ensure the software met the spec. Design Notes require the tester to be more involved in the design process and to think about whether something is really a bug before raising it. Often this will involve talking things through with analysts, developers and customers. We recognize that this is not easy, but we think this is treating testers as more equal partners in the development process. On the plus side, testers are not constrained by a spec; if something looks wrong, doesn’t flow well or is inconsistent, even if it’s doing what the Design Notes say it should, they are still free to raise it. Saying {781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f}u201Cit meets the spec{781c323b309d6e174625241ec7481c1d30d3b1f9955792182ab0278b30a7fb7f}u201D is not the end of the conversation.

Reporting on TFS Work Item Statuses

I recently had a need to regularly get an update on the numbers of TFS work items at various statuses within a particular sprint. Here’s a powershell script that will query TFS an give you back the nubmers:


param (
    [string]$project = $(throw "Parameter '-project' is required."),
    [int]$sprint = $(throw "Parameter '-sprint' is required.")
)
$query = "select System.State from WorkItems where System.TeamProject = '" + $project + "' and Conchango.VSTS.Scrum.SprintNumber = " + $sprint
push-location C:MyTFSWorkspaceFolder
[xml]$sprintitems = tfpt query /wiql:$query /format:xml
$sprintitems.selectnodes("WorkItems/WorkItem/Fields/Field[@RefName='System.State']/@Value") | group Value | format-table Name,Count
pop-location

You’ll need the TFS Power Tools installed. Plus, you’ll notice that we have the Conchango Scrum template installed in TFS.

Convert XML to a UL Tree Using XSLT

I spent a good 30 minutes hunting for this on the web this afternoon. Eventually I just wrote it myself.

The following XSLT will convert XML to a tree of <ul>and <li> items. The element names will be rendered within <strong> tags.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<ul id="certificateData">
<xsl:apply-templates select="./*"/>
</ul>
</xsl:template>
<xsl:template match="*">
<li class="closed">
<strong>
<xsl:value-of select="local-name()"/>
</strong>
<xsl:choose>
<xsl:when test="count(./*) > 0">
<ul>
<xsl:apply-templates select="./*" />
</ul>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:template>
</xsl:stylesheet>

A la Carte Software

The traditional way of designing then costing a new piece of software is broken. All too often a someone spends months refining what they want, talking to everyone involved and throwing any feature ideas that they think they might need into the melting pot. Until eventually, they think they’ve covered everything.

Then; they ask someone how much it will cost.

The first problem is that software feels like it should be cheaper than it is. People outside of IT see software as being an advanced version of a spreadsheet. And Terry over there in the corner knocked up a really useful spreadsheet in something like two weeks, so surely a bit of new software shouldn’t take any more than 4 weeks to build!

Another problem is that the list of feature requirements that they ask the potential development team to quote on contains way more than they really need. The vast majority of the value of the new system will be contained in a very small proportion of the features. But people rarely ask development teams to help them decided what they need. Probably because those unscrupulous software developers would use that as an opportunity to sell them stuff they didn’t need.

Finally, potential customers don’t understand the non-linear way that extra features effect the price of a development project. When they see a quote saying it’ll cost $500,000 to build the 20 features they need they (quite reasonably) think that each feature costs $25,000 and that even the 5 features they really cannot live without would cost $125,000 which is still way too much. Sometimes, they simply walk away at that point convinced that the price is so far from what they can afford there’s no possibility of a deal.

There are two ways of fixing this. The good way and the bad way.

The bad way would be to be recklessly optimistic when estimating. You quote the customer a ridiculously low ball offer, they accept, you then fail to deliver but the customer is locked in, you then try to claw back some sort of profit through the change control process. In other words, how a lot of software development companies work. In fact it’s interesting to wonder whether this is the reason why this industry has a chronic underestimation problem, perhaps it’s because the business model depends on it!

The good way would be to be get involved earlier in the process and to give the potential customer instant feedback on how their decisions affect the price. One way to do this would be through a menu of software modules.

Such a menu would have things like “Business Entity”, “Audit features (per entity)”, “Content Management (per page type)”, “Workflow features (per entity)”, “Custom Reports (per report)”, “Backend API”, “Document Management” and so on. Each item would have a price there in black and white and you sit with the customer, explaining how they can combine some of the items on the menu to achieve the effect they need, all the while showing them what that does to the bottom line.

Imagine what it would be like to work with a potential customer who’d bought into this process and was starting thinking creatively about how to solve their business problems with the minimum number of software components, now that’s what I call fun!

Querying TFS for Checkin Information with Powershell

One of the things that quickly became aparent when I joined my present company six months ago was the laid back approach to commenting code checkins/commits. I’m working on changing that and have had moderate success leading with by example, but the time is coming when I’ll have to start naming and shaming! To that end, I started investigating how to write a powershell script that will calculate the percentage of checkins that had a comment.

Firstly, you’ll need to install the TFS Power Tools.

Next, you can call “Add-PSSnapin Microsoft.TeamFoundation.PowerShell” to get access to the powershell cmdlets.

Finally, you can call “Get-TfsItemHistory” to get information about checkins.

Here’s my script in full

# Add the snapin if its not already added
trap {
Add-PSSnapin Microsoft.TeamFoundation.PowerShell
}

# Move to my local workspace folder
push-location C:MyWorkspaceFolder

# Get all the checkin info for the last 7 days
$history = Get-TfsItemHistory . -Recurse -Stopafter 1000 | Where {$_.CreationDate -gt (get-date).AddDays(-7)}

# Group by owner, figure out how many checkins they did, how many were
# commented and what the coverage was as a percentage. Finally, sort by
# that coverage percentage

$history |
group Owner |
select Name,
@{Name="Checkins";Expression={($_.Group).Count}}
@{Name="Commented";Expression={($_.Group | where { $_.Comment -ne $null }).Count}} |
select Name,
Checkins,
Commented,
@{Name="Coverage";Expression={[math]::round(($_.Commented / $_.Checkins) * 100.0, 2)}} |
sort "Coverage" -desc

# Move back to the starting directory
pop-location