Рабочий против класса данных - PullRequest
1 голос
/ 24 августа 2011

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

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

Итак, какой класс должен иметь метод update()?Это сам класс данных или другой класс менеджера?Метод update() требует обмена данными со многими различными объектами, поэтому я не хочу делать его членом класса данных, потому что считаю, что он не должен ничего знать о других объектах, необходимых для обновления.Я хочу, чтобы класс данных был только структурой данных.Я не так думаю?Какой будет правильный подход?

Мой код:

class RefData
{
    Matrix mX;
    Vector mV;


    int mA;
    bool mB;

    getX();

    setB();

    update(); // which affects almost any member attributes in the class, but requires many relations with many different classes, which makes this class dependant on them.

}

или

class RefDataUpdater
{
   update(RefData*); // something like this ?
}

Ответы [ 2 ]

5 голосов
/ 31 августа 2011

В книге Чистый код Роберта Мартина содержится действительно замечательный раздел, в котором прямо говорится об этой проблеме.

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

Во-первых, ваш класс данных можно считать переносом данных.Объект ( DTO ).Таким образом, его идеальной формой является просто класс без каких-либо открытых методов - только общедоступные свойства - в основном структура данных.Он не будет инкапсулировать какое-либо поведение, он просто группирует связанные данные.Поскольку другие объекты манипулируют этими объектами данных, если бы вы добавили свойство к объекту данных, вам нужно было бы изменить все другие объекты, у которых есть функции, которым теперь требуется доступ к этому новому свойству.Однако, с другой стороны, если вы добавили новую функцию в класс диспетчера, вам необходимо внести нулевые изменения в класс объекта данных.

Итак, я часто думаю, что вы хотите подумать о том, сколько объектов данных может иметь функцию обновления, которая напрямую связана со свойствами этого класса.Если у вас есть 5 классов, которые содержат 3-4 свойства, но у всех есть функция обновления, то я бы предпочел, чтобы функция обновления была частью «класса данных» (который больше похож на ОО-дизайн).Но если у вас есть один класс данных, в который, вероятно, будут добавлены свойства в будущем, я бы склонялся к дизайну DTO (объект как структура данных), которыйболее процедурный (требующий других функций для манипулирования им), но все же может быть частью иначе объектно-ориентированной архитектуры.

Все это говорится, как указывает Роберт Мартин в книге:

Есть способы обойти это, которые хорошо известны опытным объектно-ориентированным проектировщикам: ПОСЕТИТЕЛЯМ или двойномуотправка, например.Но эти методы несут свои собственные затраты и обычно возвращают структуру к процедурной программе.

Теперь в показанном вами коде есть свойства с типами Vector и Matrix, которыевозможно, более сложные типы, чем в простом DTO, могут возникнуть, поэтому вы можете подумать о том, что они представляют, и можно ли их перенести в отдельные классы - с различными функциями для манипулирования, - как правило, вы бы не открывали матрицу или векторнепосредственно как собственность, но инкапсулируйте их.

2 голосов
/ 04 сентября 2011

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

На этот раз, я хотел бы знать, почему вы используете такой метод?Я полагаю, можно с уверенностью предположить, что класс не только вызывает методы установки для списка параметров, которые он получает, но я также рассмотрю этот случай

1) тривиальный метод обновления
В данном случае я имею в виду что-то вроде этого:

public update(a, b, c)
{
    setA(a);
    setB(b);
    setC(c);
}

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

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

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

Редактировать
Я просто хотел бы добавить что-то еще.Где разместить такие методы, также зависит от вашего класса и того, какую цель он выполняет.Если мы говорим, например, о классах Business / Domain Object, и мы не используем Anemic Domain Model, то эти классы могут (и должны содержать) поведение / логику.

С другой стороны, если этоКласс данных, скажем, Entity (объекты персистентности), который также не используется в Domain Model (сложный Domain Model), я бы настоятельно рекомендовал не размещать в них логику.То же самое относится и к классам данных, которые «чувствуют» себя как чистые объекты данных (больше похожи на структуры), не загрязняют их, сохраняют логику снаружи.Правильный ответ: это зависит (от классов, что делает этот метод update, какова архитектура приложения и другие особенности приложения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...