Преобразование процедурного PHP в объектно-ориентированный PHP

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

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

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

2) Поскольку мне нужно будет включить довольно много разных классов, использовать ли класс "Loader" для загрузки их всех с помощью spl_autoload_register или просто использовать spl_autoload_register в файлах программы для моего приложения?

Редактировать: Таким образом, мой автозагрузчик будет классом, экземпляр которого я затем создам для запуска автозагрузки, или просто файлом php с функцией и регистром spl_autoload_register, который я бы включил, чтобы избежать повторения одного и того же кода в нескольких файлы?

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

Изменить: Таким образом, даже если один класс может создавать экземпляр объекта типа Player, и класс Player не включен напрямую в этот класс, он все равно будет работать, поскольку класс контроллера делает включить класс Player?

4) Есть несколько случаев, когда мне нужно работать над объектами, которые я создаю. Я задаюсь вопросом, как мне это сделать. Например, в моем классе Player мне иногда нужно отправить что-то от одного Player к другому Player. Итак, должен ли я реализовать статический метод в классе Player, который принимает двух игроков в качестве параметров и выполняет передачу, или я делаю что-то еще?

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

5) У меня есть много методов, которые на самом деле не принадлежат ни одному экземпляру класса и не подходят в качестве статических методов. Должны ли они быть объявлены в своем собственном классе как статические методы, такие как Common или аналогичные? Что делается на практике в этой ситуации?

Редактировать. Будут ли эти методы принадлежать конкретному файлу приложения, для которого они используются, или, возможно, сохранены в собственном файле «functions.php»?

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

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

Спасибо за любую помощь и понимание, которое вы можете предоставить.


person Steffan Long    schedule 14.03.2013    source источник


Ответы (3)


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

Как правило, у вас также будут классы, представляющие коллекции объектов, например. класс «Игроки», который можно использовать для извлечения одного игрока из коллекции всех игроков:

$players = new Players();
$john = $players->findByName("john");

2) Поскольку у меня будет довольно много разных классов для включения, я использую класс «Loader», чтобы загрузить их все с помощью spl_autoload_register, или я просто использую spl_autoload_register в программных файлах для моего приложения?

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

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

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

4) Есть несколько случаев, когда мне нужно будет работать над объектами, которые я создаю. Я задаюсь вопросом, как мне это сделать. Например, в моем классе Player мне иногда нужно отправить что-то от одного Player к другому Player. Итак, должен ли я реализовать статический метод в классе Player, который принимает двух игроков в качестве параметров и выполняет передачу, или я делаю что-то еще?

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

class Player {
    public function transferMoney(Player $recipient, $amount) { ... }
}

$tom = new Player("tom");
$marc = new Player("marc");

$tom->transferMoney($marc, 500);

5) У меня есть много методов, которые на самом деле не принадлежат ни одному экземпляру класса и не подходят как статические методы. Должны ли они быть объявлены в своем собственном классе как статические методы, такие как Common или аналогичные? Что делается на практике в этой ситуации?

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

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

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

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

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

person Niko    schedule 14.03.2013
comment
Спасибо за ваш пост! Ваши № 1 и № 4 действительно помогли прояснить ситуацию! Коллекция игроков определенно имеет смысл для моего приложения, и использование методов экземпляра для передачи предметов также имеет смысл. Я прислушаюсь ко всем советам и буду держаться подальше от статических методов. - person Steffan Long; 15.03.2013

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

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

2) Поскольку у меня будет довольно много разных классов для включения, я использую класс «Loader», чтобы загрузить их все с помощью spl_autoload_register, или я просто использую spl_autoload_register в программных файлах для моего приложения?

Не зная, что вы подразумеваете под «программными файлами для моего приложения», я говорю «да». Используйте автозагрузчик, потому что он просто работает, и вам не нужно беспокоиться о выполнении require_*.

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

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

Обычно вы хотите запустить автозагрузчик на этапе начальной загрузки приложения. .

4) Есть несколько случаев, когда мне нужно будет работать над объектами, которые я создаю. Я задаюсь вопросом, как мне это сделать. Например, в моем классе Player мне иногда нужно отправить что-то от одного Player к другому Player. Итак, должен ли я реализовать статический метод в классе Player, который принимает двух игроков в качестве параметров и выполняет передачу, или я делаю что-то еще?

Избегайте использования статических методов в ООП PHP. Он почти никогда не нужен. Вы могли бы подумать о другом классе, который действует как пул игроков, который заботится об «отправке данных» от одного игрока к другому.

Таким образом, не имеет значения, где находится файл с классом, пока это происходит до попытки его создания.

5) У меня есть много методов, которые на самом деле не принадлежат ни одному экземпляру класса и не подходят как статические методы. Должны ли они быть объявлены в своем собственном классе как статические методы, такие как Common или аналогичные? Что делается на практике в этой ситуации?

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

Но это трудно сказать, просто прочитав ваш вопрос. Может быть, вы можете привести пример в комментарии?

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

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

Независимо от того, имеет ли одно приложение одно пространство имен (имя приложения?) или каждый класс принадлежит своему собственному пространству имен?

Я часто подписываюсь на PSR-0, когда речь идет о пространствах имен.

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

Просто помните о принципе единой ответственности и в целом SOLID.

Также я настоятельно рекомендую просмотреть это и продолжать смотреть, пока не поймете.

person PeeHaa    schedule 14.03.2013
comment
Спасибо за ваш отличный пост. Я внес некоторые правки, уточняющие мои вопросы. Можешь взглянуть? :) - person Steffan Long; 15.03.2013
comment
Это простой метод, который я использую в настоящее время. Нет особого смысла создавать класс только для одного метода, так где же это? public function getCurrentTime() { return round(microtime(true)*1000); } - person Steffan Long; 15.03.2013
comment
Я не думаю, что создал бы метод для чего-то такого простого, как мне кажется. - person PeeHaa; 15.03.2013

  1. PlayerCollection будет допустимым классом. Конечно, его целью является одна коллекция из нескольких игроков.

  2. Используйте spl_autoload_register, и точка. Лучше всего следовать стандарту PSR-0. и используйте любой существующий автозагрузчик, совместимый с PSR-0 (например, Symfony Loader)

  3. Это сработает. Но поскольку вы используете автозагрузчик (см. 2.), вам вообще не нужно заботиться о включении классов.

  4. Отправка сообщения от игрока 1 игроку 2 легко преобразуется в вызов метода игрока 2 в игроке 1. Однако «отправка вещей» и «работа с объектами» могут означать многое, поэтому ответ таков: это зависит. Но в целом рекомендуется избегать статических методов.

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

  6. «у одного приложения есть одно пространство имен (имя приложения?) или каждый класс принадлежит своему собственному пространству имен?» - ответ находится между ними. Пространства имен полезны для группировки вещей, которые работают вместе, и они полезны независимо от того, кто будет использовать или видеть код.

  7. Первое правило объектно-ориентированного проектирования: один класс, одна ответственность.

person Fabian Schmengler    schedule 14.03.2013
comment
Спасибо за ваш пост. Я внес некоторые изменения в свой вопрос, чтобы отразить ваши ответы. Ваш № 1 действительно прояснил для меня вещи. Я никогда не думал, что коллекция игроков будет очень полезна, но вполне логично, что это можно сделать, если у вас есть в этом особая потребность. - person Steffan Long; 15.03.2013