Установите ссылку на почту с темой, содержащей амперсанд (& amp;)

Основными двумя причинами против использования статических методов являются:

    код с использованием статических методов трудно проверить
  • код с использованием статических методов трудно расширить

Наличие вызова статического метода внутри какого-либо другого метода на самом деле хуже, чем импорт глобальной переменной. В PHP классы являются глобальными символами, поэтому каждый раз, когда вы вызываете статический метод, вы полагаетесь на глобальный символ (имя класса). Это случай, когда глобальное зло. У меня были проблемы с подобным подходом с некоторыми компонентами Zend Framework. Существуют классы, которые используют статические вызовы (фабрики) для создания объектов. Мне не удалось поставить другую фабрику в этот экземпляр, чтобы вернуть настроенный объект. Решение этой проблемы состоит в том, чтобы использовать только экземпляры и внедрять методы и применять синглтоны и т. Д. В начале программы.

Мишко Хевери , который работает в качестве Agile Coach at Google, имеет интересную теорию или, скорее, советует, что мы должны отделить время создания объекта от времени использования объекта. Таким образом, жизненный цикл программы разделен на две части. Первая часть (например, метод [6]), которая заботится обо всех объектных проводках в вашем приложении и о части, которая выполняет фактическую работу.

Итак, вместо наличия:

class HttpClient
{
    public function request()
    {
        return HttpResponse::build();
    }
}

Мы должны сделать следующее:

class HttpClient
{
    private $httpResponseFactory;

    public function __construct($httpResponseFactory)
    {
        $this->httpResponseFactory = $httpResponseFactory;
    }

    public function request()
    {
        return $this->httpResponseFactory->build();
    }
}

И затем, на странице индекса / главной страницы, мы сделали бы (это шаг проводки объекта или время для создания графика экземпляры, которые будут использоваться программой):

$httpResponseFactory = new HttpResponseFactory;
$httpClient          = new HttpClient($httpResponseFactory);
$httpResponse        = $httpClient->request();

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

Miško Hevery также проводит четкое различие между синглтонами и синглтонами (с или без капитала S). Разница очень проста. Синглтоны с нижним регистром «s» выполняются проводкой в ​​индексе / главной. Вы создаете экземпляр объекта класса, который не реализует шаблон Singleton, и следите за тем, чтобы вы передавали этот экземпляр только любому другому экземпляру, который ему нужен. С другой стороны, Синглтон с капиталом «S» является реализацией классического (анти) шаблона. В основном глобальная маскировка, которая мало использует в мире PHP. Я до сих пор не видел этого. Если вы хотите, чтобы одно соединение с БД использовалось всеми вашими классами, лучше сделать это следующим образом:

$db = new DbConnection;

$users    = new UserCollection($db);
$posts    = new PostCollection($db);
$comments = new CommentsCollection($db);

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

/**
 * An example of a test using PHPUnit. The point is to see how easy it is to
 * pass the UserCollection constructor an alternative implementation of
 * DbCollection.
 */
class UserCollection extends PHPUnit_Framework_TestCase
{
    public function testGetAllComments()
    {
        $mockedMethods = array('query');
        $dbMock = $this->getMock('DbConnection', $mockedMethods);
        $dbMock->expects($this->any())
               ->method('query')
               ->will($this->returnValue(array('John', 'George')));

        $userCollection = new UserCollection($dbMock);
        $allUsers       = $userCollection->getAll();

        $this->assertEquals(array('John', 'George'), $allUsers);
    }
}

Единственная ситуация, в которой я буду использовать (и я использовал их для имитации объекта прототипа JavaScript в PHP 5.3). Статические члены - это когда я знаю, что соответствующее поле будет иметь одно и то же значение cross-instance. В этот момент вы можете использовать статическое свойство и, возможно, пару статических методов getter / setter. В любом случае, не забудьте добавить возможность переопределения статического члена членом экземпляра. Например, Zend Framework использует статическое свойство, чтобы указать имя класса адаптера DB, используемого в экземплярах Zend_Db_Table. Прошло некоторое время с тех пор, как я использовал их, поэтому он больше не может быть релевантным, но вот как я его помню.

Статические методы, не относящиеся к статическим свойствам, должны быть функциями. PHP имеет функции, и мы должны их использовать.

23
задан MikeTheLiar 15 May 2014 в 15:22
поделиться