3 ms·
Building an MVP right now. My front-ends are primarily native mobile apps, because it's a video chat app. The website is simple React app. My backend is a cu
by thewatcher23 4y ago
Building an MVP right now. My front-ends are primarily native mobile apps, because it's a video chat app. The website is simple React app.
My backend is a custom/hybrid pattern I've been developing over the last few years which is primarily focused around CQRS + Event Sourcing + DDD.
I have a single backend "command interface" (really just a single http endpoint that receives the name of a command + a data payload.
think POST the_beam_is_god.com/commands
{
command: "request_login_link_via_email",
data: {
email: "snake_case_rulez@aol.com"
}
}
The command names are arbitrarily named based on the needs of my business. I make no concern for the internal code structure of my app with naming commands. This allows business people, frontend people and backend devs to all communicate in english and focussed on the business domain only.
It's up to my handler function for this specific command to do any business logic validation, etc. If all good, an event is written to a stream (or linked to multiple streams) and the command handler function is done. Its concern ends at the point of publishing an event into a stream (or responding back with a rejection). (note: the events go into postgres, but any store would work as long as you can index on the stream names)
The above command example might publish an event called "UserRequestedLoginEmailViaTheApp" into a stream called "LoginActivity:snake_case_rulez@aol.com". I do lots of small streams of related activity. (related in context of the business logic of my domain).
The other half of my system is a series of handler functions that do arbitrary business logic things when events are published. To continue with the example:
UserRequestedLoginEmailViaTheApp is mapped to one or more handlers. One obvious handler for this type could queue up the email delivery. I can do anything in these handlers in response to the fact that X activity HAS occurred. Another frequent thing I do in an event handler (I call them Reactors) is play back a domain model stream to get its current state (via a "projection") and update my (R)ead store. Think "UserUpdatedName" event in a stream called "User:id123". Command "update_user_name" -> Event gets published -> Reactor reacts and pushes a new version (current state) of this user into the [mongo] users collection -> then a subscriber process (elixir genserver) to the mongo oplog reacts and pushes the new version of this user down a websocket to provide live data updates to any apps/frontends.
Maybe this sounds complex and bloated at first read, but my codebase boilerplate is ridiculously small, a few dozen lines. What's cool too is that this can be done in any language/runtime environment.
I started doing this in ruby in 2019, but as I was getting up to speed on elixir I realized that the beam mapped perfectly to this strategy. CQRS itself is merely a higher level execution of the actor model (the beam) itself. Upon realizing this, I actually attempted to shoe-horn my pattern here into the GenStage architecture. I did get it to work, but I did not continue down that road.
I could talk about this for days because I love it so much.
bonus: no inheritance, no dependency injection, no interfaces, no wanting to quit and become a farmer because of the insanity of complex OOP
- yisus 4y agoHey, we've created an open-source framework that is really aligned with many of the points you’ve mentioned: CQRS + Event Sourcing + DDD. Its name is Booster, it is built in TypeScript, and offers a minimalist approach to building event-sourced services, with a focus on reducing code and abstracting the infrastructure setup for a better developer experience. The framework generates a fully functional GraphQL API that's easily customizable and already used in several production projects. It's our go-to choice for new projects that fit the event-driven paradigm. If you're interested, come join the conversation on our Discord channel at https://discord.gg/Rf6cwGRxgD https://discord.gg/Rf6cwGRxgD, visit our website https://www.boosterframework.com/ https://www.boosterframework.com/ or contribute to the project on GitHub at https://github.com/boostercloud/booster https://github.com/boostercloud/booster.