Skip to main content
added 119 characters in body
Source Link
Ant P
  • 843
  • 6
  • 18

In situations like this, I think it's less helpful to dwell on abstract models of the domain (domains can be modelled very differently depending on perspective) and more consider the work that needs to be completed and focus on encapsulation and - more specifically - the concept of tell, don't ask.

If I want to calculate a GPA, it's clearly not the Student's job to know how to do that. So I want a GPA CalculatorGPACalculator*, which I'm going to pass to the Student. The student can pass that through its NotesNotes and each NoteNote can report itself to the GPA calculatorGPACalculator, which will calculate the GPA according to some algorithm that both StudentStudent and NotesNotes are ignorant of.

Something along the lines of:

public class Student { private List<Note> notes; public void CalculateGpa(GPACalculator calculator) { foreach(var note in notes) { note.ReportValue(calculator); } } } public class Note { private double value; public void ReportValue(GPACalculator calculator) { calculator.AddNoteValue(value); } } public class GPACalculator { private List<double> values; public void AddNoteValue(double value) { values.Add(value); } } 

Then, you simply pass your calculator to your student and end up with a fully populated GPACalculatorGPACalculator (either storing the note values as above and then calculating at the end, or calculating as you go, depending on what makes the most sense algorithmically).

Your GPACalculatorGPACalculator is ignorant of your Student and its properties, your Student is ignorant of your GPA calculation.

When you want to retrieve your GPA, you can either expose a property from the GPA calculatorGPACalculator or (better) have another method that allows you to pass another object for your GPACalculatorGPACalculator to report its calculated GPA to.

"Tell, Don't Ask" is, for me, the essence of good OOP.

It's of course very important to remember that the storage model and the domain model are not necessarily the same as the concerns for the two things are very different.

(* In honesty, I would be tempted to ditch the "calculator" suffix and just call this class Gpa.)

In situations like this, I think it's less helpful to dwell on abstract models of the domain (domains can be modelled very differently depending on perspective) and more consider the work that needs to be completed and focus on encapsulation and - more specifically - the concept of tell, don't ask.

If I want to calculate a GPA, it's clearly not the Student's job to know how to do that. So I want a GPA Calculator, which I'm going to pass to the Student. The student can pass that through its Notes and each Note can report itself to the GPA calculator, which will calculate the GPA according to some algorithm that both Student and Notes are ignorant of.

Something along the lines of:

public class Student { private List<Note> notes; public void CalculateGpa(GPACalculator calculator) { foreach(var note in notes) { note.ReportValue(calculator); } } } public class Note { private double value; public void ReportValue(GPACalculator calculator) { calculator.AddNoteValue(value); } } public class GPACalculator { private List<double> values; public void AddNoteValue(double value) { values.Add(value); } } 

Then, you simply pass your calculator to your student and end up with a fully populated GPACalculator (either storing the note values as above and then calculating at the end, or calculating as you go, depending on what makes the most sense algorithmically).

Your GPACalculator is ignorant of your Student and its properties, your Student is ignorant of your GPA calculation.

When you want to retrieve your GPA, you can either expose a property from the GPA calculator or (better) have another method that allows you to pass another object for your GPACalculator to report its calculated GPA to.

"Tell, Don't Ask" is, for me, the essence of good OOP.

It's of course very important to remember that the storage model and the domain model are not necessarily the same as the concerns for the two things are very different.

In situations like this, I think it's less helpful to dwell on abstract models of the domain (domains can be modelled very differently depending on perspective) and more consider the work that needs to be completed and focus on encapsulation and - more specifically - the concept of tell, don't ask.

If I want to calculate a GPA, it's clearly not the Student's job to know how to do that. So I want a GPACalculator*, which I'm going to pass to the Student. The student can pass that through its Notes and each Note can report itself to the GPACalculator, which will calculate the GPA according to some algorithm that both Student and Notes are ignorant of.

Something along the lines of:

public class Student { private List<Note> notes; public void CalculateGpa(GPACalculator calculator) { foreach(var note in notes) { note.ReportValue(calculator); } } } public class Note { private double value; public void ReportValue(GPACalculator calculator) { calculator.AddNoteValue(value); } } public class GPACalculator { private List<double> values; public void AddNoteValue(double value) { values.Add(value); } } 

Then, you simply pass your calculator to your student and end up with a fully populated GPACalculator (either storing the note values as above and then calculating at the end, or calculating as you go, depending on what makes the most sense algorithmically).

Your GPACalculator is ignorant of your Student and its properties, your Student is ignorant of your GPA calculation.

When you want to retrieve your GPA, you can either expose a property from the GPACalculator or (better) have another method that allows you to pass another object for your GPACalculator to report its calculated GPA to.

"Tell, Don't Ask" is, for me, the essence of good OOP.

It's of course very important to remember that the storage model and the domain model are not necessarily the same as the concerns for the two things are very different.

(* In honesty, I would be tempted to ditch the "calculator" suffix and just call this class Gpa.)

Source Link
Ant P
  • 843
  • 6
  • 18

In situations like this, I think it's less helpful to dwell on abstract models of the domain (domains can be modelled very differently depending on perspective) and more consider the work that needs to be completed and focus on encapsulation and - more specifically - the concept of tell, don't ask.

If I want to calculate a GPA, it's clearly not the Student's job to know how to do that. So I want a GPA Calculator, which I'm going to pass to the Student. The student can pass that through its Notes and each Note can report itself to the GPA calculator, which will calculate the GPA according to some algorithm that both Student and Notes are ignorant of.

Something along the lines of:

public class Student { private List<Note> notes; public void CalculateGpa(GPACalculator calculator) { foreach(var note in notes) { note.ReportValue(calculator); } } } public class Note { private double value; public void ReportValue(GPACalculator calculator) { calculator.AddNoteValue(value); } } public class GPACalculator { private List<double> values; public void AddNoteValue(double value) { values.Add(value); } } 

Then, you simply pass your calculator to your student and end up with a fully populated GPACalculator (either storing the note values as above and then calculating at the end, or calculating as you go, depending on what makes the most sense algorithmically).

Your GPACalculator is ignorant of your Student and its properties, your Student is ignorant of your GPA calculation.

When you want to retrieve your GPA, you can either expose a property from the GPA calculator or (better) have another method that allows you to pass another object for your GPACalculator to report its calculated GPA to.

"Tell, Don't Ask" is, for me, the essence of good OOP.

It's of course very important to remember that the storage model and the domain model are not necessarily the same as the concerns for the two things are very different.