-
-
Notifications
You must be signed in to change notification settings - Fork 184
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
Oop exercise #416
Oop exercise #416
Conversation
344e1c1
to
611b213
Compare
Hey! Congratulations on your PR! 😎😎😎 Let's do some self-checks to fix most common issues and to make some improvements to the code before reviewers put their hands on the code. Go through the requirements/most common mistakes listed/linked below and fix the code as appropriate. If you have any questions to requirements/common mistakes feel free asking them here or in Students' chat. When you genuinely believe you are done put a comment stating that you have completed self-checks and fixed code accordingly. Also, be aware, that if you would silently ignore this recommendation, a mentor can think that you are still working on fixes. And your PR will not be reviewed. 😒 A Tiny JS World -- OOP exercise check listRelates to A Tiny JS World OOP exercise. Check-list - definition of doneMinimal requirements to meet:
Optional level up (not required to implement):
Bonus:
Helpful resources: Universal recommendations:
Also take a note of the requirements above and follow them in all your future projects. By the way, you may proceed to the next task before this one is reviewed and merged. Sincerely yours, |
7fe36e3
to
611b213
Compare
Made a self-test and looked at the task from a new perspective) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OlexiyDobroskok a really good job!
A few improvements and we are done.
super({ species: "human", name, gender, saying, friends }); | ||
this.hands = hands ?? humanDefaultProperties.hands; | ||
this.legs = legs ?? humanDefaultProperties.legs; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just to set default value the same way it is done for species
?
This is not a rhetoric question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve overdone the default values a little bit. =))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
addFriend({ name }) { | ||
this.friends += name + "; "; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the requirements:
Friends list is a list of objects refs rather than names (strings)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
class CatWoman extends Woman { | ||
constructor({ name, saying = "", friends, legs, hands }) { | ||
super({ name, saying, friends, legs, hands }); | ||
this.saying = Cat.meow + " " + saying; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use static property is a good start in the right direction.
But here is the problem: if we change cat's defaut meow (which is allowed by Cat class API), cat-women's saying will be out of sync. Can you devise a way to bind their saying more tightly? You are only one step away from the solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OleksiyRudenko The easiest way I see is to assign a default value to the static property of the cat:
Cat.meow = "¡miau miau";
this.saying = Cat.meow;
but then all cats lose their identity and it makes me sad =)))
Is this the right way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as property holds a primitive value the tie is weak, i.e. simply copied once. Strings, numbers and booleans are primitives. We need something that is passed by reference. These are JS objects (arrays and functions are also objects). Class methods can also be static. There are also very specific methods - getters and setters.
Given the above find a solution that will help to both meet requirements and minimize impact on code to keep it readable (i.e. we do not want dogs and humans to have added complexity just becase we need to resolve a matter between cats and cat-women).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OleksiyRudenko Tried to bind Woman and cat by static method. Looks strange)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does. Truth is that hybrids do not fit OOP hierarchical nature really well.
Composition is a better pattern in similar cases.
The purpose of this part of task was exactly to see the weirdness of how it has to be implemented in OOP paradigm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OleksiyRudenko Good task. At a glance nothing difficult, but on the small details forces to revise a lot of materials). Do I still have to make some adjustments to the task?
const inhabitantDefaultProperties = { | ||
species: "No species", | ||
name: "No name", | ||
gender: "No gender", | ||
saying: "Hello", | ||
friends: "", | ||
}; | ||
|
||
const humanDefaultProperties = { | ||
hands: 2, | ||
legs: 2, | ||
}; | ||
|
||
const petsDefaultProperties = { | ||
paws: 4, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be a better approach to have defaults within class definitions. Not necessarily in form of explicit const definitions. KISS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
this.gender = gender ?? inhabitantDefaultProperties.gender; | ||
this.saying = saying ?? inhabitantDefaultProperties.saying; | ||
this.friends = friends ?? inhabitantDefaultProperties.friends; | ||
Inhabitant.worldPopulation.push(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a good idea to populate world from within inhabitants.
There is a Factory pattern in SW design, but this is not the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a good idea to populate world from within inhabitants. There is a Factory pattern in SW design, but this is not the case.
Can I create a separate function that will create and push objects into an array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Creating World
class would be an overkill at this stage of project development.
But please avoid .push
. Array
methods provide more semantic ways to solve this.
And you will probably want to help inhabitants make friends after they are born. At least exisiting inhabitants cannot make friends with those who are not born yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I abandoned this idea because it was originally intended to simplify the creation of the world, but Later there are problems with withdrawal of friends.What method can you recommend to replace the push?It seemed to me very convenient to work initially with an empty array. (
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed this fragment. I agree that .push
is a way to go.
The only thing remains: it is a world that consists of Inhabitants rather than world is a part of any Inhabitants.
Sure, syntax allows us to do this and make a static prop looks attractive. But having world as a part of inhabitant is counter-intuitive.
World can be a collection of inhabitants. Simplest collection is JS array. If we wanted some world-wide operations we would have multiple functions for those operations and it would make sense to scope them under class World.
Changed the default parameter settings; Removed the static method of creating world in a inhabitant;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OlexiyDobroskok nearly there.
|
||
introduceYourSelf() { | ||
if (this.friends.length === 0) { | ||
this.friends = "Looking for friends!"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen if we .addFriend
after first call of .introduceYourSelf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@
What will happen if we
.addFriend
after first call of.introduceYourSelf
?
@OleksiyRudenko Instead of an empty array, I get a string...) Done)
return `<strong>${this.saying}! My name is ${this.name}. Species: ${this.species}. Gender: ${this.gender}. Friends: ${this.friends} </strong>`; | ||
} | ||
const friendsName = this.friends.map((friend) => friend.name).join(", "); | ||
return `<strong>${this.saying}! My name is ${this.name}. Species: ${this.species}. Gender: ${this.gender}. Friends: ${friendsName}. </strong>`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fragment can be made DRY.
Optimize this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fragment can be made DRY. Optimize this method.
done
Fixed bug with adding friends.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OlexiyDobroskok well done!
const template = `<strong>${this.saying}! My name is ${this.name}. Species: ${this.species}. Gender: ${this.gender}.</strong>`; | ||
if (this.friends.length !== 0) { | ||
const friendsName = this.friends.map((friend) => friend.name).join(", "); | ||
return template + `<strong>Friends: ${friendsName}.</strong>`; | ||
} | ||
return template + `<strong>Friends: Looking for friends!</strong>`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have something for any situation about friends (0 or non-zero number of friends).
const friendsName = this.friends.length ? this.friends.map((friend) => friend.name).join(", "); : "Looking for friends"
Now you can have a single return
statement. Altogether 2 lines of code for this method.
Feel free searching for ternary operators and/or seek for explanation in Students' chat.
Ternaries are helpful, you will use them often. Worth mastering them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OleksiyRudenko Thanks. Looks cool) Need to look at ternary operators.
OOP exercise
Demo |
Code base
The code is submitted in a dedicated feature branch.
Only code files are submitted.
Please, review.