C# Design – How to Design a Class for a Fixed-Length ID

Architectureccoding-styledesign

I'm building an app in C# that needs a fixed-length id, which is a string representation of a hex number. E.g. "0fa5" is an example of such an id of length 4. The length would not need to change within the program at runtime, but may be changed in the future or for example in tests.

My question is about how to approach designing such a class. I've come up with two methods so far:

The first would be making a single class, IdType that has a static method SetExpectedLength(int) that should only be called once, otherwise it gives an exception:

class IdType 
{
    public static int ExpectedLength {get; private set;} = 0;
    public string Id {get; private set;} = "";

    public IdType(string id)
    {
        if (IdType.ExpectedLength== 0)
            throw new Exception("SetExpectedLength needs to be called first");

        if (id.Length != IdType.ExpectedLength)
            throw new Exception("Length constraints not satisfied!");

        this.Id = id;
    }

    public static void SetExpectedLength(int length)
    {
        if (IdType.Length == 0)
            IdType.ExpectedLength = length;
        else throw new Exception("SetExpectedLength can only be called once");
    }

    // other operations here...
}

The other approach would be making a base abstract class and deriving IdTypes of different lengths from it:

abstract class IdType 
{
    public string Id {get; protected set;}
}

// IdType of length 4
class IdType4 : IdType
{
    public readonly int Length = 4;

    public IdType4(string id)
    {
        if (id.Length != this.Length)
            throw new Exception("Length constraints not satisfied!");

        this.Id = id;
    }
}

The second approach seems more clean, however if I need a new length for the ids I would have to make a new class AND replace the instance of the old class everywhere it is used.

What is the best practice in this case? Is there another design pattern that I can use?

Best Answer

The second approach seems more clean, however if I need a new length for the ids I would have to make a new class AND replace the instance of the old class everywhere it is used

You already gave the two striking arguments why this is exact the opposite of beeing clean. So you should avoid specific derivations for specific lengths. However, you wrote

length would not need to change within the program at runtime

so why don't you just make the current length a constant and set it to 4 at one single place in your code? When you later need different lengths, that will be the only place you will have to change, and the need for a method like SetExpectedLength will be removed. If you need to change the expected length once at the program start, then your solution 1 is fine.

The question you have to answer for yourself is if you just expect a future scenario where you have to replace 4 by, for example 5, for all IDs in your program, or a scenario where you have both kind of IDs to deal with simultanously. If the latter is the case, you should rely on having the passed string the correct length 4 or 5