Topics:
One way to think about objects:
Objects are things that can be described and can do things, or...
the Law of Demeter (aka the Principle of Least Knowledge) is not really a law, but a rule of thumb for designing object-oriented programs.
"Only talk to your friends."
Explanation in plain English:
this
)but most everything else is disallowed, especially
If you see code like this:
let maxAge = course.students.reduce(
(maxAge, student) => Math.max(maxAge, student.age)
, 0);
if (maxAge < 18) {
then redesign your program so you can do this instead:
if (course.hasOnlyMinorStudents()) {
...which implies an object-oriented design like this:
class Course {
constructor() {
this.students = [];
}
hasOnlyMinorStudents() {
return this.maxStudentAge() < 18;
}
maxStudentAge() {
return this.students.reduce((maxAge, student) =>
Math.max(maxAge, student.age), 0);
}
don't confuse method chaining (often good) with feature envy (usually bad)
With method chaining, you are usually calling the same object -- or at least the same type of object -- again and again, so the number of collaborators is limited:
string.split(' ').map((s)=>s.toUpperCase()).join(' ')
With feature envy (a LoD violation), you are traversing a graph of collaborators until you find the one with the data or method you want:
course.students[0].phone.sendText('hi')
style | dots | collaborators |
---|---|---|
method chaining | 4 | 2 (String, Array) |
feature envy | 3 | 5 (Course, Array, Student, Phone, String) |
Each object should have limited, clearly defined responsibilities.
Do one thing, and do it well.
This makes it easier to know where in the code to look when you want to add a feature or fix a bug.
It helps to increase cohesion and reduce coupling... If there are two objects with related (but separate) responsibilities, you can change the implementation of one without affecting the other.
Objects can communicate through the same stable interface without regard for the implementation.
OO systems rely on pointers, so it's there's a risk of confusing designs, including:
It's best if dependencies are one-way and hierarchies are shallow.
CRC = Classes, Reponsibilities, Collaborators
For each class (object type) in your system, make a box (or an index card). In this box, write the Class name, a list of its Responsibilities, and draw arrows to its Collaborators.
This is a useful technique that has fallen out of favor because lots of people overused it.
Don't overspecify, and don't fall in love with your design; as soon as you start to write code, your design will change. A diagram is a model of your system -- not the system itself! -- and remember:
"All models are wrong, but some are useful" - George E. P. Box (1919 – 2013)
/