Software Architecture

Summarized using AI

From Rails Legacy to DDD

Andrzej Krzywda • March 11, 2016 • Wrocław, Poland

In the talk titled "From Rails Legacy to DDD" presented by Andrzej Krzywda at the wroc_love.rb 2016 conference, the speaker shares insights on transitioning from traditional Rails systems to implementing Domain-Driven Design (DDD). He begins with a personal anecdote from 1993, drawing parallels between early software implementations in his family's business and modern-day challenges in software development. Krzywda reflects on how early experiences shaped his view on programming and led him to understand the critical importance of software architecture.

The presentation highlights several key points about DDD and its application, including:

- Introduction to DDD: Discusses the complexity of DDD terminology and the learning curve involved, noting that it took his organization nearly two years to embrace it fully.
- Value of DDD: Emphasizes that DDD provides structure to codebases and fosters a better understanding of client needs among programmers, ultimately leading to improved software development processes.
- Implementation Techniques: Suggests starting with events to simplify the introduction of DDD principles. Events are defined as significant actions in the system, and by focusing on them, developers can clarify aggregates and contexts essential for DDD.
- Events and their Importance: Stresses the significance of event sourcing and Command Query Responsibility Segregation (CQRS). He encourages publishing events to create an audit log, which is crucial for tracking changes in applications.
- Practical Tips: Advises against prematurely transitioning to microservices, recommending a well-structured monolithic application where the domain logic is separated from HTTP concerns through service objects.
- Community Engagement: Calls for developers to become domain experts and engage customers meaningfully rather than merely processing orders.

Additionally, Andrzej mentions cases of mistakes and learning moments, such as an early incident with a software bug that instilled a sense of caution regarding programming reliability. He believes that fostering discussions around domain needs leads to better software solutions.

Krzywda concludes with the belief that adopting practices from DDD enhances codebases and encourages better relationships with clients, ultimately contributing to more effective software development. The talk concludes with a Q&A session, where he addresses concerns regarding data inclusion in events and adapting DDD to complex systems.

From Rails Legacy to DDD
Andrzej Krzywda • March 11, 2016 • Wrocław, Poland

wroclove.rb 2016

00:00:13.770 Hello everyone! I am so happy to see you all here. I am both an organizer and a speaker today.
00:00:19.380 As an organizer, I would like to ask you to do me a favor. Could you please all stand up? Thank you! I now have control of the room.
00:00:41.820 So, could everyone who is here for the first time please sit down? Thank you very much. It's great to see that most of you have returned; that's a good thing for us as organizers.
00:00:59.640 Now, could all of you sit down if this is your second time? Thank you! It's great to see so many returning faces.
00:01:13.860 Now, could all of you please sit down if this is your fourth time? We have a dedicated group of attendees who return every year, and I would like to thank you especially for sticking with us.
00:01:40.530 Thank you very much, you can sit down now.
00:01:51.160 My talk is not about choosing a new framework, because we have already chosen Rails. This talk is also not about JavaScript, even though our conference is increasingly becoming a JavaScript conference. However, JavaScript is a topic that will always come back, which is why we started with the JavaScript workshops today. Sooner or later, every programming conversation among developers ends up touching on JavaScript.
00:02:24.910 That's why we wanted to get that out of the way. I hope this will still be primarily a Ruby conference. I'd like to share a story, which is a bit personal.
00:02:53.190 Let’s travel back in time to the year 1993. I’m not sure how many of you were born by then, but I was 13 years old.
00:03:07.390 My parents ran a family business, which started as a grocery store and evolved into a grocery store supplier. It was a family business that grew bigger, eventually employing about 20 to 30 people. I was very young, and I was also helping out, but my contributions included just the basic tasks like cleaning the stores, assisting customers, and handling incoming deliveries.
00:03:24.610 In 1993, a new law was introduced in Poland: the VAT tax. What was previously a simple process became very complicated and bureaucratic. Calculating taxes turned into a complex endeavor. The year 1993 saw almost every company in Poland searching for software and hardware to help them with tax calculations. I think this was the beginning of the software boom in Poland.
00:03:55.690 In 1993, there were no computers at work, and the computers in homes were just starting to appear. As a teenager, I had my Atari and then a Commodore 64. Out of those 30 people in the company, I was the only one capable of typing on a keyboard and understanding what was going on with those machines, even if just a little.
00:04:26.000 My programming experience at that time consisted mostly of retyping snippets of code from a Polish magazine called Byte from its paper version into my Atari or Commodore 64. I had no understanding of what I was doing; I was just retyping. Nevertheless, due to my unique skills at that young age, I ended up assuming what I now realize was a CTO position at my parents' company.
00:05:04.150 At 13, I didn't realize how remarkable it was that I was the CTO; otherwise, it could have made for a great headline! Unfortunately, I didn’t have a CTO salary. I became responsible for finding the software for our company and for engaging with salespeople who approached us to choose the right software system.
00:05:43.560 At that time, I was quite short, wore a black t-shirt with skulls and blood all over it, and that was my attire while talking to the salespeople. They probably didn’t expect such a young person making decisions, and I believe it was a challenge for them.
00:06:07.680 In the end, we decided to choose a specific software company based on recommendations. The only programmer there was a talented individual, whom I'll refer to as Mr. Christophe. Other companies were already using his software, which made it a much easier choice for us.
00:06:40.430 Once we decided to proceed with Mr. Christophe's software, the introduction process took about two to three weeks, and everything started operating smoothly. To me, it seemed as though everything was just working. After all, machines are machines, and Mr. Christophe was a skilled programmer.
00:07:16.509 In that same year, we also needed to choose hardware, and I of course opted for machines that could run games like SimCity or Wolfenstein. I was more interested in that aspect as well. Once we introduced the software into our company, I remained the only person capable of using it.
00:07:55.030 I became the full-time user in our company, taking customer orders and handling everything required with the software. Mr. Christophe was very agile, as we would call him now, though I don't think that term existed back in 1993.
00:08:10.509 He would come to us with a big, old notebook, and he worked closely with me, applying changes. I think he was using Turbo Pascal at that time. Whenever he made a change, he would copy the software onto a floppy disk, and I would put that disk into my machine.
00:08:38.930 The upgrade process took about ten minutes, and everything worked without a hitch. We had several upgrades like this. However, one day, I was serving a customer who came in to buy some new products for her grocery store. We had a new kind of cookies in our offer, and she selected them.
00:09:01.540 I printed the invoice, completed the order, took her payment, and everything seemed fine. I passed the order to our employee who handled the distribution of products in the store and, out of habit, I launched SimCity, which took a minute or two to start up. Just as I began placing my new commercial building in the game, the customer returned, very angry.
00:09:52.800 I thought she was overreacting at first. She pointed at me, saying I wasn't the right person to work there, that I was making mistakes. Puzzled, I asked her what was wrong. Our employee explained that the customer wanted cookies, but instead, I had printed water— that's what came out on the receipt.
00:10:32.540 I looked again at the software, and it clearly showed cookies on the screen, yet the printed receipt said water. I called Mr. Christophe, and he arrived promptly to assess the situation. He handled it professionally.
00:11:14.050 He first focused on fixing the problem before investigating what went wrong. He gave me a new floppy disk, I applied the update, and everything worked perfectly again. He apologized to us, stating that he made a mistake in his code. He didn't delve too deeply into the details, but I realized later he might have reused records in the database.
00:11:50.070 Fortunately, we didn't lose any money in the transaction, but this incident shattered my trust in programmers. It was the moment I lost faith in all software. Mr. Christophe was a very intelligent person, and yet a bug occurred.
00:12:17.140 I don't think the term 'bug' was coined back then, but to me, a fundamental element of my life became unstable. My name is Andrzej Krzywda, and this was a story about how and why I became interested in software architecture.
00:12:48.350 Over the last 20 years, I have tried to understand how to help programmers avoid making mistakes, and I continue to face challenges in this area. Through time, I have researched various architectures and methodologies. In university, I became interested in aspect-oriented programming, which I at one time believed to be the 'silver bullet' to all problems.
00:13:39.560 Later, I learned about clean architecture from Uncle Bob, and hexagonal architecture. Many of you may have seen my blog detailing these adventures.
00:14:04.700 I was fascinated by the idea of DCI architecture—data, context, and interaction—but none of them seemed to resolve my issues. As time went on, I noticed the topic of Domain-Driven Design (DDD) frequently appearing in various blog posts.
00:14:50.000 As I looked into DDD, every post I encountered seemed laden with jargon. There were discussions about concepts like sagas, aggregates, value objects, and bounded contexts. I calculated that there were around 40 new terms to learn, making it quite overwhelming to start DDD.
00:15:43.870 It took us nearly two years as an organization to begin implementing DDD, and I often wondered if there was an easier path to take. Today, I want to share some techniques that hopefully will simplify your introduction to DDD.
00:16:09.810 I aim to show you that DDD is worth your interest and that you can apply it fairly quickly. What we’ve found in our projects is that DDD helps provide a structure for our codebase. However, it's a value that can be hard to measure. I believe that there is an increase in domain understanding among programmers once we implement DDD.
00:16:53.920 Programmers begin to grasp client needs and user requirements better. If this talk is about lessons learned, I believe our biggest mistake as a company was not applying DDD sooner.
00:17:34.120 We started implementing DDD about three years ago, and connecting various concepts has helped me realize that I do not consider myself a DDD expert. I am still learning.
00:18:04.380 At one point, Mira Craig joined our team. Mira came from the .NET world, where DDD is quite popular. Knowing that DDD principles apply across different programming languages makes it easier to communicate with developers from diverse backgrounds, whether they are using Java, PHP, or even JavaScript.
00:18:54.500 I have identified some ways to save time when navigating the world of DDD. Firstly, it’s beneficial to study example codebases. If you search for DDD on Twitter, there's a pinned tweet where I've shared DDD repositories written in multiple languages such as Scala, Java, Ruby, and PHP.
00:19:32.440 By exploring these codebases, you'll gain insight into the flow of a DDD project, which should make the principles clearer. Secondly, an important takeaway from this talk is about events; they are crucial to DDD and also to event sourcing.
00:20:29.520 When I mention DDD, I often mean DDD in conjunction with event sourcing and Command Query Responsibility Segregation (CQRS). Event sourcing relies on storing state derived from events, much like how we manage changes in our Git repositories.
00:21:19.220 CQRS, on the other hand, is the idea of splitting your system between reading and writing, but you don't need to adopt everything at once. My recommendation is to start by publishing events.
00:22:03.080 When I say publishing events, I mean identifying those points in your code where important actions occur. For instance, in a typical Rails application, you might have a situation where a post is saved in a controller.
00:22:40.540 We can frame this as a significant event in your system, which we'll call 'post published.' The act of publishing an event won’t change the system's state, just like you might log an event without altering anything.
00:23:05.840 It simply adds an additional entry to the database. By taking this step, you’re not only introducing DDD but also generating an audit log that could be useful later.
00:23:45.530 Sooner or later, for every application we work on, there will be a requirement for an audit log. If someone on your team or your client questions the DDD process, you can justify it as preparing for potential audit needs.
00:24:36.690 Once you identify those events, always name them in the past tense and prefix them with the action that was taken—for example, 'user registered,' 'user activated,' and so forth. This practice will help you recognize the boundaries of your aggregates.
00:25:25.000 Starting with events will illuminate potential candidates for aggregates. Aggregates are critical components in DDD, and if you rush into identifying them, you might struggle to select the right candidates.
00:25:54.630 By first focusing on events, patterns will emerge. For instance, in our application, we may identify that 'user' is an aggregate. Beneficially, we will also recognize distinctions among contexts, like authentication and project management, enabling a clearer understanding of how we can separate responsibilities in our system.
00:26:45.100 The primary goal of DDD is not simply to create layers in your application—though I had mistakenly thought so at one point. It's more about identifying the boundaries within your system that separate subsystems. Very commonly, when working with monolithic vs. microservice architectures, we often grapple with finding these boundaries.
00:27:39.780 In an e-commerce system, for example, frequent needs for separating context arise. The use of events will help uncover relations among aggregates and lead to better architectural organization for your application.
00:28:28.720 Publishing events could be simplified by creating a dedicated 'events' table within your database. You could create a record every time something interesting happens. Although we have developed tools for this, I suggest generating event actions manually would work just as effectively.
00:29:09.420 When implementing events, ensure your application controller has access to an event store object. You can define how these events are structured. Starting with publishing your first event should take no more than 10 minutes, and adding new events thereafter will be very straightforward.
00:30:09.020 While the idea of microservices is appealing, my advice is to avoid moving to microservices too early, especially if you are working with large Rails applications. It's crucial to retain focus on practicality.
00:30:43.840 While microservices offer significant benefits, deploying them too early can lead to complicated communication issues within subsystems. A well-planned monolithic application can be more manageable in navigating these complications yourself.
00:31:35.500 My fourth recommendation is to escape the framework. Many of you may be familiar with service objects, which avoid tight coupling with your HTTP layer. This separation is integral from a DDD perspective because HTTP is merely an implementation detail.
00:32:22.830 The Rails framework streamlines the HTTP side of things; feel free to embrace that but focus on devolving responsibility to service and repository objects when it comes to your domain logic. This isolation makes your codebase more manageable.
00:33:13.390 Ultimately, my final point to share is that DDD revolves around the domain itself. The aim is not necessarily about restructuring your codebase, but about fostering a community of developers who grow increasingly business-oriented.
00:33:56.650 When you develop bounded contexts, such as payments, identity management, and invoicing, consider the significance of becoming a domain expert in those areas. Engage with your customer in meaningful discussions about their needs in those critical components of the business.
00:34:39.860 Encourage discussions based on authentic knowledge rather than simply taking orders from customers. Often, customers only understand their area of expertise, and it is up to us to offer insights and recommendations based on our knowledge.
00:35:29.180 Ultimately, I'll emphasize that while these methods and recommendations will not resolve every issue, I believe applying these practices will enhance your codebase and improve relationships with your customers. Thank you for attending and listening! I wish you all a great conference.
00:36:34.000 I'm happy to answer any questions.
00:36:46.560 The question posed is about how to decide what data to include in a published event. Initially, I suggest gathering as much relevant data from the context as possible. For example, if a blog post is being published, include relevant details like the title, content, creation date, and author.
00:37:31.720 As you become more comfortable with events and learn how to utilize them more effectively in an event-sourced environment, you can refine what data is necessary.
00:38:22.880 The next query discusses whether it’s appropriate to publish multiple events at once. In my view, it can be beneficial because especially in Rails applications, updates often involve several components. If your updates are batched together, splitting them into various events makes sense.
00:39:12.500 Yes, I typically suggest having smaller, numerous events rather than one large event during updates.
00:39:58.560 Regarding the overhead caused by implementing DDD, it's valid to note the introductory phase may seem burdensome due to the added layers and complexity. Though you might initially grapple with managing added intricacies, these layers should eventually simplify the code.
00:40:45.610 Over time, once you get accustomed to these methodologies, you'll discover a natural reduction of code complexity as repetitive elements are condensed and streamlined.
00:41:43.110 The crucial message here is that repositories play a decisive role in separating domain objects from persistence objects. Your repositories should consistently return domain objects rather than allowing any Active Record interference.
00:42:30.550 The repositories should focus on handling aggregates' loading and saving processes. This clear separation renders it evident what the role of each component is in your design.
00:43:06.050 We’ll continue to see discussions about differentiating between read and write operations using specialized structure and patterns found in DDD. Thank you very much for participating, and I hope you found this conversation insightful!
Explore all talks recorded at wroclove.rb 2016
+23