Nowadays we can often hear that monolithic architecture is obsolete and responsible for all evil in IT. We often hear that microservices architecture is a silver bullet which helps to kill all this monolithic evil. But you probably know that there are almost no silver bullets in IT and every decision entails trade-offs. One of the most favored advantages of microservices architecture is good modules separation. You can deploy every service independently and services are easier to scale.
Watermill is a Go library for working efficiently with message streams. It is intended as a library for building event-driven applications, enabling event sourcing, CQRS, RPC over messages, sagas. Why? Lack of standard messaging library There are many third party and standard library tools which help to implement standardized RPC or HTTP communication in Golang. There are also multiple third party HTTP routers and frameworks. But when you want to build a message-driven application, there are no libraries which are infrastructure-agnostic and not opinionated.
Let me start by thanking all contributors for feedback on Watermill - it drives us to add new features. Thanks! It’s been almost a month since the initial release of Watermill. However, it’s just the beginning and we are still working hard to ship new features. What is new in Watermill 0.2? Documentation - watermill.io Godoc is great. However, it’s functionality is sometimes too limited to express more complicated documentation.
54 days of work, 12,909 lines of code, 47 Monsters and 42 KFC Twisters later finally it is Watermill v0.3.0! To keep it short, let’s go through the changes. One important thing: at the end of this post there is a 3 question survey. Please take a moment to fill it out, it will help us make Watermill even better. CQRS component One of the most important parts of the v0.
If you compare MySQL or PostgreSQL with Kafka or RabbitMQ, at first, it seems they are entirely different software. And usually, that’s true, as you would use them for quite different tasks. What they have in common is processing streams of data, and they specialize in specific ways of doing it. While Kafka and RabbitMQ are popular examples of Pub/Subs (also known as message queues or stream processing platforms), I’d like to share some patterns for using SQL databases as Pub/Subs as well.
Welcome to the first article from the series covering how to build business-oriented applications in Go! In this series, we want to show you how to build applications that are easy to develop, maintain, and fun to work with in the long term. The idea of this series is to not focus too much on infrastructure and implementation details. But we need to have some base on which we can build later.
In the previous post, Robert introduced Wild Workouts, our example serverless application. Every week or two, we will release new articles related to this project, focusing on creating business-oriented applications in Go. In this post, I continue where Robert left off and describe the infrastructure setup. We picked Google Cloud Platform (GCP) as the provider of all infrastructure parts of the project. We use Cloud Run for running Go services, Firestore as the database, Cloud Build as CI/CD, and Firebase for web hosting and authentication.
Welcome in the third article form the series covering how to build business-oriented applications in Go! In this series, we want to show you how to build applications that are easy to develop, maintain, and fun to work in the long term. In this week’s article I will describe how you can build robust, internal communication between your services using gRPC. I will also cover some extra configuration required to set up authentication and TLS for the Cloud Run.
Welcome in the third and last article covering how to build “Too Modern Go application”. But don’t worry. It doesn’t mean that we are done with showing you how to build applications that are easy to develop, maintain, and fun to work with in the long term. It’s actually just the beginning of a bigger series! We intentionally built the current version of the application to make it hard to maintain and develop in the future.
In case you’re here for the first time, this post is the next in our Business Applications in Go series. Previously, we introduced Wild Workouts, our example application built in a modern way with some subtle anti-patterns. We added them on purpose to present common pitfalls and tips on how to avoid them. In this post, we begin refactoring of Wild Workouts. Previous articles will give you more context, but reading them isn’t necessary to understand this one.
When I started working in Go, the community was not looking positively on techniques like DDD (Domain-Driven Design) and Clean Architecture. I heard multiple times: “Don’t do Java in Golang!”, “I’ve seen that in Java, please don’t!". These times, I already had almost 10 years of experience in PHP and Python. I’ve seen too many bad things already there. I remember all these “Eight-thousanders” (methods with +8k lines of code 😉) and applications that nobody wanted to maintain.
I’ve seen a lot of complicated code in my life. Pretty often, the reason of that complexity was application logic coupled with database logic. Keeping logic of your application along with your database logic makes your application much more complex, hard to test, and maintain. There is already a proven and simple pattern that solves these issues. The pattern that allows you to separate your application logic from database logic. It allows you to make your code simpler and easier to add new functionalities.
Did you ever hear about a project where changes were tested on customers that you don’t like or countries that are not profitable? Or even worse – did you work on such project? It’s not enough to say that it’s just not fair and not professional. It’s also hard to develop anything new because you are afraid to make any change in your codebase. In 2019 HackerRank Developer Skills Report Professional growth & learning was marked as the most critical factor during looking for a new job.
The authors of Accelerate dedicate a whole chapter to software architecture and how it affects development performance. One thing that often comes up is designing applications to be “loosely coupled”. The goal is for your architecture to support the ability of teams to get their work done—from design through to deployment—without requiring high-bandwidth communication between teams. Accelerate If you haven’t read Accelerate yet, I highly recommend it.
It’s highly likely you know at least one service that: has one big, unmaintainable model that is hard to understand and change, or where work in parallel on new features is limited, or can’t be scaled optimally. But often, bad things come in threes. It’s not uncommon to see services with all these problems. What is an idea that comes to mind first for solving these issues? Let’s split it into more microservices!
In the previous articles, we introduced techniques like DDD Lite, CQRS, and Clean (Hexagonal) Architecture. Even if using them alone is beneficial, they work the best together. Like Power Rangers. Unfortunately, it is not easy to use them together in a real project. In this article, I will show you how to connect DDD Lite, CQRS, and Clean Architecture in the most pragmatic and efficient way. Why should I care? Working on a programming project is similar to planning and building a residential district.
Do you know the rare feeling when you develop a new application from scratch and can cover all lines with proper tests? I said “rare” because most of the time, you will work with software with a long history, multiple contributors, and not so obvious testing approach. Even if the code uses good patterns, the test suite doesn’t always follow. Some projects have no modern development environment set up, so there are only unit tests for things that are easy to test.
Thanks to the tests and code review, you can make your project bug-free. Right? Well… actually, probably not. That would be too easy. 😉 These techniques lower the chance of bugs, but they can’t eliminate them entirely. But does it mean we need to live with the risk of bugs until the end of our lives? Over one year ago, I found a pretty interesting PR in the harbor project. This was a fix for the issue that allowed to create admin user by a regular user.
This post is a direct follow-up to Microservices test architecture where I’ve introduced new kinds of tests to our example project. Wild Workouts uses Google Cloud Build as CI/CD platform. It’s configured in a continuous deployment manner, meaning the changes land on production as soon as the pipeline passes. If you consider our current setup, it’s both brave and naive. We have no tests running there that could save us from obvious mistakes (the not-so-obvious mistakes can rarely be caught by tests, anyway).
At one point in my career, I was no longer excited about the software I was building. My favorite part of the job were low-level details and complex algorithms. After switching to user-facing applications, they were mostly gone. It seemed programming was about moving data from one place to another using existing libraries and tools. What I’ve learned so far about software wasn’t that useful anymore. Let’s face it: most web applications don’t solve tough technical challenges.
Enums are a crucial part of web applications. Go doesn’t support them out of the box, but there are ways to emulate them. Many obvious solutions are far from ideal. Here are some ideas we use that make enums safer by design. iota Go lets you enumerate things with iota. const ( Guest = iota Member Moderator Admin ) Full source: github.com/ThreeDotsLabs/go-web-app-antipatterns/02-enums/01-iota/role/role.go While Go is explicit, iota seems relatively obscure.
Hello! Please give Krzysztof a warm welcome in the first guest post on our blog. 🎉 We’ve been working with Krzysztof for the past two years, and we’re excited to share his work here. Miłosz & Robert We all struggle with software architecture diagrams, don’t we? Have you ever wondered why? If you ask yourself that question, why maintenance of up-to-date and detailed software architecture diagrams is so painful, you will come up with a long list of valid answers.
Cohesion is part of the low coupling, high cohesion principle that’s supposed to keep your code maintainable. While low coupling means few dependencies, high cohesion roughly translates to single responsibility. Highly cohesive code (a module or a function) is focused on a single purpose. Low cohesion means it does many unrelated things. I’ve written about coupling in the previous article on anti-patterns. Here are some tips on increasing cohesion in Go applications using the recently released generics.