All streams
Search
Write a publication
Pull to refresh
159
1.7
Кирилл Мокевнин @toxicmt

Программист & Предприниматель

Send message
> Сам не люблю, когда кто-то у кого-то что-то мягко говоря заимствует.
Мало того что угнал идею (http://2009.russianinternetweek.ru/news/210) так еще и прикидываешься овечкой невинной. Лови минусы большие и маленькие.

p.s. Проект билетерра жив и скоро будет запущен.
Если я правильно понял вопрос, то это делается на dev сервере. База для разработки у нас одна на всех и тесты выполняются в ней же. При текущем количестве тестов (с покрытием выполняются час) это начинает мешать и мы планируем вынести их на отдельный тестовый сервер (виртуальный).
Оффтоп: нафигачил первую статью на хабре, toxicmt.habrahabr.ru/blog/72716/ предлагаю обсудить.)
1. Забейте на мой ланчер и напишите свой phpnit.xml
2. Да я видел все их ассерты и пользуюсь ими.

Вообще это все частности. Топик не является туториалом на тему как вообще писать тесты, об этом и так много статей в том числе и та что Вы указали. Центральная тема топика создание фикстур и взаимодействие с базой.
Черт побери, я это сделал ))
Вот кстати в зенде тоже хотят такой функционал )
framework.zend.com/issues/browse/ZF-1156
Имелось ввиду что это расширение для ZF, и оно используется во всех проектах. В своем коде Вы не делаете ничего нового и не пишите ничего лишнего, все это происходит за кулисами.

А переписать пришлось findParentRow и еще некоторые связанные с ним методы. Все сводится к простому наследованию от нужных классов My_Table extends Ext_Db_Table_Abstract, My_Row extends Ext_Db_Table_Row_Abstract
На самом деле все еще сложнее), просто мы обсуждали не это и я специально не заострял внимание на деталях.
В данном случае нет правила. Делают как удобно. Я выше писал про то что разбавляя Row Data Gateway бизнес логикой мы получаем AR. И это проще чем писать еще один класс на каждую таблицу к уже существующим двум классам Table и Row. При этом если Вам хочется вынести логику выше, потому что Вы считаете так правильнее, то почему бы и нет. Ведь тогда мы придем к преобразователю данных, разделив взаимодействие c базой и логику на две паралелльные иерархии классов, но за это придется платить сложностью.
Еще забыл про использование хелперов, но это тоже не тру вей. Разделение логики и данных уводит нас от ООП и в итоге мы получим кучу функций в виде хелперов и кучу объектов представляющих собой просто контейнеры разнородных данных.
Тут несколько раз проскакивала тема про выборку зависимых объектов одним запросом, с использованием джойнов. Отвечу сразу всем).

Предположим что мы используем ZF table, кастомизируем его row и определяем там бизнес логику. Когда мы в какой то row делаем выборку этой сущности и джойном тянем другую сущность, то мы фактически в один класс row загоняем данные которые ей не принадлежат. В zf не реализовано расфасовывание объектов по своим row, отсюда возникает куча проблем.
Например мы достали статьи и к ним приосединили юзверей. При выводе статей нам нужно выводить создателей этих статей и рядом показывать значек статуса пользователя (онлайн/офлайн).
В row_user у нас был метод isOnline() который содержал какую то простую логику. А в row_article этого метода нет. Что нам остается делать? Либо писать эту проверку прямо в шаблоне (зло), либо дублиовать этот метод в row_article (зло), либо реализовывать разделение объектов (не очень просто) и самый простой и доступный способ это тянуть данные без использования джойнов через findParentRow().

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

Так вот, потом во вьюхе делается следующее.
foreach…
<?= $article->findParentRow('User')->name ?> //Тут планируется шоткат.

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

Это очень сильно упрощает код и его становится гораздо меньше. Плюс не нужно писать кучу лишних методов и тестировать их, т.к. этот функционал уже протестирован.
Вы знаете чем отличается AR от Row Gateway?
AR = Row Gateway + бизнес логика.

Фаулер:
«Иногда шлюз записи данных трудно отличить от активной записи(Active Record). В этом случае следует обратить внимание на наличие какой-либо логики домена; если она есть, значит, это активная запись. Реализация шлюза записи данных должна включать в себя только логику доступа к базе данных и никакой логики домена.»

Кастомизацией роу в зенде можно добиться любого результата.

По поводу выборок зависимых объектов, мы поступили следующим образом (кстати, в трекере зенда есть тикет на эту фичу).
Делается выборка, например, статей: $articles = $table->findLastArticles();
Не минусую. Вы сказали что зенд это не фреймворк, я с этим не согласился, все остальное это совершенно о другом.
> но это не фреймворк, слишком много нужно доводить вручную.
0_o
Фреймворк != полная автоматизация.
Очень странное у Вас представление о транзакциях.

Все Ваши примеры решаются тем инструментом который для этого предназначен — это условные операторы.
Выдержка из книги «Совершенный код»:

8 ) Кодирование путём исключения
Этот антипаттерн представляет собой реализацию нормальной логики работы программы с помощью механизма исключений. Например, рекурсивный поиск по дереву может в качестве результата поиска кидать исключение. Такая реализация на первый взгляд может выглядеть заманчиво и удобно, но не более чем на первый взгляд.
Исключения должны использоваться с одной единственной целью — проинформировать систему об ошибке. Использование исключений как инструмента для управления логикой программы вносит неоднозначность. Глядя на конструкцию try-throw-catch / try-raise-except, программисту совершенно не очевидно, для чего именно эта конструкция используется. Кроме того, управление логикой через исключения и система оповещения об ошибках, построенная на исключениях, могут попросту мешать друг другу, поскольку они построены на одном механизме.
Для обработки ошибок используйте только исключения, а исключения — только для обработки ошибок.
PHP язык с динамической типизацией, и во все функции всех библиотек можно передать пустое значение (не считаем интерфейсы и массивы). Представтье если они все начнут выкидывать исключения по этому поводу.
Вы предлагаете контролировать typeId внутри метода доступа к базе? А если я добавлю новый typeId? Кто мне напомнит что нужно залезть во все методы где стоит такая валидация и починить это?

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

Если мы говорим про вставку данных, то целостность базы должна поддерживаться на уровне базы и единственный способ сделать это, использовать внешние ключи. Без них любая база превратиться в помойку, даже при самых страшных проверках.
Черт я говорил про удаление), а в случае выборки метод опять же должен вернуть пустой набор, если он возвращает наборы, либо null, если он возвращает row.
А уже в контроллере можно делать так if ($row)

В выборках наличие непустого id контролируется, например, через роутинг -> news_id => '\d+'
Нет). Тем о чем Вы написали занимается валидация, которая конечно может быть частью модели, но никак не частью метода удаляющего данные. А в данном случае метод должен вернуть 0, он ведь не затронул ни одну строку?

Information

Rating
1,402-nd
Location
Miami Beach, Florida, США
Date of birth
Registered
Activity

Specialization

Fullstack Developer, Chief Technology Officer (CTO)
Lead