This gist contains selfcheck lists per tasks:
Last active
July 24, 2022 09:15
-
-
Save OleksiyRudenko/44bc64f66e73bc2f99a151a544374a20 to your computer and use it in GitHub Desktop.
Exercise self-check lists
Minimal requirements to meet
- Code is DRY, which means that whenever you see
a pattern in your code those should be eliminated as much as possible. Examples:
print(dog); print(cat); etc ...
should be refactored employingArray.forEach
as the least`${obj.legs}; ${obj.name}; etc...`
(yes, strings are also code) must be refactored employing appropriateArray
methods
- Properties used to form an object presentation string must be explicitly listed/specified
-
Object
methods likekeys
,values
,entries
shouldn't be used as these do not guarantee any particular order of keys/values
A self-check list. Relates to Object-Oriented JavaScript task.
Minimal requirements to meet:
- it is OK to employ ES6 features like
const
,let
etc. - the code is very DRY
- OO is implemented using JS prototype chain object model (not ES6 classes syntax)
- Requirements re Constants:
- all numbers like block dimensions, initial locations are defined as named constants
(e.g.
const STEP = 101;
) as otherwise numbers scattered across code base look cryptic; named constants add semantic meaning and improve readability - every number that have a semantic purpose (like those listed above) should be defined as constants; think of how your code reads - the closer to plain English the better
- there are core constants and derived constants
(e.g. derived constant
const FIELD_WIDTH = BLOCK_WIDTH * BLOCKS_NUMBER;
) - arrays of constants are also constants
(e.g.
const INITIAL_POSITIONS = [1,2,3,4].map(rowNumber => rowNumber * BLOCK_HEIGHT);
) - const objects help organizing and structure const data even better
(e.g.
const PLAYER_CONF = { initialPosition: {x: 1, y: 5}, sprite: '...', ...etc... };
- all numbers like block dimensions, initial locations are defined as named constants
(e.g.
- Requirements re OOP:
- classes do not refer to any global variables, like global variable
player
, which is an instance ofPlayer
class (referring to global constants and globals provided by the gaming platform likeResources
is OK); Hint: passPlayer
instance as an argument to every enemy - Separation of Concerns principle is followed
(e.g.
update
method does only rendering and doesn't contain any unrelated inline code; for example collision check is defined as a dedicated method and only called from insideupdate
) - Nice To Have: properties common for some classes are generalized into a base class
(e.g. there is
Character
base class, which is extended byEnemy
andPlayer
classes) - class extension is implemented using
Subclass.prototype = Object.create(Superclass.prototype)
, notSubclass.prototype = new Superclass(params);
; Useful resource
- classes do not refer to any global variables, like global variable
- Most common mistakes
- Make sure
target = condition ? valueWhenConditionTrue : valueWhenConditionFalse
is used instead ofcondition ? target = valueWhenConditionTrue : target = valueWhenConditionFalse
; Conditional (ternary) operator
- Make sure
Please, confirm all items above are positive. Please, ask a question if anything above requires clarification.
A self-check list. Relates to A Tiny JS World OOP exercise.
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 likekeys
,values
,entries
as well asfor...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
andArray.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 implementedprint(inhabitant)
does the job as.toString
is called implicitly -
this.constructor.name
; when used no need to storespecies
property
Please, confirm all items above are positive. Please, ask a question if anything above requires clarification.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Most common initial code example | |
const man = { | |
species: 'human', | |
name: 'Jack', | |
gender: 'male', | |
legs: 2, | |
hands: 2, | |
say: 'Argh!', | |
friends: ['Jane', 'Toby'] | |
}; | |
const woman = { | |
species: 'human', | |
name: 'Jane', | |
gender: 'female', | |
legs: 2, | |
hands: 2, | |
say: 'What a beautiful day!', | |
friends: ['Jack', 'Kitty'] | |
}; | |
const dog = { | |
species: 'dog', | |
name: 'Toby', | |
gender: 'male', | |
legs: 4, | |
hands: 0, | |
say: 'woof!', | |
friends: 'Jack' | |
}; | |
const cat = { | |
species: 'cat', | |
name: 'Kitty', | |
gender: 'female', | |
legs: 4, | |
hands: 0, | |
say: 'meow!', | |
friends: 'Jane' | |
}; | |
print(man.species + '; ' + man.name + '; ' + man.gender + '; ' + man.legs + '; ' + man.hands + '; ' + man.say); | |
print(`species: ${woman.species}; name: ${woman.name}; gender: ${woman.gender}; legs: ${woman.legs}; hands: ${woman.hands}; say: ${woman.say};` | |
+ woman.fiends); | |
print(dog.species + '; ' + dog.name + '; ' + dog.gender + '; ' + dog.legs + '; ' + dog.hands + '; ' + dog.say); | |
print(cat.species + '; ' + cat.name + '; ' + cat.gender + '; ' + cat.legs + '; ' + cat.hands + '; ' + cat.say); | |
// ======= | |
/* | |
consts -- ensures constant strings and other literals are consistent; IDE suggests const, not literal | |
toStr with print inside -- breaks Single Responsibility / Separation of Concerns principle | |
toStr -- separate string conversion and media output | |
toStr -- map/join; issues with Object.* | |
.toStr: say => saying -- naming conventions | |
friends[''] => friends[{}] -- we want friends, not just arbitrary names | |
.getFriends -- extract names from listed objects | |
.addFriend -- bonus: a method with mutual addition | |
world = {} -- bonus: an object representing world and comprising inhabitants + output method | |
*/ | |
// =========== | |
let objToString = function(obj, delim = ';') { | |
let result = ''; | |
for (key in obj) { | |
result += obj[key]; | |
result += delim; | |
} | |
return result; | |
} | |
const toString = function(inhabitant, delimiter = ';') { | |
return [ | |
'species', | |
'name', | |
'gender', | |
'legs', | |
'hands', | |
'saying', | |
'friends' | |
] | |
.map(key => inhabitant[key]) | |
.join(delimiter); | |
} | |
[man, woman, dog, cat].forEach(inhabitant => print(toString(inhabitant))); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment