2010-12-10 3 views
8

Я стараюсь разрабатывать следующие принципы SOLID. Я обнаружил, что когда вы используете «принцип единой ответственности» (S SOLID), вам обычно приходится разделять классы между контейнерами данных и процессорами данных. Например, если у меня есть человек класса с 5 свойствами, который считывается из БД вместо помещения всего внутри класса, я создаю класс Person со свойствами и другим классом PersonReader, который считывает эту информацию из базы данных и создает Person.Использование «Принципа единой ответственности» заставляет мои контейнеры иметь публичные сеттеры

Если я это сделаю, мне нужно открыть свойства Person, чтобы PersonReader мог получить к ним доступ, но тогда у меня меньше инкапсуляции, чем помещение всего в черный ящик и внесение свойств только в чтение.

Я что-то упустил или это недостаток этого принципа?

Заранее спасибо

EDIT: Я изменил лицо писателя к читателю человека, потому что не было никакой необходимости, чтобы сделать сеттеры собственности общественности в начале.

+0

Почему у вас есть PersonWriter, чтобы ваши специалисты-персоналисты были публичными? – Marcie

+0

@Marcie: Спасибо, это было плохо. Я отредактировал вопрос. –

ответ

3

Большинство стратегий доступа к данным (методы ORM) включают компромиссы, которые вы описываете. Наименее интрузивные используют отражение (или самоанализ и т. Д.), Чтобы заполнить ваши сущности, когда им нужно (например, когда нет публичных сеттеров).

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

+0

Спасибо Джеффу, но я не думаю, что это анемичная модель домена, потому что я не разделяю бизнес-логику из модели домена, я выношу упорство из модели домена. Все, что я прочитал, берет меня на этом пути, просто прочитайте пример здесь. Http://p2p.wrox.com/content/articles/design-and-test-driven-development –

+0

@SoMoS - извините, я имел в виду, что я получил что вы уже разделили бизнес-логику с моделью домена (поскольку вы описали объекты как простые контейнеры). Если бы это было так, я бы не был слишком суетлив к СРП. Поскольку это не так, это справедливая проблема. –

0

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

Нет проблем с инкапсулированием с открытием свойств Person, чтобы DatabaseReader мог обращаться к ним, поскольку Person избыточен, если ни один класс не способен его создать. Это неотъемлемая часть ответственности любых классов за то, что они являются творческими и разрушаемыми.

+0

Открытие класса позволяет другим изменять свои данные, когда они не подаются, чтобы сделать это (еще хуже, когда они являются публичными классами, которые могут использоваться сторонними людьми, которые не знают, что у них есть публичное свойство, которое они не должны используйте его. –

+0

В любом случае, мне жаль, но ваш ответ не имеет никакого отношения к моему вопросу. Я мог бы согласиться с тем, что читатель может все прочитать, проблема все еще существует, у вас есть публичные сеттеры, когда у вас будут только геттеры, если бы читатель был внутри класса Person. –

+1

@SoMoS: большинство языков обеспечивают более мелкомасштабный контроль. В C++ вы можете «дружить», а на C# вы можете создавать свойства внутри и иметь вложенные классы. Я думаю, что Java тоже может иметь эквивалент. public , защищенные, частные не являются единственными элементами управления доступом. – Puppy

1

Я определенно согласен с вами в том, что иногда вы сталкиваетесь с этой проблемой. Я испытал это с сериализацией, которая похожа на ORM. В моем случае мне нужно было записать состояние объекта в (двоичный) файл.

В некоторых случаях может быть целесообразным создать интерфейс, через который можно записать и прочитать внутреннее состояние. Таким образом, ваш персональный класс получит два метаданных «сохранить» и «загрузить» (или «написать» и «прочитать», или что вы считаете нужным). Этим методам передаются «IPropertyWriter» и «IPropertyReader» соответственно. (В моем случае я назвал их InStream и OutStream).

Person :: сохранить (IPropertyWriter писатель) затем сделать

writer.writeProperty("name", this.name); 
writer.writeProperty("age", this.age); 

Вы можете возразить, что вы по-прежнему нарушают принцип единой ответственности, но я бы утверждать, что никто не должен знать внутренности лица. (Особенно в моем случае сериализации, мне пришлось сохранить внутреннее состояние, которое частично недоступно через геттеры). Главное, что Person не связан с каким-либо кодом базы данных. Ваш IPropertyWriter может быть всем. Кроме того, ответственность за «знание своих свойств» на самом деле не является новым свойством, но все равно привязана к каждому объекту.

Возможно, вы также зададите вопрос, насколько вероятно, что человек изменится. Если это очень маловероятно, я думаю, что friend классы, как в C++, являются хорошим способом, но если это может измениться, я бы предпочел, чтобы методы сериализации были правы в том месте, где объявлены свойства, поэтому вы не забудьте обновить зависимый код.

+0

Мммм, это немного сложно, но в любом случае это рабочее решение. Я окончательно попробую его в своем коде. Спасибо! –

3

Возможно, мне что-то не хватает, но почему бы вам не написать конструктор класса Person, который принимает все его свойства? Таким образом, PersonReader сможет создать человека без открытия свойств человека.

Другой вариант - пометить сеттер свойств человека как внутренний (и сделать внутренности сборки видимыми для сборки PersonReader, если она находится в другой сборке). Это позволит вам получить доступ к свойствам человека, но не позволит никому изменять их вне сборки.

+0

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