OOD: trouble identifying objects - oop

This should be a simple one.
Let's say I'm designing a very simple timeclock application. The user enters his ID, and the application shows him his hours for the week, hours for the day, and then allows him to punch in our out. It is smart enough to know whether an employee is currently punched in. No breaks or lunch or shifts or anything.
So I've got an Employee. I've got a Timecard which has multiple EventRecords. I've got a Timeclock which of course maintains the time, but is also sort of the front end to the whole model (perhaps).
Should the Employee have a Timecard, or should the Timecard reference an Employee?
Should the Timecard be responsible for calculating hours for the day, etc?
Should the Timeclock be responsible for instantiating Employees and Timecards and relating them?
Should the Timeclock do punchIn and punchOut, or should the Employee?

I think that you are a bit too hoked up on physical objects here. The Employee is probably good to have as object as it has an identidy and is a player in the scenario, but I don't see either the Timecard or Timeclock as any good candidates to be objects. The Timecard would just be a list of EventRecords that belong to an employee, so you could just as well keep those in the Employee object or in a collective list. The Timeclock doesn't do anything at all but hand out DateTime.Now...
The EventRecord is good, or perhaps it could be a WorkTime object; a pair or punch-in and punch-out times. If there is no punch-out time in the last record, the employee is punched in.
Keeping the time records in the Employee object or keeping them in a separate list with a reference to each Employee is rather a matter of taste.
Well, as I scrapped the Timecard and Timeclock objects, most of your questions fall... ;)

Just answer your self these questions, in a end-user perspective, not from a programmer point of view.
Should the Employee have a Timecard, or should the Timecard reference an Employee?
Who owns the timecard?
*Should the Timecard be responsible for calculating hours for the day, etc?**
Should it?
Should the Timeclock be responsible for instantiating Employees and Timecards and relating them?
Does time clocks instantiate employees?
Should the Timeclock do punchIn and punchOut, or should the Employee?
same...
First, you have to analyze the problem. Then design the solution and only after that code it.
So, you should separate each process from another. Here it seems you're analyzing with implementation in mind and then designing etc.
See this answer from Steve A. Lowe
Once you have clear in your mind what object is responsible of what, and during implementation, you may tweak a little bit your design and adapt it if it makes sense.
The three process may happen really, really fast in your head, once you have more experience. But, you have to be patient.

Yeah, this sort of thing is pretty classic. The easiest thing is to apply another rule. my favorite is Parnas' Law: every object "hides" something that can change in the requirements behind its interface.
Okay, so it's pretty clear an Employee has a TimeCard which is a time ordered list of start and stop times.
When you "clock in" as far as the domain is concerned, all you're doing is making a "time-started" record. Sounds like "clock in" and "clock out" might be TimeCard methods, and if we think about it, that also hides the probably requirements changes (eg, is it a record in a data base, a line in a flat file, and are you storing local time, GMT, or UNIX time?)
The Employee is the representatin of an employee, and contains all that employee-specific information; name, address, etc.
So far, there's no obvious need for a TimeClock except as the "implementation" of clocking in and out in the outside world domain.
Now, as you build an application, but have to build up from the domain, and now you'll need some kind of UI, a way to authenticate (establishing which Employee you want) and from there get the Employee's TimeCard -- which suggests a method for Employee. Then you need a place to "clock in" and "clock out" in the UI. That makes it sound as if you timeClock may well be a View object in the implementation. It needs a couple buttons and whatever your login protocol is.
One more piece here is the "business process" or "log in first, then clock in. Later, clock out, then log out" or something similar. There's a controller; how you split that off is somewhat dependent on how you do the UI.

Note: as with most modelling there is not always a single way to do it.
Should the Employee have a Timecard,
or should the Timecard reference an
Employee?
The Domain would suggest that an Employee has a Timecard (and as pointed out, more than timecards over time).
Should the Timecard be responsible for
calculating hours for the day, etc?
I would make that the resposnibility of a TimeCardCalculator.
Should the Timeclock be responsible
for instantiating Employees and
Timecards and relating them?
I think the instantiations should be done at a higher level, by your application perhaps.
Should the Timeclock do punchIn and
punchOut, or should the Employee?
The TimeClock. The employee calls PunchIn/PunchOut on the TimeClock.

This is a decent example of when your OO model should, basically, mirror the real world.
Should the Employee have a Timecard, or should the Timecard reference an Employee?
The employee should have a time card. If it was a real time card, you would be carrying it. You would not be in the time card's pocket.
Should the Timecard be responsible for calculating hours for the day, etc?
I'm not sure what you mean. Do you mean calculating the number of hours from check out minus check in? This is probably something your timecard can do.
Should the Timeclock be responsible for instantiating Employees and Timecards and relating them?
Probably. What exactly is "Timeclock"? When I think of creating and associating employees with timecards, I think more along the lines of "Office." I'm not sure what the full scope of your model is, though.
Should the Timeclock do punchIn and punchOut, or should the Employee?
Have you ever seen a time card punch itself in and out? I think it's safe to say that's an action of the employee.
Edit: As TheTXI pointed out, the Employee would call punchIn and punchOut methods on the Timecard. But the Timecard itself is not responsible for knowing when to punch in or out.

Related

Composition or aggregation

Please take note of my class diagram. It shows an excerpt from a software for the management of movie showings in a cinema and comes from a study book.
The study book explains that there is a composition between the room and the seat. If a cinema employee deletes a room, the seats must of course also be deleted.
About my problem: I want to extend the example with the classes Showtime, Reservation and Movie. However, a reservation always refers to a concrete seat. I would pass a reference to a seat to the reservation:
In this case, can the composition between Room and Seat still remain or does it becomes an aggregation?
Translated with www.DeepL.com/Translator (free version)
Preliminary side remark: for the sake of simplicity, you could remove all the shared aggregation (white diamonds), because UML doesn’t define their semantic and they do not fundamentaly change the meaning compared to ordinary associations.
Let’s look at the whole scenario and keep the composite aggregaton. The consequence is the following:
If you delete a room, the seat would die. This sounds logic, because the seat does not make any sense without the enclosing room.
If you accept that a room gets deleted if still in use by a showtime, you accept that some showtimes may not be linked anymore to a room.
In a similar manner, this may propagate to the reservation, since some reservations would loose their link to a seat.
Now is this scenario a problem? I routinely have a reservation for a flight without the reservation being linked to a seat. So it is up to you to decide how you want to handle it:
You could constrain the deletion of the room to require that it is not linked to any showtime. You therefore avoid the described situation.
You could accept any room deletion, if you decide to offer some reallocation functions that would allow to deal with showtime and reservations without room and seat (at least temporarily) and reassign a showtime and the reservation to a different room.
You may even go further and opt for a mixed scenario, and accept that deletion of the room is possible if no showtime exist in the future (active showtime) bust simply do not care for for reservations on past showtimes.

Company hierarchy class diagram

I want to create an UML class diagram of a company hierarchy and I want to especially to mention that every employee has a superior in the hierarchy (for exemple every department in a company has chief and a chief is a superior of other employees in the departement ).
I build this diagram but I feel that there is some thing wrong
I would omit every generalization, it leads to hell (imagine simple situation - you have a hospital with doctors and patients. How many instances of one person will you have, if a doctor brakes his ankle and becomes a patient? And now you decide to have a library. A doctor can borrow a book as well as a patient.). Anyway, I would depict your domain as is at the diagram below (with example).
As for you requirement: I want especially to mention that every employee has a superior in the hierarchy. It is not feasible in a real world. So I use 0..1 multiplicity.
According to your description I'd come up with this:
A Department is composed of Employees. A Chief is an Employee and there's exactly one Chief per Department.
There are definitely other ways to model this. Especially the generalization might be done in different ways. This depends on lots of domain details which can't be discussed here. But basically you could start with this approach.

Single Responsibility(SRP) vs Tell Don't Ask(TDA)?

I understand that many design principles conflict with each other in some cases . So, we have to weigh them and see which one is more beneficial.
Till now I was aware of SRP principle and did my lot of designs solely based on that but internally I was feeling sometimes wrong while following
this principle. Now I came to know about TDA , My feeling got more support with that :)
SRP :- Object should be worried about its own concern not anyone else
TDA :- Behavior (which is dependent only on its object state) should be kept inside the object itself
Example :- I have different Shapes like Rectangle, Square, Circle etc. Now i have to calculate area.
My design till now :- I was following SRP where I had AreaCalculatorService class which will ask state of shape and calculate the area. The reasoning behind this design
was shape should not be worried about area calculation as it's not shape responsibility. But ideally i used to think area calc code should reside under each shape
as if down the line if new shape comes up I have to modify AreaCalculatorService class(which violates the Open for extension and closed for modification principle(OECM)).
But always gave preference to SRP. That seems to be wrong
Myth is broken(At least mine) :- With TDA, looks like my feeling was correct where I should not ask about the state of the object but tell the shape to calculate it's area. Though
it will violate the SRP principle but will support OECM principle. As I said design principles conflict with each other some times, but I believe where behavior
is completely dependent on its object state, behavior and state should be together.
Another Example :- say I have to calculate the salary of all departments of all Employees in an organization, then we should follow the SRP where SalaryCalculatorService
will depend on department and employees.
It will ask the salary of each employee and then do summation on all salaries. So here I am asking for state of employee but
still not violating TDA calcSalary is not dependent only on salary of each employee.
Let me know if my interpretation of both these principle is correct or not where I should follow TDA in first case but SRP in second ?
I think your TDA understanding is correct.
The problem is with SRP, in my experience it is the SOLID principle most misunderstood.
SRP says that one class should have only one reason to change. The "reason to change" part is often confused with "it should have only one responsibility" so "it must do only one thing". No, it's not like that.
The "reason to change" depends completely from the context of the application where the class resides. Particularly it depends on the actors that interact with the software and that in the future could be able to ask for changes.
The actors could be: the customer who pays for the software, the normal users and some super-users. The DBAs that will manage the database of the application or the IT department that handles the hardware where the application runs. Once you have enumerated all the actors around your software, in order to follow what SRP says, you have to write your class in a way that it has only one single responsibility, therefore only the requests from one actor could require some changes on your class.
So, I think you should follow TDA putting data and behaviors that use those data inside the same object. In this way you can manage the relations among the objects telling them what to do instead of asking data, reducing coupling and reaching a better encapsulation.
SRP as explained above will guide you to decide which behaviors put in one object rather than another one.

MVC design: Deleting an entity with undeletable children

I develop a lot of MVC applications on my own and I am looking for good resources related to a particular problem.
In a lot of my applications, I need to give the end-user CRUD abilities on a lot of entities. But, often times I'll find that these entities are parents of un-deletable children records. Take the following model as an example:
Here, I want to give the user the ability to delete employees (maybe because they've left the company, etc.). However, these employees are listed on projects. To change the creator_employee_id on projects would make the data obviously incorrect, and to cascade delete the projects where that employee is listed is clearly a no-no.
So, I've handled this in the past by adding a flag:
So, when a user goes to delete an employee, I check if deleting that employee violates any foreign key constraints. If it doesn't, I delete the employee. If it does, I set the employee to "active = 0".
However, this entire process of checking, iffing, deleting or deactivating is really complicated and cumbersome to compensate for on the code-level. Because an employee might not just be tied to projects, but to other entities as well, you have to write a check for each entity, determine if it makes sense to "delete" or "deactivate," etc. Then you have to give the user a way to view/reactivate inactive records.
My question is: Are there any other approaches to handling this specific kind of problem? I've tried looking around the web, but this problem is difficult to find the wording for. Perhaps even just the right words will help point me in the right direction. I hope this problem makes sense.
I think that the only clean alternative to deleting entities is to manage their history, possibly with an active flag as in your example (or better with lifecycle timestamps). However, you have to treat all entities in a uniform manner and not delete some of them (those that don't have dependent entities), but not others (having dependent entities).
My approach would be to set the active flag to false in all cases when an employee leaves. Keep that code simple and don't try to use branching logic to handle different scenarios based on the existence of related projects.
If you really set on removing old employees when they don't have any projects related to them, then setup a maintenance task that runs monthly, weekly, or whatever, that cleans out any inactive employees with no related records.

Database design: Multiple non-identifying relationships between two tables

I'm new to database design and have some uncertainties about how best to model this particular case. I'd appreciate any suggestions for this fairly simple scenario.
When a production task begins, two people are involved at all times. One is in charge of the production, and a second is tasked with quality assurance. For any task in the database, it must be possible to identify these two people. They'll both exist in a Person table and have IDs, so I just want the best way to relate them to the production task. The following rules exist:
Either person may be swapped out for a different person at any time.
Each task always involves both people (Neither of these are null).
There are never any other people involved in the task that we want to record.
Each person may be involved in multiple tasks, or none at all.
If we had a whole host of relationships between the task and the people, I'd create some sort of convoluted relationship structure describing their relationship (As producer, quality assurance person, overseer, etc.), but here I feel as though it's sensible to just stick the IDs of the two people in the Task table, in separate columns for Production Person and Quality Assurance Person. Is this bad for some reason that I can't see?
What has really prompted my question is that I'm trying to design exactly that in DBDesigner 4, which I'm new to, and it just doesn't like it - When I try to set up a second non-identifying relationship between Task and Person, it won't give me a second field. It also won't seem to let me rename the fields in Task that refer to the persons, so it'd be impossible to differentiate between the two anyway. Since no-one else seems to share this problem, I've began to wonder whether it's a good idea at all. Is it standard to introduce additional tables as soon as there are two or more links between two entities? What would that look like if I wanted to enforce the above rules? I can't see how I'd ensure that an n:m table always has entries for both people working on the task.
If you are confident your requirements will stay this rigid forever, then just create two NOT NULL FKs:
This declaratively enforces that exactly two people are associated to the task at all times, which would not be readily achievable with just the junction table (as you already noted).
OTOH, if you anticipate your requirements might change at some point in the future, then the added flexibility of junction table might be more important than the completely declarative enforcement of your business rules.
I'm not familiar with DBDesigner, and therefore with your particular problem, but in ER modeling in general, multiple relationships with the same entity are distinguished by their "rolenames" which determine the names of migrated attributes (see the section on "Rolenames" in the chapter 3 of the ERwin Methods Guide). Try locating something along those lines in the UI of your tool.
If you want to know the current state and not who held the role previously #Branko Dimitrijevic's solution will work.
But if the statement 'Either person may be swapped out for a different person at any time' implies you need to know who previously held that role consider a 3 table design
Task; TaskID, <other details>
Assignee; TaskID, PeopleID, role, start_date, end_date
People; PeopleID, <other details>
Then in the assignee table you need constraints to ensure that for each TaskID, Role combination the dates are reasonable e.g. dates don't overlap or have gaps. That you have only 1 of each role active for each task at a time. To manage this would probably require code either in triggers or the application.