Каковы методы повышения сцепления при сохранении слабой связи? - PullRequest
2 голосов
/ 10 сентября 2009

Слабое сцепление, высокая когезия для ремонтопригодное приложение

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

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

Однако я чувствую, что никогда не слышал никаких конкретных предложений по повышению сплоченности. Кто-нибудь может предложить?

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


У меня довольно слабосвязанное приложение MVP для Windows Forms на C #, которое основывает многие из своих компонентов на интерфейсах, внедряет их через конструкторы и использует контейнер Inversion of Control (Castle Windsor) для сборки всего этого вместе.

Я бы сказал, что он достаточно хорошо спроектирован - он уже подвергся нескольким большим запросам на изменения и довольно легко их обработал. Я в целом вполне удовлетворен этим, но я просто не могу отпустить ноющее сомнение, что это не особенно сплоченно. Это не проблема для меня как единственного разработчика, но я боюсь, что это может запутать кого-то, кто впервые входит в приложение.

Позвольте мне привести пример - приложение используется компанией A для заполнения и обработки исходящих грузовиков продуктом. Это означает, что существует объект OutgoingTransactionInfo , OutgoingTransactionInfoControl (для фактического ввода указанной информации), OutgoingTransactionValidator и OutgoingTransactionPersister . Когда приложение было запущено в производство, мы получили запрос на обработку входящих транзакций - к ним прикрепляется разная информация, другая проверка и другой способ их сохранения. Затем компания B также захотела использовать приложение для обработки своих транзакций, идея аналогична, но опять же, информация, проверки, постоянство и, возможно, несколько других компонентов отличаются.

Поскольку мое приложение имеет хороший набор тестов и свободно, я смог удовлетворить эти запросы довольно легко. Однако я понимаю, что слишком легко случайно настроить его в недопустимом состоянии. Например, вы можете подключить его к использованию объектов OutgoingTransactionInfo при проверке с помощью IncomingTransactionValidator . Если различия незначительны, ошибка может даже остаться незамеченной в течение некоторого времени.

У вас есть предложения для меня? Какие методы вы использовали, чтобы уменьшить такой риск?

Ответы [ 4 ]

3 голосов
/ 10 сентября 2009

Сплоченность означает, что вы не соединяете несвязанные вещи в модуле (класс, ...). Из вашего описания вы, кажется, делаете это хорошо. Надлежащее тестирование (которое вы, похоже, делаете также) должно контролировать риски.

Возможно, вы могли бы использовать систему типов (generics / templates), чтобы убедиться, что информация и ее валидатор соответствуют друг другу, и, возможно, сохранить некоторый код / ​​сделать его более единообразным (хотя стоит убедиться, что дополнительная сложность того стоит).

В противном случае продолжайте в том же духе.

1 голос
/ 10 сентября 2009

Вот интересная презентация Джима Вейриха по вопросам сцепления и сплоченности с точки зрения Ruby с конференции Ruby Mountain Mountain 2009. Имеет дело с различными степенями и когда они могут или не могут быть уместными.

1 голос
/ 10 сентября 2009

Одна вещь, которая приходит на ум, это контролировать видимость. (Я буду говорить в терминах Java, но я предполагаю, что концепции переносятся на другие языки). Что может «увидеть» OutgoingTransactionValidator ? Допустимо ли, чтобы он был виден вне пакета my.org.outgoing ?

Таким образом, неправильное подключение можно контролировать, не объявляя что-либо публичным.

Дальнейшее развитие этой концепции. OSGi позволяет вам явно объявить, какие пакеты экспортирует пакет, а какие использует пакет, так что зависимости становятся намного более явными и контролируемыми.

1 голос
/ 10 сентября 2009

Вы получаете очень связную систему, когда каждый компонент системы сфокусирован на одной ответственности. Как говорится, «Делай одно и делай это хорошо». Когда вы чувствуете, что класс начинает «делать слишком много», вы можете реорганизовать его в два или более классов, каждый из которых отвечает за одну вещь. Это приводит к слабой связи: поскольку обязанности были локализованы для определенного класса, классы, скорее всего, будут иметь очень дискретные взаимодействия друг с другом.

Быстрое предложение для вашей проблемы с проводкой: не мог ли ваш класс OutgoingAbc проверить, получает ли он OutgoingXyz при соединении вместе, и выдать исключение, если он неправильного типа?

...