- 3 minutes read #pontification , #project management , #water cooler

On Platitudes

This post was originally written while I was at LShift / Oliver Wyman

I hope we can agree that ad hominem attacks in discussion are undesirable, but I’ll suggest that platitudes can sometimes be the other side of the same coin, it’s rebuke being delivered in a wrapper of inoffensiveness.

“A remark or statement, especially one with a moral content, that has been used too often to be interesting or thoughtful.” Oxford Dictionaries

To distinguish a platitude from something merely banal, try to state the opposite of it and see if it still makes sense. E.g. the phrase “We should lower taxes” is often used as a seemingly irrefutable political position, but the opposite “We should raise taxes” is a position that could plausibly be argued (if, for example, public services are currently underfunded). Therefore the former is not a platitude. On the other hand “I want to keep our children safe” seems impossible to negate: “I want to keep our children unsafe”. Really? Throw them to the wolves and see what happens? Send them to school surrounded by guns? (maybe I need a better example). The problem with platitudes in technical discussions is that they get used merely to terminate discussion.

Some examples for your game of Business-Meeting Bingo:

  • “I just want the simplest thing” – whereas the ‘simple’ in KISS and ‘minimum’ in MVP are useful notions, this phrase so often means “I don’t want to learn anything” or “Coordinating with other people is hard and messy”. The cry of “I want to keep things simple” can kill conversation with the result of teams, or individuals, heads down in silos churning out code with integration as an afterthought.
  • “This is the standard way of doing things” – While a common language and approach can aid communication in teams, an appeal to ‘standard’ can be quite aggressive. It implies there is only one way of doing things and any dissenter is foolish. Whose standard (there may be many)? When was it agreed? When was the last time it was challenged? If ‘tradition’ is the only reason for doing things then perhaps it’s time to re-evaluate.
  • “I want the best of breed” – thank you for pointing that out, personally I was hoping to integrate something less.
  • “We should be using best practice” – this is similar to ‘standard’. ‘Best practice’ depends on the circumstance, and if we’re engineering something new then maybe there isn’t any history or experience to compare with.

I had a hard time thinking of a conclusion to this post: an exhortation to ‘do better’ seems pompous and I feel unqualified for many concrete suggestions. Maybe we can just fall back on the general social ideas of generosity and humour. If someone supports their position by claiming ‘standard’, then perhaps jovially inquire if they are referring to ‘the’ standard or just ‘a’ standard. When faced with a drive for the ‘simplest thing’, agree that everyone wants that and then gently point out the pragmatic trade-offs for short-term gain and long-term maintenance. When asked for ‘best of breed’ inquire whether a Shire Horse or Racing Greyhound would be appropriate (hopefully generating a conversation about requirements).

That feels like best practice.

- 3 minutes read #project management , #water cooler

'5 Whys' Considered Harmful

This post was originally written while I was at LShift / Oliver Wyman

Adverse events happen – a website breaks down, a project doesn’t get delivered on time – and a  proposed technique to find ‘the root cause’ is to ask the “5 Whys”. Attributed to Sakichi Toyoda in the 1930’s and adopted by Toyota and other formal techniques it’s basically the technique of listing a fault and then asking “Why did that happen?” – repeat until you get to a cause that ‘feels’ like the root. The name comes from the observation that 5 repetitions are usually enough.

I find this problematic for several reasons:

  • This is the analysis technique of an attention-seeking three year old
  • It often raises the question “Why did you do that!!!” and the resulting blame game never helps…
  • In my experience there is never a single root cause

Let’s pick a well-known example: “why did so many people die in the Titanic disaster?”

  • The watcher didn’t see the iceberg
  • The message didn’t get back to the helm
  • The management insisted on cheap rivets
  • The bulkheads were too low because of the ballroom
  • There weren’t enough lifeboats
  • Nearby boats didn’t recognise the meaning of flares
  • The “SOS” radio sequence wasn’t well known (at the time)

And so on…  Maybe some of these are debatable, but the point still stands: in any significant failure it’s usually the case that a whole sequence of partial failures had to happen for the main failure to occur. Fixing any one of them would prevent the disaster happening again, but it’s clearly better to fix as many as possible (which may also prevent other, related, failure scenarios).

This is why I prefer the 4 (or 5) whats:

  • What happened (what were the symptoms)? Be precise and objective:
    • “the service melted down” is not enough (if you look in the server room there will be no puddles of plastic or aluminium in sight)
    • “the service had a latency greater than N seconds resulting in new connections being rejected” is objective.
  • What did we do as an immediate workaround?
  • What was the damage (and what do we need to do to make up for it)?
  • What do we have to do to ensure it never happens again? This will usually be a set of actions, not just one.

This avoids any blame game, avoids the futile attempt to pin down a single ‘root’ cause, and, most importantly, in light of the new information empowers the creativity and ownership of your engineering team to come up with the best solutions. After all, they should be the people who know most about the system.

- 4 minutes read #project management , #water cooler

Just enough design

This post was originally written while I was at LShift / Oliver Wyman

On the one hand it’s become a bit of a cliché to say that Waterfall doesn’t work (in fact ‘waterfall’ may never have existed), but we know that rigid projects don’t deliver—when the level of resources is the only contingency in a project then budget overrun and missed deadlines (or lowered quality) become almost inevitable.

On the other hand, the original “Agile Manifesto” is now more than 15 years old and is starting to seem like it’s missing a few things. Certainly some of the processes inspired by the manifesto seem to be of a benefit, for example: the frequent touch points of the daily stand-up, regular retrospectives (as long as there’s the organisational will to implement the recommendations), personal and regular communication, and so on. But there are occasionally huge drawbacks—how many times have developers heard things like:

  • “You’re doing sprints now so you can deliver in less time yes?”
  • “Yes I know I’ve changed my mind 4 times but you’re Agile so you can cope right?”

Also ‘Agile’ seems to encourage projects where the deadline and budget have been set but only against the vaguest notion of a requirements list; the development team is gathered together and the first question is “what is it we’re doing exactly?”.

At the other extreme, I have seen projects that languish with the Enterprise Architecture team for years while the Transformation Maps are drawn to full impact scope along with software designs, object integration designs, data schema, and vendor evaluation, etc., in the finest detail so “the programmers can just get it done (and properly this time)" – and perhaps never even really starting.

But some projects just have a nature that isn’t amenable to fast-spinning agile.

“This style of short-term planning, direct customer contact, and continuous iteration is well suited to software with a simple core and lots of customer visible features that are incrementally useful. It is not so well suited to software which has a very simple interface and tons of hidden internal complexity, software which isn’t useful until it’s fairly complete” – David Jeske
“A designer cannot claim to have truly designed something until they also know how that thing will be made” – Terence Conran, designer, and founder of the London Design Museum.

So what can we do? I’m certainly not claiming that design and architecture are bad things – commercial software projects shouldn’t start unless there’s confidence of delivery – but there needs to be a balance between rushing in blind and agonising over the unknown (and my contention is that his balance should be found before the main budgets and timelines are set).

Well, AgilePM (formerly DSDM) introduces a notion of governance to an Agile project:

The circle in the middle represents the ‘traditional’ sprints (a manifesto that’s 15 years old can be referred to as ‘traditional’ by now I think…) but supported by a well-reasoned set of gateways and light-touch documentation. With regards to Enterprise Architecture, the important columns in the diagram are the two near the left marked Feasibility and Foundations: they represent the notion of ‘lJust Enough Design’.

LShift (acquired by Oliver Wyman in December 2016) has a 17 year history of successful major software product delivery using agile methods including DSDM/AgilePM. The technical Feasibility and Foundations phases are what might be termed Architecture and Design (Enterprise or otherwise) under other formalisms but there are important differences:

  • It needs to be Just Enough and no more. Just enough to clearly communicate the vision and scale of the project and bring confidence of delivery but without so many trees that the wood becomes obscured.
  • It must closely involve at least some members of the team who are likely to produce it. Any Enterprise Architecture team completely separated from implementation inevitably loses touch with the reality of delivery.

Just Enough design – the technical Feasibility and Foundations – is essential, but once it’s been done the process of delivery should be handed over to the engineers. I’ve been on both sides and it’s clear to me when, in an Architect role, I should get out of the way. With apologies for taking an example from the military, “Intent and Initiative” is becoming seen as clearly more effective than “Command and Control”.

Like the three bears, Big Design Up Front is too much, and a ‘headless chicken’ Agile Manifesto is not enough – but maybe the processes of AgilePM can be Just Enough governance. Certainly software projects need design to be successful – not too much or too little, Just Enough.

- 4 minutes read #APIs , #technology

GraphQL is really TreeQL (and that's ok)

This post was originally written while I was at LShift / Oliver Wyman

Let’s have a look at GraphQL. It came out of Facebook as a replacement for REST style requests for querying data. It was initially developed from 2012 and made open source in 2015. As Facebook’s main database is the “social graph” it was naturally named GraphQL but, as we’ll see, that’s not a completely accurate name (though that doesn’t really matter in practice).

In GraphQL object types are described in a type schema and queries are specified as templates referring to those objects.

query BooksWritten {
  author {
    name
    books {
      title
      genre
    }
  }
}

Note these templates are document templates and not graph templates. Document-like objects such as these are effectively trees; there’s only a parent-child relationship between items (in fact, a container-contained relationship) and no natural way to reference an item in another part of the document. Databases (“in-memory” or SQL) often represent full, possibly cyclic, object graphs – but GraphQL can only express tree-like queries (SQL only expresses table-like queries even though the joins may be mapping over a cyclic graph, and you’d never expose raw SQL as an API).

A full graph query language would be able to specify cycles directly by naming nodes and referring to them elsewhere in the query. For example, in fraud detection it’s often useful to find loops in a graph to show where a group of people are suspiciously acting in common and graph query languages like cypher do this very well, even if the size of the loop is not known in advance. Another example relating to unknown path size is the “7 degrees” question which, in Cypher, is a one-liner:

MATCH p=shortestPath(
  (bacon:Person {name:"Kevin Bacon"})-[*1..7]-(meg:Person {name:"Meg Ryan"})
)
RETURN p

In GraphQL you’d have to construct a “recursive tree” query, with all the problems of combinatorial explosion, and search through all the intermediate nodes and leaves.

{
 actor(name:"Kevin Bacon) {
   movie {
       actor {
         movie {
           actor {
             movie {
               actor {
                 movie {
                   actor {
                    movie {
                     actor {
                      movie {
                       actor {
                        movie {
                         actor
}}}}}}}}}}}}}}

A query like that would probably return the entire database.

On the other hand this may be a benefit to some degree – unconstrained full-graph queries can clearly bog down the database if not developed carefully, so it would be a mistake to expose an API which allowed that. By restricting queries to trees the consumer has to think carefully about the queries they write as combinatorial queries become obvious, and most GraphQL implementations also support restrictions on query execution time in practice.

Once you’ve decided what your set of root query objects are going to be, and the schema that relates them to other objects, then you don’t need any other endpoints to fetch data related to any of those roots (or data related to data related to that root, and so on…). For a social graph a convenient root is the ‘user’, for a bookshop root queries may include ‘book’ and ‘author’ etc. The schema can be evolved by adding more ‘root’ queries. In this way a GraphQL endpoint can usually be extended over time by adding new items in a self-describing way without needing versioning or new endpoints to be created.

Evolving a GraphQL endpoint to remove items is slightly more tricky. Object types, fields, queries etc. can all be marked as “deprecated” such that IDEs and other tools subtly hide them from the developer and encourage their disuse and refactoring in existing client code. But they still need to exist for as long as there are clients that rely on them. Over time those clients diminish, as security and functional patches are adopted, until those items can be finally removed from the server. It may occasionally, but rarely, be necessary to rudely remove support for “long tail” clients – but this may be no bad thing as it merely forces the user to upgrade (and pick up security patches).

GraphQL can also be used to update data via the same endpoint, but rather than using limited http verbs like POST, PUT or DELETE the schema specifies the set of available mutations. These are more expressive than REST endpoint updates: they look more like function calls and attributes can be complex objects that fit the schema.

Evolving mutations can also reasonably simple: adding and removing mutations are dealt with in the same way as queries, and parameters are objects from the schema so are self-describing and can be evolved in the usual way.

So GraphQL is an extremely useful framework with several major benefits:

  1. removing the “N+1 requests” problem of REST where you have to do a request to get an object, and then make further requests to enumerate various linked objects. All data requested in the query template is returned in one round trip.
  2. REST has many other problems that GraphQL schemas solve
  3. Schema evolution which avoids the need for versioned APIs.

It’s just that the query language itself should really be called TreeQL.

- 5 minutes read #pontification , #programming , #project management

Given When Then

This post was originally written while I was at LShift / Oliver Wyman

There are, of course, a large number of techniques described as being The Way To Do Software Engineering. I’m sure I’ve not come across them all but the ones I know about and use currently include at least: Impact mapping, Pert charts, Gantt charts, Personas, Wardley mapping, Agile, DSDM, MoSCoW, SMART, INVEST and BDD (I’ve not done Prince for two decades at least), and then actually writing the software in Sprints which, in turn, includes: PRL, DDD, Unit Testing, Integration Testing (‘Continuous’ or otherwise), TDD, and Fuzz testing, etc. It’d be nice to bring all of these into some kind of coherent model we can utilised to produce correct and usable software.

Books have been written about each of the above techniques and more which I’m not going to repeat here though it may be useful to quickly skim through at least some of them. I’m bound to say something slightly contentious or incomplete in these summaries; if I do then I defer to the greater literature.

Impact mapping covers the ‘Why are we bothering to do this?’ of the system:

  • Four main concepts: Goal/Why, Actor/Who, Impact/How (the Actors change their behaviour or do their task), Deliverable/What
  • Personas are useful descriptions of various aspects or variations of the Actors
  • Agile Stories can then be read directly out of the Impact Map. I.e. “As an [actor/who,] I want to [deliverable/what], so that I can [impact/how].”

Agile was publicised at least as a manifesto for communication and rapid iteration. Early versions of the manifesto continue to be criticised, but this is unfair as ‘Pragmatic Agile’ techniques like DSDM (Dynamic System Development Method) are now well developed.

  • Software is manufactured in a series of timeboxed Sprints or Iterations (in the order of weeks rather than months or years) with a retrospective and refocus at the end of each sprint.
  • During a Sprint a list of Stories is considered for solving. Ergo if a story is too big for a sprint, or it will take a whole sprint (or, even, more than a few days) then we re-label it as an ‘Epic’ (really just a very big story) and break it down into more manageable parts (which we then call Stories – i.e. they should still be expressed in the ‘as a [], I want to [], so I can [*]” triple).

Possibly a good way to break down an Epic is to write out all the acceptance criteria (see below); if done well it’s likely the criteria can be grouped into orthogonal sets where each set is likely a candidate for a story of its own. Acronyms like SMART and INVEST are often thrown around at this point. SMART has many possible meanings, but a common one is ‘Specific, Measurable, Achievable, Relevant, and Time-bound’ – but there are a lot of tautologies in there (how can something be either Time-bound or Achievable without being both Measurable and Specific?). INVEST seems more useful: ‘Independent, Negotiable, Valuable, Estimable, Small, and Testable’.

Note that slide 6 on this deck is misleading:

It seems to indicate a straight line top left to bottom right that one could execute in order and good software just pops out at the end. But really it’s the grey background boxes that show the correct timeline: i.e. everything overlaps. And as for suggesting there should be a tiny ‘do the coding’ box at the end, well, let’s move on…

BDD (Behaviour Driven Development) simply describes the set of Acceptance Criteria and/or Scenarios that should be attached to each story to give the ‘Definition Of Done’:

  • GIVEN a condition, WHEN something is done, THEN something happens

Wardley maps are a way of modelling what parts of the system are most visible to the user; perhaps giving an indication of priority for tackling them:

  • Graph of ‘real things’ and ‘depends-on’ links between them
  • Things tend to be nouns
  • The things more visible to the user, the ‘User Anchors’, are the Deliverable/What/Epic/Story we saw above – which, in turn, are a set of Behaviours.
  • The things less visible to the user are likely to be the underlying substrate of system units and integrations that make those Behaviours possible.

Planning is quite useful:

Given the set of stories we’ve now identified for the system, and the relationships between them, we need to decide in which order to tackle the stories so we can have the best chance of producing something useful within the allocated time frame and budget. So at this point we can use a MoSCoW (Must, Should, Could, Won’t) technique to prioritise each feature and end up with the PRL (Prioritised Requirements List).

We can now use the PRL to populate the sprints directly or, as an extra bonus, create a Pert chart and a (probably aspirational) predictive Gantt chart to plot our course.

Software that satisfies the set of stories is, in some way, made up of units of capability and integrations between those units. In vague terms unit tests examine the behaviour of each unit in isolation and integration tests check how the units behave when communicating with each other and the glue between them (no surprises there). But it may be that producing a behaviour takes a whole collection of units and, likewise, a unit may be fundamental to a whole set of behaviours. So we may end up with a matrix of behaviours against units and integrations – i.e. a many-many join from behaviours to unit and integration tests

This may all seem like a huge palaver, and indeed it will be if one is tempted to follow all the techniques to the letter! But in practical development, and by looking at the scale of the problem, it’s often easy to do at least some of these techniques in one’s head. That is: each technique should be followed ONLY if it adds value to the current project, and fastidiously following all of them may even get in the way. There’s an interesting balance to reach:

none of these techniques are strictly necessary, and following all of them is no guarantee of success – however, the correct techniques used at the appropriate time can greatly improve one’s chance of success.

So do we have a coherent model now? Perhaps something like this:

What could be simpler?

- 5 minutes read #pontification , #programming , #water cooler

Programming is not a performance

This post was originally written while I was at LShift / Oliver Wyman

Programming is more like writing a novel then executing a performance. No I don’t mean the likes of If Hemingway Wrote JavaScript  – I mean, apart from ridiculous job interviews involving a whiteboard and pen  (NB. LShift never does that) coding is very unlikely to be a performance in an instant of time. Usually when writing software, developers get to test, review, seek opinions,evaluate, rewrite and polish an artefact useful to the customer (well, when given appropriate resource and a professional culture at least). If you want to take an artistic analogy; programming seems more like sculpture, carpentry or, for this blog post, writing a novel, rather than singing a song or playing an instrument.

To continue the analogy, students of creative writing have access to a wealth of training e.g.: courses, books and videos, writers’ circles etc. Similarly for programming there are: reams of open source code hosted on public servers, peer review and feedback through pull requests, discussions on aesthetics and elegance , and so on.

Using the musician analogy it may be tempting by some to regard a Lead Developer as a kind of orchestra conductor, but I’m more attracted by the analogy to a literary editor (or cat-herder, which may be the same thing “I love deadlines. I love the whooshing noise they make as they go by”) not least when it comes to the issue of Coding Style. For example, in my opinion, the best book on code style ever written is Perl Best Practices by Damian Conway – not because of perl as such (superb in its day, but it’s time to let it go for all but the simplest text munging) but for these 3 paragraphs on page 6:

Other readers may object to “trivial” code layout recommendations appearing so early in the book. But if you’ve ever had to write code as part of a group, you’ll know that layout is where most of the arguments start. Code layout is the medium in which all other coding practices are practised, so the sooner everyone can admit that code layout is trivial, set aside their “religious” convictions, and agree on a coherent coding style, the sooner your team can start getting useful work done.

But remember that each of piece of advice is a guideline … Whether or not you agree with all of them doesn’t matter. What matters is that you become aware of the coding issues these guidelines address, think through the arguments made in their favour, assess the benefits and costs of changing your current practices, and then consciously decide whether to adopt the solutions offered here.

Then consider whether they will work for everyone else on your project as well. Coding is (usually) a collaborative effort; developing and adopting a team coding style is too.

[my emphasis] and it’s often useful to pick an off-the-shelf style and stick with it (for a project) rather than agonise about tiny optimisations.

So can we perhaps look further to literary practice to guide us in software development? Well, here’s part of Gwynne’s introduction to Strunk’s “The Elements of Style”:

Remember always, when you are writing for anyone other than yourself, that you are giving. Do not, therefore, write to suit yourself: write with your readers constantly at the forefront of your mind. Put yourself in their shoes when you are deciding how to express yourself. It is not enough that you yourself can easily understand what you are writing down; you are not writing for yourself. Will they understand it? Can you make what you have just written clearer, so that there is no possible excuse for their misunderstanding it, or even for their having to pause over it for a second or two in order to see its meaning?

[Gwynne’s emphasis]

And a key paragraph from Strunk’s guide itself (NB. this was written in 1918, so I apologise for the jarring gender bias):

It is an old observation that the best writers sometimes disregard the rules of rhetoric. When they do so, however, the readers will usually find in the sentence some compensating merit, attained at the cost of the violation. Unless he [the student of English writing] is certain of doing as well, he will probably do best to follow the rules. After he has learnt, by their [tutor’s] guidance, to write plain English adequate for everyday use, let him look, for the secrets of style, to the study of the masters of literature.

I don’t think the similarity of the sentiment in these three pieces is a coincidence. Quite simply I hold the opinion that programming should be the act of communicating clearly to another programmer (it’s a useful coincidence that the computer can also understand what’s desired and even prove it in some circumstances).

This is a notion I was trying to convey in my post on Scripting vs. Engineering; software engineering (as opposed to mere scripting) is a team activity, not a solo one, and readability and clarity is everything even if the team is just you and your future self.

Here are some more ideas in that direction:

So how could my colleague and I have such a differing opinion ? Well, Matthew is great friend and an accomplished musician, and I have (some minor) aspirations of being an author – i.e. perhaps, like all people, we each understand and explain in terms of what we know. Unfortunately though, with my seemingly limited imagination I’m more likely to continue writing software and blogs than getting rich rich rich from that novel… Oh well, back to the creation.

- 7 minutes read #pontification , #tools , #water cooler

Why bother testing?

This post was originally written while I was at LShift / Oliver Wyman

It’d be nice to be able to make a definitive case for the benefits of software tests, but I can’t due to this one question:

Is it possible to prove the correctness of a program using tests?

The answer is unfortunately “no of course not” and I’ll show why below. But all is not lost – please keep reading while I take a meander through the realms of confidence…

Imagine attempting to prove the correctness of a simple Fibonacci function using just tests (e.g. in a TDD based process) when paired with a malicious programmer – how can you specify the full range of inputs and outputs?  If the input parameter is a long do you write 2^64 tests? Worse than that, in languages that allow buffer-overrun bugs, and in a function that takes an unchecked array parameter (yes, it happens), the number of input states is effectively equal to the total number of different states of the entire process address space 256^(2^64).

While writing this blog I’m reminded of something I first came across as a fresh-faced undergrad in the 80’s reading Douglas Hofstadter’s version of Zeno’s paradox in Godel Escher Bach:

Achilles told the tortoise, “If A and B, then C. You must accept that”

The tortoise says, “Yes, but if A, and B, then C, is a logical premise, then the premise you just stated, which I’ll call ‘D’ is also true. So, if A and B, and C, then D”.

Achilles relents and says “Okay, but surely you must stop there!”.

The tortoise says, “Yes, it is certainly true that I can stop there, but that would be yet another premise related which I’ll call ‘E’. If A and B and C and D, then E”.

And so on…

Frameworks like Idris or Coq attempt to be a solution but, to some, seem harder to use than just writing the software.

In any case, if absolute total correctness is what you’re interested in then completely different techniques are available. For example the take-off control systems of the space shuttle 

“Take the upgrade of the software to permit the shuttle to navigate with Global Positioning Satellites, a change that involves just 1.5% of the program, or 6,366 lines of code. The specs for that one change run 2,500 pages”

that is, only 3 lines of code from a whole page of specification…

So what about the 99% of the rest of software that we all write, where the budget and incentive just isn’t there for this sort of thing. For that we can at least improve confidence as much as possible using testing as a series of layered techniques, and we have to come to terms with the fact that our confidence can only ever be an asymptotic curve at best.

But why even do tests at all? I did in fact come across a programmer once who maintained that “unit tests prove you’re a bad programmer – if you need to write tests then obviously you don’t understand your code!” Needless to say this person wasn’t exactly a  team player, instead maintaining “I’ve been programming this way for 20 years and I’m not going to change now” It was a PHP shop, but we won’t hold that against them…

Tests can exists at various levels of abstraction and scope:

  • Unit tests; automated
  • Nearly integration tests; automated
  • End to end (installed system) tests:
    • Feature acceptance test; if a ticket claims to add a feature or fix a bug, then manually check that feature only
    • “Poke around a bit” tests; scripted and/or a short, manual, defined sequence
    • CAT / full regression smoke tests; scripted and/or a probably very long, manual, defined sequence
    • Real users; manual, exploratory testing producing horribly vague bug reports (often shared with their friends rather than you)

And this last type is the real point: if you don’t do testing, and find the bugs, then your users will!

Each of these techniques, particularly given the previous, can result in more confidence, unfortunately each type tends to be far more expensive and painful to set up than the one before. End to end tests can be automated but may take a large test server farm or container system for the whole installation, and may not even be possible if there are external service dependencies. Also some tests may be of a visual UI – automated tests can only tell if the expected data objects in the UI model have the expected settings, but it takes a manual test to determine subjective usability issues.

But aren’t unit tests the most fine-grained and focused tests? Can’t we just stop with them? I think not as there is a mock/fixture chasm. I.e. to unit-test a client and server one mocks the server in the client tests and uses client-fixtures in the server tests. But this is a declaration of contract and not a test of the contract – every project I’ve ever seen (ever!) has had at least one failure in deployment because a mock and fixture didn’t agree. And here’s a philosophical question too: when is a mock so complex you’d be better building a stub service instead? Compare with the notion of a “fake”: in Freeman and Pryce and the problem of verified fakes.

So should we just get rid of unit tests (as some may suggest)? Well, again, no. Integration tests can only give vague “smoke signals” when a test fails – to find the exact location of the bug will take unit tests, interminable logging, or single-stepping with a debugger (which is the punishment for not writing unit tests). Unit tests can form essential documentation – the language Pyret even makes unit tests a first-class citizen rather than an add-on – and this is particularly true for interface tests:

“Your interface is the most vital component to test. Your interface tests will tell you what your client actually sees, while your remaining tests will inform you on how to ensure your clients see those results.”

While we’re on automated tests let’s talk about the cult of 100% code coverage. We all know that 100% coverage means nothing as we can fake coverage with stupid tests. But there’s this odd idea that “if thing X doesn’t completely prove what you want there’s no point doing it” which seems to forget that “failure of X really does show you have a problem!” 100% static code coverage certainly means nothing, but having only 10% code coverage really means a lot.  There’s an asymptotic diminishing return worrying about code coverage, and do you really want to waste your time writing unit tests for accessor boilerplate etc? By the way – due to an incompatibility in JVM tooling, using Java with Lombok means it’s difficult to get more than 50% coverage in any case – which is a good thing as it highlights how annoying java is, just use Kotlin or Ceylon instead…

The technology has moved on enough now though that static code coverage measurement should be retired in favour of mutation testing e.g. pitest.org

Speaking of technology, let’s consider automated continuous integration. If you’re using source control with a sensible team policy, e.g. git with “branch per feature”, and why wouldn’t you be, then I hope you also make use of code reviews on merge/pull requests. The load on your team-mate and reviewer is greatly reduced if your software actually works! Maybe you are a genius and always remember to run the tests before pushing a commit, but most people aren’t (myself included) so having the review/CI system automatically report on tests is a valuable safety-net. Github can be configured to enforce this. Your peer-reviewer is not your debugging tool – well, unless you feel you already have too many colleagues…

In short:

  • Just because you can’t get to 100% it’s still worth getting to 80% (and to recognise that 100% is possibly a waste of time)
  • No single technique will solve all the problems
  • In fact, using all the techniques may not solve all the problems
  • Your end-of-sprint customer-facing demonstration should go flawlessly because your “Automated Demonstrations” have run through it many, many times already…

See also

- 4 minutes read #programming

Scripting vs. Engineering

This post was originally written while I was at LShift / Oliver Wyman

I’ve come to the conclusion that the terms like “programming”, “coding” etc. have become horribly ambiguous which has enabled:

  • organisations to offer courses on html/css editing as “coding”
  • people to make claims like “nodejs is more productive than java” (which is a nonsense statement either way)
  • various arguments along the lines of “is X a PROPER programming language”.

I think it’s more helpful to think in terms of “scripting” vs. “engineering”:

  • Scripting is geared towards the short-term, small team or solo, quick prototyping.
  • Engineering is geared towards the long-term, larger teams, maintainability(i.e. readability), refactorability and extensibility.

It’s probably impossible to agree on whether a language is “scripting” or “engineering”, but obviously I have personal opinions about some characteristics of each:

  • In the long term, the time taken writing software is 90% reading what’s already there. Languages that don’t support readability (or IDE analysis support) fall towards the Scripting end. IMHO the reason nodejs has encouraged microservices is because nodejs is quickly unreadable – you don’t extend a nodejs app, you just write another service…
  • Monkey-patching automatically precludes a language from Engineering (it violates the Principle of Least Surprise) – how can anyone reason about code that can extend an object’s methods at runtime?
  • Static-typing moves the language towards Engineering by increasing correctness and readability. Completely pathological strict typing languages like Haskell may be a learning barrier though (along with Haskell programmers’ irresistible temptation to use punctuation as function names it seems – quick, quick, tell me what the difference is between foldl and foldl’)
  • If the language has static typing then good type inference cuts down on the boilerplate. These days I wouldn’t write any Java without using lombok.
  • Immutable objects are good Engineering. Likewise functional languages can aid Engineering, except that the temptation towards one-line-itis reduces readability.
  • Encapsulation and clear techniques for Dependency Injection help Engineering as it supports mocking in unit tests.
  • Automatic resource management aids Engineering.

So I can possibly come up with a completely unscientific and arrogantly self-opinionated table of languages: 5 is good, 0 is bad (if the square is blank then I haven’t formed an opinion):

Readability Least surprise Static types Type inference Immutable Functional DI Mocking Resource Management
Java with lombok 4 4 4 3 2 5 31
Kotlin 4 4 4 5 4 5
Ceylon 4 4 52 5 5
Rust 5 5
Clojure 3 33 1 3 5 5 4
Python 4 4 3
Python with Coconut 5
Javascript 3 24 0 4 05
PHP 3 26 17 0 1 3 0
Bash (just for fun) 4 38 0 0 0 0 49
  1. “try” with resources
  2. inline Union types look interesting
  3. things get turned into null at the drop of a hat
  4. https://www.destroyallsoftware.com/talks/wat
  5. everything is in a global namespace
  6. https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/
  7. annotations for run-time checking
  8. space handling in values
  9. all resources are in pipes

Scripting vs. Engineering databases

I think we can extend this to databases too. The NoSQL/schema-less fashion of databases are definitely up the scripting end:

“The problem is that in the absence of a formal schema, the “schema” is an emergent property which is reflected in the code used to manipulate the database” – comment in Why You Should Never Use MongoDB

The “MEAN stack” – mongodb, express, angular and nodejs – is certainly for prototypes only. It should be called the WONGA stack: Write Only Node, monGo and angulAr (possibly only UK readers will get the reference). Angular and React are good for “single page application” building, though possibly vastly improved by using typescript (and flow) instead of javascript.

Responses to “static typing is bad / gets in the way”

The post “Static vs. Dynamic” Is the Wrong Question for Working Programmers, in the section"static typing benefits”, makes the correct statement “Proof that certain kinds of dynamic errors are impossible” but I’d maintain the suggested “drawbacks” are incorrect:

  • Increased verbosity or reduced expressiveness – not true if the language has good type inference, and type annotations improve readability immensely.
  • Rejection of otherwise correct programs – how can a program be correct if it has a type error? See how an uninitialised variable cost $90,000.
  • Slower programmer iteration (possibly lengthy compile/run cycles) – IDE integration and incremental builds removes this completely
  • A need for the developer to learn “static typing” language feature – I’d suggest that if you really know what your program is doing then you do know about types (unless you’re programming in the Stringly style)

Reading through some python documentation blogs and this paragraph caught my eye:

If you’re coding in Haskell the compiler’s got your back. If you’re coding in Java the compiler will usually lend a helping hand. But if you’re coding in a dynamic language like Python or Ruby you’re on your own: you don’t have a compiler to catch bugs for you. – https://codewithoutrules.com/2016/10/19/pylint/

And that’s why I like types (which can be added in python)

- 4 minutes read #social pontification

Euro Will Replace Sterling in 10 years (and here’s how Brexit made it happen)

Ok so that’s quite a fanciful claim, but just for fun here’s how it might happen.

Step 1: Scotland leaves the UK

In the 2014 Referendum on Scottish Independence there was the issue that Scotland would have to re-enter the EU as an independent country. I.e. it would have to exit the EU first and fulfill the 35 rules before re-entering. This was a bit of a ruse by the various EU leaders, including our own, as there were a number of other countries facing the same breakups e.g. Spain with Catalonia. So making the future look bleak for any breakaway factions was part of a larger, stabilising plan.

But, in 2016, once Article 50 has been triggered the UK is already out of the EU and Scotland voted against that!

So Scotland is almost compelled to have a second referendum and the EU issue has disappeared, in fact the reverse is now true. Scottish independence is phrased as “those Sassenachs are nothing to do with us”, victory is assured, and the EU welcomes them with open arms.

Step 2: Scotland trades oil (in Euro)

Scotland adopts the Euro as their currency; there’s no reason to take Sterling and plenty of emotional reasons against. They also get a large part of the oil reserves from their newly assigned North Sea territories.

But why trade oil in US Dollars? Much of Scotland’s oil trade will be with other EU countries, so a new oil exchange is formed, probably in Frankfurt or maybe Edinburgh, trading in Euro.

In the meantime Northern Ireland, which had a large Remain contingent, has a referendum to unify with Ireland and there’s a good chance of success – and the UK ceases to exist (well, the United Kingdom of England, Wales and a few small islands).

Euro finance trading is hemorrhaging from London to Frankfurt and oil income is greatly reduced. From this point on it’s inevitable – Sterling sinks, GB converts to Euro and probably rejoins the EU.

And it’s all the Brexiter’s fault. Well, ok, it’s also the fault of SNP-Remain running a much better campaign than Corbyn and Cameron managed…

Bonus: US Dollar also crashes

Ok, this one is not so likely, and would take 25 years, but here goes.

The future of the world lies in clean energy. Countries like Dubai are already building huge solar-electricity plants. Once the technology matures massive investment is made in all the equatorial countries, which includes southern EU, with high-voltage grids selling power to the north. The, now strong, Euro oil exchange market expands to cover all energy types with inward investment from various equatorial Eastern nations.

But no matter how good electric cars and rains become, there will always be plastic products and trucks needing diesel. Oil demand only reduces a little and the Arab oil producing nations want a part of this new market – they start trading some oil in Euro as well.

From here the Euro oil market just continues to grow, a side effect is that Frankfurt becomes a finance powerhouse, and the “reserve currency” value of the US dollar starts to collapse.

Silver Lining Alternative

The European Common Market (now called the European Economic Area) was actually an excellent idea, but the thoughts of “closer European Union” – i.e. a federated United States of Europe – and the increased distancing of the European Commission from the “ordinary” public is causing significant segments of the EU population to hate the EU.

So maybe a bunch of other countries get their EU Referendums in before Scotland gets the UK one. The EU basically collapses except for maybe a few core countries.

Out of this rubble a new Economic Zone is created. We’d still have to pay just as much as now (perhaps more as there’d be no rebate) and migration would still be open (it must to be to allow free trade and exchange of services). It would take 10 years to wind the clock back to pre Maastricht 1991…

- 3 minutes read #project management

Can you do it?

This post was originally written while I was at LShift / Oliver Wyman

You’re somewhere in the middle of an Agile project. As usual, once you’ve actually started development, the true nature and scope of the project is becoming clear and the client asks ‘Can you do <some “clarified” feature>?’.

This, of course, is a trap of linguistics. As programmers we can do anything so confidently say yes, but the question they’re really asking is “WILL you do this?” with a side order of “as well as all the other stuff”. It’s related to the other trick question “Can we bring this task/feature/bug into the sprint (as well as all the other stuff)?”

As Agile practitioners (all LShift lead developers are trained in DSDM), to stop project expectation/scope/costs/deadlines spiralling out of control the conversation needs to encompass ALL of these four questions:

  • Can we do it?
  • Should we do it?
  • When should do it?
  • What shall we displace so we have time? – or, Is there a case for more budget to be made available, or a subsequent phase (these may signify a change in business goals)?

and it’s the last step that is the hardest.

In manufacturing there is the adage: “Cheap, Quick, Good – pick two”. In Design & Manufacturing (which is what software development is) the model is “Time, Cost, Quality, Features – at most three can be fixed”.

atern pick 3

You always want high quality, so the negotiation has to be found in at least one the other three areas. But budget is often fixed and a deadline has been promised – so the variable is usually features (if newly discovered items are important, and nothing can be displaced, then new budget must be found).

NB. This is related to the Project Management Triangle though there’s a subtle difference: clients tend to think in terms of budget and deadline whereas implementation teams think in terms of features, velocity (related to team size) and deadline.

In a related post:

“reaching the very end edges of our ability to anticipate how we are going to want things to be and coping with the unknowns we encounter is part of the fundamental nature of developing software.”

True Agile is not just “morning standups and you’re done”, it’s a constant conversation between the client and developers about the relative priority of features. As the project progresses new ideas come to mind, or it’s apparent a feature implies more requirements than you thought (or occasionally less), and this is perfectly natural. An agile project team can respond to the changing requirements, but an agile project manager needs to lead the client through all four of the replanning questions.

xkcd1425

This page and its contents are copyright © 2020, Ian Rogers. Theme derived from Prav