Wednesday, August 24, 2011

Крик души, мнение о Zend Framework.

Меня тошнит от Zend Framework. Вот получили задание, переписать существующий сайт на Zend Framework. Задача не сложная, текущий код "портяночный", неправильный, там нет разделения логики от вида и т.д. Но вот я смотрю его, он простой, легко читаемый, прозрачный. Видно что его писал неглупый, возможно неопытный человек. Но в нем присутствует стройность. Более того, я считаю, что код вполне соответствует задаче.

И вот мы начинаем его переписывать. В своей жизни я создал порядка 5ти сайтов на ZF. Начинал еще с версии 0.6, потом 0.9, далее не помню. Тем не менее считаю что сам фреймворк не знаю абсолютно.

И вот как я представлю в какое умно все это превратится. И ведь даже выразить это невозможно.

Я уважаю Zend Framework как набор компонент, они удобны, хороши, просты, с ними мало проблем. И я удивляюсь, насколько убого создано то, что является MVC Framework'ом на основе этих компонент.

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

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

Так сука и хочется спросить. Если вы такие умные хуле вы на пхп пишете?

Казалось бы нытье? Наверное да. Но вот открываю я quickstart zf. А конкретно http://framework.zend.com/manual/en/learning.quickstart.create-model.html вот этот раздел.

Нас в мануале учат что для работы с базой мы будем использовать DataMapper, который нам вернет модели, которые мы assign в темлейте и будем там использовать. Т.е. получается.

1. наследни DbTable
2. Кастомный DataMapper
3. Кастомная модель??? Структура с кучей геттеров.

Что я вижу?

1. Классы не требуются, т.е. это идет на уровне соглашения. Т.е. в мануале нам говорят как писать, но это не требуется, более того применения не будет.
2. Весь такой клевый гибкий ооп зенд, в своем мануале нам показывает как в DataMapper ОБЪЕКТ!! превращают в сырой массив (словарь,хэш) который передается дальше! Вообще в этом так то плохого ничего нет. Но как это делается!!!
 
<?php

foreach ($resultSet as $row) {
$entry = new Application_Model_Guestbook();
$entry->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created);
$entries[] = $entry;

Что меня тут убивает. Вообще row я как понимаю инстанс Zend_Db_Tale_Row у котого есть метод toArray()

Application_Model_GuestBook в конструкторе может принимать массив значений.

т.е. написать $entries[] = new Application_Model_Guestbook( $row->toArray() ) ; Видимо религия не позволяет.

Ну конечно они возможно хотели показать как должны идти преобразования данных в том случае когда хранение данных отличается от доменной модели. Но ведь нет таких объяснений. И пример крайне неудачный. Даже далеко не у самых глупых программистов должен возникнуть простой вопрос. А на хрена?

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

Ну ладно так то мелочь и можно забыть, таки мануал и я 100% уверен что люди так не пишут. НО!!!

http://habrahabr.ru/blogs/zend_framework/123285/

Финиш. Все. Приплыли. Люди так пишут! Правда они умные, они блять парсят sql. И генерят код чтобы не опечататься.

У них ведь даже базовые классы появились :(

Бли до какой степени все убого, даже углубляться не хочется :( Как я люблю yii framework.

Ну вот получите
 

class I_Love_Zend_Naming_Huh_Model
{
protected $_properties = array();

protected $_data = array();

public function __construct(array $options = null )
{
if ($options !== null )
$this->fromArray($options);
}

public function __set($name, $value)
{
$this->__checkProperty($name);//check if property exists

$setterMethod = 'set'.$name;//buid setterName

if (method_exists($this, $setterMethod))// if setter exists
return $this->$setterMethod($value);//call it

$this->_data[$name] = $value;//no setter, remember data
return $this;
}

public function __get($name)
{
$getterMethod = 'get'.$name;

if (method_exists($this, $getterMethod))
return $this->$getterMethod();

if (key_exists($name, $this->_data))
return $this->_data[$name];

return null;
}

public function toArray()
{
return $this->_data;
}

public function fromArray(array $options)
{
foreach ($options as $key => $value)
$this->$key = $value;

return $this;
}

private function __checkProperty($name)
{
if (!in_array($name, $this->_properties))
throw new Exception('Undefined property ' . $name );
}

}


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

class Super_Puper_Model extends I_Love_Zend_Naming_Huh_Model
{
protected $_properties = array('id', 'first_name', 'last_name');
}



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

Да на те

 

class Super_Puper_Model extends I_Love_Zend_Naming_Huh_Model
{
protected $_properties = array('id', 'first_name', 'last_name');

public function getId()
{
return $this->first_name . $this->last_name;
}
}

Все, можете не париться, ваш код как вызывал $entity->id, так и вызывает, а поведение поменялось.

А мне в ответ: "Ага! У тебя волшебные методы, все пиздец приплыли тормоза!" А в мануале их бля нет....

Я еще про могучие плагины не рассказал, а инверсия зависимостей ага, работает. Хрен найдешь что вызывается на самом деле. Код нельзя прочитать! (Ну конечно можно, особенно с опытом) Но вот на yii я написал 3 сайта, и считаю что его уже знаю. А на zf 5 и считаю что его не знаю :(

Я не спорю что он крутой. Но такой некрасиый, такой нестройный. Такой не логичный. В yii framework достаточно понять смысл CComponent класс вроде из (40-100) строк, и дальше уже все понятно. А тут :(.

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

4 comments:

Станислав said...

добавлю:
- они почему то не любят встроенные типы. Например, зачем нужен Zend_Config, когда есть ассоциативный массив?
- они создавать классы на каждый чих. Например, зачем нужно извращение с созданием своего formatter'а для логов, если можно тупо отнаследоваться от Zend_Log и перекрыть один метод. Или, например, Zend_Acl_Role, состоящий из одного свойства
- они любят конфигурации, вместо наследования. Везде private. Чтобы перекрыть 2 строчки реализации, приходится заниматься копипастой.
- DI на основе registry это уже даже не смешно. Ленивой инициализации нет, защиты от подмены нет, контроля нет.

cd said...

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

Форматер - из той же оперы.

private да, злоупотребляют.

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

Вот кстати пример хороший получается.

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

Т.е. просто идет некая не стройность. Кривость.

Станислав said...

ini и база, это источник конфига, а не сам конфиг. Ассоциативный массив это хороший dto, который удобно таскать между библиотеками, потому что он встроенный. Если бы вместо Zend_Config был какой-нибудь Zend_Object я бы это хоть как-то понял. Но нафига делать объект с уникальным интерфейсом?

cd said...

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

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

Сырые массивы в качестве конфигов проигрывают Zend_Config и его наследникам, хотя бы потом что в проекте придется реализовать чтение хотя бы из формата ини файла, и его преобразование в массив.

В конце концов, если вам нравится хранить конфиги в виде массива, то достаточно легко делается такая вещь как.

$config = new Zend_Config_Ini('path');
$myConfig = $config->toArray();

И все.

Нет у меня нет претензий к Zend_Config. Как компонент он очень неплох, и вполне логично им самим его использовать.

 
Каталог сайтов, Добавить сайт