кукольное наследование VS кукольная композиция

17

В последнее время я только что получил кросс-кукольное наследование. Несколько вопросов вокруг него:

  1. Хорошо ли использовать кукольное наследование? Мне рассказали некоторые из опытных марионеточных коллег. Наследование в марионетке не очень хорошее, я не был полностью убежден.

  2. Из мира ОО я действительно хочу понять под прикрытием, как работает кукольное наследование, как и надменные работы.

задан Shengjie 22.06.2012 в 12:02
источник

2 ответа

38
  1. Это зависит, поскольку существуют два типа наследования, и вы не указываете, что вы имеете в виду.

    1. Наследование узлов: наследование от одного определения node fqdn { } другому. Это, в частности, настоятельно рекомендуется против, поскольку он имеет тенденцию терпеть неудачу принцип наименьшего удивления . Классический пример, который улавливает людей, таков:

      node base {
        $mta_config = "main.cf.normal"
        include mta::postfix  # uses $mta_config internally
      }
      node mailserver inherits base {
        $mta_config = "main.cf.mailserver"
      }
      

      Переменная $mta_config оценивается в базовой области, поэтому «переопределение», которое выполняется в почтовом сервере, не работает.

      Невозможно напрямую повлиять на то, что находится в родительском узле, поэтому мало пользы от композиции. Этот пример будет исправлен путем удаления наследования и в том числе mta::postfix (или другого «общего» / «базового» класса) из обоих. Затем вы можете использовать параметризованные классы .

    2. Наследование классов: использование для наследования классов заключается в том, что вы можете переопределить параметры ресурсов, определенных в родительском классе. Переопределив приведенный выше пример таким образом, получим:

      class mta::postfix {
        file { "/etc/postfix/main.cf":
          source => "puppet:///modules/mta/main.cf.normal",
        }
        service { ... }
      }
      
      class mta::postfix::server inherits mta::postfix {
        File["/etc/postfix/main.cf"]:
          source => "puppet:///modules/mta/main.cf.server",
        }
        # other config...
      }
      

      Это работает, но я бы избегал идти более чем на один уровень наследования, поскольку он становится головной болью для поддержания.

    3. В обоих этих примерах их легко улучшить, указав данные заблаговременно (через ENC) или запросив данные inline через extlookup или hiera.

  2. Надеемся, что приведенные выше примеры помогут. Наследование классов позволяет только переопределять параметры - вы не можете удалить ранее определенные ресурсы (общий вопрос). Всегда ссылайтесь на ресурс с именем заглавного типа ( file { ..: } станет File[..] ).

    Также полезно, что вы также можете определить параметры как undef , эффективно отключив их.

ответ дан Dominic Cleal 22.06.2012 в 19:43
3

Сначала я просто определяю различия между ними, Inheritance - это отношение «is-a», а «Composition» - это отношение «has-a».

1) В кукольном наследовании одиночное наследование , что означает, что мы не можем получить более одного класса. Наследование хорош в марионетке, но мы должны знать, где она применяется. Например, Раздел кукольных документов [«Рядом: когда наследовать» по этой ссылке Ссылка , они фактически назовут ровно две ситуации, когда наследование должно происходить:

  • , когда вы хотите перезаписать параметр ресурса, определенного в родительский класс
  • , если вы хотите наследовать от класса параметров для стандартных значений параметров

Но обратите внимание на некоторые важные вещи здесь:

  • В марионетке есть разница между наследованием узла и класса.

  • Новая новая версия марионетки не позволяет наследовать Node , пожалуйста, проверьте это Ссылка .

2) С другой стороны, композиция - это метод проектирования для реализации has-a relationship. которые мы можем сделать с помощью include кукольного ключевого слова , а также с class {'baseclass':} , более поздняя версия, если вы хотите использовать параметры.

( Обратите внимание . В марионетке мы можем использовать «include» несколько раз , но не синтаксис «class» , так как марионетка будет жаловаться на двойные определения классов)

Итак, то, что (наследование или композиция) лучше использовать в Puppet : это зависит от контекста, который я имею в виду, какого кукольного кода вы пишете в данный момент и понимаете ограничения марионетки наследование и когда использовать композицию.

Итак, я постараюсь сохранить все это в нескольких точках:

1) Сначала кукольный использует одиночную модель наследования.

2) В марионетке общий консенсус вокруг наследования заключается в том, чтобы использовать его только тогда, когда вам нужно наследовать значения по умолчанию из Base / Parent

3) Но посмотрите на эту проблему, когда вы хотите наследовать значения по умолчанию от родителя:

class apache {
}

class tomcat inherits apache {
}

class mysql inherits tomcat {
}

class commerceServer inherits mysql {
}

На первый взгляд это выглядит логичным, но обратите внимание, что модуль MySQL теперь наследует значения по умолчанию и ресурсы из класса tomcat. Мало того, что это не имеет смысла, поскольку эти услуги не связаны друг с другом, это также дает возможность ошибаться в ваших манифестах марионеток.

4) Таким образом, лучший подход состоит в том, чтобы просто выполнить включение в каждый класс (я имею в виду композицию), который вы хотите использовать, поскольку это устраняет все проблемы с областью такого рода.

Вывод: . Мы можем попытаться упростить наши марионеточные манифесты, используя наследование, этого может быть достаточно, но это будет только выполнимо до точки. Если вы окружаете окружающую среду сотнями или даже тысячами серверов, состоящих из более чем 20 или 30 разных типов серверов, некоторые из которых имеют общие атрибуты и тонкие различия, распространяются в нескольких средах, скорее всего, вы получите неуправляемую запутанную сеть унаследованных модулей. На данный момент очевидным выбором является композиция.

Пройдите по этим ссылкам, это помогает правильно понять марионеточную композицию и наследование (лично они мне помогли):

  1. Разработка Puppet - это действительно хорошо, Ссылка
  2. Ссылка на Wiki: Ссылка
  3. Модельный класс классов с параметризованными классами: Ссылка

Я в основном программист, лично strong сторонник Inversion of Control / Dependency Injection, который представляет собой концепцию / шаблон, который может быть возможен через композицию.     

ответ дан user3278897 04.06.2015 в 06:08