1

Given that this question is related to my work, I will simplify what I need to do. The system consists of 4 primary types of statuses (internally, we call them events):

  • Working, not operating machinery.
  • Working, operating machinery.
  • Break period.
  • Off work.

Based on those types of events I have to keep 4 different counters with:

  • A counter for total work hours (counter 1).
  • A counter for work hours of operating machinery (counter 2).
  • A counter for tracking break periods (counter 3)
  • A counter for off work hours (counter 4).

In principle, this looks very simple, but the counters can have very complex rules of how to calculate the hours (i.e, "break period" is only considered as such if the worker was on that status for more than 40 minutes, otherwise it should be considered as "working not operating machinery"). In addition, there can be new event types which mix features of other events (i.e., "break period eating ice cream" [new event type] or "working while being off-work" [yep, it doesn't make sense]).

The current solution is a canonical example of spaghetti code: the business rules are defined in a tangled mess of if/then/else statements. It has been declared un-maintainable. That is why I have been tasked with implementing a new solution.

What I have thought is to implement the status events as a class hierarchy so it is easy to mix functionality of different types of events (i.e., a new event type that inherits from "break period" and "off work"). However, I haven't been able to think of an elegant and easy-to-extend way to process the rules of each counter. I don't want to end up with a long sequence of if-else statements.

My goal is to achieve a solution which, later on, can support new type of events and the counters will do the right thing. For instance, a new event "Break period while working not operating machinery" is added, and counters 2 and 3 will take it into account without having to modify them.

What I want is some general design ideas of how this could be achieved in an elegant and extensible manner.

closed as too broad by BobDalgleish, Robert Harvey Mar 20 at 1:31

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • I get that you are looking for general idea of a direction to go/start, but could you show anything from what you have tried? Any classes, general code, or pseudocode. – eparham7861 Mar 19 at 3:05
  • you might want to look into dependency injection, let me explain: you create an interface, lets say ICounter and have a Count method which your rules implement and a Name to display what kind of counter it is. than you register these in the container and resolve them by name or id or however you like it to be then call count on them. in this way you could extend your counter easily – Mightee Mar 19 at 6:56
  • IMHO there is one thing which makes your question hard to understand: you use the term "event" in way which looks very unusual to me. The system seems to have 4 different states, not events. The term "event" would fit to a signal which may trigger a state change. I recommend you recheck your terminology. – Doc Brown Mar 19 at 8:23
  • @DocBrown, I get what you mean, I called it events because each time that a user changes their status, an event is fired to notify the system of the status change. However, there are, in fact, states. – Rayniery Mar 19 at 8:50
  • @Rayniery Have you looked at the decorator pattern? From your remark at the beginning, "in principle, this looks very simple, but the counters can have very complex rules of how to calculate the hours" and your main design requirement at the end, "goal is to achieve a solution which, later on, can support new type of events and the counters will do the right thing" - this might be a good fit. – YSharp Mar 19 at 19:39
2

I recently made a system like this, I did it by tracking events.

In your case each state change would be an event with a state change as an attribute, that way the state changes can be anything, you don't have to worry about adding new ones because there is not a set list of state changes. Then after each state change you would update the logger, probably in the background, so you would end up with a list of all the events that caused a state change and a log of all the state changes.

In my case both the state changes and logger are tables in a PostgreSQL database. You could do it with Redis and a SQL database or just do the entire thing is a NoSQL database.

I also made sure that when an event was updated, deleted it was reflected in the logger.

I got the idea from my system from this video from Nordstrom. https://www.youtube.com/watch?v=O7PTtm_3Os4&t=

Good luck I hope this helps.

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