Являются ли вложенные блоки Python try-кроме плохим кодом или запахом кода? - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть ситуация, когда я получаю объект fillable_object, который мне нужно заполнить, и у меня есть другой объект, filler_object, который я использую для заполнения первого объекта.Однако filler_object может быть разных типов, которые не имеют одинаковых атрибутов.В этом случае я хочу, чтобы поля, связанные с этим в fillable_object, получили значение null.

Я думал о том, чтобы сгруппировать для каждого класса, который может быть fillable_object, в try, кроме block.Поскольку наборы атрибутов различных классов являются взаимоисключающими, он либо получит все их, либо нет, затем попытается использовать следующий тип и т. Д. В настоящее время существует не слишком много классов, которые может иметь fillable_object, но я вижу, что это раздражаетподдерживать позже, если число увеличивается.

def fill_with(fillable, filler):
    try:
        fillable.attr1 = filler.attr1
    except AttrError:
        try:
            fillable.attr2 = filler.attr2
            fillable.attr3 = filler.attr3
        except AttrError:
            try:
                #Continue for each class filler can be.
            except AttrError:
return fillable

1 Ответ

0 голосов
/ 13 февраля 2019

Да, это определенно запах кода, и вы обнаружили почему: что происходит, когда вы добавляете новые filler объекты?Вы должны переписать свою функцию.Это нарушение принципа Открыто-закрыто .

. Программные объекты (классы, модули, функции и т. Д.) Должны быть открыты для расширения, но закрыты для модификации

Конкретно, вы можете использовать некоторые обходные пути, но вы находитесь в типичном «большом переключателе», который можно / нужно заменить мудрым использованием полиморфизма.

В вашем примере это filler, который вызывает исключения: если filler.attr1 не существует, тогда попробуйте следующий атрибут (ы) и так далее.Объект filler обладает знаниями, поэтому вы должны поместить метод fill_with в filler.

class FillerA():
    ...

    def fill(self, fillable):
        fillable.attr1 = self.attr1

class FillerB():
    ...

    def fill(self, fillable):
        fillable.attr2 = self.attr2
        fillable.attr3 = self.attr3

...

Теперь ваша функция просто:

def fill_with(fillable, filler):
    filler.fill(fillable)

Эта функциязакрыто для модификации, но вы можете расширить его, добавив новый тип filler (с методом fill).Бонус: filler больше не нужно выставлять свои атрибуты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...