2011-12-31 2 views
7

Я запустил сайт аркады, и за последние несколько лет у него появилось много функций, оно дошло до того, что процедурное программирование выглядит слишком сложно и добавляет новые функции или делает простые модификации дизайна могут быть очень сложными.Выбор классов, которые нужно использовать в php OOP-дизайне

Поэтому я решил попробовать и перекодировать сайт с нуля с теми же функциями, но в формате ООП.

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

На данный момент я начал со следующего класса и функций, но они вписываются в эту категорию?

<? 
class User { 

    var $userId, 
     $username, 
     $userRole, 
     $userEmail; 

    function isLoggedIn(){ 

    } 

    function login($postusername, $postpassword) 
    { 

    } 

    function increaseLoginCount(){ 

    } 

    function logout(){ 

    } 
} 
?> 

я мог бы иметь что-то вроде следующего в page.php .. (подключение класс не показан)

<? 
$db = new Connect; 
$db->connect(); 

$user = new User; 

if(!$user->isLoggedIn()) 
{ 
    echo "Please Log In."; 

    if($_POST['user']) 
    { 
     $user->login($_POST['username'], $_POST['password']); 
    } 
} 
else 
{ 
    if($_POST['logout']) 
    { 
     $user->logout(); 
     exit; 
    } 

    echo $user->username." Logged In.<br />"; 
} 
?> 

Но тогда сайт будет иметь страниц, чтобы показать игру категории и я не» t знать, где функция displayGames() будет соответствовать, поскольку это не одна игра, поэтому не пойдет в класс «Игра»?

Я пытался найти «реальный мир» примеры, но PHP код, показывающий мне, как сделать изменить цвет слона или танец на самом деле не поможет ...

+0

У меня есть функции закодированы, но упростить этот пример, они были удалены. – Dan

ответ

9

Давайте начнем с некоторым анализом текста, подчеркивает мной:

Я бег в аркадного сайта и над в последние несколько лет

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

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

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

Поэтому я решил попробовать и перекодировать сайт с нуля с те же функции но в формате ООП.

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

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

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

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

Проблема у меня есть это собирание классы,

Я пытаюсь перефразировать: Для чего писать классы для?

Я понять ООП и как она должна работать, но всегда кажется есть проблема начала работы.

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

Я не уверен, должен ли я быть пытаюсь сделать функции для классов, таких как класс пользователя с журналом в функции пользователя, или если класс пользователя должен просто добавить/обновить/показать информацию о пользователе и часть журнала будет лучше в системном классе?

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

Приложение должно предоставить этого пользователя любому компоненту-потребителю, поэтому каждая команда/сценарий не должна иметь дело с: a) получением информации о пользователях и обработкой пользователей (например, при входе в систему); b) проверкой того, действителен ли компонент для пользователь (управление доступом). Это должно быть размещено где-то в другом месте, например. в application controller­PofEAA.

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

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

Возможно, просто напишите, что должно происходить вместо написания кода.

В настоящее время я начал со следующим классом и функции но делают они вписываются в эту категорию **? **

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

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

$application->getDB(); 

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

/** 
    * @package command.modules.games 
    */ 
function ListGamesCommand(Request $request, Response $response) 
{ 
    $application = $request->getApplication(); 
    $user = $application->getSession()->getUser(); 
    $games = $application->getModels()->build('games'); 
    $games = $games->findByUser($user); 
    $response->setProp('games', $games); 
} 

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

Создать фабрику, которая производит пользователя для объекта приложения - все, что нужно будет сейчас или в будущем (см две груды объектов в The Clean Code Talks — Inheritance, Polymorphism, & Testing). Если вам понадобится аутентификация, добавьте ее в объект сеанса или интерфейс пользовательского объекта.

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

То же самое верно для доступа к переменным запроса. Если вы хотите использовать преимущества ООП, которые очень связаны с косвенностью (и каждый уровень косвенности связан с ценой), вы должны в первую очередь сделать ваши базовые классы работать с определенными данными, а не с любыми данными (например, globals и supgllobals, я видел $_POST в вашем примере кода).

Так включить новый код для работы по запросу и доставить ответ (вход - Обработка - выход):

$request = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV); 
$response = new Response; 

Пример взят из BankAccount - Sample application used for PHPUnit training

Теперь все, что ниже этого могут работать на Request и объекте Response - обрабатывать вход и преобразовывать его в выходной сигнал. Команде домена (ваши скрипты/команды, которые делают эту вещь) больше не нужно заботиться об извлечении ввода из HTTP-запроса, например, используя $_POST или $_GET, они могут принимать его непосредственно из Request - или если вы пишете класс собственные команды - это может быть еще более адаптировано. И некоторые команды могут работать с запросами и ответами самостоятельно.

Следующая большая тема - пользовательский интерфейс. Вы пишете Вы хотите:

Я решил попробовать и перекодировать сайт с нуля с теми же функциями, но в формате ООП.

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

Бьюсь об заклад, вы любите сайты. Вы любите заставить их работать и отлично выглядеть. Вы создали свой сайт на протяжении многих лет, и даже не все так, как вы этого хотите, вы не хотите его бросать. Поэтому для повторной записи очень важно, чтобы вы не разрушали все, но вы можете сохранить свою рабочую форму отныне до будущего (см. Также Preserve a Working Application; last point of the list).

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

Если вы нарушите его,

  1. вы даже не заметить?
  2. Вы можете исправить это?

С другой стороны, вы хотите, чтобы ваш код приложения (функции, функциональные возможности), чтобы не быть слишком тесно связан с ней больше , чтобы иметь преимущество в переписывании кода. Как вы хотите переписать приложение, давайте посмотрим:

 .---------.       .-------------. 
    | website | ---> [interface in ] ---> | application | 
    | user | <--- [interface out] <--- |    | 
    `---------´       `-------------´ 

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

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

В случае, если процедуры регистрации и утери пароля являются частью существующего приложения и продолжают существовать.

Теперь вам нужно принести старый и новый код вместе.

Итак, вы, вероятно, начнете с интерфейса для HTTP-запросов и ответа HTTP. Вид начинается с этого Интерфейс Out. Вы назначаете/передаете все необходимые данные для представления через этот интерфейс, ваше приложение не знает. Вы не имеете дело с CSS, Javascript или HTML-кодом в своем новом коде приложения. Это только сахара на вершине для выхода. Ваше приложение должно взаимодействовать также через консоль/telnet в виде обычного текста или в виде удаленной службы XMLRPC, конечная точка AJAX - независимо.

Таким образом, вы можете, скорее всего, просто обобщить свой код представления и ввести в него переменные. Чтобы написать слой представления, он может быть таким же простым, как включение файла PHP. Он работает с переменными, которые доступны в его области. Он может использовать «вспомогательные» функции (шаблоны шаблонов), которые доступны в его области. Он может использовать Показать объекты модели. Можно даже написать свой собственный язык для представления (язык шаблонов, доменный язык (DSL)).

Но это возможно только в том случае, если вы создаете интерфейс, который позволяет использовать код приложения.

Итак, теперь вы должны удалить HTTP/HTML/CSS/JS из своего приложения в собственный адаптер. Этот адаптер может сформулировать общую команду, которая может быть передана любым приложениям через интерфейс в.

Приложение выполнит только выполнение команды и передает ответ через интерфейс . Итак, теперь у вас есть два домена: ваше приложение и веб-сайт.

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

У вас также есть «два» приложения рядом друг с другом. Они, наконец, связаны вместе (невидимыми в своем коде) с вашей базой данных, которая заботится о том, чтобы данные вашего сайта были в порядке. И для этого нужна база данных. Отделите данные от своего кода, чтобы вы могли изменить свой код с течением времени.

Также, если вы хотите перекодировать, нарисуйте границу между существующим кодом и новым кодом.

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

Так как в HTTP/PHP:

[Interface In] Plain Text HTTP request 
[Application] Free to go 
[Interface Out] Plain Text HTTP response 

Вы обычно нужны только некоторые функциональные возможности для анализа ввода и построить выход.

Кроме того, не используя жирные модели, вы получаете доступ к своим данным быстро и последовательно, например. если вам не нужно передавать вывод сразу (буферизованный, одноблочный), вы можете извлечь выгоду для потоковой передачи вывода на сервер.

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

  1. Если вы нарушите его, вы даже заметите?
  2. Если вы нарушите его, можете ли вы его исправить?

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

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

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

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


Смотрите так же:How to implement MVC style on my PHP/SQL/HTML/CSS code?­SO Q&A

0

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

7

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

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

Но классы имеют области ответственности, и, как указано выше, класс должен иметь дело с областью ответственности и ничем иным. Предоставление страницы не несет ответственности за любой из классов объектов, упомянутых выше. Это место, где входят классы, которые не представляют собой сущности вашей системы. Вам, вероятно, понадобится класс для страницы, класс для сеанса, класс для соединений с базой данных (хотя PHP вы уже там использовали PDO и некоторые другие модули DB, такие как mysqli).

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

class Page 
{ 
    private $user = NULL; 
    private $games = array(); 

    public function setUser (User $user) 
    { 
     $this -> user = $user; 
    } 

    public function getUser() 
    { 
     return ($this -> user); 
    } 

    public function addGame (Game $game) 
    { 
     $this -> games [] = $game; 
    } 

    public function getGames() 
    { 
     return ($this -> games); 
    } 

    public function generate() 
    { 
     $user = $this -> getUser(); 
     $games = $this -> getGames(); 

     $pageFile = '/path/to/a/php/script/representing/the/page/markup.php'; 
     require ($pageFile); 
    } 

    public function __construct (User $user, array $games) 
    { 
     $this -> setUser ($user); 
     foreach ($games as $game) 
     { 
      $this -> addGame ($game); 
     } 
    } 
} 

Фактический markup.php сценарий вероятно, будет выглядеть примерно так:

<html> 
    <head> 
     <title>Games page for <?php echo ($this -> user -> getName()); ?> 
    </head> 
    <body> 
    <p>Hello, <?php echo ($this -> user -> getName()), here are your games.</p> 
    <?php if (count ($this -> games)) { ?> 
    <ul> 
     <?php foreach ($this -> games as $game) { ?> 
     <li><?php echo ($game -> getName()); ?>: your best score is <?php echo ($game -> getHighScore ($this -> user)); ?></li> 
     <?php } ?> 
    </ul> 
    <?php } ?> 
    </body> 
</html> 

Как вы могли заметить, если вы используете этот подход то модули вашего приложения будут относиться к одной из трех категорий. Ваши бизнес-логические объекты, такие как User and Game, логики отображения, такие как файл markup.php, и третья группа, которая служит в качестве формы логики и координации клея, как класс Page.

Хотя в этом конкретном случае это специфично для вашего сайта, если бы вы обобщали этот подход, он попадал бы в шаблон проектирования, известный как MVC, который обозначает Model, View, Controller (ну, на самом деле, он ближе к шаблону так называемый PAC для презентации, абстракции, контроллера, но он почти всегда называется MVC в сообществе PHP по какой-то причине, поэтому мы просто скажем MVC на данный момент). Шаблон представляет собой обобщение класса проблем, которые программисты набирают на достаточно регулярной основе, что наличие набора готовых решений является удобным.

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

Поскольку MVC является шаблоном, уже существуют инструментальные средства, которые существуют для создания MVC (хотя они и не являются MVC;)) приложениями на PHP. Они называются фреймворками. Есть много вариантов, таких как Symfony, CodeIgnitor, Zend Framework и т. Д. Самой популярной структурой в наши дни является Zend, хотя я лично не поклонник этого. (Я бы сказал, что бета-версии Zend Framework 2 выглядят намного лучше, чем текущая версия фреймворка).

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

+1

+1 Отличный комментарий о MVC в PHP. Меня всегда раздражает то, что теперь становится общим термином, когда он не подходит для парадигмы PHP (конечно, не в среде с запросами). Я бы поставил под вопрос, является ли Zend наиболее популярной структурой: http://www.google.co.uk/trends?q = zend + framework% 2Csymfony – liquorvicar

+0

Я основывал этот комментарий относительно популярности на своем недавнем опыте в поисках лучшей работы. Казалось, что всем нужен опыт Зенда. :) – GordonM

+0

Достаточно честный. Я сомневаюсь, что кто-то мог сказать с уверенностью, что является окончательно самой популярной инфраструктурой PHP. С того места, где я сижу, Symfony2 кажется «одним», но тогда я с готовностью признаю, что я вообще не вникал в ZF2. – liquorvicar

0

Сообщение GordonM является хорошим, чтобы вы начали. Я бы, конечно же, рекомендовал использовать установленную структуру, чтобы вы начали - они делают много тяжелой работы для вас и помогут вам привыкнуть к ООП в PHP. Лично, если вы используете PHP5.3, я бы рекомендовал Symfomy2, но это личное предпочтение. Я бы также предложил вам получить копию the "Gang of Four" book. Это довольно существенное чтение, и хотя оно происходит в основном из фона, не зависящего от запроса, многие шаблоны по-прежнему актуальны в PHP.

Смежные вопросы