Closed pixelzoom closed 4 years ago
I should also point out that the code-review checklist also has this item:
- [ ] Is there too much unnecessary decoupling? (e.g. by passing all of the properties of an object independently instead of passing the object itself)?
This identifies a trade-off between doupling and number of parameters in a constructor/method. If a class needs to know about most of the API for another class, then you may decide that it's preferable to pass the entire object instance. Use your judgement.
If you're looking for a good introduction to Coupling (and how it contrasts with Cohesion), see https://www.javatpoint.com/software-engineering-coupling-and-cohesion.
In the latest commit, I fixed some cases in which model
could be easily replaced (or just removed).
About this, I also went and counted the number of model attributes that some of the other classes that got model
as a constructor parameter used: at least 4. Is it justifiable to pass the entire model
instance in these cases?
I don't know if 4 is the magic number, but that sounds reasonable for this sim.
I inspected the remaining occurrences of @param {...} model
, and have a few suggestions:
model
from MassNode, it's not used by MassNode, its used by subclasses. And subclasses can use their constructor args. Also these fields are not needed in MassNode, you can just use the constructor args:this.mass = mass;
this.modelViewTransform = modelViewTransform;
this.model = model;
model
with springsVisibilityProperty
-- it's the only model field that is used. Also you don't need these fields, you can just use the constructor args:this.spring = spring;
this.modelViewTransform = modelViewTransform;
this.model = model;
this.model
this.modelViewTransform
Makes sense, those didn't need to be added as attributes as they could be used directly on the constructor.
About SpringNode
, I didn't change it in the last commit because I was thinking if the property was really necessary, so I waited to take a look at it again today. Anyway, I'll do what you suggested and, if necessary, create another issue about SpringNode
.
Thanks!
Made the discussed changes in the previous commits.
On OneDimensionScreenView
and TwoDimensionsScreenView
, though, this.modelViewTransform
wasn't set by a constructor argument; it was created inside the constructor, so this wasn't changed.
Right. But this.modelViewTransform
does not need to be a field, it can be a const
. See above commit. In general, try to create fields (this.something
) only when necessary.
I removed the design:interviews label from this issue. I added it by mistake when the issue was created. That label is typically used for things that need to be tested with users.
Understood! It's something to remember. If I come across any more cases of unnecessary fields that could be replaced in this way, I'll do it.
Went through all the files looking for fields that were not used or that could be replaced for const. In the latest commit I probably fixed all of them.
I think this can already be closed.
What do you think, @pixelzoom? Assigning for review.
Looks great @Hyodar! Closing.
Related to #2 (code review):
Unnecessary coupling is when a class knows about (or has access to) things that are not related to its responsibilities. And it's one of the biggest factors in writing maintainable code.
In this sim, there are many constructors that take a
model
parameter. This is a red flag that there is unnecessary coupling. Generally, only a couple of things in the model are needed by a class, not the entire model.For example
SpringNode
is passed the entire OneDimensionModel instance:But it uses only
model.springsVisibilityProperty
. So a better API design would decouple SpringNode from OneDimensionModel like this:Based on this use of
model
parameter, the following constructor should be revisited, to evaluate whether they need the entire model or just a few of its Properties: