Versioning is always a compromise between improving developer experience and the additional burden of maintaining old versions. We strive to achieve the former while minimizing the cost of the latter, and have implemented a versioning system to help us with it. Let’s take a quick look at how it works.
Explicitly modeling changes between versions via a DSL.
PumpkinDB is essentially a database programming environment, largely inspired by core ideas behind MUMPS. Instead of M, it has a Forth-inspired stack-based language, PumpkinScript. Instead of hierarchical keys, it has a flat key namespace and doesn’t allow overriding values once they are set.
The core ideas behind PumpkinDB stem from the so called lazy event sourcing approach which is based on storing and indexing events while delaying domain binding for as long as possible. That said, the intention of this database is to be a building block for different kinds of event sourcing systems, ranging from the classic one (using it as an event store) all the way to the lazy one (using indices) and anywhere in between.
In my experience, when an architecture review brings attention to a problem and proposed solutions from multiple perspectives, decisions become less controversial. When a decision appears to be obvious to a broad group (“Question: should we (or should we not) take backups of critical databases? Decision: Yes.”) how a decision gets made almost disappears.
But there’s a deeper problem. I actually think ten lines of code is too big for an abstraction (Metz agrees). Ten lines of code that happen to be repeated are so unlikely to have any interesting properties, including being bug-free, reusable, and composable, that you should be very skeptical of being able to factor the whole thing out as common.
However, don’t despair! You can more often than not find lots of one-, two-, or three-line bits of code that are 1.) easy to name and 2.) reusable. If you break enough of those out, you may start to see some underlying structure to those repeated ten lines as they become replaced by your new, small abstractions.
The source code for the site lives in a Git repository which means I have a consistent source for update times that I can rely on. So, I’ve added a helper that asks Git for the last commit time of a file and falls back to its last modified time if the file isn’t currently tracked in Git.
Building applications following domain-driven design and using CQRS feels really natural with the Elixir – and Erlang – actor model. Aggregate roots fit well within Elixir processes, which are driven by immutable messages through their own message mailboxes, allowing them to run concurrently and in isolation.
I too think that Elixir is a good fit for CQRS/ES applications.
The post provides a thorough walkthrough that builds an event sourced/CQRS Elixir application using Phoenix, Commanded, and Eventstore. The Commanded and Eventstore libraries look to have implemented most of the features I’m looking for.
Clean and robust state management for React and React-like libs.
The library grew from the idea that state should be just as flexible as your React code; the state containers you build with freactal are just components, and you can compose them however you’d like. In this way, it attempts to address the often exponential relationship between application size and complexity in growing projects.
Like Flux and React in general, freactal builds on the principle of unidirectional flow of data. However, it does so in a way that feels idiomatic to ES2015+ and doesn’t get in your way.
The single state object, reducers, and selectors associated with Redux feels overwrought and often gets in the way. Freactal looks like an interesting alternative.
The single biggest bad thing that Young has seen during the last ten years is the common anti-pattern of building a whole system based on Event sourcing. That is a really big failure, effectively creating an event sourced monolith. CQRS and Event sourcing are not top-level architectures and normally they should be applied selectively just in few places.
Young also believes there will be more use of Process managers, especially with more and more use of Actors since they for him make perfect Process managers. He describes an Actor framework as a Process manager framework.
Cap’n Proto RPC employs TIME TRAVEL! The results of an RPC call are returned to the client instantly, before the server even receives the initial request!
There is, of course, a catch: The results can only be used as part of a new request sent to the same server. If you want to use the results for anything else, you must wait.
However, Cap’n Proto promises support an additional feature: pipelining. The promise actually has methods corresponding to whatever methods the final result would have, except that these methods may only be used for the purpose of calling back to the server. Moreover, a pipelined promise can be used in the parameters to another call without waiting.
An interesting feature which limits the number of network hops in the query is a pipeline of dependent requests.
From my point of view, the CQRS-induced complexity is largely accidental, and thus can be avoided. To illustrate my point, I want to discuss the goal of CQRS, and then analyze 3 common sources of accidental complexity in CQRS-based systems.
I find myself nodding to the sentiments of this post. It feels like doggedly pursing a theoretical ideal can lead to unnecessary difficulty in CQRS implementations.
In the recent years, I have adopted a method for system design, which I think yields good results. For a lack of better word, I overloaded “stack” yet again, and use it as a metaphor for this design.
The baseline is level 0 in the stack, and now we try to move the system upwards in the stack by adding another level. It is important to stress that transitioning is a best effort method. We make an attempt at increasing the operational level of the system, but if we can’t we stay put at the current level.