Code Duplication is a Myth

I know that code duplication is not good. We try to avoid code duplication. In a perfect world, you do not have code duplication. What annoys me is that we seem to forget to ask some critical questions to ourselves.

  1. Is it really that bad in all circumstances?
  2. What might be worst if we try to avoid code duplication?

Let’s take a typical web application where you have features to add and edit a user.

With 2 separated models

    public class CreateUserModel
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public DateTime? DateOfBirth { get; set; }
    }

    public class EditUserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public DateTime? DateOfBirth { get; set; }
    }

Or one single User Model?

    public class UserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public DateTime? DateOfBirth { get; set; }
    }

In single user model, if the Id is 0, assume that is creating a new user.

In the real world application, the model is complex. I make this example to demonstrate the point: There are many duplications in 2 models. The question is whether it is good or bad?

Well, it depends … on the context.

Why do we see it duplicated? Mostly because the code looks the same. I, however, want to look at another angle, from the purpose and context angle.

In term of business view, create and edit a user are 2 different features. They operate on the same data object (User). But they are not the same. Let’s assume that we have a web application. There are 2 screens, one for Create and one for Edit.

        public IActionResult CreateUser(CreateUserModel model)
        {
            return View();
        }

        public IActionResult EditUser(EditUserModel model)
        {
            return View();
        }

        // Reuse the same model for 2 different features: Create or Edit
        public IActionResult SaveUser(UserModel model)
        {
            return View();
        }

In the SaveUser action, if the User.Id is 0, use the Create logic, otherwise, use the Edit logic. So we can put aside the logic.

Initially, both Create and Edit screens look the same. They operate on the same piece of data. The single model sounds a right choice. However, I will choose the 2 models. I do not see them duplicated. I do not see benefits of unifying them.

Here are why

  1. Each is an independent feature.
  2. They have different input and output. Sooner or later you will end up some information on a feature not make sense on another.
  3. By separating them, we can have 2 teams (groups) work on 2 features without stepping on each other toes.

Ok then, when will it make sense?

I will consider a duplication when

  1. A piece of code that carries logic. Not just data or POCO.
  2. Independent of context. The refactor code (as a result of killing duplication) might depend on the input parameters. However, keep an eye on the number of parameters and make your instinct decisions base on your experiences.
  3. Easy to understand. There should be a very limit of condition/switching in the implementation.

From my experience, killing duplication is not an easy task. It requires a lot of skills

  1. Skill to ask the right question about the value of the code, the logic of the code, … One should ask themselves serious questions.
  2. Skill to read the code and get a brief of what it does.
  3. Skill to capture just enough to refactor out.
  4. Skill to refactor.

Did I tell you that Naming is one of the hardest tasks? Given that you have a piece of duplicated code, what would you name them?

I fell in love with the slice (with Feature approach) architecture when I first saw it. I saw its value when traditional architecture caused my headache when the code was out of control. Especially, when I have to develop a new feature. The biggest fear when adding new features is the chance of breaking existing features, aka causing regression bugs. With the feature approach, we can limit the risk.

Every approach has its pros and cons. We, developers, have to weigh them and pick the one that fits most.

There are some valuable links from experts.

Jimmy Bogard SOLID Architecture.

Steve Smith ASP.NET Core Feature Architecture.

Application structure: Concepts and Features.

Isolated Feature from Ayende.

Or checkout Jimmy repo here. A wonderful resource to learn how to build a web application with the Slice + MediatR + Feature.

Write a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.