Как стать автором
Обновить

Комментарии 56

меГафрейворк!!! в первом попавшемся class`е Timestamp который extends Date
protected static function getFormat() { return 'Y-m-d H:i:s'; }
Убиться, простите, веником! Зато у нас ООП!
Ну, ребята не зря значит ведущего разраба ищут :)
Извините, что отвечаю не на тот коммент, но внизу мое сообщение не заметят.
mc_dir, в чем претензия к данному коду? Да static, да protected, и да — описывает формат. Если внимательно почитать код, то можно понять почему сделано именно так. Мы не принуждает использовать наш фреймворк. Кстати, мы его не продаем. ;)
Если он вам не по душе, просто не обращайте на него внимания. Если хотите улучшить — код открыт, патчи приветствуются. )

vaevictus Мы ищем ведущего разработчика не для того, чтобы переписать класс Timestamp, у нас и без этого хватает работы ;)

OnPHP — это фреймворк, который используется для вполне утилитарных задач. Вряд ли кто-то будет писать туда код «чтобы было». В последнее время код пишется под конкретную задачу. То же самое касается правок — если старый код никто не исправляет, значит он работает.
Претензий никаких. Скорее недоумение. Почему например не константа класса, свойство класса или параметр — почему именно метод который ни че не делает, зато " Да static, да protected, и да — описывает формат." — возвращает строчку?
Раскройте уже сакральный секрет, почему именно так? Остальных «фичь» фрейворка и без меня уже тут описали.
не константа класса

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

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

А это противоречит логике.

Данный метод нужен для создания даты — github.com/onPHP/onphp-framework/blob/master/core/Base/Date.class.php#L75
Для ее импорта из примитивов или базы — github.com/onPHP/onphp-framework/blob/master/core/Base/Date.class.php#L302
И для toString() по-умолчанию — github.com/onPHP/onphp-framework/blob/master/core/Base/Date.class.php#L256

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

фичь

Это от слова «дичь»? )
Т.е. Данный метод нужен для создания даты — без него никак?
И И И… Мот таки не создавать protected static function getFormat()? «Да, возможно, реализацию можно сделать лучше» — так как можно ее сделать лучше? Предложите свой вариант, если мои не устроили.

А то ж без глубокого понимания LSB мозг можно поломать как это все работает (
Слово «фичь» взята в скобки — ели не понятно его значение, считайте его дичью — так проще ж. Проще сказать, что работает, чем сделать качественно, производительно, понятно и красиво.

«Мало у кого хватает мудрости предпочесть обманчивой похвале благотворную критику.» Ларошфуко
«меГафрейворк!!! в первом попавшемся class`е Timestamp который extends Date
protected static function getFormat() { return 'Y-m-d H:i:s'; }
Убиться, простите, веником! Зато у нас ООП!»
О да. Настоящая благотворная критика, как это никто ее не распознал. Восклицательных знаков больше чем предложений. И не важно критику что статья о другом, главное заявить о себе погромче (!).
Предложите свой вариант, если мои не устроили.

А что вы предложили? Перенести строковую константу из метода в свойство? Шило на мыло, не находите?
Предложите красивое решение с вашей точки зрения.
Для чего?
У нас нет открытого issue по поводу «некрасивости» Timestamp. Как только его заведет кто-нибудь из пользователей фреймворка, мы обязательно предложим решение.
Ребят, Вы просто говорите на разных языках. С точки зрения кододрочерства, да, нужно придумывать красивые решения. С точки зрения практичности — в профайлере кусок кода не выбивается, свою работу делает — да и фиг с ним.

dovg, научитесь отвечать в стиле «Да, Вы правы, но в данный момент у нас есть более приоритетные задачи. Но мы будем очень рады, если Вы окажите нам помощь, и предложите лучшее решение.»
Если бы Ваш метод выглядел как
protected static function getFormat() { return _DATE_FORMAT; }
Вопросов не было бы. Сейчас же, чтобы поменять формат даты, мне прийдётся либо менять код ядра (хоть и не значительно), либо плодить наследника из-за одной строчки.

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

Нужный формат при выводе можно получить используя toFormatString($format); — github.com/onPHP/onphp-framework/blob/master/core/Base/Date.class.php#L261
И всё равно, делать строковую константу в коде не хорошо :).

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

if ($firstFormat) return _DATE_FORMAT; else return _SECOND_DATE_FORMAT;
(название констант, конечно же, можно сделать куда более значимыми)
Сейчас же, такой код будет выглядеть в лучшем случае, как то так:
if ($firstFormat) return parent::getFormat(); else return "another format";
Что, согласитесь, не совсем хорошо.

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

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

Спасибо. )

По теме — ваша идея понятна. Обсудим в рассылке.
Фреймворк не должен писаться под конкретную задачу. Фреймворк — это набор общих правил и инструментов. А под конкретную задачу вы добавляете свои изменения/модули.

В противном случае, Вы можете внести изменения в фреймворк, которые сделают его не применимым для некого рода других «конкретных» задач.

И да, код
for ($i=1, $b = $a; $i<10; $a+=$b, $i++);
тоже вполне рабочий. Хотите сказать он имеет право на существование?
Фреймворк не должен писаться под конкретную задачу.

Вы неправильно меня поняли. Фраза начиналась со слов «в последнее время». Это важно.

В противном случае, Вы можете внести изменения в фреймворк, которые сделают его не применимым для некого рода других «конкретных» задач.

Поэтому у нашей компании есть свой форк, который слегка отличается от master. github.com/WapStart/onphp-framework/
Код общего назначения мы сливаем в него. Иногда он попадает в мастер, а иногда сообщество его не принимает. По похожим причинам, кстати :)
Не переживайте по поводу отдельных комментариев — с отдельными товарищами и их подходу к проектированию я уже успел столкнуться в комментариях к другой статье.

А в общем идея Ваша мне понравилась — что-то полезное для себя извлек.

Вот только меня смущает этот момент:
SequentialCache — представьте, что у вас есть хранилище, которое иногда падает или просто недоступно. Например, оно может иногда выводиться на обслуживание, перезапускаться и т.д. При этом, данные приложение хочет получать всегда. Для покрытия этой ситуации можно использовать SequentialCache, примерно с таким конфигом:

Вы представляете сколько будет ожидать приложение подключения к упавшему серверу кеширования прежде чем отвалится по timeout-у? Это только увеличит время получения данных а не уменьшит его.
Спасибо.

В представляете сколько будет ожидать приложение подключения к упавшему серверу кеширования
прежде чем отвалится по timeout-у? Это только увеличит время получения данных а не уменьшит его.

У нас мемкеши — это не только кеширующая подсистема, но и система хранения.
Т.е. если данных нет в кеше, то приложение считает, что их нет вообще.

Приложение будет ждать столько времени, сколько мы указали в конструкторе PeclMemcache. Я вон тут писал, что сейчас можно использовать float в качестве timeout
Если я не ошибаюсь в спецификации протокола TCP минимальное значение UTO равно одной секунде. Так что тут еще под вопросом как это было реализовано в PeclMemcache.
Не обязательно дожидаться ошибки нижележащего протокола для генерации ошибки по тайм-ауту.
Обязательно. Пока TCP сессия не закроется — а она идентифицируется четверкой <client_ip, client_port, server_ip, server_port> — соединение не будет установленно. У нас же не одно соединение устанавливается.
Вы его недооцениваете =)
Между прочим, единственный формат даты, позволяющий корректно сравнивать даты в строковом виде (ну, единственный с точностью до украшательств).

Не знаю, зачем это могло понадобиться, но, вполне возможно, такая архитектура взята не с потолка.
как думаете, что будет быстрее сравниваться
1352731759 > 1352731760
или
'2012-11-12 18:50:21' < '2012-11-12 18:50:60'
?
Придумать можно много чего — в языке декораторов ( не следует путать с одноимённым шаблоном проектирования) нет, че ж их тоже можно придумать.
Не всегда есть «быстрее» означает «лучше».
Например, в некоторых хранилищах целочисленных ключей может вообще не быть.
Например, их нет в файловой системе (понимаю, для кэша это очень странный выбор, но разве Timestamp используется только при кэшировании?)
А что вас смущает в данном коде?
mc_dir озвучьте свою позицию, пожалуйста
Меня вот лично смущает несколько моментов:

1. Хардкод. Зачем нужен метод всегда возвращающий одну строку?
2. В чем разница между вот такими вызовами: date('DEFAULT_FORMAT') vs Timestamp::now()?
3. Cтатические вызовы увеличивают связанность кода и невозможность его повторного использования.
date('DEFAULT_FORMAT') выглядит ужасно.

Timestamp::now() выглядит понятно и самодокументируемо.
facepalm)

Вы хоть смотрели что отдает Timestamp::now()?
Как вообще надо думать, чтобы ожидать значение этого вызова как дату в определенном формате?

Ваш подход скорее функциональный, а мы же придерживаемся ООП со всеми плющками (переопределение, наследование ...), кстати onPHP один из не многих фреймворков, где с самого начала идет жесткая привязка к ООП, т.е вы не встретите часть кода функционального а часть ООП, мы старались с ссамого начала избежать такой путаницы.
покажите свой код, который вы прикрепляете к резюме, или ссылку на ваши репозитории на github
Это вы еще не добрались до реализации Singleton при помощи eval в Singleton.class.php
...
// can't call protected constructor through reflection
eval(
   '$object = new '.$class
   .'($args['.implode('],$args[', array_keys($args)).']);'
);
...


Вы год копирайта посмотрите

ps. Если его до сих пор не трогали — значит он работает видимо без нареканий, когда кто-то с багом столкнется или ему захочется актуализировать его — он перепишется, возможно даже с late static binding.

Вам та же просьба что и к товарищу выше: покажите свой код, который вы прикрепляете к резюме, или ссылку на ваши репозитории на github
если прокомментировать код в вашем стиле то: открываю файл DesignerConnections.php {{{
<?php
return array(
);
}}}

wtf?

А если посмотреть www/system/app/Application.php то:

1. какого этот файл находится в docRoot как я понимаю?

2. Многочисленные нарушения coding style, trailing tabs и т.п.

3. {{{

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

wtf?

4. Комментарии в стиле капитан очевидность

5. У вас что-то есть в архитектуре что не является static? От "::" рябит в глазах

6. Это не ООП, у вас god функции, отсюда и необходимость писать «комментарии»

7. метод run вообще за гранью {{{
public function run()
{
header('Content-Type: text/html; charset=utf-8');

$page = Request::getInstance()->getPart(0);

if($page === self::$_mainConfig['adminPath'])
$this->_runBackend();
else
$this->_runFrontend();
}
}}}

getPart(0) — любой поймет конечно что это

header — конечно же вы знаете что ваше Application всегда отдает text/html а если ему надо будет отдать text/xml — вы что будете делать? подозреваю что костылить

вот так примерно выглядит ваш пост по Singleton.
С удовольствием обсужу с вами все ваши замечания. Но не в этом треде.
PS: DesignerConnections.php заполняется автоматически системой, как и многие другие файлы конфигурации.
Тут нечего обсуждать, на вкус и цвет как известно фломастеры разные.
Не вижу ничего плохого, если кто-то покажет на недоработки и огрехи. Эту информацию можно собрать проанализировать, исправить проблемы. Всего учесть невозможно, тут знающие люди могут подсказать варианты решения.
Нет, тут проблема была в том, что у вас тоже не совсем «идеальный» код, но при этом вы «тычете» другим на это, не стоит так делать. У вас тоже по коду есть много притензий, которые были отмечены в вашем посте давнишнем на хабре, но приэтом там умолчали о половине «плохо пахнущих» моментов, т.к. это никому не нужно просто.
Я не оправдываюсь тем, что раз так, значит работает. Планомерно исправляю претензии и открыт конструктивной критике, не претендую на гениальность. И для меня свои фломастеры пахнут ( к разговору о статиках и например вашем сессионном хранилище, да и вообще по коду)

Использование eval, не мне вам объяснять, что так не стоит делать.

Еще одно отличие я не заявляю что у меня " Аутичный/ Аутентичный" фреймворк, то что вы смотрели это приложение, которое выполняет четко определенную функцию. Остальное на вкус разработчиков, какие фреймворки брать и как их использовать. Про непонятные моменты есть typeHint (в library не капитанские комменты, хотя соглашусь их нехватает). Про ООП, оно используется там где необходимо, например в реализации сложной структуры кодогенератора js. (Приоритеты у проектов совершенно разные в нашем проекте не приветствуется излишняя абстракция )

Не хотите слышать упреки советы по поводу своего кода не публикуйтесь.
Как вы общаетесь со своими коллегами с такими болезненными реакциями?

PS: Мне показалось интересным то, что вы реализовали множество адаптеров для различных бэкендов кэширования и сами подходы… Жаль, что рассуждаем мы сейчас не об этом…
Интересная ссылка у меня есть: Ad hominem.
У вас критика неконструктивная.

Можно сказать: у тебя сын дебил
В ответ получить в табло

А можно: твоему бы сыну таблицу умножения подтянуть
И в ответ получить информацию что сыну два года и он только начал ее учить

Вот вы занимаетесь первым
Зашибись. Coh сначала пишет коммент не «об этом», а потом чуть позже пишет в P.S. «жаль что рассуждаем мы сейчас не об этом...». А заставлял то кто писать не «об этом» отчего теперь надо сожалеть?
Читайте внимательнее тред начался с «Обратите внимание на не лучшую реализацию Singletone» в onPHP и к чему мы пришли в итоге?
Тред начался с «Это вы еще не добрались до реализации Singleton при помощи eval в Singleton.class.php». А это несколько более недружелюбный тон нежели «Обратите внимание на не лучшую реализацию Singletone».
Тут я придерживаюсь мнения: «Не нравится — исправь». Open source же. Предложите решение лучше.
В общих чертах если можно — как происходит работа с записью во все эти кэши и какую роль выполняют кэш-сервера, кроме локального и бэкапного/запасного? Пишем разово в мастер-кэш и потом кастим изменения для остальных, не удерживая скрипт, либо пишем все сразу? Короче с синхронизацией всего этого чуда как, примерная схема?
Мы решаем частную задачу: нам нужно максимально быстро показывать хорошие баннеры. Списки баннеров, которые предположительно подходят для показа, строятся в одном месте и раскидываются по всем сервера. Запрашиваются же они всегда с localhost (только localhost для всех разный :). Мгновенная синхронизация нам не нужна. Не будет ничего страшного если на какое-то короткое время значения на серверах будут немного разные.

Последовательный кеш мы писали для другой не менее частной задачи:
У нас есть приложение, которое весьма похоже на мемкеш — habrahabr.ru/company/wapstart/blog/146957/ Оно умеет отдавать характеристики запроса по переданным заголовкам. Грубо говоря может «собрать» географию, оператора по переданному Ip адресу и т.д.
Само собой характеристики запроса меняются крайне редко, поэтому мы сделали двухуровневое кеширование: локальный кеш -> удаленный кеш -> очередь -> СУБД.
Благодарю за развернутый ответ, похоже что решение именно такое, как и должно быть.

Если позволите — еще короткий вопрос. Если, как я понял, существует задача максимально быстрого сбора инфы с нескольких источников в одну точку (верно?) с функциями резервирования — то как Вы смотрите на такой вариант: есть между скриптом/бизнесс-логикой и кэш-серверами некая прокси, к примеру, написанная как консольная/сетевая софтинка, выполняющая при запросе к ней по ключу запросы ко ВСЕМ кеш-серверам СРАЗУ, асинхронно, и отдающая первый полученный результат. После отдачи она реализует минимально необходимые функции по сбору статистики (наподобие пинга до каждого, количества запросов, задержки) для оптимальной раздачи и максимальной скорости.

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

Рассматривали ли Вы подобные варианты и если да — почему подобное не оказалось приемлемым. Спасибо.
Может быть мы когда-нибудь и придем к этому, но пока такой задачи не стоит. При этом я не говорю, что это плохо или нереализуемо :) Любой дополнительный компонент увеличивает сложность системы и понижает надёжность, пусть даже и опосредованно.
Сейчас сбор характеристик запроса и подходящих баннеров у нас не является узким местом.
Когда-то были проблемы с производительностью этого источника, мы его переписали, производительность нас удовлетворила, и мы успокоились.

Другими словами, у нас задача не в том, чтобы отдать контент максимально быстро, а в том, чтобы отдать контент не медленнее, чем за N миллисекунд. И мы не занимаемся оптимизацией пока укладываемся в эти N.
Еще интересный момент — как обрабатывается ситуация, когда мемкеш лежит — первый сервер, второй и т.д. Ждем по секунде на каждом запросе в кэш или у Вас есть более интересное решение конкретно с мемкэшем?
В текущей версии pecl memcache (3.0.5) Можно задавать таймаут в float, хотя документация утверждает о int.
Пруф — svn.php.net/viewvc/pecl/memcache/tags/RELEASE_3_0_5/memcache.c?revision=303968&view=markup (строка 1104 и далее). Соответственно можно задать таймаут меньше одной секунды, чем мы и пользуемся. :)

А так Вы правы, в случае, если лежит всё, мы будем ждать по timeout секунд на каждый сервер. В нашем случае — 0.1. На самом деле сервера memcached падают крайне редко.

ps. К слову, в trunk у параметра уже стоит Int.
Значит int все-таки выпилили, отлично, надо будет пощупать как это реализовано на самом деле.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий