sapai
sapai copied to clipboard
Best Practices
If we aim to follow best practices in the code base, it should make the project more maintainable, customisable and easier to use.
Here are a few suggestions High priority:
- [ ] Replace all occurrences of
type(<obj>).__name__ == "<Class>"
withisinstance(<Class>, <obj>)
. This will allow custom subclasses to be made and used with the project in the future
- [ ] When checking for None
obj is [not] None
should be used instead of type (as above) or==
- [ ] Default arguments in should never be mutable (e.g. a list or dictionary) as they are not reset between function calls and this can lead to bugs. Instead, set default to None and replace None with the required value in the function.
- [ ] When checking if a value is True or "Truthy" use
if value
and neverif value == True
.if value is True
should be avoided unless checking for exactly True (will be false if compared to numpy's value of True)
Medium Priority:
- [ ] Use f-strings instead using
.format
on strings, this makes reading and writing much clearer e.g. replace"pet-{}".format(name)
withf"pet-{name}"
- [ ] Define all class attributes (self.attribute) inside the
__init__
function, even if setting to None. - [ ] Never use
import *
as this makes it hard to find the source of a function. - [ ] Use type annotations in public methods (e.g.
oteam: Team
) making it easier to understand and gaining better autocomplete - [ ] Use clearer names, not always clear what oteam / fteam / apet means, friendly_team, enemy_team is much clearer (and autocomplete will help with the extra characters)
- [ ] Follow public/private naming conventions. Anything that starts with an _ (e.g.
self._variable
) should be treated as private and not be used outside the Class definition. At the moment we regularly use _health and _attack of the pet class. A solution could be to create setter functions (.set_attack) or rename them (.base_attack)