In the last post we described infrastructure related innovations. Let’s continue analyzing Thoughtworks’ findings.
Here are the things I found important and worth pointing out when speaking about software development.
Development trends - are you as curious as these two little owls?
Photo by Zdeněk Macháček on Unsplash
Backend development trends
When building a backend for multiple targets, like web browsers and mobile devices, I’ve found GraphQL - a resource aggregator on the server-side - very handy, especially in combination with SpringBoot. A quite common approach to building a micro-services oriented architecture in the Java world is to define boundaries between functionalities and write SpringBoot applications for each of them. We also find a gateway in front of our architecture which, among others is responsible for request routing and API composition. Instead of exposing REST endpoints to every thinkable scenario, expose a GraphQL endpoint to decouple back-end development from the constantly evolving and changing front-end requirements.
Additionally GraphQL Inspector can be run as part of a CI pipeline to validate the graphql schema, to find similar or duplicate types and to compare it with the previous version to catch breaking changes and to send notifications to Slack.
Be event driven
During the last couple of years when you had to introduce a pub-sub messaging system to your architecture, Apache Kafka seemed to be a default choice. But Kafka is no longer advertised as a pub-sub but rather a whole streaming platform. Additionally a new kid on the block - Apache Pulsar - is reaching for the crown. There are a few very compelling reasons to adopt Apache Pulsar, like tiered storage, geo-replication or support for tenants, but I’d go with a proof of concept first, until treating it as a safe, default and battle proven option.
Kafka is a quite well known messaging system and can serve as an intermediate layer between various systems. For example to offload data from an SQL database into a data warehouse. This task can be solved with the Kafka Connect framework and particularly with the JDBC source connector. A standalone connector, a Scala application, is also available, called Tamer.
Both mentioned tools, Kafka and Pulsar, fit well in an event-driven architecture. While you may be familiar with OpenAPI (formerly known as Swagger) in the context of working with synchronous REST APIs, AsyncAPI is the complement part for asynchronous APIs typically found in any EDA.
We're on a mission to standardize message-based communication and increase interoperability of the different systems out there.
This project is about to set up a standard as well as provide tooling, like code and documentation generators, mocking and testing libraries as well as validators.
Microservices cherries on top
Node.js developers looking for tools to build a microservices oriented architecture may find NestJS useful. It supports the most common communication styles, like request-response, asynchronous messaging and based on events. The framework supports TypeScript, makes use of Express (exchangeable with Fastify), integrates well with messaging systems like Kafka, RabbitMQ and NATS and supports various protocols like gRPC and MQTT. All this and more to:
… allow developers and teams to create highly testable, scalable, loosely coupled, and easily maintainable applications.
Testing HTTP APIs is essential to keep your clients safe, when deploying a new version of an application. Also in a modern microservices architecture, you need to make sure that updating one service here won’t blow up another service there. In the Spring Cloud world you can get away with Spring Cloud Contract, but other than that there are plenty of options available, one of which stands out: Karate. It’s especially useful for less techy people like product owners, domain experts or testers who can work with a domain specific language, like in Cucumber, just without the hassle of writing glue code or step definitions. Moreover Karate has become a full end-to-end testing framework with the introduction of UI test automation.
Microservices are leaking into frontend development
The Microservices architecture is as old as the crossroads when developing backend applications. Micro-frontends on the other hand, although recognized, are far less being used. The concepts are similar: decoupled codebases and therefore teams, independent life cycles and deployments, and clear ownership boundaries just to name a few. One of the core ideas though is about favoring native browser features over custom APIs. Being in contradiction with what you find in microservice based architectures is using browser events for communication instead of a global pub-sub messaging platform.
So far we’ve been experimenting with Frint and single-spa and are eager to introduce this technique in a front-end application of a larger scale. Keep in mind though, that Frint is a whole framework and requires all your apps to obey its rules. We’ve got the impression to be violating the idea of favouring browser events over custom libraries for communication and therefore our applications became less technology-agnostic. You may wonder how to combine all these micro frontend applications, if you can mix server-side rendered and client-side rendered code and if start-ups could benefit from this technique.
These and other topics are covered in Software Engineering Radio’s podcast about micro frontends.
Frontend testing - do you speak it
When you write unit and integration tests in Jest, you may find Testing Library an interesting extension. Available for the most common frameworks - React, Angular and Vue - it allows querying DOM nodes with a user friendly API like searching by title, label, text, role and test id. Using test id properties in components is a pattern to make your test less fragile to changes, since classes, their names or other attributes may change during the lifetime of an application, whereas a test id can stay constant. Finally you can write assertions like toBeInTheDocument which is in line with the philosophy of Testing Library:
The main utilities it provides involve querying the DOM for nodes in a way that's similar to how the user finds elements on the page. In this way, the library helps to ensure your tests give you confidence that your application will work when a real user uses it.
You’re only interested in what is displayed, or rather what the user can see. You want to be able to refactor components and don’t break any tests at the same time, when changing just their implementation and not the functionality. This approach makes your test suite more maintainable.
Another kind of tests are visual regression / validation tests. You can verify the whole page as well as its parts, the layout but also particular elements like buttons, text fields and images.
Validating appearance means that the font, color, brightness, contrast, density, texture, visual weight, graphics, etc. of the visual elements must look proper.
Keep in mind though, that at the very beginning of development, depending on your strategy, a web application’s UI/UX may not be set in stone and frequently changes may turn you away from this testing technique.
One of the leading tools in this category of testing is BackstopJS. It supports parallel test runs, can simulate user interactions, allows to test against not only a reference collection of images, but also a whole environment, like staging, UAT or production, integrates with CI pipelines and Slack, just to name a few of its features.
Yet another build tool, yet another css tool
Starting frontend development can be overwhelming due to the sheer amount of build tools, dependencies and libraries being updated faster than you can type. Starter apps like CRA (Create React App) try to hide away this over-complexity and there seems to be a new rising star - Snowpack - completely removing the need for a bundler, at least at the beginning of web development promising a faster startup of development environments, instantly reflected changes in the browser and supporting TypeScript, Babel, JSX, Sass and CSS modules. It works with React and Vue among others and integrates with the webpack bundler to produce production-optimized builds. The Snowpack App strategy is about starting new projects using modern ESM syntax and Snowpack to install npm dependencies that run natively in the browser omitting completely the need for a bundler.
Adding to the over-complexity, Tailwind CSS is another CSS framework that is less extensive though. No pre-designed components hence no overriding of unwanted styles and no more debugging of specificity rules. It supports responsive designs and allows to extract repeated patterns and finally is designed to be customized, as it is advertised as:
… more than a CSS framework, it's an engine for creating design systems.
It’s worth keeping in mind what audience the authors target: developers making sites that stand out with custom design instead of being based on the same ol’ components found in the web - I’m looking at you, Bootstrap!
Something for all of you!
Not necessarily limited specifically to backend or frontend development, GitPod allows setting up your dev environment in the cloud. All required 3rd party services, like databases, queues, etc. can be included to the environment through docker. Moreover multiple team members can work on the code simultaneously seeing each other’s changes in real-time - by sharing one and the same workspace. It integrates well with GitHub, GitLab and Bitbucket.
You no longer need an over-powered laptop to work, Gitpod works just as smoothly on a Chromebook. You can even code on the go with a tablet.
The IDE is based on VS Code, features code intelligence, like syntax highlighting, smart completions, linting, code navigation, debugging and refactoring just to name a few, it allows to install any VS Code extensions and when self-hosted it has a free plan for up to 5 users.
Stay tuned for the final part is about Machine Learning techniques, projects and tools!
Check out all the tools you just read about