Можно ли использовать в основном статические классы? - PullRequest
5 голосов
/ 09 марта 2010

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

Новая система основана исключительно на MVC, и у меня есть Bootstrapper, который загружает контроллеры на основе текущего URI, и последние используют модели для реальной работы - как с сеансами, так и с базой данных.

tl; dr Это мой первый проект без готового фреймворка.

Я очень неопытен, когда дело доходит до шаблонов проектирования. Я знаю, как работают большинство популярных, но никогда не использовал их.

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

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

Любые комментарии или советы будут высоко оценены.

РЕДАКТИРОВАТЬ: , несмотря на все эти образованные ответы, я не убежден. Хотя, скорее всего, это из-за моего отсутствия опыта, я все еще не предвижу ничего плохого в текущей настройке. Я имею в виду, что даже не представляю себе ситуацию, в которой у меня были бы какие-либо неудобства из-за архитектуры кода, как сейчас. Надеюсь, я не получу сурового урока, когда уже слишком поздно что-либо менять ...

Ответы [ 7 ]

5 голосов
/ 09 марта 2010

Вы правы, это запах кода, и все скажут вам, что это baaaad.

Так что здесь я предлагаю скорее сделать самооценку серьезности проблемы:

  • У вас есть классы со многими геттерами и сеттерами ?

  • Ваши статические функции похожи на приведенные ниже?

    Если да, попробуйте переместить логику в классе MyClass, что будет уже намного больше ОО. Это классическая ошибка в мире процедур / сценариев.


 static void myMethod( MyClass anObject )
 {
     // get value from anObject
     // do some business logic
     // set value of anObject
 }

  • Есть ли у вас много глобальных состояний , таких как данные, которые вы извлекаете из текущего сеанса?

    Если да, сделайте оценку, хотите ли вы изменить его. ОО-способ - передать сеанс по цепочке вызовов. Но на практике удобно обращаться к сеансу как к глобальному объекту. Но это затрудняет тестируемость. Попробуйте удалить глобальное состояние и превратить его в обычный объект, который вы передаете и манипулируете в методах.

Сделайте эту оценку и попытайтесь определить служебные классы, сервисы классы и бизнес-объекты . Служебные классы - это вспомогательные классы с служебными методами (например, форматированием, преобразованием и т. Д.), Которые могут быть статическими. Класс обслуживания выполняет некоторую бизнес-логику, но он не должен иметь состояния и достаточно одного экземпляра. Бизнес-объекты user, products, article и т. Д. - это то место, где вы должны сосредоточить свои усилия. Попробуйте превратить обычные данные в объекты с некоторым поведением.

Взгляните на , если сущность немая . Даже если это для Java, концепции являются общими.

EDIT

Вот мой анализ, основанный на вашем комментарии:

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

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

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

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

Мои 2 цента

4 голосов
/ 09 марта 2010

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

4 голосов
/ 09 марта 2010

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

Если вы имеете дело с базами данных, у вас может быть статический класс db и простой бизнес-уровень, и ваше php-приложение взаимодействует с бизнес-уровнем, который, в свою очередь, взаимодействует с вашим уровнем базы данных. Это становится вашей типичной 3-уровневой архитектурой (некоторые люди любят называть ее 4-уровневой и отделять фактическую базу данных от слоя данных, тоже самое).

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

1 голос
/ 09 марта 2010

Технически в этом нет ничего плохого. Но практически вы теряете много преимуществ объектно-ориентированного программирования. Также напишите код / ​​функциональность, к которой он относится .. например:

 user.doSomeTask()

для объекта пользователя имеет больше смысла, чем

 UserUtils.doSomeTask(User user)

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

1 голос
/ 09 марта 2010

Краткий ответ: все в порядке, но вы упускаете преимущества ООП.

Одна из причин использования объектов заключается в том, что большую часть времени существует несколько типов объектов, которые выполняют роль. Например, вы можете поменять объект доступа к данным DBVendor1 с объектом доступа к данным DBVendor2, который имеет тот же интерфейс. Это особенно удобно, если вы используете модульные тесты и вам нужно поменять объекты, которые действительно работают с фиктивными объектами (макеты и заглушки). Подумайте о ваших объектах с тем же интерфейсом, что и кирпичи Lego с разными цветами, которые сочетаются друг с другом и легко взаимозаменяемы. И вы просто не можете сделать это со статическими объектами.

Конечно, повышенная гибкость объектов имеет свою цену: инициализация объектов и их объединение - это больше работы (как вы написали) и приводит к увеличению количества кода и объектов, которые собирают вместе другие объекты. Именно здесь вступают в игру шаблоны креативного дизайна, такие как builder и factory .

Если вы хотите пойти по этому пути, я советую вам прочитать о внедрении зависимостей и использовании DI framework .

1 голос
/ 09 марта 2010

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

Однако, если вы пытаетесь поддерживать состояние на разных страницах, вы должны сделать это либо с помощью ViewState, либо с помощью объекта Session.

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

0 голосов
/ 09 марта 2010

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

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