Быстрое прототипирование: от прототипа к коду, часть 2
Предыдущий пост демонстрирует проделанную большую работу по использованию чего-то, что когда-то было быстрым прототипом, и переносу этого прототипа в код. Если вы не следили за нами, мы сделали следующее:
- обсудили и построили прототип плагина,
- схематично один объектно-ориентированный подход может работать,
- и преобразовали наш прототип в реальный код.
На данный момент есть еще несколько вещей, которые мы можем сделать, чтобы улучшить наш код. А именно, мы можем ввести понятие пространств имен. Это продвигает организацию на шаг вперед и может принести дивиденды для более крупных проектов.
Итак, вот посмотрите, как это проявляется в нашем текущем проекте.
От прототипа к коду: пространства имен
Я подробно рассмотрел пространства имен в предыдущих постах. Если не читали, то рекомендую. Затем вернитесь и проверьте остальную часть поста.
Если вы решите пропустить статью, вот краткое определение пространства имен :
Пространства имен предназначены для решения двух проблем, с которыми сталкиваются авторы библиотек и приложений при создании повторно используемых элементов кода, таких как классы или функции…
И общая идея заключается в том, что мы организуем наши классы на основе логической связи, которую они имеют друг с другом.
Кроме того, мы также организуем файлы в каталогах, которые соответствуют пространству имен. Это не то, что нужно делать, но я считаю, что это помогает логически организовать классы на диске так, как они виртуально организованы в пространстве имен.
С учетом сказанного давайте организуем файлы.
Организация файлов
Вместо того, чтобы начинать с основного файла плагина, давайте сначала организуем наши файлы.
- Файлы Meta Box и Meta Box Display будут находиться в каталоге Display. Это совершенно произвольно, но поскольку эти файлы делают именно это, кажется, имеет смысл, что именно там они будут находиться.
- Мы также можем поместить файлы message-description.php и no-post-list.php в этот каталог, но давайте поместим их в подкаталог Views. Вы можете назвать это Templates или Partials или что-то подобное.
- Далее у нас есть классы, отвечающие за запросы к базе данных, и класс, отвечающий за координацию обмена сообщениями. Давайте поместим каждый из них в Utility. Конечно, есть и другие места, куда они могли бы пойти, но помните, что цель — продемонстрировать, как использовать пространства имен. Поэтому, если вы чувствуете себя так склонным, не стесняйтесь настраивать свои файлы по своему вкусу.
Если вы следовали тому, что мы сделали выше, то у вас должна быть структура каталогов, которая выглядит примерно так:
Один из способов организовать ваши файлы.
Теперь пришло время определить пространства имен для каждого из классов. Поскольку мы организовали их все в свои каталоги, будет легко указать пространство имен; однако важно понимать, что нам нужно будет использовать ключевое слово use, когда мы используем классы, расположенные в других пространствах имен.
Давайте пройдемся по каждому из наших файлов, начиная с файлов в Utility. Во-первых, мы начнем с Post Messenger :
<?php
/**
* Display content for the meta box when requested.
*
* @author Tom McFarlin
* @since 0.2.0
*/
namespace McFarlinTRPUtility;
use McFarlinTRPUtilityPost_Query;
/**
* Retrieves information from the class responsible for querying the database and
* renders it in the context of our meta box when called via the Meta Box Display.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Post_Messenger {
// Snip for brevity.
}
Вы заметите, что пространство имен файла появляется в заголовке вместе с объявлением об использовании созданного нами класса Post Query . Я добавил имя класса в конец пространства имен, поэтому мне не нужно использовать его во всей кодовой базе.
Обратите внимание, что конструктор теперь выглядит так :
<?php
/**
* Instantiates the class by setting a reference to the query.
*
* @param string $plugin_dir The path to the root of the plugin directory.
*/
public function __construct( $plugin_dir) {
$this->query = new Post_Query();
$this->plugin_dir = trailingslashit( $plugin_dir );
}
Я добавил аргумент $plugin_dir, потому что нам нужно использовать его для правильного отображения результатов запроса. И поскольку теперь они находятся в другой области приложения, функции выглядят так :
<?php
/**
* Displays the description of the content of the meta box.
*
* @access private
*/
private function get_post_message() {
include_once $this->plugin_dir. 'Display/Views/post-list.php';
}
/**
* Displays the description of the content of the meta box.
*
* @access private
*/
private function get_description() {
include_once $this->plugin_dir. 'Display/Views/message-description.php';
}
/**
* Displays a message of there are no recent posts.
*
* @access private
*/
private function get_no_posts_message() {
include_once $this->plugin_dir. 'Display/Views/no-post-list.php';
}
Далее, давайте посмотрим на класс Post Query . Ничего особенного в этом классе не изменилось, за исключением того, что мы дали ему пространство имен, и мы также обновили запрос только для извлечения трех сообщений (согласно этому комментарию ).
<?php
namespace McFarlinTRPUtility;
/**
* Queries the database for three most recent posts. Returns the query to the
* caller so that it can be interrogates for posts or not.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Post_Query {
// Snip for brevity.
private function get_posts() {
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 3,
'orderby' => 'date',
'order' => 'desc',
);
$this->query = new WP_Query( $args );
return $this->query;
}
}
Обратите внимание, что в коде я также поставил перед WP_Query косую черту, потому что это часть глобального пространства имен.
Давайте перейдем в каталог Display и посмотрим на класс Meta Box. Ему также было присвоено пространство имен, а также используется полное имя класса Meta Box Display, которое мы сейчас рассмотрим.
<?php
namespace McFarlinTRPDisplay;
use McFarlinTRPDisplayMeta_Box_Display;
/**
* Registers the Meta Box with WordPress. Defines the ID, title, display function,
* and the post type on which it will live.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Meta_Box {
/**
* A reference to the class that will display the contents in the meta box.
*
* @access private
* @var Meta_Box_Display
*/
private $meta_box_display;
/**
* Instantiates the class by setting its property equal to a reference to its display.
*
* @param string $plugin_dir A reference to the root of the plugin's directory.
*/
public function __construct( $plugin_dir) {
$this->meta_box_display = new Meta_Box_Display( $plugin_dir );
}
// Snip for brevity.
}
Обратите внимание, что этот конструктор также принимает каталог плагинов в качестве аргумента и также передает его в класс отображения Meta Box . Это делается для того, чтобы функции, отвечающие за отображение сообщений, можно было правильно найти в их расположении в каталоге Views .
Наконец, давайте рассмотрим класс отображения Meta Box . Это простой класс, который включает в себя пространство имен и ссылается на Post Messenger, который мы рассмотрели выше.
<?php
/**
* Defines the display for the meta box.
*
* @author Tom McFarlin
* @since 0.2.0
*/
namespace McFarlinTRPDisplay;
use McFarlinTRPUtilityPost_Messenger;
/**
* Defines the display for the meta box that will render the content in the
* context of its meta box.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Meta_Box_Display {
/**
* A reference to the class that will display the contents in the meta box.
*
* @access private
* @var Post_Messenger
*/
private $messenger;
/**
* Instantiates the object by setting a property equal to that of the class
* responsible for rendering the messages from the post query.
*
* @param string $plugin_dir A reference to the root of the plugin's directory.
*/
public function __construct( $plugin_dir) {
$this->messenger = new Post_Messenger( $plugin_dir );
}
/**
* If there are posts to display, renders them in the metabox. Otherwise, displays
* a note that there are no posts to display.
*/
public function display() {
$this->messenger->get_message();
}
}
На данный момент мы прошли полный круг через плагин. За одним исключением: файл начальной загрузки. Мы добавили к нему пространство имен и должны обновить способ его создания :
<?php
namespace McFarlinTRP;
use McFarlinTRPDisplayMeta_Box;
include 'Display/class-meta-box.php';
include 'Display/class-meta-box-display.php';
include 'Utility/class-post-messenger.php';
include 'Utility/class-post-query.php';
add_action( 'add_meta_boxes', __NAMESPACE__. 'trp_start' );
/**
* Starts the plugin.
*/
function trp_start() {
$meta_box = new Meta_Box( dirname( __FILE__) );
$meta_box->init();
}
А именно, у нас есть:
- определил пространство имен,
- ссылаться на расположение класса Meta Box ,
- обновлены пути, чтобы указать, где найти файлы (что в конечном итоге можно сделать с помощью автозагрузчика),
- и обновил вызов add_action .
Вот что касается вызова действия добавления: поскольку WordPress необходимо найти эту функцию, а функция находится в пространстве имен, необходимо определить полное имя функции, чтобы WordPress мог ее вызвать. Отсюда и необходимость NAMESPACE в имени функции.
Теперь мы организованы (за одним исключением)
Как вы понимаете, пространства имен и каталоги, которые им соответствуют, делают проект более организованным. За ним легче следить, легче понять, куда идут дела (как для существующих, так и для новых файлов). И это дает меньше ощущения, просто собирая много файлов в одном месте.
Даже если класс немного монолитный, его все же можно организовать таким образом, чтобы упростить обслуживание.
С учетом сказанного, есть еще кое-что, что я бы изменил в этом плагине: передача каталога плагина таким образом не помогает с низкой связностью, и это более тесно связывает классы вместе, потому что файл начальной загрузки должен передавать значение в один класс передает его другому классу, который использует его для загрузки файлов и так далее.
Так есть ли способы исправить это? Абсолютно. И, возможно, мы рассмотрим это в последнем посте.
До тех пор помните, что самая последняя версия плагина доступна в основной ветке с тегом 0.3.0 на GitHub.
Сообщения серии
- Быстрое прототипирование с помощью WordPress: от концепции до плагина
- Быстрое прототипирование с помощью WordPress: анализ концепции
- Быстрое прототипирование: от прототипа к коду, часть 1
- Быстрое прототипирование: от прототипа к коду, часть 2
- Быстрое прототипирование: знакомство с автозагрузкой