Question

I've got one requirement that is:

When one employee starts working on a project and when he finishes working on it he must inform the system so that it can generate a report afterwards of how much hours a certain project required.

The requirement itself is simple, I just want to see if I'm thinking right about it. My initial idea was an event based approach: when the employee starts working on it one event is raised informing that, and when the employee finishes working an event is raised informing that.

On the end of the day, to count the hours needed for a given project we just need to retrieve the relevant events and compute time spans and sum them up.

There are some loose ends still, however. For instance, finding a way to connect two such events so that we know that one refers to work started and the other referes to the ending of that started work. My idea was to make one event hold a reference to the other, but I don't know if this is usually done.

By the way, the other approach I thought seemed to bloat the employee class. It was basically to make the employee class hold a reference to the project the employee is currently working on, and a property refering to the work start time. When it is finished, just one entry for the timespan is recorded on the project.

The second approach is much simpler but it seems to add responsibilites to the employee class, I'm unsure though.

Is the event approach really the most natural and simpler approach here, or going to one event approach is overengineering and just making the employee class responsible for managing this the simpler approach?

Was it helpful?

Solution

Reading your question and the other answers, I am under the impression there is some confusion caused by the fact the term "event based system" often is used differently from the way it is used in your question. I am pretty sure the requirement

he must inform the system so that it can generate a report afterwards of how much hours a certain project required.

does not mean your system needs to generate such a report immediately when an employer informs the system he stops working on a certain project. That is what the term event based system would make sense for, to trigger sequences of dependend actions to another, independent part of the system, avoiding time lags and polling. In your case, however, the Report generation is probably triggered later by a person (for example the project manager), and not by the fact an employee ends his work on a certain day.

Here, just logging tuples (employee, project, time, [start|stop]) somewhere will be sufficient. When you have your employees and your projects in a relational database, with tables Employee and Project (and corresponding classes), this will mean you add a table/class with four columns/attributes EmployerID, ProjectID, Time, StartStop to the system. One could call this table/class Event, indeed, but to avoid any confusion, I recommend you pick a more specific name, maybe WorkLog. Then, when it comes to report generation, one can evaluate this table and easily

retrieve the relevant events work log entries and compute time spans and sum them up.

This should already solve your "loose ends". For example,

finding a way to connect two such events so that we know that one refers to work started and the other referes to the ending of that started work.

is easy - there should be always pairs of WorkLog entries in the table for the same combination (EmployeeID,ProjectID), one with the state "Start" and one some hours later with the state "Stop", both on the same day. Of course, you need to make sure you have a strategy in your system to deal with situations if one employee forgets to record his begin or end of work on a certain day, but that is not a technical problem, you will have to solve this problem indepently from the solution you pick.

the other approach I thought seemed to bloat the employee class [by...] make the employee class hold a reference to the project the employee is currently working on

Obviously not. The solution above does neither add something to Employee class nor to the Project class.

OTHER TIPS

I would say that you are better off having employees log hours against a project rather than start and stop events

Start and stop events can be come problematic when someone forgets to fill them in. Or when someone is working on more than one thing at a time. Or if they have to account for breaks.

eg. say I start work on project X at 9am this morning and finish at 5pm 4 days later.

  • Is it 4*8 hours or did I work 24h a day on it?
  • What if those days are friday to monday? Did I work over the weekend?
  • What about lunch breaks?
  • What about bathroom breaks?
  • What about the meeting for project Y?
  • What about that emergency bug fix for project Z?

I like the event approach.

Events fits with event sourcing approaches that people talk about, and sometimes in conjunction with Domain Driven Design (DDD) and/or Command Query Responsibility Separation (CQRS).

If you reduce events to calculation of the hours worked as you are able to correlate the start/stop events — and throw away the underlying events as soon as you are able to do so — this looses potentially useful business information that is contained in the events.

For example, by replaying (or otherwise analyzing) the event log, you can determine how many people were on the project at the maximum, or, say, on average or at some point in time. Lots of other thing can also be computed from the events. Who was working together on the team, for example. (A few more different kind of events and you'd really have some data to analyze.)

It is fairly straightforward to replay the event log to compute some information, like hours worked. Making some other party, like the employee themselves, or the employee class, compute some intermediate answer seems counterproductive and premature data analysis.

I would suggest capturing something along the lines of the following business events (as per your specific requirements):

  1. start, stop, suspend, resume, and complete project
  2. assign person to project
  3. suspend person from project (e.g. vacation);
  4. resume person on project (e.g. back from vacation)
  5. taken person off project (e.g. reassigned to another project)

(With these events you can assume that a person that is assigned to a project works the project daily on regular work days until another event changes that. Holidays would not be normally be counted unless perhaps you had special events for working overtime. Yes, there's room for error if events are not captured; ideally that is automated.)

In summary, there is an approach called event sourcing that advocates that business events are captured in an append-only log. This approach separates concerns and reduces coupling of those wanting calculations/results-analysis from those who are (closer to) collecting the results.

Without this separation, the collectors have to know exactly what results to compute and keep for other entities to use, which conflates responsibilities and tightens coupling. For example, in your second approach, a timespan would be computed and saved for later use as the original problem identifies this as the requirement, whereas the events used in deriving the timespan are discarded.

The event sourcing approach also offers business value in the sense of supporting analytics (especially in postmortem).


Edit: reworded events as active business operations as per @Ewan's comment.

Licensed under: CC-BY-SA with attribution
scroll top