This spring, we had the opportunity to attend GOTO Conference 2018, hosted at Chicago’s Navy Pier. Here are our key takeaways:
Containers, Containers, Containers
Microservices are one of the hottest trends in the technology industry right now, so it’s no surprise that the GOTO Conference dedicated a whole track to the topic. To explain microservices, first we take a step back to explain monolith applications and the problem microservices are trying to solve.
Source: High-performance Architecture
Taking a look at the monolith application in the diagram above, everything is tightly coupled and one small change requires resources from every part of the application. Since this application is so large, it will require multiple teams to deploy one minor change. It will also increase the amount of time to onboard one developer as they will need to dive into a large, tightly integrated codebase. With a microservices-based architecture, the application is split into multiple services, and when a functional area is modified, only one service will need to be changed and deployed, greatly reducing the resources required. This also allows you to scale one functional area at a time or, if a service fails, the rest of the application will still work.
In Kenny Bastani’s talk, Cloud Native Java, we explored ways to migrate from monolith architecture to a microservice architecture. One method to migrate, the strangler pattern, was explained by a quote from Martin Fowler, “Gradually create a new system around the edges of the old, letting it grow slowly over several years until the old system is strangled.” The basis of the pattern is to create all of your new features as microservices around your monolith and over time you will have a microservice architecture.
However, microservices can create a lot of administrative overhead. In a monolith, you would scale the entire monolith at once and only have to manage one large application. Microservices allow you to scale individual functional areas by themselves, but doing this manually requires a lot of time and effort. In the Containers, Containers, Containers track at GOTO Conference, we explored different ways to manage and orchestrate microservices. Tools such as Docker and Kubernetes remove a lot of the manual effort required to manage microservices allowing you to focus on development.
At West Monroe Partners we use many of the tools and methodologies above to build modern solutions and transition our clients to microservices and other high-performance architecture patterns enabling them to accelerate their ability to scale, develop new features faster, and innovate with lower risk. For more information on microservices at West Monroe Partners visit High-performance Architecture.
Errors aren’t going anywhere
If there’s one universal topic in programming that we can’t get away from, it’s errors. We’re always trying to find a better way to handle what happens when things don’t work the way we want.
In Tomas Petricek’s talk, Learning to Live with Errors, four ways of viewing errors were presented:
- As part of the process
Errors are part of the core philosophy behind the development methodology known as “Test-Driven Development.” In Test-Driven Development (TDD), the developer writes a set of tests for a feature before writing any code. This allows errors to inform your development process. Once all of the tests pass and errors stop happening, you’re done! Here, errors aren’t a problem as much as they are an indicator of something you haven’t completed yet.
- As contradictions
When computer scientists designed early programming languages, they often came up with languages that felt like proofs: Your program is just a proof of what you want to happen, so there’s no risk of unexpected behavior. This approach is evident in functional programming languages like LISP or Ocaml, where side effects are highly discouraged, making it easy to understand what will happen.
- As the unavoidable
Treating errors as an unavoidable fact of life that must be accounted for is probably the most common approach to handling errors. The classic try/catch programming paradigm is the purest representation of this, and although it works, treating errors this way can lead to bad habits like “pinball programming,” where upon catching an error the program simply retries the operation.
- As inspiration
Treating errors as an inspiration may sound sort of weird – don’t we want things to work? But, there’s more precedence than you might think. The slinky, a common household toy, was invented by accident when an engineer dropped a tension spring and noticed how it behaved: The result was nothing like the nautical equipment he was trying to build in the first place. An error in development might lead to an even more interesting product. Perhaps you’ve heard the not-always-joking-adage: It’s not a bug, it’s a feature!
When writing our own software, the language we use and the applications of our software should guide how we see errors. Regardless of what perspective we take on errors, we can always take steps to limit the amount of errors we need to deal with. Michael Feathers’ talk on Unconditional Code outlined some interesting ways to write code to avoid errors:
- Avoid tunneling
Tunneling is kind of like what happens in old adventure games – you forget to pick up a hammer in the beginning of the game, and five hours later you’re trapped in a wooden box! It’s creating a large distance between a decision and doing something about it. In software development, this makes code harder to read and extremely hard to maintain.
- Extend the domain
One of the biggest error causes in software development is “edge case” errors – when you have everything working just about right, but it doesn’t work for a specific case when your input set is empty. We can make our software much more robust and oftentimes simpler by structuring our logic to avoid writing special logic to cover edge cases.For instance, let’s assume you’re writing an algorithm to count the number of recurring sequences of ‘1’s in a string of 1s and 0s.The string 011001 would have 2 sequences, while the string 000001 would have 1 and so on.You might start with the following code:But, there’s a problem here: if your sequence is 1111111, you’ll never encounter a 0, so this will return 0. Time to write a bunch of edge case code, right? Or, we could extend the domain by inserting a 0 before and after the input string. This way, we guarantee we’re always entering a sequence and that we’ll always leave it.
The result is less code and our algorithm can run without pesky edge cases to consider!
- Change the requirements
Errors, and conditions that cause them, are often results of complicated requirements we have to figure out how to implement. The best and simplest way to limit this is to change requirements to avoid having to deal with them in the first place. In the above example, we could, for instance, have requested that the user provide a sequence with 0s at the beginning and end.The unfortunate reality is that requirements are often driven by more pressing needs than handling errors, but it’s still an important factor to consider when planning software development.
We’ll never escape errors, but there’s always a way to mitigate them. Thinking critically about how your application should limit errors (and treat them when they do occur) is an important part of software development.
GOTO Conference was a great opportunity to understand trends and market demands. We’re curious to see what trends will dominate the conference in 2019 – we don’t expect microservices to go away, certainly, but the rise of Kubernetes and other container-related technology will probably create increased attention on ‘containerization’ – already a trend today – and how to handle a technology architecture that relies on these things.
One thing we didn’t cover here that we’d like to call out is Chaos Theory, an interesting topic that’s a bit related to both of our takeaways above. If you’re interested in that or any of the other talks from GOTO this year, make sure to check out their website and download the GOTO Play app to view all of the talks!