Introduction At the end of 2013 I was invited by Tomas Roos to join the team of HappyPancake, largest free dating site in Sweden. It was initially written in ASP.NET with MS SQL Database server, soon to become a rather complex solution that was expensive to scale. Together with Pieter Joost, our small distributed team of 3 people started redesigning this site towards a simpler design that would be easier to evolve in the future.
Last night we had a really productive pairing session with Pieter, discussing the design of HPC2 and trying to decompose it into a bunch of components aligned with the use cases. Components are represented by golang packages composed of a bunch of small files each. Examples of such packages are: auth register profile notify poke etc This maps to C# projects in .NET world but with a lot less ceremony, which feels really good.
The answer to the problem of finding a proper way to decompose existing complicated system into smaller components is two-fold: Use known methodologies for finding potential boundaries; Iterate a lot to see if system system could be divided across these boundaries. Let's start with examples of methods for finding potential boundaries: Look at the domain model from the perspective of Domain-Driven Design, seeking out bounded contexts and aggregate boundaries there (although classical DDDish BCs and aggregates could often be split in smaller focused parts as well).
Last week we released a new version of business backend at Lokad. Previous version was based on message-driven design with heavy use of CQRS principle, event sourcing and queues. There is a case study on that at Microsoft CQRS Journey. As I've discovered soon after, this architecture was a big pain in the ass due to being too monolithic and dogmatic. There was a lot of unnecessary ceremony involved in the simplest actions.
Over the course of the last few days I've been studying Go language (or golang), as a part of my job at happypancake.com. These days helped me to realise that requirement to learn new things is one of the best job benefits in my mind. Here are a few things that I've discovered about go: Golang programs can be compiled to run on FreeBsd, Linux, Max OSX and Windows. Once compiled, you just distributed a single binary and run it.
10 years spent in .NET were fun, but it is time to try something radically different. As you probably already know, I'm moving to a new project at HappyPancake - large free online dating website (largest one in the North Europe, if I'm not mistaken). I'll be working with outstanding people there: Tomas Roos and Tom Janssens. I'm a completely newbie in this development stack (summarised by Tom): Migrating a large free dating website from the Microsoft stack to Erlang/Linux...
During the course of the last years, software development somehow took a wrong turn and got vastly overcomplicated. These days we just tend to over-design and overdo things. Consider projects that never get shipped because stakeholders keep on drawing UML diagrams for the requirements. Consider web sites that never surface the public web because of ever changing UI designs. Consider implementations so convoluted that development teams spend their entire lives playing "hot potato" with JIRA bugs that keep on showing their ugly heads up.
A bit earlier I posted a sample drawing with evolution options for a component in a big software application. This diagram is merely a convenience snapshot of performance optimisations and tech options available at any given point in time. Knowing about them in advance helps in planning future development. Each node on the tree of component evolution represents a design pattern that has its own advantages and costs. Costs almost always include increased complexity.
Recently I mentioned 6 steps of an evolutionary design in software development. These steps describe iterative process aiming at continuous improvement. Such an improvement process can happen at two distinct levels: High-level view of the entire system involving components and their interactions; implementation details of a component. While high-level system evolution is covered pretty well in methodologies like domain-driven modelling (strategic design), implementation level can be more project-specific and hard to explain in uniform fashion.
For the last few weeks I've been really busy with development at Lokad, without time to reflect about things publicly. This development was (and still is) focused around refactoring of Lokad backend infrastructure and a few standalone products that integrate with it. Previously, all systems were based on regulated Lokad.CQRS design: large system is broken down to one or a few bounded contexts; each bounded context is captured in the code using one of a few predefined blocks: Aggregates with event sourcing Application services (wired to receive messages from queues) View Projections all communication happens via messaging (command messages and event messages); events are stored in dedicated event store and then published around.