Modest architectures. A playful methodology for solid results | by Dmitry Kolomiets

A playful methodology for solid results

Photo by Christofer Maximilian on Unsplash

This is a short post about principles I apply to everything I build — whether it is a class interface, web API, Infrastructure as Code (IaC) template, or architectural design.

I didn’t plan for this; I was thinking about principles for building good IaC templates, but I quickly realized that these are the general principles I constantly use. I put together a list, took the first letters, and used WordFinder to get a word. I was amused by how good the word was:

Modest — not wanting to talk about your abilities or achievements and to say that you are good at something, even when you are — used to show approval.

Longman Dictionary of Contemporary English

The principles are:

  • Meaningful defaults
  • Orthogonality
  • Documentation
  • Extensibility
  • Security
  • Testability

So here we are, one more mnemonic acronym. There is always a place for a new one.

Let’s start by covering the principles. Just for your amusement, I will provide examples from the IaC domain to illustrate that they are quite general.

Meaningful defaults

Simple things should be simple, complex things should be possible.
Alan Kay

Meaningful defaults help you minimize the friction required to use your artefact. As with API design, consider the sort method in Python:

Note that by default, sort returns the items in ascending order. You can request descending order by providing a non-default parameter, as shown below:

Similarly, in the IaC world — imagine you have a large CloudFormation stack with tens of parameters. For the sake of argument, Jaeger Quick Start has more than 50. Still, all parameters have default values, and you do not have to change them if you want to try the Quick Start out. This frictionless experience builds up confidence and spurs further experimentation.

Orthogonality

Orthogonality is an important principle in software design. As Wikipedia defines it, an orthogonal operation changes just one thing without affecting others. A traditional example is pure functions — pure functions do not have side effects, and therefore, it is easier to compose multiple functions and reason about them.

An IaC example may be a bit more difficult to grasp. Let’s say we have a large infrastructure deployment that provides the following options:

  • DNS: Disabled / Private Hosted Zone / Public Hosted Zone
  • Storage backend: In-Memory Storage / Elasticsearch
  • Export metrics: Disabled / Enabled

These are orthogonal options — you can mix and match them as you want, and you will always get a valid combination:

  • No DNS configuration + In-Memory Storage + Disabled metrics
  • Public DNS + Elasticsearch + Enabled metrics

Approaching IaC design with orthogonality in mind usually results in solutions that are easier to test and support, as all features are independent.

Documentation

Documentation is one of the most neglected areas of software engineering. Good documentation is very difficult, and (almost) nobody likes to write it. It is not clear what is more challenging — creating sophisticated code or writing meaningful documentation for it.

To be clear, by documentation, I don’t mean comments like this:

Trivial things don’t need an explanation. It’s more about more involved snippets that you can’t easily comprehend without knowing some background information:

Knowing what you need to document comes with practice, like everything else. You need to write (and read!) a lot of documentation to know what looks good like. If in doubt, explain your code to an imaginary friend (or a duck) and think about the things that may raise their eyebrows (not sure if ducks have the eyebrows, though).

In the IaC domain, documentation plays a central role as well. How many times have you seen templates with undocumented parameters so you had to guess the correct values ​​you can use? How many times have you guessed incorrectly?

CloudFormation template with no documentation for parameters

Would it be better to have parameters logically grouped, with meaningful descriptions and links to web pages where clients can get further information?

A more polished version with parameters grouped and documented

Remember the last time you complained about a sluggish mobile application, unintuitive user interface, or crappy error message. That is how your fellow teammates may feel working with your IaC template.

Do better; they deserve it!

Extensibility

Whether you design a class that will be used by your teammates or build a large-scale microservices architecture — extensibility is something you probably need to think about. Likely, you haven’t envisioned all the possible usage scenarios, so creating an open solution would benefit you long term.

Open here is for O in SOLID — another popular mnemonic and something you may want to remember for your next interview. It would be amusing (for both parties) if you talk about MODEST principles with your interviewer as well.

An example from the IaC domain: Imagine that you build infrastructure for a product and deploy resources that other teams will use— VPC, security groups, IAM roles, etc. Later, a different team wants to deploy a microservice in the VPC. They would probably need a VPC ID, a list of subnets, and maybe a security group to attach to their service. What would be the process for the team to retrieve this information?

They can open AWS Console, get the identifiers/ARNs and hardcode them in service configuration files. If you have multiple environments (Dev/Test/Prod) — ask them to repeat the process for each environment (and run).

Surely we can do better. What if, as part of your IaC implementation, we provide a set of SSM parameters with all the necessary identifiers? Then a service team can import the bits they need using the well-defined parameter names. Treat these parameters as your IaC “public interface” — once published, you have to maintain them and ensure backward compatibility.

Security

Security is a catch-all principle. If you don’t know where to start, start with security.

Seriously though, you need to think about security, regardless of what you are building. From static code analysis, container runtime security tools, network scanners, log analysis, anomaly detection, and IaC security tools — the spectrum is huge. Thoughtworks Technology Radar is a good place to start.

Testability

I think we’ve made very good progress over the years — even the legendary Is Unit Testing worth the effort StackOverflow question is closed for comments.

Let’s post the following for the sake of the final MODEST principle: testing is good and automated testing is even better.

Designing for testability means that your artefact can be efficiencies either during development or by your clients during integration. Think about load/integration tests the clients may want to conduct against the class/API/IaC/architecture you developed.

Continuing our IaC examples, you can do a lot to make your IaC code testable. Start with unit tests for your IaC provider and consider actual deployment tests for different combinations of parameters and target regions. This is especially valuable if you need to support non-standard regions, such as China or GovCloud. Here is an example of a TaskCat test file (from quickstart-jaeger repository):

Whatever you are doing, there is a way to test it.

Being modest is not always a good life strategy, but designing and building MODEST architectures is something you should consider.

Apologies for this mischievous nonsense. I will be back with more serious thoughts on distributed tracing and OpenTelemetry shortly.

Leave a Comment