views:

188

answers:

8

Given the classes Company, Employee, and Car what is the preferred practice for methods to retrieve Cars associated with Company or Employee?

Employee.GetCars(params...)
Company.GetCars(params...)

Or:

Cars.GetByEmployee(params...)
Cars.GetByCompany(params...)

The first approach is the one I have generally used and always seemed the most intuitive to me. But after seeing a large code-base that used the second approach I have to admit that it's growing on me. The two things I really like about the second approach are:

  • It groups all Car related code together into one file, making the code more modular and easier to maintain.
  • There is an intuitive logic to having any method with a return value of Car (or more like List<Car> in this case) grouped into the Car class.

Is there a best practice that covers this?

+4  A: 

I would use the first approach in the entity classes. There should be no params to these methods as they only return all associations. The second approach which involves some simple business logic should be placed in a helper class or maybe the CarDAO, if you have one.

tob
Great suggestion tob! I really like this approach as it offers the best of both worlds.
Chris Pebble
A: 

Its all about releationships. Can one employee have more then one car? (1:N) Never reference the 1 side from the N side, thats what my teacher said. Same for the other things. If you have a 1:1, you can do both. Employee.getCar and Car.getOwner ;-)

InsertNickHere
There is nothing wrong with wanting to use Employee.getCars() and Car.getDrivers(). *And* you are not answering the question, which is about Car.getCarsByOwner().
relet
+2  A: 

I think there isn't a single solution. It depends how you argue. If it is the responsible of the cars to know by whom they are owned, I would used the second approach. But if it is the responsibilty of the employee to know which cars he has, then I would use the first approach.

However I personally would prefer the first approach because it seems to be easier to implemented.

Roflcoptr
A: 

An employee has a car (or some cars, for that matter), so every employee naturally knows which cars (s)he uses. But does the car know or care who "owns" it? I'd say no. It may know who is driving it, but that's a different question.

Either the car does know which employee owns it (which feels wrong, it's a weird has-a relationship), or it has to search all employeed to find itself, which is even worse (illogical, dog slow, everything but loose coupling).

delnan
+2  A: 

Both approaches seem a little off to me. Why should the Employee class know about the Car class? Why should the Car class know about Employee? Neither class needs the other to function, so coupling them is unnecessary. I would just store a dictionary somewhere that mapped employees to a collection of cars and another that mapped companies to a collection of cars.

Peter Ruderman
Why should an Employee class know about the age or salary of the Employee? Just make a map (one for each attribute)! And after some time, somebody decides to collect all the maps related to the Employee class in one class...
Sjoerd
The issue here is coupling. In general, you should avoid coupling one class to another whenever practical.
Peter Ruderman
I didn't even think about this, great point, maybe the method belongs in a dal class, and instead of returning an employee that has a list of cars, returns a dimensional class EmployeeByCar which behaves like Tuple<Employee,Car> or something of the nature like Tuple<DBDimension1,DBDimension2>
Jimmy Hoffa
+1  A: 

There is no best way. It depends on what your application needs to do. Two applications that use the same data can have completely different object models, depending on their use cases.

anon
A: 

Run this problem through Law of Demeter logic processing. Very helpful, right! hehe

The question is presented in a way that will always have a coupling between Employee and Car classes. If you can change car.GetByEmployee(...) to car.GetByDriversLicenseNumber(...) (or something similiar) then you would decouple the two classes.

The best approach would be to reduce the number of objects that are coupled toghether. So, it all depends on how the next level object in the chain will the Car.

I don't think there's one right awswer to this question, it all is about the current situation.

Jerod Houghtelling
FYI: I know you haven't violated the Law of Demeter. I'm suggesting that us programmers should think about it before violations occurs.
Jerod Houghtelling
A: 

Neither.

Have an interface called ICarOwner that is implemented by Employee and Company (or their derivations), then create the class CarOwnership with attributes Car (of type Car or ICar) and Owner (of type ICarOwner).

When you need to need to find car ownership, you don't need to care whether the owner is an employee or a company. You just need to do CarOwnerships.GetByOwner(ICarOwner).

I hope this helps.

jeyoung