tags:

views:

96

answers:

5

I am confuse between the best way to organize dependency between multiple classes
assume i have the following classes Employee, Salary, DataAccess

Should i go for: Option1

Employee emp = new Employee();
Salary sal = new Salary();
DataAccess data = new DataAccess();

sal.Calculate(emp);
data.Save(emp);

or Option2

Employee emp = new Employee();
Salary sal = new Salary();

sal.Calculate(emp); //once salary has been calculated salary object will initialize  data access class to do the actual saving.

or Option 3

Employee emp = new Employee();
emp.Calculate(); // employee object will encapsulate both the salary and data access object
+1  A: 

Seems to me that 'CalculateSalary' should be something that happens as part of some other object, and it is given various information about the employee. Some sort of 'SalaryCalculator' object, perhaps ... Something like:

employee.Salary = SalaryCalculator.CalculateFor(employee); 

As to how the saving happens; well I'd leave that up to the ORM you use, personally.

Noon Silk
That violates the Create-Set-Use pattern that the Framework Design Guidelines recommend. For example, instead of asking the developer to supply an external SalaryCalculator there should be a SalaryType property that handles that for him.
Jonathan Allen
@Jonathan: I believe this would depend upon the implementation. The other implement "could be" to come up with a generic `SalaryCalculator` class that would calculate the salary based upon employee's attributes. Attributes meaning, for instance an employee is a `Manager`, and his `Duration` is 15+ years, has 3 certifications. So, based upon similar sort of attributes the `SalaryCalculator` can calculate the salary. And `SalaryCalculator` class can load business rules from some datasource.
KMan
A: 

The short answer is "It Depends".

For most scenarios like salary calculation, my guideline would be to look at what data is needed by the computation. If a majority of inputs belong to ClassA, then it indicates that it should be a method of ClassA.

Persistence is however a special case. Persistence is a 'service' ; you tell someone to go write this to disk for later retrieval. There is no state of any one object that is being accessed. So create a stateless service that accepts the input that needs to be serialized/deserialized

DAO_Service.Save(anEmployee);
DAO_Service.Save(preferences);
DAO_Service.Save(taxRecord);
Gishu
A: 

Agree with It depends answer.

If you want to keep your domain model clean (logic is quite complicated) you can ask object to calculate value (in case it doesn't need some external data from another sources) and use another service for persistance.

However, you can put DataAcccess into your objects (if logic looks simple) and use them as some kind of Proxy between other services and persisted version but don't forget to inject DataAccess to your objects as a interface (in a setter or constructor) to have an easy ability to test or change.

Andrei Taptunov
+1  A: 

Usually Employee HAS-A salary. So I'd go with something like:

Employee emp = new Employee();
emp.Salary = new Salary();

You can create a generic class that would fetch all of the salary calculation business rules in it(from a data source), and calculate salary for employees based upon employee attributes.

SalaryCalculator.CalculateSalary(emp); //I'd agree with Silky
DataAccess.Save(emp); //This shall save changes in emp as well as in salary.

--EDIT--

This is in response to your comment.

Your hrms object(if any) should then encapsulate the Employee, and provide a CalculateSalary option.

How about something like:

yourHrms.Employees.Add(new Employee(Age, Name, DateOfBirth, EmployedSince, TotalExperience, IsManager, new Salary(someStartPointForSalaryIfAny));

Here your Salary class would inherit from your abstact BaseSalary class, that would contain the business rules, and would perform the Calculate()ions. Therefore, the new Salary(someStartPointForSalaryIfAny) would perform the calculation internally.

To save your object you can have:

yourHrms.Employees.Save();//Saves all employees.
yourHrms.Employees[0].Save();//Save this.
KMan
great answerbut wouldn't it be easier for other programmers to reuse my code if i were to encapsulate the data access and salary calculator in object employee itself?, all they need to do is initialize the employee object and call emp.Calculate() function.
CliffC
There are two schools of thought. The "Active Record" school says yes, encapsulate Save/Load into the data model for clarity and easy of use. The "Single responsibility principle" school says no, the data model shouldn't be polluted with database logic. I prefer the Active Record school for most things.
Jonathan Allen
@Cliff: Please see my edit in response to your comment.
KMan
@KMan: thanks for the answer@Jonathan: i understand the "Single responsibility principle" school of thoughts,any link or reference for "Active Record" school?
CliffC
There are two types. One is a literal mapping between classes and tables, properties and columns. This is discussed on Wikipedia. http://en.wikipedia.org/wiki/Active_record_pattern This pattern works really well with ORMs.
Jonathan Allen
The second type is a more domain-driven approach, where in you design the class first the way you want to use it. Then you hide the ugly mapping between it and the database in the Load/Save methods. You can't use ORMs with this design, but it works just fine with stored procedures.
Jonathan Allen
A: 

You can implement ActiveRecord pattern for Employee, to look like this:

Employee emp = new Employee();
emp.Salary = SalaryManager.CalculateSalary(emp);
emp.Save(); //Save to some IDataStore logic.
dario