Antique inspirations for software architects

The Roman architect Vitruvius around the year 15 BC completed his impressive, ten-volume treatise on architecture—De Architectura. It covers every possible type of man-made structure ever needed by the people of his time, but starts out wisely by prescribing basic qualities that good architecture must embody:

All… must be built with due reference to durability, [utility], and beauty. Durability will be assured when foundations are carried down to the solid ground and materials wisely and liberally selected; [utility], when the arrangement of the apartments is faultless and presents no hindrance to use, and when each class of building is assigned to its suitable and appropriate exposure; and beauty, when the appearance of the work is pleasing and in good taste, and when its members are in due proportion according to correct principles of symmetry. [emphasis mine, and I prefer ‘utility’ over ‘convenience’ in the original quote]

Vitruvius, De Architectura, Wikiquote

Sounds familiar? It certainly did for me when I was brainstorming the set of values that our newly minted team of software architects was to adopt. Durability, Utility and Beauty described perfectly how I thought about good software architecture.

  • Durability means that software must stand the test of time. Work as long as necessary without crashing or requiring mid-way reboots. And it shouldn’t need to be rewritten from scratch every few years, but instead adapt well to changing needs. This principle guides the selection of languages, platforms, frameworks and tools.
  • Utility means the software must fulfill requirements that it was given and must do so well. If it’s a user-facing application, it must be easy to use and supportive, if it’s meant to handle high load, it needs to scale well. If it exposes an API for others to connect to, that has to be comprehensive and flexible. We need to build software always with its intended purpose in mind.
  • Beauty means the software must be pleasing to the eye. A clean, simple UI, laid-out and colored for readability. Inside, a logical layout of components, packages and modules. Good, clear but concise naming, plenty of whitespace, short functions, variables of unambiguous purpose. Computers will read anything. We need to code for people. This principle underlies front-end and coding style guides.

We unanimously decided to adopt these two-millennia-old qualities as our team’s values and to visualize them, I proposed an image that would become our logo: the Millau Viaduct—a spectacular bridge designed by sir Norman Foster, built near the city of Millau in southern France.

Millau Viaduct

Bridges ideally embody durability, some serving the public for centuries, like the Charles Bridge in Prague, opened in 1402. Getting people efficiently and safely across rivers, valleys and canyons is as clear an illustration of utility as we could hope for. And while beauty is in the eye of the beholder, to us Millau Viaduct truly is beautiful, with its slender structure suspended over the Tarn valley like a delicate web of strings.

We’re using these values to ask better questions. Is it durable? Will this fancy framework you have spotted at some conference be around in two years? Are you sure we need the user to click three times to submit the order? Can we make it easier? Can you read your own code? Can your new team colleague read and understand it? Old lessons that continue to hold true in an age technically so much more sophisticated than when they were put in writing.

Photo of Millau Viaduct by Phillip Capper.

The state of the craft at CraftConf 2015

CraftConf in sunny Budapest aims to be the conference in Central Europe where developers share what’s state of the art in building software. Joining the 2015 edition was an easy choice, after the first edition a year earlier received rave reviews from attendees. Three days, 16 talks and a workshop later I emerged with 6,062 words worth of notes, distilled into a few broad trends that seem to represent the edge of the industry right now.

CraftConf 2015 Stage

Microservices entering the mainstream

At SoCraTest 2014, less than a year ago, a lot of people were still asking basic questions about microservices—what they are, how to build them, how are they different from any other SOA approach. Not anymore. CractConf saw a lot of companies sharing battlefield experiences with these architectures—what works, what doesn’t, whether to consider the approach at all and how much it will cost.

  • Microservices are a means to scale the organization—allow many people to work on the same system, reduce dependencies, and thus enable rapid development without having to coordinate huge releases or continuously breaking one another’s code. They’re routinely described as “easier to reason about” and built to “minimize the amount of program one needs to think about” by the very virtue of being small and focused on doing one task well.
  • Microservice ecosystems at established companies routinely consist of 50+ and even 100+ services, usually built in a whole range of technologies. If a single service is small enough, say “2,000 lines of code“, or “takes 6 weeks to build from scratch by a newcomer” (both actual definitions), then building one in a wholly new technology is easily sold as an inexpensive POC.
  • All companies successfully implementing microservices started out with monolith applications and afterwards split out the services one at a time. This approach was broadly recommended, even for greenfield projects, because monoliths are easier to refactor while the organization works to research and understand its product better.
  • The supporting tooling is already there and mostly quite mature. Early adopters, like Netflix, had to build their own tools, which they later shared and improved with the open source community. Meanwhile, commercial tools popped up, offered by specialized vendors, with support contracts and other conveniences that pointy-haired bosses like so much.

But most importantly:

To benefit from microservices without getting killed, you need to:

  • automate everything—builds, testing, deployment, provisioning of virtual machines and container instances. It’s the only way to manage hundreds of running service instances.
  • monitor everything—each service must have its own health checks, showing whatever information is most relevant. Typically numbers of transactions, timings, latency, hardware utilization, but often also business KPIs. You’ll also need a means to track requests flowing through the system, ie. by IDs being passed in service calls. This information must be available to development teams in real time.
  • build for failure—crashes, disconnections, load spikes, bugs, all of which will occur more often than with monoliths. Make sure failures are reported, tracked, and the system is self-healing, via techniques like circuit-breakers, bulkheads or resource pools. Work with business representatives to determine for each use case whether consistency or availability are more important, because you cannot always offer both.

Not everyone was pleased with such a high degree of saturation with microservice themes at CraftConf:

But that only proves that this architecture is well past the stage of early adoption and entering into the mainstream.

Everybody has an API

The consequence of adopting microservices is that APIs become the norm, starting out internally, and often “sooner than you think” being made available to the outside world, either to support different devices or integrate with 3rd parties. Their costs also became more evident:

  • An API is for life. Once it becomes public, it’s very difficult to change, so early design mistakes become much more difficult to fix.
    • Use techniques that allow you to add new fields and methods to an API without disturbing clients.
    • Semantic versioninig, coupled with decent deprecation procedures, help move the process of making backwards incompatible changes.
    • You’ll still have customers who “missed the memo“, whom you may have to offer commercial legacy support for an additional fee.
  • Create good documentation, generated and published automatically.
  • Assign people who will be monitoring community sites, like StackOverflow, for questions regarding your API.

@ade_oshineye (of Apprenticeship Patterns fame) was spot-on summarizing the process of deciding whether to create an API by showing an analogy to puppies—everybody wants one, but not everyone is ready.

Moving towards Domain-Driven Design

Frameworks these days tend to dictate the design of applications by suggesting organizing code by layers into packages like models, controllers or views. The consequence is that:

  • modifications to a single business scenario require often changing code in many packages,
  • it’s all too easy for components to reach into layers outside their hierarchy, too deep down for their own good, while they should only be calling public APIs,
  • there’s very little information presented by the package structure on what the application does.

Several speakers postulated that this should stop and instead code should be packaged by business units, with relevant models and controllers sharing the same packages. Encapsulation could further be improved by changing method and component access to package instead of the common public. It’s an old theme that finally seems to be getting traction, with past support from developer celebrities like Uncle Bob:

What do you see? If I were to show you this and I did not tell you that it was a Rails app, would you be able to recognize that it is, in fact, a Rails app? Yeah, looks like a Rails app.

Why should the top-level directory structure communicate that information to you? What does this application do? There’s no clue here!

Robert Martin, Architecture, the Lost Years

Well worth watching.

TDD and Agile now taken for granted

Two themes notably absent from the vast majority of CraftConf talks were TDD and Agile. They implicitly became accepted as defaults—the baseline, cost of entry and survival in the game of software development.

  • Microservices will only reach their full potential when their owning teams can work and make decisions independently from central authority, including frequent deployments to production.
  • Frequent, decentralized deployments require comprehensive, automated test coverage.
  • TDD drives the design of code, meaning every line exists only to make a failing test pass. “Every new line of immediately becomes legacy code” so code as little as possible.
  • Google continues to build new tools to satisfy business problems they are facing—tools that often get adopted company-wide, but never enforced. They call it an evolutionary approach, where the best ideas will be adopted simply on merit, while the others will die in obscurity.
  • @cagan argued how the whole top-down oriented product design cycle is broken by being grossly inaccurate and too heavy, and companies need to adopt bottom-up idea spawning and rapid testing instead.
  • Transparency is key, so that everybody can make better decisions based on as much information as possible.

Oh, and “doocracy” is a word now:

A vibrant community

It’s been a blast to mingle with some of the 1,300 energetic attendees, meeting friends, old and new. @MrowcaKasia and @kubawalinski turned from Twitter handles into real, live, and engaging persons. The slightly grumpy but ever competent @maniserowicz is always a pleasure to meet, and then there’s the whole SoCraTes gang of @leiderleider, @c089, @Singsalad, @egga_de and @rubstrauber, whose passion for community and craftsmanship continues to inspire.

The 2015 CraftConf was only the second edition, but already organized with such painstaking detail, that I can easily call it the best conference I’ve ever been to. The team’s already fishing out and working to improve what didn’t quite work this year, so next year’s event is bound to be even more polished.

API thinking vs. client thinking

Have an API? No? So obscure. Everybody has one these days as APIs were the foundation of online success in the last decade. But building a good API is hard. In fact, the mindset that’s required is peculiar enough to consider separating people who will build it from those who will use it.

APIs were all the rage that, along with AJAX, kicked off Web 2.0. By allowing others to tap into the features and data of your application, you could spark a whole community of clients and mash-ups, making you the platform. Twitter is a well known child of this era, where an API was built first, then Twitter’s own clients as well as all the independent ones on top of it.

APIs, APIs everywhere

This obviously takes away control of the application’s future from its creators, putting it into the hands of a broader community. Example being again Twitter, where features such as retweets were only added to the platform once they became widely used in independent clients. At some point Twitter decided to reclaim control of its brand and user experience, which started to diverge between applications. Certain requirements were imposed on how tweets may be displayed and what functions should be available. Break those and you may be kicked off the API completely.

For System Architects, APIs are the panacea in a multi-device world. With the variety of client applications being demanded – web, native, embedded, large-screen, tiny-screen etc. – we want to keep complexity low by reusing as much code as possible. A properly written API can be shared between all clients and even allow for gracefully dropping support for a legacy generation, like a browser that’s becoming obsolete.

Trello makes excellent use of this graceful degradation pattern:

[T]he website is just a face that chats with the Trello API and that the iOS and Android apps are also just faces and you can make your own face.
(…)
[T]here’s a special face out there for people using Internet Explorer 9.

There’s the API shared by all official and unofficial clients, each one called a “face”, and there’s a special, older version of the web face that’s left to support the remaining users of Internet Explorer 9. Brilliant.

  • Yes! I want to build an API. How do I go about it?
  • With foresight and planning.

APIs are a special case of Separation of Concerns and here’s where I’m starting to think that APIs and clients should be built by different people:

  • clients are focused on their immediate needs; I’m building feature X and need data A, B and C formatted this way.
  • APIs are catering for many clients and their different, often incompatible needs.

If the same person writes the client and the API, or even if they’re separate but on one, tightly knit team, they are much more likely to reconcile the conflict by leaning towards the immediate need of the client, away from the broader needs of the ecosystem. Every subsequent client that comes in with their needs will receive their own, special endpoints. Soon you’ll have an explosion of similar, oddly named methods for very specific use cases, little reusability, where a simple change may require modifications to hundreds of lines of code. In other words, you’ll have built a monolith where “API” will merely be a different name for the application’s model layer, and since that model will be separate from the rest of the application, complexity becomes even worse.

Then, once it’s in production, you’re dead in the water, because:

Public APIs are forever.

Joshua Bloch, How to Design a Good API

Anyone can use a public API and you’ll have to maintain backwards compatibility for a long, long time.

However, if you task different people with building APIs and clients, you’ll get a lot of conversations, often conflicts, which are essential for getting the best result for the broadest amount of use cases.

Make sure the API team consists of people who have as wide a perspective as possible. Keep thinking well beyond the immediate requests they receive, weighing those against all similar requests in the past and thinking forward into the future. What else could be required from this method later? What else might someone want to extract from this particular data set? Will it need filtering, sorting, paging?

Building a good API requires following guidelines, which are not the ones usually proposed for client design:

  • violate YAGNI – think of what might be useful in the future, but leave out things that are easy to add, because removing anything is much harder;
  • write a broader than usual set of features for the method, weighing the possible performance penalties against power;
  • displease everyone equally – clients will often times need to curb their requirements, to allow for broader reusability;
  • document extensively – your documentation will become a guide to understand the contract of each method – what it expects and returns. Without it, you’ll be swamped by questions and complaints.

Joshua Bloch, creator of, among others, the Java Collections API, shares a number of excellent recommendations for building APIs in a Tech Talk he gave years ago at Google. It’s well worth the hour to see it:

If the API is done right, it’s an investment that pays back many times the effort put into it. The multitude of clients that can use it, the flexibility to rapidly build features that weren’t previously thought of. For any regular software company it’s possibly the most complex task it will handle and you should put your best, brightest people on it. And make sure they spark conflicts with all the developers building clients, because that means they’re having real conversations about how to build the best solution for everyone.