One thing I always struggle with, when designing software, is to find a good way to keep track of an object's status.

For example, let's say I wanted to keep track of a car being built. It could have a status of "Paint job completed". But from a different perspective, this status could also be considered "Ready for assembly". Or from a sales perspective, it would be "In production".

So now my code object for the car would contain three properties:

public string StatusFromPaintShopPerspective { get; set; }
public string StatusFromAssemblyPerspective { get; set; }
public string StatusFromSalesPerspecitve { get; set; }

Now obviously I could just have the status as an ID (and in this case I probably would), but what if something goes wrong and the status changes to "Requires manual attention" (or the ID for that status). In that case, the status wouldn't tell me how far it was in the process, only that it requires manual attention.

So where am I going with this? I always struggle to design good systems for tracking a status. And I find it difficult to believe that I am the only one who struggles with this. But I cannot find any good articles or literature on the topic.

Does anyone have any suggestions for how to implement process tracking?

  • Nice question. If it were me I'd use an enum rather than a string to denote each status type (SalesStatus, AssemblyStatus etc.). If the status values need watching for conflict (i.e. if it has to be in an Assembled state before ReadyForSales (both different properties)) I'd pass it through a fluent validator. – JᴀʏMᴇᴇ Mar 13 '18 at 9:41
  • @PhilipKendall - I will. – JᴀʏMᴇᴇ Mar 13 '18 at 13:34

I would normally place responsibilities for complex creation processes and their tracking states into a separate object like a CarBuilder. But for the sake of demonstration, lets assume those properties are part of a Car.

lets say I wanted to keep track of a car being build. It could can a status of "Paint job completed".

A basic property of a car could be its Color (with a special value None for unpainted cars). So a status like "Paint job completed" is already a derived property, and a boolean PaintJobCompleted status may look like this:

          public bool PaintJobCompleted
              get{return Color!=Color.None;}

(As I wrote, this property is IMHO better placed in a CarBuilder, since a car object should not know there is a "paint job" involved to make it colored, but lets ignore this).

But from a different perspective, this status could also be considered "Ready for assembly"

Lets assume "ready for assembly" involves the car being painted and the wheels being available, and WheelsAvailable being another boolean property. The dependency between those states then leads to a property like this one:

 public bool ReadyForAssembly
    get{return PaintJobCompleted && WheelsAvailable;}

Or from a sales perspective, it would be "In production".

Lets say a car has an array of wheels, and when that array is not null, the wheels are assembled.

 Wheel[] wheelsArray;
 public bool WheelsInPlace
    get{return wheelsArray!=null}

"In Production" may be true as long as the car is not painted and the wheels are not in place:

 public bool InProduction
    get{return ! (PaintJobJobCompleted && WheelsInPlace);}

So I hope you get the idea:

  • make a clear distinction between basic properties (or attributes of the object, which are mostly independent from the process), and derived properties

  • assign only storage for those basic properties, and encode the business rules for the derived properties into their implementation

Of course, there might be derived properties with complex business rules where storing them internally (as a cache) becomes necessary for performance reasons. But I would recommend to avoid this as long as you don't measure a noteable performance impact.

  • Great points. How would you keep track of changes in the log (generally speaking). Using a change log, or by keeping all statuses with a timestamp (and then have the latest one as the active status)? – Noceo Mar 13 '18 at 11:09
  • 2
    @Noceo: I guess this depends heavily on your logging requirements, and it is a quite different question than the one you asked in your post (maybe worth to be asked separately). A status with a timestamp does not look to me as if it provides any basic logging functionality. And a "latest status" makes no sense in the given example, a change of the color of a car can change all "derived" states simultanously. – Doc Brown Mar 13 '18 at 11:51

The trouble here is that you have three properties to represent just one value - you shouldn't be able to independently set the "sales status" and the "paint shop status", because the first is dependent on the second. Instead, have one single source of truth for the status, and the different views onto that status: for example, "sales status" should just return "still in production" or similar if the underlying status is in any of the states which indicate the paint shop work is incomplete.

I suspect you will find you need to consider the status as a tree rather than a linear process, but that's down to the complexity of the system you're modelling.

As for "needs manual attention", that probably becomes a boolean flag and gets reflected into the high-level status reporting.

  • Thanks. I do like the simplicity of using a flag/boolean for manual attention. – Noceo Mar 13 '18 at 8:50
  • 1
    Status shouldn't be a tree, as you should not have to back up the tree to get to a new status. It should be a directed graph. – Bent Mar 13 '18 at 10:31
  • @Bent would that mean that if a status can go from A to B, then it cannot go the other way (from B to A)? – Noceo Mar 13 '18 at 11:15
  • 1
    @noceo Please read this on directed graphs: mathinsight.org/definition/directed_graph – Bent Mar 13 '18 at 14:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.