В какой класс вы бы поместили эти методы? - PullRequest
3 голосов
/ 25 августа 2009

Если у меня есть класс User, и его учетная запись может быть приостановлена ​​путем добавления записи в таблицу suspensions, какая из этих сигнатур класса / метода, по вашему мнению, более подходит?

User::suspend($reason, $expiryDate);
Suspension::add($userid, $reason, $expiryDate);

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

Что ты думаешь?

Ответы [ 10 ]

10 голосов
/ 25 августа 2009

Вы приостановить пользователя.

User.Suspend()

В вашем методе User.Suspend вы можете добавить их в таблицу «приостановки» или вызвать объект приостановки. Это приведет к более чистому интерфейсу, так как все, что вам нужно сделать, это вызвать метод one.

3 голосов
/ 25 августа 2009

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

Это поднимает еще одну проблему: вы минималист? Есть те, кто пытается сохранить много легких классов, в отличие от нескольких тяжелых.

Лично я считаю, что сплоченность / сцепление перевешивают все эти факторы на порядки . По сути, для меня это будет зависеть от того, должны ли другие системные объекты знать о приостановках, не имея объекта User для запроса. Если это так, класс подвески будет рожден. Если нет, я бы оставил его как часть класса User.

2 голосов
/ 25 августа 2009

* Это мое мнение 100% спорно, учитывая, что я не знаю ваш весь код базового / намерения

Я бы сказал, что нет. Но это действительно зависит от того, как вы смотрите OOAD. Я считаю, что классы User и Suspension имеют одну цель. Класс User отвечает за хранение информации, непосредственно связанной с пользователем (таблица пользователя), а класс Suspension несет ответственность за хранение информации, непосредственно связанной с приостановкой (таблица приостановки). Я бы предложил создать класс UserSuspention, который отвечает за приостановку работы пользователя.

Этот подход к OOAD связан с SOLID принципами проектирования. Если ответственность за приостановку работы пользователя возлагается на класс User или Suspension, это нарушит SRP (принципал единой ответственности) ..., поскольку каждый класс уже несет ответственность за поддержание информации из соответствующих таблиц.

Ваш потенциальный API может выглядеть примерно так:


  public class UserSuspension
  {
    public void SuspendUser(User user, Suspension suspension) {  ...   }
    public void SuspendUser(Guid userId, string reason, DateTime expiryDate) { ... }
  }

2 голосов
/ 25 августа 2009

Хорошо, если добавление приостановки - единственное реальное действие, я бы выбрал первый вариант и сделал его действием, выполняемым классом User.

Однако, если вы намереваетесь создать больше функциональных возможностей для приостановок, я бы подумал о создании такого класса, как:

class SuspensionManager
suspendUser(....)
getSuspendedUser(...)
....
1 голос
/ 25 августа 2009

Из этих двух вариантов я бы проголосовал за Suspension::add(), если на самом деле этот вызов добавит запись в таблицу приостановок . Таким образом, эффект, который имеет этот вызов в коде, с точки зрения самого кода (т. Е. Не концепций, представленных кодом), будет ясен: если бы я увидел код User::suspend(), я бы ожидал, что он изменит "suspended" флаг для объекта User, не изменяющий что-либо еще в каком-либо другом объекте.

С другой стороны, в данном конкретном случае, я думаю, User::suspend() в целом более понятен, поэтому я бы проголосовал за него, если бы это означало, что для этого объекта User будет установлен флаг suspended, или если бы это выглядело так из интерфейса , т. е. если вам не нужно заботиться о том, где хранится приостановка, так как интерфейс класса User может показаться, что это одно из его свойств.

0 голосов
/ 25 августа 2009

Я часто борюсь с одной и той же проблемой, и я спрашиваю себя, имеет ли это смысл за пределами мира программирования. Вы бы попросили в реальной жизни, чтобы пользователь приостановил себя? Вы бы попросили кредитную заявку, чтобы одобрить себя? Если ответ «нет», то необходим специализированный орган / компонент / служба, который обрабатывает эти и подобные сценарии. В случае заявки на получение кредита, одобрение должно быть частью службы одобрения кредита или специалиста по ссуде. Если в вашем случае запрос пользователя о приостановке имеет смысл в моделируемой области, он должен принадлежать пользователю. Если нет, то сервис, который обрабатывает приостановку учетной записи пользователя и подобные сервисы уровня учетной записи пользователя, может быть лучшим местом.

0 голосов
/ 25 августа 2009

Как уже говорили другие, это очень субъективно.

Лично я предпочитаю альтернативу User :: suspend () просто потому, что она позволяет мне внедрять (или изменять реализацию) приостановку всякий раз, когда мне нравится. Он оставляет всю логику приостановки скрытой за пользовательским интерфейсом.

0 голосов
/ 25 августа 2009

Это зависит.

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

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

Простой? Не совсем .

Кто-то еще может утверждать, что более разумно было бы описать приостановку как «AccountAction», а применение приостановки - как глагол. Это может привести вас к модели, в которой различные подклассы AccountAction имеют метод applyTo , который действует на другие типы объектов.

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

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

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

0 голосов
/ 25 августа 2009

Я был бы склонен иметь Account, который связывал User и Suspension

0 голосов
/ 25 августа 2009

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

Первое лучше с точки зрения ООП, вопрос в том, не скажется ли это на производительности:

User user = GetUser($userId); // unnecessary database hit?
user.suspend(reason, expiryDate);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...