Когда класс слишком большой или слишком маленький?
Недавно я просмотрел мой код у старшего разработчика в моей компании. Он критиковал мой дизайн за использование слишком большого количества классов. Мне интересно услышать ваши реакции.
Мне было поручено создать службу, которая создает xml файл в результате манипулирования тремя другими файлами xml. Назовите эти aaa.xml, bbb.xml и ccc.xml. Услуга работает в два этапа. В первой фазе он сглаживает aaa.xml против bbb.xml. На втором этапе он объединяет продукт первой фазы с ccc.xml для получения конечного результата.
Я выбрал дизайн с тремя классами: класс XmlService, который использовал два других класса, класс скруббера и класс слияния. Я сохранил классы очистки и слияния отдельно, потому что оба класса были большими и отличались различной логикой.
Я думал, что мой подход хорош, потому что он держал мои классы маленькими и сплоченными. Мой подход также помог контролировать размер моего тестового класса.
Старший разработчик утверждал, что классы очистки и слияния будут использоваться только классом XmlService и поэтому должны быть частью этого. Он чувствовал, что это сделает XMLService сплоченным, и это то, что является связующим, по его словам. Он также считает, что разрушение классов таким образом делает их ослабление сплоченности.
Ирония заключается в том, что я пытался сломать эти классы для достижения сплоченности. Как вы думаете? Кто прав или не прав? Мы оба правы? Благодарим вас за ваши предложения.
Ответы
Ответ 1
Если вы следуете принципу единственной ответственности (и исходя из тона вашего вопроса, я думаю, что вы его следуете), тогда ответ ясно:
- Класс слишком велик, когда он совершает несколько действий; и
- Класс слишком мал, когда он не выполняет свою задачу.
Это очень широкое и действительно субъективное - следовательно, борьба с вашим коллегой. С вашей стороны вы можете утверждать:
- Абсолютно никакой проблемы при создании дополнительных классов - это не проблема, компиляция и время выполнения.
- Текущая реализация службы может предполагать, что эти классы "принадлежат" ей, но это может измениться.
- Вы можете протестировать каждую функциональность отдельно.
- Вы можете применить инъекцию зависимостей.
- Вы ослабляете познавательную нагрузку на понимание внутренней работы службы, потому что ее код меньше и лучше организован.
Кроме того, я думаю, что у вашего босса есть ошибочное понимание сплоченности. Подумайте об этом как о фокусе: чем меньше фокус вашей программы, тем выше сцепление. Если код на ваших классах спутников сливается в классе обслуживания, последний становится менее сосредоточенным (менее сплоченным). В целом принято считать, что более высокая когезия предпочтительнее более низкой когезии. Попытайтесь просветить свое мнение об этом.
Ответ 2
Сплоченность - это мера того, насколько сильно связана функциональность внутри тела кода. Тем не менее, если слияние и очистка не связаны друг с другом, в том числе и они в одном классе уменьшают сцепление.
Здесь также стоит упомянуть принцип единой ответственности. Создание класса с единственной целью очистки и другое с единственной целью слияния следует этому принципу.
Я бы сказал, что ваш подход лучше всех.
Ответ 3
Что бы вы назвали классами? ScrubXml
и MergeXml
- хорошие имена. ProcessXML
и ScrubAndMergeXml
нет, первое из них слишком общее, а второе имеет конъюнкцию. Пока ни один из классов не полагается вообще на внутренности одного или других (т.е. Низкое сцепление), у вас там хороший дизайн.
Имена очень полезны при определении сплоченности. Коммуникативный модуль делает одно и, следовательно, имеет простое конкретное имя. Модуль, который делает больше чем одно, менее сплочен и нуждается в более общем или более сложном имени.
Одна проблема с объединением функциональности в X в Y, если X используется только Y, является абсурдом reductio ad absdamdam: если ваш график вызовов ацикличен, вы завершите все свои функции в одном классе.
Ответ 4
Как человек, который возвращается от строительного фестиваля GodClass в течение нескольких лет, и теперь очень стараюсь избежать этой ошибки в будущем; ошибка создания единичного источника с 6000 до 10000 строк с одним классом, с более чем 250 методами, 200 полей данных и некоторыми методами более 100 строк, принцип единой ответственности выглядит как нечто, достойное защиты от пристрастий вашего непросвещенного супервизора.
Если, однако, ваш руководитель и вы не согласны с вопросом, принадлежат ли 2000 строк кода одному классу или трем, то я думаю, что вы оба ближе к здравомыслящему, чем я. Возможно, это вопрос масштаба и перспективы. Некоторые объектно-ориентированные программисты любят определенную "Коэффициент автономности" для каждого класса, прямо нарушая общепринятые представления о том, как улучшить сцепление и минимизировать сцепление.
Набор из 3 классов, которые хорошо работают вместе, объективно является более объектно-ориентированной системой, чем один класс, который делает то же самое. можно утверждать, что если вы пишете приложение, использующее только один класс, что приложение вообще не является объектно-ориентированным.
Ответ 5
Если скруббер и слияние не имеют смысла вне контекста основного класса, я согласен с вашим рецензентом, особенно если вам нужно было разоблачить любые детали реализации, чтобы разрешить это разделение. Если вы используете язык, поддерживающий вложенные частные классы или что-то подобное, это может быть разумной альтернативой для поддержания логического разделения, не подвергая детали реализации внешним потребителям основного класса.
Ответ 6
Это очень субъективная область и будет отличаться в зависимости от правил кодирования и стиля, и кто одобряет ваш код.
Тем не менее, если ваша защита вашего дизайна не задерживалась, а ваш старший член команды все еще настаивал на слиянии ваших классов, тогда вам нужно идти на компромисс:
Вы уже отделили логику. Напишите один класс обслуживания и сохраните методы отдельно, как и другой хороший дизайн, а затем напишите метод клея. Добавьте некоторые комментарии выше каждого метода, объясняющие, как они могут быть легко разделены на несколько классов, если это необходимо в будущем.