DDD & CQRS & Event Sourcing. Part 1: Creating a basic domain model

This is the very first post in a series about using DDD (Domain Driven Design), CQRS (Command Query Responsibility Segregation), and Event Sourcing. I’m going to create a small project, which will use the above-mentioned approaches for solving some real-life scenarios. Before we start, I want to underline, that this posts series among the code project will be created for presentational purposes only. That means, that the business challenges which will be handled here could be solved without any above described practices. At this point, I’m not sure how far and deep this will go, so I will start with very simple and naive examples. It is always better to go in direction of complication, rather than simplification.

I’ve not decided so far what problem this project will solve, but I’m sure that we will need registered users for it. So let’s start with a User Service.

First of all, we have to create a User Entity class with some basic properties

Entity – an object that is not defined by its attributes, but rather by a thread of continuity and its identity.

    public class User
    {
        public string FirstName { get; private set; }
        public string LastName { get; private set; }
        public string Email { get; private set; }
        public string Status { get; private set; }
        
        public User(Guid id, string firstName, string lastName, string email)
        {
            FirstName = firstName;
            Id = id;
            LastName = lastName;
            Email = email;
            Status = UserStatus.Awaiting;
        }

        public static class UserStatus
        {
            public const string Awaiting = "AWAITING";
            public const string Confirmed = "CONFIRMED";
        }
    }

As you could see above, all properties have a private setter. In such a way, we could guarantee, that entity will be created with all necessary information and will not be in a non-valid state (for example User without FirstName).

We could check if all necessary parameters are valid in the constructor.

   public class User
    {
        public string FirstName { get; private set; }
        public string LastName { get; private set; }
        public string Email { get; private set; }
        public string Status { get; set; }
        
        public User(Guid id, string firstName, string lastName, string email)
        {
            CheckNullOrEmpty(firstName, nameof(firstName));
            FirstName = firstName;

            CheckNullOrEmpty(lastName, nameof(lastName));
            LastName = lastName;

            CheckNullOrEmpty(id, nameof(id));
            Id = id;

            CheckNullOrEmpty(email, nameof(email));
            Email = email;

            Status = UserStatus.Awaiting;
        }

        private void CheckNullOrEmpty(string paramValue, string paramName)
        {
            if (string.IsNullOrWhiteSpace(paramValue))
                throw new ArgumentException($"{paramName} could not be null or empty");
        }

...

I believe that now you have a question “So if properties have private setters, how could change their value?”. Very reasonable one, the answer is that we are going to create methods, which will describe the business perspective of that operations. For example, we are going to create a method, which will change the first and last names. This method will check if it is not empty and also that it does not break the business requirement of max length 100 characters:

...

public void ChangeName(string firstName, string lastName)
{
    CheckNullOrEmpty(firstName, nameof(firstName));
    CheckMaxLength(100, firstName, nameof(firstName))
    FirstName = firstName;

    CheckNullOrEmpty(lastName, nameof(lastName));
    CheckMaxLength(100, lastName, nameof(lastName))
    LastName = lastName;
}

private void CheckMaxLength(int maxLength, string paramValue, string paramName)
{
    if (paramValue.Length > maxLength)
        throw new ArgumentException($"{paramName} could not be longer the {maxLength} characters");
}

...

After that, we could reuse this method in a constructor, to be sure, that our Entity has a valid state during the creation and change of the name properties:

...

public User(Guid id, string firstName, string lastName, string email)
{
    ChangeName(firstName, lastName);

    CheckNullOrEmpty(id, nameof(id));
    Id = id;

    CheckNullOrEmpty(email, nameof(email));
    Email = email;

    Status = UserStatus.Awaiting;
}

...

The ChangeEmail method also should be implemented (with some email regex etc), but I’m going to omit that for simplicity for now. The important thing is that the User Entity will not have a ChangeId method, because it would break the business requirement and the User just could not change its own identification number. So in a such way, we guarantee that Entity will always be in a valid state.

Below you could find a potential example of usage of such Entity:

...

public void ExampleOfUsage()
{
    var user = new User(Guid.NewGuid(), "John", "Doe", "john.doe@email.com");
    
    //We also could change user name or email if we want
    //But there is not way to change the Id of the user, 
    //because Id has private setter and entity doesn't have ChangeId method
    user.ChangeName("Barbra", "Streisand");
    user.ChangeEmail("barbra.streisand@email.com");

    // Also we could check the user status, which has been set to Awaiting,
    // as the Entity has been created in a valid s
    Console.WriteLine(user.Status)
}

...

So now we have a basic Domain Entity, which ensures a valid state and encapsulates business logic inside.

The last but not least, if you an interested to go deeper into the topic of DDD, which we touched on today (in a very very superficial way) I would like to recommend a few resources, which could be useful for a deeper understanding of key concepts like Value Objects, Bounded Context, Aggregates, etc. :

The latest code base version of the project could be found on Github Org Page.

In the next post, we will get familiar with the Events, and how we could use them in Entities.

Why learning foreign languages is important and why Duolingo didn’t work me

When last time did you learn something fundamentally? From the basics to the advances, day by day improving you skills..

That was the question I asked myself some time ago, and the answer was not very satisfying – a few years ago. Usually, as a software developer, I use Pareto principle which in the modern world of tight deadlines and continuous complications doesn’t have alternatives. People need fast results from the easy solutions: “Quick Start”, “How To”, “Live Hack”, etc. Most probably we will not remember any of that in a few months after the last usage. So we are not very good at developing our long-term memory which requires many more hours and effort to allow us to use acquired knowledge even a decade after.

After understanding the problem area, the next question popped in my mind – what could do to train my brain every day in a more effective way? For me – it was an easy one. I relocated to Poland almost 5 years ago and immediately started learning the Polish language. Poland is a modern European country with a very multicultural environment and in time I’ve started learning polish, a lot of expats asked the same question: “Why do you that? You could use English everywhere, it is just time waste“. Be honest my initial motivation and the benefits I gained in the future – were very different 😉

In the beginning, I just liked how the Polish language sounds, it is a beautiful language which is sometimes called “Slavic French” because of sounds like “Ä… [aw]” and “Ä™ [ew]“. It is very melodic and soft (you know all these jokes about how the German language sounds). So I felt a lot of motivation and “power” inside me, but after the first lesson, I also understood that it is not going to be an easy win with a C2 level in 3 months. Even though it’s a Slavic language, which has a lot of similarities with my native Ukrainian, Polish has some very unique differences (greetings by “rz, ż, ź”) which make a lot of difficulties for even now, after almost 5 years of living here.

As time went and I started to create some connection with people, and resolve everyday routine problems I understood two things:

  • If you want to find friends or close people – you have to speak with them by the language they feel the most comfortable with (by default it is their native language). During my stay in Poland, I’ve met a lot of awesome people which I could rely on and I could not imagine that we will be so close if I would not speak Polish, just because it’s more simple “to open yourself” in front of someone if you just speak as you feel, without struggling with finding an appropriate word and building a correct grammatical sentence. Furthermore, people are always very friendly when see that you do your best to know their language and culture, it very helps with creating an emotional bridge.
  • It doesn’t matter in how open and multicultural a country you are, someday you will meet a local person who does not speak in any language except the local one. I’ve faced that situation a dozen times, especially in nontouristic places like public hospitals or car registration office. There are 0 chances you will get the deal with those people because often they just refuse to speak with you.

So after my successful adventures with the Polish language, with passed C1 national exam, I thought that probably it’s a good time to start with something new. There is one language which is used by even 4 countries in Europe – German language, so I decided that it will be useful from both perspectives – the popularity of the language and learning itself. Previously, with the Polish language, I was spending at min 1 hour daily with a teacher or homework, this time I decided that I will go with a more “flexible and modern” approach – Duolingo. It is easy, does not require to much time, and always in your pocket, at least that how I hoped it will be.

So my own impressions after 300 days are:

  • 5 minutes per day is not enough time to learn new words. Sure you could spend more, but the amount of the information in app grows exponentially, so with every additional lesson, learner has to remember all words from previous one + few extras.
  • You don’t have a possibility to make a mistakes, in a free version (which I used), everyone has only 5 “hearts” to lose, each by one mistake. So at some point, I’ve started cheating by googling, just to pass the lesson.
  • Is it very easy to skip. I mean if you pay for the lessons in school or private teacher, then probably you want to gain something for your money, which is also some kind of motivation. Additional point is that you could not skip the real lesson with teacher at any day you want, just because you forget, or have a hangover or whatever else. After few such “changes in schedule”, any teacher will be mad as hell and refuse to work with you. But in application it is very simple, you just do skip the day and that’s it – no obligations, no penalties and the worst – no result.

The initial plan was to give me a try with year’s daily routine and see how it will go, but after ~200 days, I just started using the application because of the year’s target plan, but not because I wanted to learn something new. It took some time for me to realize that, so after reaching 304 days streak I’ve uninstalled the application from my phone.

As a conclusion for the post, I want to highlight that in fact, I’ve gained some basic knowledge in German (which I hope to use it someday in the future), but the level of expectations vs reality doesn’t match too much. And my personal lesson after these 304 days is – no pain, no gain. It is a very simple and obvious rule of life, but I forgot about that so many times.

Finally, I believe that applications like Duolingo, Drops, Babbel, etc. help people to learn new language horizons and my negative experience is unique. In fact, sometimes old samurai philosophy works the best – success is a journey, not a destination.

Book review – Outliers: The Story of Success

I picked the book Outliers: The Story of Success by Malcolm Gladwell for the listening seeing it pushed as a recommendation from Amazon several times. Most of us think about success stories that are about “a miracle” or a self-made person, but if we will dig deeper into the stories itself, it becomes clear that there are a lot of “hidden” obstacles that allowed “a miracle” has happened. Read or scroll to understand what helped famous people to be so successful and how everyone could use this knowledge to improve own daily life.

Part 1: Opportunity

When we thinking about success stories, the first thing most of us have in mind is – “How much effort he or she invest to make it real?!”, but the real question everyone should ask themselves are: “What circumstances did allow this to happen?”, “Who or what did help them?”, “Is there any chance, that this success could come to everyone?”.

It could be not so clear at the beginning, but let’s think of the success story as a beautiful apple tree. First of all, let’s agree on something – it is a garden apple tree, not wild in the forest. The wild apple trees are not the same as we expect to see as an “ideal apple” and most of them are small and bitter. That’s mean that someone is taking care of this apple on early-stage by regularly pouring and kill pests. During the grow, every detail matters – geography localization of the garden (probably it will be tough for the apple tree to grow in Nevada desert), the distance to the next tree, soil quality, etc. The tree will have a chance to grow only if all of these factors will be “good enough”. The same rules apply to the outliers, but unfortunately, it requires more investigation to the history, then just googling “how to grow an apple tree” 😉

The book describes a few examples of opportunities that allow success one, but not another. So here are few of them:

  • The eligibility cut-off for the age-class hockey in Canada starts at 1 of January. Which in theory (and in practice as well) means that children who born in the first quarter of the year have slightly more time to practice in comparison with their teammates who born in 3-4 year quarters. As a result, most of the top players in Canada’s top hockey teams born between January and May (Quant Hockey Ranking). So if you want your kid to become a Hockey star in Canada, try to think about it, even before you consider having a child.
  • The 10,000-Hour rule – the idea behind it is very simple – you could be an expert in any area if you worked and practiced enough. History shows that “enough” is about 10,000 hours or 10 years of daily practice. It could sound very obvious from the definition, but let’s think about Bill Gates’s history. Literally he spent a lot of time coding during computer classes in General Electric Company and Computer Center Corporation in the early ’70s. But let’s how many children had such an opportunity to spend so much time with a computer at that time? Probably your parents had to reach enough and you should grow in the country which allows you to use such kind of technology. So if analyze the opportunities and circumstances which were given to Bill Gates, it is hard to imagine it could happen in any other part of the world at that time.

So as you could see, sometimes it’s not about being but even about to be born in the right place and at the right time. Sure, it will not guarantee anything and it is still a matter of hard work, but at least it will give the opportunity to make it possible.

Part 2: Legacy

Like every story, it is hard to predict the future and handle the present without analyzing the past. Sometimes it is enough to check the last 10 minutes before something happened, but in some particular cases, it is necessary to analyze 100 years before.

One of the great examples from the book describes the aircraft crash of Flight 52 Avianca from Bogota to New York in 1990. Investigation of the catastrophe lasted for more than a year first conclusions were about the multiple errors of the crew, bad weather conditions, and a broken engine on each wing. It could sound as a sequence of very unfortunate circumstances, but in fact, the most important thing in this situation was a misunderstanding between the crew and the flight tower.

The author introduces a term of Power Distance Index (PDI) which describes as “the extent to which the less powerful members of organizations and institutions (like the family) accept and expect that power is distributed unequally”, which means how likely people question authority and attempt to distribute power. This term is extremely important for understanding Avianca’s tragedy.

If we compare the USA and Colombia (even with actual 2020’s data), we will find, that Colombia has 30% highest PDI and 7 times less individualism. During that flight, the second pilot communicated with the flight tower and followed the instruction of the captain without questioning and expressing his opinion about the situation to anyone and especially the flight tower. He just used the Hint or Preferences level of Mitigated Speach which wasn’t enough in such a critical situation, but the Colombian (as any other) culture dictates the rules you should follow in the daily world. Due to Hofstede Insights, in Colombia people less criticize supervisors and more rarely take an initiative, just because it’s Boss’s responsibility to solve the problems.
You could find a full record Cockpit Voice Recorder here.

Source: https://www.hofstede-insights.com/country-comparison/colombia,the-usa/

That particular situation shows us, that culture in which we grew up influences our behavior and our choices during the life path. The only thing we could do to flat the cultural curve between intercultural differences is to communicate by using the ubiquitous mechanism of expressing our thoughts with a common level of understanding.

Conclusion

I highly recommend this book for everyone who thinks that he is not good enough for getting a better job/create start-up/try something new in life. This book helps to understand that everything around us, could help to reach the target and we should use every chance to do it.