Принцип единой ответственности и классы сущностей

Что касается принципа единой ответственности и повсеместных предупреждений о слишком больших классах, как все это применимо к классам сущностей? Разве сущности по самой своей природе не должны заключать в себе все, что связано с сущностью, которая идет вместе? Разве это не их «единственная ответственность»?

В противном случае предположим, что ваш класс сущности становится «слишком большим», как некоторые могут сказать, как бы вы на самом деле разбили это, не нарушая естественную инкапсуляцию, которую эта сущность должна обеспечивать? Если у вас есть класс Person, только с именем, возрастом и любимой едой, тогда, очевидно, все они должны быть свойствами Person. Но что, если вам нужно добавить еще 20 похожих свойств, таких как цвет глаз, isRightHanded, ReligionOfChoice и т. Д.? Означает ли это, что их нужно разделить на разные классы только потому, что их много? Кажется глупым иметь отдельный класс для «Properties1To5» и «Properties6To10», а затем составлять из них классы Person?

Или более правильно хранить даже 100 свойств (которые теоретически могут быть не связаны друг с другом, за исключением того факта, что они принадлежат объекту Person) непосредственно внутри класса Person, поскольку единственная ответственность класса Person заключается в том, чтобы инкапсулировать все, что касается объекта человек?


person BCA    schedule 11.01.2014    source источник


Ответы (1)


Если вы посмотрите на некоторые стандартные документы по кодированию, вы, возможно, натолкнулись на аргумент «Классы не должны быть больше, чем методы 'x'». Эти «стандарты» существуют добросовестно, веря, но не имеют особого смысла. Идея заключалась в том, чтобы остановить разработчиков, создающих 8000 линейных, монолитных, универсальных классов. Я знаю, я видел это раньше, и это ужасно. Однако ограничение «количества методов на класс» или в вашем примере «количества свойств на POCO» может запутать вещи.

В самом деле, если взять пример «Не более 30 методов на класс» (например, что?), Вы получите фрагментированные классы, которые фрагментированы чисто из-за ограничения в 30 методов. Это действительно делает ситуацию хуже.

классы должны быть настолько большими, насколько они должны быть. И это действительно сводится к дизайну и требованиям вашего приложения. Что мне действительно нужно знать о человеке и что имеет значение в рамках моих требований? Если мне нужно 100 атрибутов, а в правилах бизнеса есть defacto необходимость записывать каждый из этих атрибутов - и они используются в отчетах и ​​/ или бизнес-логике, тогда имеет смысл, что ваш Person имеет 100 атрибутов. Разделение их на блоки просто сбивает с толку данные, сбивает с толку код и превращает вещи в кошмар.

Тем не менее, бывают случаи, когда вы можете захотеть разделить определенные черты на другие классы, связанные с нашим основным POCO Person. Вы упоминаете религию как атрибут, и, возможно, в бизнес-приложении это необходимо. Но если цель вашего приложения - выяснить, как люди меняют свою религию с течением времени, нет смысла быть частью Person, не так ли? У нас внезапно появился ReligionInstance POCO, который записывает их убеждения в определенный момент времени. Я уверен, что вы понимаете, к чему я клоню, поскольку я уверен, что из этих 100 атрибутов - в зависимости от потребностей проекта - другие могут быть выделены в их собственные объекты, потому что это то, что логические потребности. Например, было бы легко добавить поля 7/8, необходимые для адреса. Звучит хорошо, красиво и просто. Однако, если человек переезжает, у нас нет сведений о том, где он был ранее. Внезапно Адреса выглядят как хорошие кандидаты для перехода к их собственному объекту и обратной связи с человеком, если нам небезразлично, что он переехал.

Когда вы упоминаете о компоновке, я думаю так же, потому что будут объекты, которые вы хотите создать, которые будут составными частями другой информации. Если мы представим, что мы храним Person, а также храним 1 или несколько Address POCO ... в зависимости от бизнес-логики, мне может понадобиться просто этот человек или он и их адреса.

Это то, что я называю композитингом. В нашей базе данных есть наши Person и наши Address, и у нас есть не относящийся к базе данных POCO, называемый PersonWithAddresses (например), который предоставит нам информацию о человеке и все его адреса. Бизнес-правила определяют эти объекты, и я считаю PersonWithAddresses составным.

Теперь вот что: какой репозиторий этим занимается? у нас могут быть PersonRepository и AddressRepository, оба берут на себя ответственность за свои индивидуальные POCO. Может быть, у нас также есть CompositePerson репозиторий, который использует оба этих репозитория для создания более тяжелого POCO, содержащего всю необходимую нам информацию? Мы придерживаемся модели единой ответственности. Мы делаем вещи легкими, когда это необходимо, и ничто не делает ничего больше, чем должно.

person Moo-Juice    schedule 11.01.2014
comment
Большое спасибо за ваш хорошо продуманный ответ; Я буду пережевывать это какое-то время. - person BCA; 11.01.2014
comment
Реорганизация большого класса в многоуровневую иерархию классов кажется элегантной, но разве это не означает, что существующие клиенты нашего исходного класса в конечном итоге нарушат закон Деметры, чтобы получить доступ к свойствам, которые теперь похоронены? 2 или 3 уровня в глубину? - person BCA; 02.04.2015