in Design on Design principles, Eventsourcing-series-2020
The previous post might have left you wondering - we have decided to reject the widespread and battle-tested architectures based on locking, caches, and transactions to something that needs clustering, automatic recovery and failure detection. This is true - the architecture we have picked has to have these features for the application to work. However, we haven’t had to build them ourselves - our decision making was based on an existing third-party library that can handle all these things for us - Akka. Let’s take a look at how we used it to achieve the project goals.
in Design on Design principles, Eventsourcing-series-2020
The previous post left us at the beginning of the design phase - I and my team have gathered the functional and non-functional requirements for the system, and we were ready to start designing a solution for the problem. In this phase of our journey, we needed to come up with an architecture that would allow us to achieve the required consistency, availability, and throughput goals, and also be easy to evolve, maintain and explain. To do so, we spend some time brainstorming, evaluating, and experimenting with multiple architectures. In this post, I’ll touch base on some “head-first” architectures, why have we rejected them, as well as our final approach and the reasons for us to pick it.
in Design on Design principles, Eventsourcing-series-2020
Eventsourcing is probably among the most controversial and tricky design principles. In “classical” application design, the state is written to the persistence store, mutated, and fetched from the DB on virtually every operation, while events causing state changes are transient and discarded the moment the change is applied. In eventsourcing, to the contrary, events are written to the store, never mutated, and read from the DB on rare occasions; while the state is transient and obtained from the log of events. To some extent, eventsourcing is like a mirror reflection of the “classical” approach. One day I and my team embarked on a journey through it - and this post is the beginning of the story.
Code reviews are an integral part of modern software development workflow and a highly debated one. A lot is said on why code reviews are important (e.g. Atlassian, Fullstory), how to do them (Google), what to look for (JetBrains), etc., etc. There’s no shortage of “internet wisdom” on the topic, but there’s one quite common flaw that might influence “your mileage” from code reviews quite significantly and cause them to harm your team’s productivity. In short, different aspects of the code (design, performance, security, style, naming, etc.) have a very different cost of making a mistake vs. cost of finding it during code review. Let’s take a look at how this affects the review process (“what to look for”) and a few techniques that can help improve it.
It wouldn’t be a major overstatement to say that majority of the applications - at least in the startup and enterprise world - and are built to model and automate certain real-life business processes. As such, the application inevitably has to have a model - an idealized representation of the “domain” - the entities, events, and interactions found in the real-life process. The application also has to do something useful with that model, so it has to interact with the real world (through UIs, printers, actuators, etc.) and other applications (such as other services, databases, queues, etc.). A common shortcut (and/or a caveat) is to use the same model to fulfill all these needs - however, this isn’t always the best course of action. Let’s take a look at other options.