C# Extend with Extension Method

Many C# developers know the existence of Extension Methods. It gives developers the ability to extend functionalities of the existing API without modifying the original source code.

A simple example is to check if a string is a numeric value. There are more than one solution to solve that problem. And one of them is that we want to write code like this:


string houseNumber = "123";
bool isNumber = houseNumber.IsNumeric();

The IsNumeric is not a built-in method on the string type. With the extension method, we could implement the IsNumeric easily.

public static bool IsNumeric(this string input)
{
    return Regex.IsMatch(input, "^[0-9]+$");
}

That is the basic concept. LINQ is the main consumer of the benefit. Or we might say that LINQ was the reason why the extension method concept was born. Of course, we do not have to know it to use LINQ.

So what is this post about? We could take advantages of the extension method to improve our design and implementation even when the code is under development, which means we are free to change our code.

Take a look at this simple interface

public interface IDocumentRepository
{
    /// <summary>
    /// Get a document of given type <T> by id. Return null if not found
    /// </summary>
    T GetDocument<T>(Guid id);
}

A simple, generic repository. The detail implementation does not matter here.

Later in the development, there are many places having this kind of logic (code)

var document = _repository.GetDocument<Product>(id);

if(document == null)
    throw new ObjectNotFoundException();

// Do something with the document here

Just some checking. It is not a big deal, except the fact that we need to do it in many places. So we want the ability to write this code

var document = _repository.GetOrThrow<Product>(id);

So what are options?

Modify the interface and implementation

One could go with this approach

public interface IDocumentRepository
{
    /// <summary>
    /// Get a document of given type <T> by id. Return null if not found
    /// </summary>
    T GetDocument<T>(Guid id);

    T GetOrThrow<T>(Guid id);
}

And implement the method in all derived classes. The approach works but I do not like it much for a couple of reasons

  1. That logic does not fit there naturally. It is a logic added on the existing functionality
  2. All the implemented classes are modified. In the best case, there is only one implemented class
  3. And what about later we need other kind of that functionalities? Will we keep expanding the interface?
  4. Usually the interface is at the infrastructure, but the extended functions are in the service or small bounded contexts. Some functions do not make any sense in other boundaries

Extend by extension methods

We could keep the interface clean as it was designed and extend the function by using extension methods as shown

public static class DocumentRepositoryExtensions
{
    public static T GetOrThrow<T>(this IDocumentRepository repository, Guid id)
    {
        var document = repository.GetDocument<Product>(id);

        if(document == null)
            throw new ObjectNotFoundException();

        return document;
    }
}

And we are free to place this code in the place that uses it. If it is required in many layers, assemblies, consider to put it in a separate assembly.

However, be reasonable otherwise you end up with extension methods everywhere. It is about placing the responsibilities in the right place.

I have been using this approach in my recent projects. And I am glad I have done it!

Retrospective – Lily Grade 2 Speaking Contest Preparation 2020

With the spreading of virus nCoV-2019 (Covid-19), schools are closed for weeks. My daughter teachers sent homework, recommendations to us so we can support kids during the slow time. Out of many subjects, there was an instruction to prepare for the school speaking contest. My daughter is grade 2, and this year topic is Go Green—Save the Planet.

Note: English is foreign language. We are Vietnamese.

My daughter delivered a speech to me. Wow, fantastic Lily! I really meant it—every single word. A few days later, the teacher gave her example speech in written form and a video. Oops! "it is not that simple", I uttered.

I knew there is a lot of work that my daughter and I have to go through. But, wait, I have not seen anything like this in my school years including the high school. Maybe there was, but not in my memory. I went through a quick reflection. That I had problems with explaining in writing. That a major of my colleagues had the same problem. We are developers, we write code. But we have problems with writing the design, explaining the root cause and solution in … writing. I wondered what if they were given this challenge. I did not bet on that.

For a speech, a thesis, there are usually 3 parts: Introduction, Main Ideas, and Conclusion. And that is the easiest part. My daughter knew that from Youtube. However, what includes in each part? Explaining that to a grade 2 kid is not easy.

Rewrite the whole speech

So the first thing I did was to convince my daughter to rewrite her teacher’s speech. She read the speech, watched the video. She understood and liked it. However, I was sure that she did not have a visualization of the scope—of how big the speech is, what are in the speech.

"Why do I have to write it?", she asked many times. Good question, kid! Why? Because "we are going to analyze the speech and that will help you do your own speech", I answered. She understood the reward. Let’s grasp a pencil and paper.

After 1 hour, with the motivation that we will play after completed the writing, she finished the task. WOW! "That’s a lot", she said.

I asked her to read it out loud. My mind was blown away with her result. I smiled with a happy thought that she is in a good school with great teachers.

Why do I ask her to write down?

  1. Writing will help you remember longer, easy to visualize things, scope. With the developing of technologies, people can access information easily, and most of them stop at the reading stage—not a good habit IMO
  2. Develop a habit of thinking on paper
  3. Learn vocabularies

Analyze the structure

By analyzing her teacher’s speech structure, I had a better chance to convince her what are included in a speech. And the importance is that we have to do it together. Get her involved in the process.

The introduction paragraph is easy. She knows and does it well. The topic and introduction are general information.

They include

  1. Theme (Go green, save planet): The importance of bees
  2. Topic: Specific areas that bees contribute—food, plant

Lily chose Birds. So she had to do some research how the birds contribute to the environment. She did her first research with Google. People found what they looked for. So did she.

The main paragraphs is challenging. Here they are

  1. 1 paragraph about role and contribution of the bees with numbers—facts, statistics
  2. 1 paragraph about they are in danger and why with numbers—facts, statistics
  3. 1 paragraph about calling for actions, what actions we should do

Of course, we do not focus too much on the scientific facts.

We went through each paragraph and read it out loud. We prepared another paper. I asked Lily what the paragraph was about. She explained and I helped her rephrasing them. After 1 hour or less, we had our second paper filled with the structure of her teacher’s speech.

We practiced saying the structure without looking at the paper, if could not remember, read them again. I wanted her to visualize the structure. So she will have a mental map of the speech.

So far so good! Lunch time.

Let’s write the speech

Nothing happens if we do not take action. Lily wrote her first draft of the speech base on the structure and facts we found on the internet–fact is crucial, not so detail, but they have to be there.

She could not make it in one go. But she did it beyond my expectation. I was impressed with how far she’s done. She completed the final paragraphs the next day.

It turned out this step was easier than I thought. She was comfortable with writing once she knew what to write.

Review and feedback

I asked her to write them again in a Word document (stored in OneDrive) so that I could send it to her English and Science teacher (thank you for your support); another good chance for her to remember the speech and ICT skill (computer skill in her academic program).

I didn’t do any correction. I sent whatever she wrote, original version. Her teacher was so nice that she gave a correction version with corrections highlighted. She did not change the content, she corrected the words, sentences, and asked questions for sentences that were not clear. I was so graceful to have my daughter in her class.

Lily and I went through the feedback.

"Are all the corrections correct?", I asked.
"Yes", confirmed after she compared changes with her version.

There was one sentence that was not clear in term of the intention.

"Should we remove it?", I asked.
"Yes. It is not important.", she replied.

Practice speaking and recording

After going through class lessons, we did not have much time to practice the speaking. We have practiced and recorded many times and finally submitted the recording.

Result

She got to the final ground in the campus. She was one of the 2 best, and her friend was chosen to compete in the school round. She was happy with the result. We made a promise to participant every year regardless of the result. The benefit that she have gained from the preparation is far more the prize.

Summary

I was amazing what a grade 2 kid can do. Many people think that it is too hard, too soon for them to work at that level. However, from that experience, I can say that it is not true. Everything is a matter of technique, preparation, a sense of humor. Learning, competition are fun if you prepare your kid mental in that direction.

Learn to encourage the kids, participate with them, support them but do not do it for them.

I wrote this post a diary without modifications to keep it honest and real. It was a journey and we handled the pandemic in the best way we could.

I am looking forwards to writing the same post next year.

Event Sourcing – Generate Consecutive Ordering

Interesting things happen when system is under load with many concurrent requests. I got one when working on a big project. We got the problem during the development where the system was under many concurrent requests and there were many requests to insert data.

Our system employed Event Sourcing (ES) architecture. It has been chosen before I joined the project. It had been working great until that moment.

We got many exceptions in the system. And soon we tracked down the root cause of those exceptions was that some events were not projected thus resulting inconsistent data in the query model (the read side). But how could that happen? What was the root cause of that root cause?

Our approach depends on the order of events persisted in the Event Store which is a SQL implementation. And some of the events were not in the right order that they were supposed to be.

Let say there are 2 requests R1 and R2

  1. R1 generates 3 events in order: A1, A2, A3
  2. R2 generates 3 events in order: B1, B2, B3

Events in a request are sent to an Event Store in a transaction. And we expect them to have consecutive orders. With the 2 above requests, we expected the orders is

A1, A2, A3, B1, B2, B3

Or

B1, B2, B3, A1, A2, A3

And it has been working like that for years.

We designed the Events table with Order column is the primary key with Identity(1,1) so SQL handles the ordering for us.

One day!

When the system is under load with many concurrent requests

The event ordering is not consecutive.

What does it mean? Instead of having the orders as described earlier, we got this in the database:

A1, A2, B1, A3, B2, B3

Notice the order of B1 and A3

Because the way our projection was designed and implemented, when the ordering was wrong, not consecutive, some events were not projected.

But how could that happen? According to SQL documentation, there is no guarantee that the values generated by Identity column are consecutive in a transaction. If you want to ensure consecutiveness, you have to set proper isolation level and locking. Unfortunately, we could not do that. It will hurt the write performance. We want to write events as fast as possible.

Consecutive values within a transaction – A transaction inserting multiple rows is not guaranteed to get consecutive values for the rows because other concurrent inserts might occur on the table. If values must be consecutive then the transaction should use an exclusive lock on the table or use the SERIALIZABLE isolation level.

So what could we do? There is always a solution.

If you need orders, you have to be in charged

The first thing is that we have to manage orders manually instead of delegating to SQL Identity feature.

We know the number of events in a request/transaction. So if we know the current order number, we can preserve a range of values from Current + 1 to Current + Number Of Events. And then set the current order to the max in the range. If we can ensure that preserving a range and update the current order is performed in an atomic manner, other requests will get correct orders. It is impossible to have 2 requests with the same range. And even if there is, the SQL will throw an unique key constraint exception.

We need a EventOrdering table to store the current ordering.

Take the power of SQL to preserve a range. SQL allows getting values from an update statement. This query does all the power. It allows setting new value in an atomic operation and gets back the old and new values

const string sql = "UPDATE EventOrdering " +
                    "SET CurrentOrdering = CurrentOrdering + @numberOfEvents " +
                    "OUTPUT Deleted.CurrentOrdering + 1 as Lowest,Inserted.CurrentOrdering as Highest " +
                    "WHERE EventOrderingId=@eventOrderingId";

To access the old value, use the Deleted temp table. To access the new value, use the Inserted temp table

/// <summary>
/// Get the current (latest) ordering and reserve a range of ordering from [Current + 1] to [Current + <see cref="numberOfEvents"/>]
///
/// Example: Current:        11
///          numberOfEvents: 5
///          reserved range: 12, 13, 14, 15, 16
///          Updated Current:16
///
/// The returned value: [12 - 16] where
///     12: Lowest
///     16: Highest
/// </summary>
/// <param name="numberOfEvents"></param>
/// <returns></returns>
private OrderingRange GetOrderingRange(int numberOfEvents)
{
    const string sql = "UPDATE EventOrdering " +
                    "SET CurrentOrdering = CurrentOrdering + @numberOfEvents " +
                    "OUTPUT Deleted.CurrentOrdering + 1 as Lowest,Inserted.CurrentOrdering as Highest " +
                    "WHERE EventOrderingId=@eventOrderingId";

    using (var conn = new SqlConnection(_connectionString).AsOpen())
    {
        var param = new
        {
            numberOfEvents = numberOfEvents,
            eventOrderingId = EventOrderingId
        };
        var ordering = conn.QueryFirstOrDefault<OrderingRange>(sql, param, commandTimeout: CommandTimeout);
        if (ordering == null)
        {
            throw new InvalidOperationException("Cannot read the global ordering record from the table EventOrdering. " +
                                                "Ensure that the table is in the database with one row");
        }

        return ordering;
    }
}

/// <summary>
/// We might just need the Lowest value and increase by 1 for each event.
/// However, having both values sounds right with the range, and might support the debugging/logging
/// </summary>
public class OrderingRange
{
    public long Lowest { get; set; }
    public long Highest { get; set; }
}

Once we got the range, we simply assigned them to the events to be saved.

The problem solved! And I have learned new things about SQL.

Plan your day tips

The term Plan your day might trigger the thinking that Oh! I (or that guy) must be very busy. I do not have to be busy to learn how to plan my day. It is just another fun thing in life that I can try. It is cool if things are planned and organized before getting started.

When starting a day, everyone has different expectations depending on their job, their position, the nature of business they are in. Regardless, one must have something done in the day.

Being a developer and team leader of a team of 10, here are typical things that are expecting me when I start a day

  1. Unread messages in MS Teams channels
  2. Emails from pull requests (PR) that need to review
  3. Emails from comments, discussions on the PR that I reviewed
  4. Emails from product backlog items (PBI), bugs that team members asked
  5. My own PBIs, Bugs that I have to work on today

Very short and simple list. But sometimes, I had problems.

  1. Jumped between PRs
  2. Forgot to answer some questions/discussions

Most of the time, they are not big deals. But it is cool to be better at it. Here are what I have come up with.

Plan your day

Everyday, before starting a working day, I spend around 25 minutes or less (a Pomodoro) to plan for the day. It is a habit that I want to develop and be disciplined about. Instead of chasing around my day, I step back and plan.

It is quite easy and simple to improve the siuation with existing free tools—Browsers and Microsoft To Do app.

Browser tabs

I usually have a couple of browsers opened. There are some tabs in each. The content is vary. Some are just news, some are technical bogs, some are social media.

Why did I not have one for planning purpose? Let’s try that. And it works for some weeks for me.

  1. Open a new blank browser (I use Chrome)
  2. Go through my emails. Skim through one by one and open the links in the email in that empty browser. It is important that I do not proceed them immediately. Just read through quickly and open the links
  3. Sometimes I prioritize them by reordering the tabs

During the day, I close one by one. And for any new things come up while working, the same approach is used.

Microsoft To Do app

I use it to jot down my tasks as quick as possible. It has a cool feature called My Day that allows me to jot down things I have to do in that day.

  1. Answer John questions on MS Teams channel
  2. Ask Anna how things is going with the PBI 1234
  3. ….

If my To-Do list is empty, I have a quite, good day.

Summary

It is simple but it works. All the tools are there and free

  1. A browser: Chrome, Edge, Firefox, …
  2. A to do app: Microsoft To Do is free and good if you have Microsoft account
  3. A little bit of discipline

Being a Scrum Player

Teams approach the Scrum with the eyes looking at the benefits of SCRUM without paying enough attention to what it costs to get them. We will get all those benefits if we have the right people. And that each member knows what to do in a SCRUM team. Unfortunately, that is the key part. If we have a team knowing what to do, any method will work. The reality is that a very few people know what they have to do. Human being is different. In a team, everyone has different abilities and skills.

The SCRUM guides encourages the team effort. It does not say anything about how the development team should be organized and run. That is the implementation detail part and very dependent to organizations, cultures.

The work is delivered by the Scrum Team. And a unit of work is done by a person. The actual work is carried by a person. So eventually, it comes to how to build a strong team and get the work done. At this level, it is not bounded to SCRUM anymore. It is a universal thing—team. And it is not something new. It started long time ago when human started hunting for food.

Context matters (since we are not teaming up for hunting anymore). We need to build a team that plays well in Scrum.

Welcome to Scrum Player. What does it take to play well in a Scrum team?

The below applies for a Software Development team.

Communication

Communication skill is vital for every job. Communicate well, you will get what you want. The opposite will confuse you and the others. How can it help if no one understands what you are trying to say.

Who do you communicate with?

  1. Teammates: happen daily via chatting, discussions, meetings, arguments, …
  2. Clients: Anyone outside the development team—PO, SM, employees in the same company when you ask for help

How?
If there is a formula, then no one will surfer from the misunderstanding, miscommunication. I have not found that formula yet. However, there are some guidelines from others, from book.

Read this for a complete guidelines from Basecamp. I pick here and there and make up a list

  1. Write a complete dialog before pressing the Send button. Do not force other to read 3 or 4 messages to understand what you are trying to say. Look at the rules 3,4, and 6
  2. Do you homework first before asking for help. When raising a problem, make sure to include your analysis and proposed solutions (if there is). It is not good that you raise a problem without spending time and effort on investigating first
  3. When a problem is raised, if you are looking into it, let others know
  4. It is ok to say "I do not know", "I am busy atm so I cannot help"
  5. Do not expect responses immediately. And do not let others wait too long. In daily work, 30 minutes is a good period to wait. So if you ask a questions, it is fine that there is no response within 30 minutes. And if someone mentioned your name, it was not ok if you have not responded within 30 minutes
  6. For urgent issues, do not use chat. Find other channels: Direct talk, SMS, phone call, … whatever it works

Be accountable

Every member should care for the outcome of the team. But that does not mean that all members should care all issues in the team. Everyone is encouraged to join solving problems. But there will be only one person in charge of the problem.

What does it mean by in charge?

  • Means be able to answer the question: What is the status?
  • Means find a way to solve the problem either by him/herself or by asking others internal or external. He/she can ask for the team effort if that is the way to solve it
  • Means report the final status and say thanks to the team effort

Why is it important?

  • It shows that each member cares about the team outcome; that they raise their hands to solve problems so other can focus on other tasks. That is the teamwork in action
  • Well-organized, well-managed. We know what problems we are dealing with and that they are in good hands
  • Personal growth. It is a chance to improve problem solving skill.

Specialized

Let’s face this: Everyone has different ability and skill so the price. No matter what kind of team you are in, a level 10 developer cannot just do the work that can be done by level 5. And a level 5 developer is not supposed to do the work that requires level 10. It is just delusion. It will not work.

For a software development team to work, these roles are required

  1. Architect: Without architect, the software is just a piece of code added over the time. And soon enough, it will fall apart. It will be hard, even impossible, to add features. This role is hard to find
  2. Abstract thinker: I want to use the term designer but afraid that it will confuse with the existing designer role. This role has the ability to think of component, of design pattern, of trade off between choices
  3. Specialized implementer: Good at low level implementation. He/she has specialized skill in certain languages, framework. For example, a FE developer that specializes in Angular
  4. Labor: Developers with limited experience. For every project, there are easy, repetitive but time-consuming tasks.

Do you think that it is good idea to assign an architect a labor task? No, of course not.

A developer can play many roles at the same time. It is a matter of knowing the strengths and weaknesses and assign the right tasks to the right person.

I like this saying from a wise man

Don’t send your ducks to an eagle school.

It won’t work!

 

So let put it to work. Let’s play well – Scrum Player.