mardi 18 février 2020

Refactoring of a class structure in which one class iterates over collection of classes and execute their's methods

Today I had to solve a problem which made me to write some horrendous code. I'm looking for the ways to refactor class structure in my code so similar "features" won't add up to a pile of horrendous code.

This part of code is a configuration updater which sends some HTTP requests to API Endpoints in order to receive updates, after that, based on said updates - update related objects.

I'm using python thus simplified code that describes the problem is in python

I have a class structure for objects that need to be updated:

class AbstractObject:

    def create():
        ...

    def update():
        ...

    def delete():
        ...


class Object1(AbstractObject):
    ...

class Object2(AbstractObject):
    ...

And a class structure for updaters:

class Updater:

    api_method = None
    object = None

    def __init__(self):
        self.last_record = None


    def get_updates(self):
        """Receive updates over HTTP and call appropriate methods on self.object
        Save last record id to self.last_record attribute.
        """
        # updates related code and such.



class Object1Updater(Updater)

    api_method = '/object1/'
    object = Object1


class Object2Updater(Updater)

    api_method = '/object2/'
    object = Object2

Also a config updater class, which is used to get updates for every object every 30 seconds:

class ConfigUpdater:


    def __init__(self):
        self.updaters = (Object1Updater, Object2Updater)


    def get_updates(self):
        for updater in self.updaters:
            updater.get_updates()

Today I had to implement solution that would set last_record attribute on Object2Updater, and all the following updaters in the self.updaters chain, to None, if atleast 1 create update was received in Object1Updater. And in order to do that I modified Object1Updater class like this:

class Object1Updater(Updater)

    api_method = '/object1/'
    object = Object1
    reset_record = False

    def create(self, *args, **kwargs):
        super().create(*args, **kwargs)  # call Updater.create()
        reset_record = True

And my ConfigUpdater class like that:

class ConfigUpdater:

    ...

    def get_updates(self):
        reset_record = False
        for updater in self.updaters:
            if reset_record:
                updater.last_record = None
            updater.get_updates()
            if getattr(updater, 'reset_record', False):
                reset_record = True

Which is working but is very bad looking. Is there a more appropriate solution for such kind of problems? I've looked for the common structural patterns but wasn't able to find any which would be a good solution (although I think it's a lack of knowledge and I just can't see how to apply said patterns)

Aucun commentaire:

Enregistrer un commentaire