2

I am building a Path Planner that will help people plan a path through an RPG console game.

I want to create a table that shows each step through the stage. I have actually implemented a working version of this, however, it is seemingly awful OOP design; it breaks all sorts of principles, and I believe it is not even legitimate OOP. The problem is, clearly, that Table is a God Class.

Due to this, I have decided to rewrite it while trying to keep in mind proper OOP principles. I want to break up Table into multiple classes.

My problem is I need various objects to talk to each other. However, my solution is to always use composition. This breaks the dependency principle as well as the single responsibility principle.

Here is the main Table that will store the player's steps:

class PathTable(object):
    ''' A path table. '''

    def __init__(self):
    # table is a list of dicts, representing rows
        self._table = []

    @property
    def table(self):
        return self._table

    def addStep(self, step):
        ''' Adds a step to the table. '''
        self._table.append(step)

    def rmStep(self):
        ''' Removes the last step from the table. '''
        try:
            del self._table[-1]
        except:
            raise IndexError('Tried to remove item from an empty table.')

Now, I have created an InputManager that is responsible for accepting and validating user input:

class InputManager(object):
    ''' Responsible for managing user input. '''
    def __init__(self):
        pass
    def addFight(self, position):
        ''' Add a 'fight' at table[position]. '''
        # table._table[position]['input'] = 'fight'
        # Need to somehow edit a particular row in the Table.

However, now I do not know how I can access PathTable._table[position]. Without breaking all kinds of OO design principles.

It is frustrating, because the entire job of InputManager is to access PathTable. But I cannot use composition to place InputManager inside PathTable, because it is bad design.

What is a clean way to accomplish this?

I am a beginner, and I am trying to learn.

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
BBedit
  • 7,037
  • 7
  • 37
  • 50

1 Answers1

1

First add support for editing a step's row in your PathTable class:

class PathTable(object):
    def __init__(self):
        self._table = []

    ## NB : This defeats the whole point of making `_table` private
    #@property
    #def table(self):
    #    return self._table

    def add_step(self, step):
        ''' Adds a step to the table. '''
        self._table.append(step)

    def rm_step(self):
        ''' Removes the last step from the table. '''
        return self._table.pop()

    def update_step(self, position, key, value):
        self._table[position][key] = value

Then pass a PathTable instance to your InputManager:

class InputManager(object):
    ''' Responsible for managing user input. '''
    def __init__(self, path_table):
        self._path_table = path_table

    def add_fight(self, position):
        ''' Add a 'fight' at table[position]. '''
        self._path_table.update_step(position, 'input', 'fight')
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Is it ok to so this, because now InputManager depends on PathTable? – BBedit Apr 08 '15 at 09:33
  • How could a mediator or controller (that's mostly what your `InputManager` is) not depend on the objects it has to work with ? But if you reread the code, `InputManager` doesn't depend on the `PathTable` *class*, it just expects to be initialized with an object exposing the same (implicit) interface as `PathTable`. FWIW, having UI layer objects depending on domain model layer objects is expected - how else could they do their job ? -, what you don't want is having the domain model layer depending on the UI layer. – bruno desthuilliers Apr 08 '15 at 11:03