Lesson 9
No Object is an Island
Chapter 7: More classes for your robot!
Implementing new classes
The next step will be to implement these new classes and refactor your code appropriately! After refactoring, hopefully your code will read like objects interacting with one another.
Here are some tips and my thought processes.
Refactor incrementally
Perform the refactoring incrementally, making sure that your code still behaves correctly after any updates. You can start with simpler classes that do not depend on other classes (Drink
in my example). Then move on to Grid
(which relies on Drink
). Then update Robot
and subsequently main.py
to incorporate Grid
(and perhaps Drink
).
Be prepared to change!
As you implement your code, you may start to identify more classes that might be useful. For example, I ended up with a DrinkFactory
class to create new drinks. The class is used by main.py
to create new drinks for each Robot
, and the drinks passed on to the Grid
class to be placed onto a random corner cell. Feel free to update your design as you go along.
What did I end up changing?
Compared to my proposed class diagram from the previous page, I have discovered things that I did not anticipate before, and have readapted accordingly.
- I found that
RobotFactory
needed to haveGrid
as an attribute since it needs this to construct eachRobot
. So I replaced thegrid_size
attribute withgrid
. - Created a
DrinkFactory
class to generate drinks. Grid
has taken on more responsibilities than I originally anticipated.- I delegated the task of generating random positions to
Grid
. WheneverRobotFactory
wants to create a random position for a newRobot
, it now asksGrid
to do it on its behalf, sinceGrid
knows better which cells are valid. - I let
Grid
decide where to place the drinks when adding. It is possible to delegate this job to aDrinkPositioner
class (left for open future improvement)
- I delegated the task of generating random positions to
- I can even add a
NavigationManager
class in the future and move some of the navigation logic frommain.py
into its own class (left for open future improvement)
No need to be perfect!
Do not try to obtain the ‘perfect’ design (because there is probably none!) You can always refactor your code later on when the details get clearer, and when you realise that you might need more classes or that things can be done in a better way. Just make the immediate changes, make sure that your code still runs correctly, and then come back to refactor later. Remember that code correctness is more important than elegantly designed code!
Refactor your code!
Now, try designing and refactoring your robot code to introduce more object classes that interact with each other. Then update your code in main.py
to reflect the new design.
You can simply use my design if you like. As mentioned, start with the most independent class first (Drink
), and grow from there. Feel free to go through and analyse my solutions to learn from anything I have done. Do remember that my implementation is not necessarily the ‘best’ solution - there might be many different ways to achieve the same goal!
I’m purposely leaving this task open-ended and flexible. If you are in a hurry, you can just work on a small bit for now and then move on with the lesson. I actually spent about 1 hour 45 minutes refactoring my own code! You can come back and tweak your code later at your own pace, when you have more time and need to practise your OOP and OOAD skills a bit more! You will get better at it with more practice, and having a practical project like this is really helpful.