3.9. ADR Dragon Position Set
Smok w trakcie gry może być ustawiony w dowolne miejsce ekranu
EN: Set new position to x=10, y=20
PL: Ustaw nową pozycję smoka na x=10, y=20
3.9.1. Option 1
>>> dragon.fly(10, 20)
>>> dragon.teleport(10, 20)
Pros and Cons:
Good: easy to use
Good: encapsulation
Good: easy to add validation if needed
Good: easy to extend to 3D - add parameter with default value
0
Bad: method names are too use-case specific
Bad: arguments are implicit, require knowledge of an API what are the values provided as arguments
Decision: rejected, too use-case specific names
Example:
>>> dragon.fly(10, 20) # does the same, but different name
>>> hero.walk(10, 20) # does the same, but different name
>>> snake.slide(10, 20) # does the same, but different name
>>> fish.swim(10, 20) # does the same, but different name
Use Case:
>>> mycache = DatabaseCache()
>>> mycache.insert()
>>> mycache.select()
>>> mycache = FilesystemCache()
>>> mycache.write()
>>> mycache.read()
>>> mycache = MemoryCache()
>>> mycache.store()
>>> mycache.retrieve()
3.9.2. Option 2
>>> dragon.set_position(10, 20)
Pros and Cons:
Good: easy to use
Good: encapsulation
Good: easy to add validation if needed
Good: easy to extend to 3D - add parameter with default value
0
Bad: arguments are implicit, require knowledge of an API what are the values provided as arguments
Decision: candidate
Example:
>>> dragon.set_position(10, 20) # 2D, maybe
>>> dragon.set_position(10, 20, 30) # 3D, maybe
>>> dragon.set_position(10, 20) # ok
>>> hero.set_position(10, 20) # ok
>>> snake.set_position(10, 20) # ok
Use Case:
>>> mycache = DatabaseCache()
>>> mycache.set()
>>> mycache.get()
>>> mycache = FilesystemCache()
>>> mycache.set()
>>> mycache.get()
>>> mycache = MemoryCache()
>>> mycache.set()
>>> mycache.get()
3.9.3. Option 3
>>> dragon.set_position_xy(10, 20)
Pros and Cons:
Good: verbose
Good: does not require knowledge of an API what are the values provided as arguments
Good: easy to use
Good: encapsulation
Good: easy to add validation if needed
Bad: name
set_position_xy()
ties to 2D pointDecision: rejected, ties to 2D point
Example:
>>> dragon.set_position_xy(10, 20) # 2D, bad
>>> dragon.set_position_xy(10, 20, 30) # 3D, bad
>>> dragon.set_position_xy(10, 20) # 2D, bad
>>> dragon.set_position_xyz(10, 20, 30) # 3D, bad
3.9.4. Option 4
>>> dragon.set_position(x=10, y=20)
Pros and Cons:
Good: easy to use
Good: arguments are explicit
Good: encapsulation
Good: easy to add validation if needed
Good: easy to extend to 3D - add parameter with default value
0
Decision: candidate
Example:
>>> dragon.set_position(x=10, y=20) # 2D, ok
>>> dragon.set_position(x=10, y=20, z=30) # 3D, ok
3.9.5. Option 5
>>> dragon.set(position_x=10, position_y=20)
Pros and Cons:
Good: easy to use
Good: arguments are explicit
Good: easy to add validation if needed
Bad:
set()
is too generic and allows for abuseBad: encapsulation is in question
Decision: rejected, possibility of abuse
Example:
>>> dragon.set(position_x=10, position_y=20)
Problem:
>>> dragon.set(name='Wawelski')
>>> dragon.set(health=50)
>>> dragon.set(position_x=50)
>>> dragon.set(position_y=100)
3.9.6. Option 6
>>> dragon.position_x = 10
>>> dragon.position_y = 20
Pros and Cons:
Good: easy to use
Good: arguments are explicit
Good: can use
property()
for validation if neededBad: violates encapsulation (OOP Principle)
Decision: rejected, violates encapsulation
Use Case:
>>> model = KNearestNeighbors()
>>> model.k = 3
>>> model.weights = [0.75, 0.50, 0.25]
3.9.7. Option 7
>>> dragon.position.x = 10
>>> dragon.position.y = 20
Pros and Cons:
Good: more or less easy to use (Simple is better than complex)
Good: arguments are explicit
Good: can use
property()
for validation if neededGood: namespace
Good: more or less readable (Readability counts)
Good: extensible, easy to refactor to 3D
Bad: violates encapsulation - OOP good practices
Bad: flat is better than nested (PEP 20)
Bad: require knowledge of an API
Bad: violates encapsulation (OOP Principle)
Decision: rejected, violates encapsulation and Python convention (PEP 20)
Use Case:
>>> model = KNearestNeighbors()
>>> model.hyperparameters.k = 3
>>> model.hyperparameters.weights = [0.75, 0.50, 0.25]
3.9.8. Option 8
>>> dragon.position = (10, 20)
Pros and Cons:
Good: easy to use
Good: can use
property()
for validation if neededBad: arguments are implicit
Bad: require knowledge of an API
Bad: always 2D
Bad: not extensible, hard to refactor to 3D
Bad: violates abstraction (OOP Principle)
Bad: violates encapsulation (OOP Principle)
Bad: violates Tell, Don't Ask (OOP Principle)
Decision: rejected, violates OOP principles
Use Case:
>>> model = KNearestNeighbors()
>>> model.hyperparameters = (3, [0.75, 0.50, 0.25])
3.9.9. Option 9
>>> dragon.position = {'x':10, 'y':20}
Pros and Cons:
Good: easy to use
Good: can use
property()
for validation if neededBad: arguments are implicit
Bad: require knowledge of an API
Bad: always 2D
Bad: not extensible, hard to refactor to 3D
Bad: violates abstraction (OOP Principle)
Bad: violates encapsulation (OOP Principle)
Bad: violates Tell, Don't Ask (OOP Principle)
Decision: rejected, violates OOP principles
Use Case:
>>> model = KNearestNeighbors()
>>> model.hyperparameters = {'k':3, 'weights':[0.75, 0.50, 0.25]}
3.9.10. Option 10
>>> dragon.position = Position(x=10, y=20)
Pros and Cons:
Good: easy to use
Good: can use
property()
for validation if neededGood: arguments are explicit
Good: readability
Bad: require knowledge of an API
Bad: extensible, easy to refactor to 3D
Bad: violates abstraction (OOP Principle)
Bad: violates encapsulation (OOP Principle)
Bad: violates Tell, Don't Ask (OOP Principle)
Decision: rejected, violates OOP principles
Use Case:
>>> model = KNearestNeighbors()
>>> model.hyperparameters = HyperParameters(k=3, weights=[0.75, 0.50, 0.25])
3.9.11. Option 11
>>> dragon @ Position(x=10, y=20)
Pros and Cons:
Good: easy to use
Good: using
@
(matmul) it is easy to add validationBad:
@
(at) makes sense only in EnglishBad: require knowledge of an API
Bad: extensible, easy to refactor to 3D
Bad: violates abstraction (OOP Principle)
Bad: violates encapsulation (OOP Principle)
Bad: violates Tell, Don't Ask (OOP Principle)
Decision: rejected, violates OOP principles, misleading for non-English speakers
Use Case:
>>> model = KNearestNeighbors()
>>> model << HyperParameters(k=3, weights=[0.75, 0.50, 0.25])
3.9.12. Decision
>>> dragon.set_position(x=10, y=20)
Pros and Cons:
Good: easy to use
Good: arguments are explicit
Good: provides encapsulation
Good: easy to add validation if needed
Good: extensible, easy to refactor to 3D
Implementation:
>>> class Dragon:
... def set_position(self, *, x: int, y: int) -> None:
... ...