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

New index.js (tiny JS) for OOP Exercise #342

Merged
merged 7 commits into from
Oct 9, 2022

Conversation

Levi123
Copy link
Contributor

@Levi123 Levi123 commented Aug 29, 2022

OOP exercise

Demo |
Code base

The code is submitted in a dedicated feature branch.

Only code files are submitted.

Please, review.

@github-actions
Copy link

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 list

Relates to A Tiny JS World OOP exercise.

Check-list - definition of done

Minimal requirements to meet:

  • Implement a base class to inherit from
  • Employ default parameters
  • Each species is represented with its own class
  • No need to specify species at instantiation
  • Classes for species that do not have hands by natural design, do not consequently have hands or any equivalent property and do not inherit such properties from any base classes
  • All inhabitants are stored in a container (array or object)
  • JS native features are intensively employed (const, let, Array.map|join|forEach|..., etc)
  • Object methods like keys, values, entries as well as for...in shouldn't be used as these do not guarantee any particular order of keys/values
  • Properties used to form an object presentation string must be explicitly listed/specified; Use Array.map and Array.join to build a presentation string from the list.
  • A parent class shouldn't know anything about its children's props. Child classes must have good reasons to assign or refer to any parent's props. There are no such reasons in this task. Method overloading is to the rescue when building an inhabitant's presentation string.
  • OOP, SOLID and DRY principles are intensively employed

Optional level up (not required to implement):

  • Friends list is a list of objects refs rather than names (strings)
  • Cat-woman class is built employing composition rather than inheritance only

Bonus:

  • toString magic method; when implemented print(inhabitant) does the job as .toString is called implicitly
  • this.constructor.name; when used for output then no need to store species property

Helpful resources:

Universal recommendations:

  • Give variables and functions meaningful names. Avoid generic names like item, element, key, object, array or their variations. Exception: helper functions that are specifically and intentionally designed to be multipurpose.
  • Function names should start with a verb as they denote actions; variables are normally nouns; boolean variables/functions start with is, does, has etc; variable containing multiple entities and functions returning lists contain entity name in plural form.
  • Have consistent code style and formatting. Employ Prettier to do all dirty work for you.
  • Use common sense or seek for an advice whenever requirements look ambiguous or unclear.

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,
Submissions Kottachecker 😺

@Levi123
Copy link
Contributor Author

Levi123 commented Aug 31, 2022

@OleksiyRudenko I'm ready to check

@Levi123
Copy link
Contributor Author

Levi123 commented Sep 5, 2022

@OleksiyRudenko Hello? tell me, are you all right? when will you be able to give feedback? Thank you.

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.

@Levi123 need to make the code OOP compliant.

If two classes have the same property then they need a common base class that handles this shared property.
This will be OOP-compliant and will make the code DRY.

Also see comments below.

const allResidents = [woman, man, dog, cat, catWoman]

function printAllResidents(allResidentsArray) {
for (let i = 0; i < allResidentsArray.length; i++){
Copy link
Member

Choose a reason for hiding this comment

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

Why not an Array method to loop through the residents?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


function printAllResidents(allResidentsArray) {
for (let i = 0; i < allResidentsArray.length; i++){
const prop = Object.keys(allResidentsArray[i]);
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 checklist:

  • Object methods like keys, values, entries as well as for...in shouldn't be used as these do not guarantee any particular order of keys/values

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the checklist:

  • Object methods like keys, values, entries as well as for...in shouldn't be used as these do not guarantee any particular order of keys/values

Done

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.

@Levi123 there are improvements, although in other parts the code became less clear.
Note that a comment can relate to multiple similar code fragments. You will need to extrapolate it by yourself.

Check the comments below. Double-check yourself against the checklist posted by bot and refer to the learning materials if needed.

class Human extends Entity {
constructor(options){
super(options);
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.

From the checklist

A parent class shouldn't know anything about its children's props. Child classes must have good reasons to assign or refer to any parent's props. There are no such reasons in this task. Method overloading is to the rescue when building an inhabitant's presentation string.

// }

class Entity {
constructor (options){
Copy link
Member

Choose a reason for hiding this comment

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

Code is written for other people.
As a peer developer I am tasked to add a class that extends entity. In our team we are used to rely on code editors intellisense. Having current constructor specification it will only tell that constructor expects some "options". We would need to go through the code and read the method body to understand what is expected. As a team member you will also love when peer developers take care of you and write clear code.

At the same time if function specification is detailed there is no such need. There are methods to write self-explaining functions specifications: (1) regular list of parameters, (2) object destructuring syntax when parameters are supplied as objects. Use either of those.

Copy link
Contributor Author

@Levi123 Levi123 Sep 6, 2022

Choose a reason for hiding this comment

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

Code is written for other people. As a peer developer I am tasked to add a class that extends entity. In our team we are used to rely on code editors intellisense. Having current constructor specification it will only tell that constructor expects some "options". We would need to go through the code and read the method body to understand what is expected. As a team member you will also love when peer developers take care of you and write clear code.

At the same time if function specification is detailed there is no such need. There are methods to write self-explaining functions specifications: (1) regular list of parameters, (2) object destructuring syntax when parameters are supplied as objects. Use either of those.

Object destructuring, I understood correctly?

For example:
class Entity {
constructor ({name, species, gender, saying}){
this.name = name;
this.species = species;
this.gender = gender;
this.saying = saying;
}
}

@OleksiyRudenko OleksiyRudenko self-assigned this Sep 20, 2022
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.

@Levi123 good job.
Let's leverage the power of OOP, so that you are able to use JS OOP mechanism to their full extent when a bigger project arrives.

Comment on lines 72 to 73
arrayAllObjects.forEach((characters) => {
toPrint(characters);
Copy link
Member

Choose a reason for hiding this comment

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

Does forEach receive multiple characters or a single character on every iteration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@OleksiyRudenko single character on every iteration

Comment on lines 62 to 69
const allProp = ['name', 'species', 'gender', 'saying', 'legs', 'hands', 'paws']


function toPrint (arrayAllResidents) {
const propToPrint = allProp.filter((propOfObj) => arrayAllResidents[propOfObj] !== undefined)
.map((propOfObj) => arrayAllResidents[propOfObj]).join('; ');
print(propToPrint);
}
Copy link
Member

Choose a reason for hiding this comment

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

This approach was good enough before OOP.
Following the OOP paradigm classes encapsulate properties and behaviour (properties handling).
Every class handles props it owns immediately.
Method overloading and explicit call to inherited method version via super methods are to the rescue.
Task and original project docs offer links to the materials you will find helpful in these regards.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This approach was good enough before OOP. Following the OOP paradigm classes encapsulate properties and behaviour (properties handling). Every class handles props it owns immediately. Method overloading and explicit call to inherited method version via super methods are to the rescue. Task and original project docs offer links to the materials you will find helpful in these regards.

done

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.

@Levi123 great job!
Let's polish it.
Naming is important. Take learnings for any future proejcts - educational or commercial - you will contribute to.

Comment on lines 1 to 7
// class Animal {
// constructor (species, name, gender){
// this.species = species;
// this.name = name;
// this.gender = gender;
// }
// }
Copy link
Member

Choose a reason for hiding this comment

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

Don't keep comments in production code.
Exception: comments that explain reasons behind implementation peculiarities, that cannot be understood from the code itself (e.g. we cache data because server is down often and we want users to have some data anyways)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

// }
// }

class Entity {
Copy link
Member

Choose a reason for hiding this comment

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

entity is a generic term. Business domain and task requirements are a good source of naming ideas. Name should describe what entity it represents at a given level of abstraction - dog, cat, human, mammal, herbivore - in the given business domain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


class Animal extends Entity {
constructor(name, gender, saying){
super(name, 'Animal', gender, saying);
Copy link
Member

Choose a reason for hiding this comment

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

"Animal" is not a species.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the name of the main parent class entity to mammal. The animal class has a species - animals, and a person - human species I think this is not a mistake, but simply a manifestation of fantasy in this task. We do not receive a clear structure that should be followed.


class Woman extends Human {
constructor(name, saying){
super(name, 'Woman', saying)
Copy link
Member

Choose a reason for hiding this comment

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

Men and women are the same species.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, a man and a woman get one species - a person. But it has a gender property to display gender, if that's what you're after.

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.

@Levi123 great job!

@OleksiyRudenko OleksiyRudenko merged commit 763d6be into kottans:main Oct 9, 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.

2 participants