Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js oop exercise tiny world #219

Merged
merged 6 commits into from
Aug 26, 2022
Merged

Conversation

DmytryjK
Copy link
Contributor

OOP Exercise Tiny JS

Demo |
Code base

The code is submitted in a dedicated feature branch.

Only code files are submitted.

Please, review.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DmytryjK good try.
Still need to leverage power of OOP

this.saying = saying;
}
print() {
const specs = [this.species, this.name, this.gender, this.legs, this.hands, this.saying];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base class shouldn't know anything about child classes' internals.
This breaks SOLID principles.

constructor(name, gender, saying) {
super(name, gender, saying);
this.legs = 4;
this.hands = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A creature that doesn't have hands (or anything else) shouldn't have it. Not zero or explicitly undefined or null. Not prop at all. Imagine you add fish, birds, kangaroo. What a burden to keep track of all possible props. OOP helps to avoid this.

class Human extends Inhabitant {
constructor(name, gender, saying) {
super(name, gender, saying);
this.species = 'human';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

species is a shared property of all inhabitants. It should be defined at some base class. This helps to keep code DRY and have any related in a single place.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DmytryjK good fixes.
We still need to make the code OOP and SOLID principles compliant.
You will find the linked docs here helpful. Feel free asking specific questions based on your learnings from OOP/SOLID.

this.name = name;
this.gender = gender;
this.saying = saying;
this.props = [this.spacies, this.name, this.gender, this.saying];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen if the inhabitant's saying changes? Same refers to other props, saying is just the more likely to change.

this.props = [this.spacies, this.name, this.gender, this.saying];
}
print() {
print(this.props.join('; '));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base class shouldn't handle children's props. This breaks SOLID principles.
Use method overloading where appropirate.

}
}

class CatWoman extends Animal {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the task specs:

whenever you change cat's saying cat-woman's saying should change accordingly, they are strongly tied on some astral level

Will this happen under current implementation? How can we test this?

@OleksiyRudenko OleksiyRudenko self-assigned this Aug 21, 2022
@DmytryjK
Copy link
Contributor Author

I hope now everything is okay. This topic some difficult for understanding((

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DmytryjK nice fix.
Still need to work to make code SOLID/OOP compliant.
Consider reiterating through related learning materials.
Feel free asking questions.

Comment on lines 45 to 47
constructor (name, gender, saying, spacies, legs, hands) {
super(name, spacies, gender, saying);
this.spacies = 'human';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(1) We receive spacies from the caller. We send it to the super class. We assign it directly. Something is not required.

(2) If we hardcode species here. WHy do we need class user to specify any at all? Why not to send the hardcoded value to the super class constructor, as it belongs to it, and let the super class handle it as they like it?

this.spacies = 'human';
this.legs = 2;
this.hands = 2;
this.property.push('legs', 'hands');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not want a superclass to handle child class properties.
This breaks Encapsulation principle of OOP and Open-Closed principle of SOLID.
The language has tools to handle this situatuion.
Use method overloading and opportunity to call inherited method.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DmytryjK great!
Now the final touch. Looks like legs is something that all inhabitants have.
No good reason not to generalize this property and its handling to the base class.
This will be OOP/SOLID compliant and also the code will be DRYer.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DmytryjK you did a great job!
Hierarchical classes are perfect.
Hybrid is questionable, but this was intentional. Check the comments below.
Anyway you did the great job with the hybrid, considering the limitations of OOP/SOLID principles.

Comment on lines +59 to +61
get props() {
return super.props;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as child class doesn't add any new behaviour to the overloaded method, we do not need to overload it. It is inherited anyway.
You do not need to fix this. Take the learning. Let's consider this a stub for next iteration where we probably would want to add tails, whiskers or retractable claws.

Comment on lines +75 to +79
super(name, gender, cat.saying);
this.spacies = 'catWoman';
this.legs = 2;
this.hands = 2;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like CatWoman has more in common with humans than with cats.
Also note that we had to "re-add" hands and overwrite legs.
Actually OOP is not good with hybrids. The proper pattern for hybrids is composition.
You will have a chance to study composition patterns.
For now we done as much as possible in these regards with OOP.
Take this learning. Also check class static methods and properties. This is yet another way to "borrow" behaviour from another class.

@OleksiyRudenko OleksiyRudenko merged commit 28186fa into kottans:main Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants