C чего начать внедрение ERP |
В прошлой статье я рассказывал о том, Что такое ERP система, а также о том, в каких случаях внедрение этой программной системы принесет реальную пользу, и на что обращать внимание при выборе ERP. А сейчас я хочу поговорить о том, как получить практическую пользу от ERP-системы. А для этого программный продукт необходимо внедрить.
Я уже писал о внедрении программных продуктов в серии статей «Внедрение программного продукта. Особенности работы бизнес-консультанта». И многие рекомендации из этой серии статей можно применять также при внедрении ERP. Но все же эта система предназначена для среднего и крупного бизнеса, а потому и внедрение ее имеет определенные особенности из числа тех, что в прошлых статьях, посвященных преимущественно малому и среднему бизнесу, я не раскрывал. Еще одна важная особенность ERP – это многофункциональная, сложная система с очень широким функционалом, и при внедрении этот факт также необходимо учитывать.
Самый важный вопрос, который возникает накануне внедрения любой программной системы, это «с чего начать»? Если вы знаете, как и с чего начинать внедрение, и начнете работу правильно, скорей всего, процесс пройдет без лишних сложностей, переделок и конфликтов. А результат оправдает ожидания бизнеса.
О том, как вести проект внедрения ERP-системы от и до, я также постараюсь рассказать в следующих статьях. А сейчас я хочу поговорить о самом важном – начале внедрения.
Существует несколько подходов к внедрению ERP-систем, которые я видел в чужом исполнении и/или сам применял на практике. Каждый из них имеет свои плюсы и минусы, какие-то «подводные камни» и преимущества.
В принципе, все подходы к внедрению ERP, также актуальны для любых сложных систем, например, 1C УПП, 1С ERP, SAP Bussines ONE, ODOO и др. Давайте о них поговорим подробно.
ERP-система – это продукт очень технологичный. А потому как у разработчиков, так и у бизнесменов очень часто возникает соблазн по максимуму распланировать внедрение еще до начала работ. Казалось бы, все логично. При таком подходе исходят из того, что технологическая программная система должна быть максимально алгоритмизирована. И к процессу внедрения можно и нужно подходить с точки зрения алгоритмизации и математической модели.
Как это реализуют:
На составление подобного технического задания могут уйти месяцы. Я лично видел, как специалист составлял техническое задание по внедрению ERP в течение полугода. В этот период он регулярно выезжал на объект, вникал во все нюансы и вносил их в документ.
От такого подхода плюсы получают, прежде всего, разработчики:
Минус подхода заключается в его объеме и сложности. Создать всеобъемлющее техническое задание, в котором будут предусмотрены все модули, документы, все нюансы будущей работы невозможно. Система многофункциональна, и любые изменения в одном модуле могут повлечь за собой необходимость внести изменения в другой.
Аналогично и с ошибками при составлении технического задания: любые неправильные решения в одном модуле могут повлечь за собой множество изменений в других. Например, какой-то бизнес-процесс мог быть понят не верно, и тогда при внедрении выяснится, что часть документации и справочников – не нужны, а требуются совсем другие. Слишком большой объем информации, слишком высокая сложность системы – в результате, оказывается невозможно заложить изначально все нюансы и предусмотреть все возможные ошибки.
В этом случае составляют список наиболее значимых для бизнеса направлений и модулей для работы с ними. На их основе составляют некий план внедрения, который и является основой для начала работ.
В этом случае техническое задание также имеется. Как и календарный план при варианте работы, где за основу берут объемное ТЗ. Но здесь техническое задание не является таким всеобъемлющим, возможно составление для разных этапов работы собственных технически заданий. Т.е. основной документ в данном случае – План выполнения работ.
Например:
В качестве первого этапа внедрения выбираем участок Финансы и Движение товаров. Этот участок работ является очень важным для любой компании. Разбираемся с особенностями движений финансовых в организации, изучаем хранение и продажу товаров. На основе этого составляем ТЗ для автоматизации в ERP выбранного участка. И внедряем необходимый для этого участка функционал.
На следующем этапе выбираем другое направление, например, производство. И также работаем с этим направлением плюс учитываем проведенные работы (и возможные доработки) в уже готовых модулях, относящихся к финансам и продукции.
Основное преимущество такого метода – реалистичность. Охватить все и сразу крайне сложно. Внедрять поэтапно – намного проще, ошибок при этом обычно допускается меньше. И результаты работы видны уже в процессе внедрения. Я и сам чаще всего выбираю этот подход.
Минусы – увеличение сроков, которое заказчик может рассматривать как затягивание. При частичном внедрении сроки проведения работ могут затягиваться как по объективным причинам, так и по разных поводам, связанным с финансированием, человеческим фактором и т.д. Кроме того, если руководитель бизнеса стремится получить все и сразу, его также может не устроить отсутствие точных данных о внедрении (когда будет завершено, какова будет точная сумма и т.д.).
Этот метод работы очень осторожный, и чаще всего требует времени больше, чем при других вариантах внедрения. Так, если при первом подходе (составлении ТЗ) все сроки и суммы рассчитаны заранее, до начала работ, то здесь все предварительные цифры примерные. А технические задания для разных этапов составляются в процессе внедрения.
Также при первом методе работы по автоматизации работы разных подразделений могут проводиться параллельно. Клиент будет видеть автоматизацию и бухгалтерии, и продаж, и склада, и производства. Здесь же работа проводится этап за этапом. И подразделения подключаются к ERP также по очереди.
В этом случае работы по внедрению начинаются сразу без какого-то подготовительного этапа. Казалось бы, это неприемлемо, ERP-системы слишком сложны, чтобы внедрять их без предварительного изучения особенностей бизнеса и составления документации. Тем не менее, на практике я подобную работу видел.
Некоторые разработчики даже в случае ERP-систем действуют по принципу «начнем, а потом разберемся». Согласно этому подходу создается предварительно общий план внедрения, который по мере необходимости делится на мелкие части.
Чаще всего подобный метод работы практикуют продавцы «коробочных» программных продуктов. Причина заключается в том, что прибыль от продажи «коробки» они получают в любом случае, а внедрение для них – только сопутствующая услуга.
Основной плюс такого метода – работа по внедрению начинается сразу после принятия решения. Без длительной подготовки. Именно это и привлекает бизнесменов. Например, было принято решение – автоматизируем отдел продаж – сразу приступили к работе. Решили – надо перенести остатки – тут же они переносятся.
В принципе, успешное внедрение по такому принципу также вполне возможно. Но это очень сложно и для успеха потребуется очень высокий уровень профессионализма руководителя, а также значительный опыт внедрения подобных проектов. И даже в этом случае профессионалы чаще выбирают другие пути. Просто потому, что они позволяют снизить число ошибок и накладок, влияния человеческого фактора. В итоге, варианты работы по ТЗ или внедрения по частям позволяют получить нужный результат с меньшим количеством накладок и переделок.
Минусы – отсутствие планирования комплексного внедрения. Здесь проблемы возникают практически по тем же причинам, что и при составлении всеобъемлющего ТЗ: ERP – сложный комплексный программный продукт, и ошибки при внедрении одного модуля могут повлиять на работу другого модуля. Но если в первом случае такие проблемы возникают из-за попытки заранее предусмотреть слишком много, то здесь – по причине отсутствия планирования. Т.е. специалисты при внедрении решают сиюминутные задачи, не задумываясь о том, что на следующем этапе им потребуются данные и документы из текущего модуля для организации работы другого подразделения.
Еще один минус – при таком подходе вовлеченность сотрудников компании в процесс внедрения значительно ниже, чем при любом из описанных выше. Это отрицательно сказывается на решимости сотрудников принимать участие в тестировании и переходе на новую систему, а также провоцирует саботаж использования новых инструментов.
Еще один подход к внедрению ERP я лично называю “Понемногу, но все и сразу”. Этот вариант также вполне может быть успешным и удобным решением. Я лично его применял не один раз. И если при частичном внедрении в работу берут один или два модуля, полностью их настраивают, и только потом приступают к работе над другими модулями, то в этом случае работа также ведется постепенно, то нет такого четкого ограничения — только этот модуль и никакие другие.
При таком подходе первым делом также составляется план проекта. В этом плане основными этапами считаются не модули (один, потом — другой и т.д.), а какие-то виды работ, которые могут затрагивать одновременно все модули или выборочно какие-то из них. При этом для каждого этапа указываются примерные сроки и стоимость.
В самом общем случае подобный план выглядит следующим образом:
Подобный план составляется и отдельно для каждого модуля, что позволяет максимально конкретизировать для заказчика стоимость каждого этапа работ, а также наиболее точно определить возможные сроки. При этом с заказчиком обязательно оговаривается возможность в процессе внедрения в случае необходимости изменить какие-то виды запланированных работ другими.
Такой метод удобнее и реалистичнее, чем составление технического задания, так как общее ТЗ для всего проекта потребует 2-3 месяцев работы или даже больше, а полученный в результате объемный документ со всеми подробностями заказчику изучить будет очень сложно.
Здесь заказчик видит план со сроками и суммами для каждого этапа. А техзадания под каждый этап работ создаются отдельно, они небольшие и не требуют значительных временных затрат. Желательно еще и называть каждый из документов понятным образом. Например, «Бухгалтерия и финансы» или «Отдел продаж».
Плюсы такого подхода:
Минусы подхода:
Важная особенность планирования: При подсчете бюджета независимо от вашего опыта и точности оценки следует “заложить” дополнительную сумму на случай непредвиденных ситуаций. Оптимальный размер такой суммы — 30% от стоимости запланированных работ. Это можно назвать согласованное планированное отклонение стоимости проекта. Эти средства могут потребоваться при возникновении каких-то сложностей — организации обмена данными с программой, которая не поддерживает существующий API, доработка базовых справочников, сложности при переносе данных, реализация необходимых для работы функций, которые по той или иной причине не сумели предусмотреть заранее и т.д.
Эти 30% учитываются в бюджете, но выплачиваются исполнителю только в случае необходимости. Если вы при реализации проекта сумели уложиться в базовые цифры бюджета без «резерва», прекрасно! Заказчик будет благодарен, а довольный клиент — это и новые заказы, и лучшая реклама по «сарафанному радио» (рекомендации друзьям и знакомым).
Если все же понадобится использовать резерв, очень важно грамотно и понятно обосновать, на какие работы потребовались эти деньги. Включать же эту сумму в бюджет нужно для того, чтобы не возникало неприятных ситуаций, когда бюджет увеличивается, а у заказчика такая статья расходов не предусмотрена.
Количество модулей, которые может предложить система ERP, вызывает нередко вопросы, с чего же начать, ведь возможностей очень много, как говорится, «глаза разбегаются». Я рекомендую начинать с наиболее критичных для работы компании направлений и связанных с ними модулей:
Иногда я слышу возражения, что у компании могут быть свои нюансы, например, в связи с высокой текучкой кадров наиболее критичным является HR. На самом деле, скорей всего, какая-то автоматизация работы HR в компании на момент начала внедрения ERP имеется. И независимо от того, насколько критична для бизнеса работа этого подразделения, некоторое время управление персоналом можно будет вести в той системе, которая есть. А если в процессе будут выявлены определенные ошибки – это будет минусом, но не самым критичным для существования компании.
Также и проектный отдел или маркетинг какое-то время смогут работать в привычном режиме и вести учет автономно в той системе, которой они пользовались ранее.
В то же время строгий учет и контроль движения основных ценностей (финансовых и материальных), а также отсутствие ошибок в бухгалтерском и налоговом учете – это те «столпы», без которых не сможет существовать ни одна компания.
Я надеюсь, что материал о том, с чего стоит начинать внедрение ERP, и какие методы работы с этой системой практикуются, был вам полезен. В следующих публикациях я расскажу о своем личном опыте внедрения ERP, поделюсь информацией об ошибках, которых лучше избегать, а также о том, на что нужно обращать внимание в процессе внедрения и как лучше построить эту работу, чтобы переход на ERP был максимально эффективным.
Метки: author JustRamil управление разработкой управление проектами erp- системы erp |
PHP-Дайджест № 113 – свежие новости, материалы и инструменты (16 – 30 июля 2017) |
Свежая подборка со ссылками на новости и материалы. В выпуске: PHP 7.2.0 Beta 1, свежие RFC из PHP Internals, материалы по асинхронному PHP, видео с конференций и митапов, и многое другое.
Приятного чтения!
setcookie()
и другие функции для работы с куки предлагается добавить поддержку стандарта Same-site Cookie.json_encode()/json_decode()
предлагается бросать ошибку класса E_WARNING, вместо использования функции json_last_error()
.$writeln = {Util\writeln};
// is a simplification for
$writeln = Closure::fromCallable('Util\writeln');
$writeln = {$terminal->writeln};
// instead of
$writeln = Closure::fromCallable([$terminal, 'writeln']);
function foo(mixed $arg): mixed {
return $arg;
}
Спасибо за внимание!
Если вы заметили ошибку или неточность — сообщите, пожалуйста, в личку.
Вопросы и предложения пишите на почту или в твиттер.
Прислать ссылку
Быстрый поиск по всем дайджестам
<- Предыдущий выпуск: PHP-Дайджест № 112
Метки: author pronskiy разработка веб-сайтов php блог компании zfort group дайджест php- ссылки symfony yii laravel zend reactphp |
Перевод отрывков из книги Роберта Хайнлайна «Заберите себе правительство» — часть 27 |
«К чему стремимся, для кого,
Приобретая и теряя?
Для тех обычнейших людей,
Кого дурачат раз за разом.
Добро, достоинство и разум,
Неторопливо вкруг посей // американский поэт Карл Сэндберг
«Когда вы собираете группу людей, чтобы сконцентрировать их объединенную мудрость, вместе с ними вы неизбежно собираете все их страсти, предрассудки, заблуждения, эгоизм и недальновидность. Как от таких собраний можно ожидать совершенства в решениях и поступках?
И, тем не менее, меня изумляет, насколько близка к совершенству работа этой системы». //
из речи Бенджамина Франклина на Конституционном Конвенте
Искусство политики хаотично и многослойно как рагу в тарелке, и так же бесконечно туманно, как зашифрованный текст. Несмотря на многочисленные отступления и дополнения, я в этой книге не коснулся многих встречающихся в политике нюансов. Какие-то из них слишком долго разъяснять, их не уместить их в этой книге, и вдобавок они не стоят того, чтобы писать о них в книге для начинающих политиков. Все эти нюансы вы узнаете, занявшись практической политикой. Вы не совершите никаких фатальных ошибок, если твердо будете придерживаться своих принципов.
Мы не рассмотрим такие моменты, как проведение партийных съездов уровня страны и штата, работу законодателей штата, где бывают такие явления, как законы, которые принимать не собираются, используя их только для получения денег от заинтересованных корпораций, и законы, которые обязательно нужно принять, потому что без них вся работа остановится. Не будем говорить о том, как оратор может убедить комитет проголосовать за или против. Не станем описывать работу комитета по регламенту, практику приостановки голосования по принятию закона для его дальнейшего обсуждения, проигнорируем всю внутреннюю кухню конгресса. Обойдем молчанием лобби, лоббистов, честные и нечестные способы пополнения фонда кампании, политические блоки, выборы с оценкой предпочтительности кандидатов в баллах, издание политических газет, законодательный запрет государственным служащим заниматься партийной деятельностью, организацию национальных партийных комитетов и национальных предвыборных кампаний, а также взаимодействие политиков уровня города, штата и страны. Все эти вопросы имеют свои нюансы, однако, по сути, все они решаются теми же методами, которые я вам описал выше. Только названия сущностей могут поменяться.
И все же, когда большая семья собирается в путь, то как бы тщательно ни планировалась упаковка багажа, после окончания погрузки, всегда останутся какие-то забытые вещи, которые надо взять с собой. И тогда эти вещи собирают, заворачивают в оберточную бумагу и несут сверток в руках. Эта глава – как раз такой сверток.
Скажу сразу: вы можете быть достаточно активным политиком, не тратя на это ни цента. Однако, небольшие расходы сделают вашу работу намного легче и приятней. Вот минимальный недельный бюджет, позволяющий вам не попадать в неловкие ситуации и в своей политической деятельности ни в чем себя не стеснять:
Одна трапеза в кафе: | $1.00 |
Расходы на работу политической организации (распределяемые по всем членам организации) | $0.50 |
Расходы на транспорт | $0.40 |
Дополнительные расходы | $0.25 |
Итого на неделю: | $2.15 |
Усреднение затрат компенсирует повышенные расходы на активную политическую деятельность в период кампании, за счет периодов политического затишья, когда все ваши расходы за неделю составляют пара открыток и один телефонный звонок. В расчетах затрат игнорируется также тот факт, что в то время, когда вы заняты политикой, вы не тратитесь на походы в кино, игру в бридж на деньги, и на другие хобби и развлечения. Обычно траты на политику гораздо меньше затрат на развлечения. Таким образом, занявшись политикой вы можете снизить свои расходы, даже несмотря на то, что связанные с политикой издержки оплачиваете из своего кармана.
Конечно, на пожертвования политическим организациям и поездки на политические съезды можно потратить сколько угодно. Поэтому, вам нужно научиться говорить «нет, у меня нет столько денег», когда вас будут уговаривать потратить столько, сколько вы не может себе позволить. Уважать вас за это не перестанут, и в перспективе эти отказы не отразятся на вашем политическом влиянии.
Коммунистов в нашей стране немного, но они есть, и вы можете их встретить где угодно. У нас в политике распространено заблуждение, что коммунистов можно встретить только в организациях левого крыла Демократической партии, но я лично убедился в том, что это не так. Коммунистическая партячейка может объявиться в любом месте, где собралось больше четырех человек. Я находил их в таких консервативных организациях, где сам факт их обнаружения вызвал бы среди руководителей организации эпидемию смертей в результате сердечного приступа.
Коммунистов лучше всего рассматривать как особый вид религиозных фанатиков. Говоря это, я имею в виду американских коммунистов, потому что в России никогда не был и русских коммунистов не встречал. После принятия точки зрения на коммунизм как на религию, становятся понятными все странности в поведении коммунистов. У них есть свое, совершенно антинаучное Священное Писание, которое сами они считают последним словом в науке, и которое существует в «каноническом» и в «еретических» переводах. У них есть свой бог – идея «пролетариата», свои великие и малые пророки, и свои вероотступники. Они уверены в абсолютном превосходстве своей точки зрения над всеми другими и нетерпимы к спорам на эту тему. Для них допустимо все, что помогает пропагандировать их веру, неважно, насколько ущемляя при этом чувства неверующих в их религию. Их мораль и справедливость – «высшая», а вся остальная – «декадентская» и «буржуазная». Они неутомимы и нетерпимы. И обычно они альтруистичны и искренне убеждены в правильности своей «религии». Вы услышите еще множество подобных характеристик от остальных политиков.
Любимый метод действия коммунистов – это захват политических организаций изнутри. Обычно так делают тайные коммунисты, скрывающиеся под маской каких-то других партий – с точки зрения их кодекса чести это допустимо. Они применяют парламентские процедуры и демократическую свободу слова для того, чтобы, в конце концов, покончить и с тем и с другим. Их понятие свободы слова заключается в том, чтобы на собрании, организованном вами, выступать с речами на темы, выбранные ими. И эта их свобода слова – отнюдь не обоюдная – попробуйте-ка сами придти выступить на заседании коммунистов!
Коммунисты чаще всего действуют в ячейках по трое – один делает заявления по порядку ведению собрания, второй его поддерживает, а третий – выступает с речами. Обычно они рассеяны по залу, и даже могут делать вид, что незнакомы между собой. Столкнувшись с таким тройным противодействием, ведущий собрание председатель может попасть в сложную ситуацию. Для выступлений на чужих заседаниях, коммунисты всегда выбирают животрепещущую для слушателей тему, не связанную напрямую с коммунизмом. Всего три коммуниста, действуя согласованно, могут сподвигнуть собрание на действия, фатальные для будущего их организации, но благоприятные для каких-то долгосрочных коммунистических планов.
Увидев, что имеет дело с коммунистами, опытный председатель собрания может предотвратить нежелательное развитие событий, воспользовавшись приемами, описанными ранее в этой книге. К счастью, обычно эти приемы помогают. Американские коммунисты редко бывают очень умными, хотя, многие из них – довольно яркие личности. Они, скорее, склонны вести себя, согласно шаблонным приемам, которым они обучены, и по которым можно определить их партийную принадлежность. Самый надежный их отличительный признак – склонность к одним и тем же наборам трескучих фраз и лозунгов, которые меняются год от года, но которые вы скоро начнете узнавать, наслушавшись их в политике. Несколько лет назад таким признаком было слово «активизировать». Довольно долго в ходу было выражение «объединенный фронт» и словосочетания со словом «народное». Я не могу предсказать, какие лозунги появятся у коммунистов в ближайшем будущем, так что узнавайте это сами, заглядывая время от времени в их газету «Поденный рабочий», чтобы быть в курсе новых веяний в коммунизме.
Некоторые из коммунистов сами раскрывают себя, называя себя «сочувствующими коммунистам». Такие субъекты обычно говорят, что симпатизируют коммунистическим социальным идеалам, но сами коммунистами не являются. Вы когда-нибудь слышали о сочувствующих Республиканцам, или Демократам, но не являющихся ими? Таких просто не бывает!
Однако, в целом, являясь источником досадных неприятностей, коммунисты не представляют собой серьезной угрозы для нашего общества. Только самые пугливые или злонамеренные политики могут говорить об опасности коммунистической революции в нашей стране. Любой знакомый с американским менталитетом и культурой, ясно увидит, что девяносто девять американцев из ста не захотят иметь ничего общего с коммунизмом: он просто не совместим с нашим индивидуализмом и с нашими амбициями.
Чем же тогда могут быть полезны американские коммунисты? Тем, что даже если бы их у нас не было, их бы следовало у нас завести, потому что они могут сослужить отличную службу, выступая в роли индикатора для определения настоящих источников угрозы нашей Республике.
Для всех добропорядочных американцев коммунизм настолько одиозен, что появление групп населения, в которых он становится популярным – признак того, что стране нужно срочно предпринять действия для исправления ситуации. К сожалению, гораздо чаще мы такие группы населения игнорируем, ограничиваясь лишь наращиванием брошенных против них отрядов полиции.
Юристами является около половины всех наших депутатов в собраниях штата и в Конгрессе. Число занимаемых ими выборных постов находится в явной диспропорции с общим их количеством в нашей стране. Многие принимают это как должное, и действительно – такое положение вещей – логическое следствие некоторых особенностей структуры нашего общества. Я уже писал, что юристам легче выделить время для участия в выборах, чем людям других профессий, и что, работая в правительстве, юристы могут брать взятки на почти законной основе. В целом, нахождение юристов у власти возражений у меня не вызывает: они настолько же честны и патриотичны, насколько любая другая группа людей. Я даже думаю, что, в среднем, типичный юрист умнее среднестатистического человека. И все же, тот факт, что юристам доверяют писать законы, у меня вызывает большое беспокойство. И я бы еще добавил, что юристы не должны работать судьями, что вам может показаться совсем уж радикальной идеей. Но работа судьи – далеко не та же самая работа, что и та, которой занимаются юристы, адвокаты, и поверенные, это должны были бы быть совершенно отдельные профессии, а их слияние, похоже, идет от тех библейских времен, когда священник, учитель, судья и юрист составляли одну ту же профессию. Две из этих ипостасей стали отдельными видами деятельности, две другие – тоже могли бы быть разделены, как, например, в Англии, где юрист и поверенный – это две совершенно разные профессии. Да и у нас сейчас нет закона, требующего, чтобы судьи Верховного суда являлись юристами.
Но самый большой вред юристы наносят в законотворчестве. И в первую очередь – тем, что законы они пишут на своем юридическом языке, непонятным обычным гражданам, вынужденным нанимать других юристом, чтобы те растолковали, что имели в виду их коллеги – авторы закона. В среде юристов распространено мнение, что законы необходимо писать на их профессиональном языке, потому что обычный человеческий язык, дескать, недостаточно точен для описания законов. Это весьма сомнительное утверждение, которое оспаривают многие лингвисты, занимающиеся смысловыми аспектами человеческих языков. Обычный человек, не знающий птичьего юридического языка, также вправе усомниться в необходимости нагромождения юридических терминов в законах, резонно заметив, что после того, как юристы написали закон, они сами же начинают оспаривать его смысл в судах. Интересно, что бы случилось, если бы кто-нибудь подверг сомнению соответствие наших законов нашей же Конституции, на том основании, что взрослый человек со средним образованием не в состоянии понять текст законов? При этом государство требует от него соблюдения законов, что подразумевает то, что он должен понимать смысл законов, дабы их соблюсти. Но как можно требовать соблюдения законов, которые невозможно понять? Даже юрист не должен требовать от меня «хримфования», если он мне не сможет объяснить мне на человеческом языке, что я должен cделать для того, чтобы «хримфовать».
И при всем при этом, тот иностранный язык, на котором написаны законы – это еще не самый большой грех законотворцев от юриспруденции. Иностранным языком еще можно худо-бедно овладеть, или нанять переводчика с него. Хуже всего то, что юристы творят законы в неверном направлении. Вы слышали когда-нибудь о сказочной птице Филилу? Согласно мифу, она летает задом наперед, потому что хочет видеть не то место, куда летит, а те места, где она уже пролетела. Юристы подобны этой птице – своими знаниями прецедентов прошлого, недалекостью, и стремлением сбиваться в стаи. Они всегда смотрят в прошлое. Для создания совершенно новых законов, регулирующих совершенно новые ситуации, это – совершенно неподходящий способ мышления. Сейчас мы как раз видим обескураживающую ситуацию, когда юристы пытаются создать законы, регулирующие вопросы атомной энергии, для чего пытаются найти подобные прецеденты в прошлом человечества, где таких прецедентов никогда не было. Но это юристов совершенно не смущает, потому что в их систему образования не входят, ни данные, полученные точными науками, ни научные методы, которые в них используются.
Проблема не нова, просто сейчас она встала наиболее остро. Группе людей, разбирающихся в явлениях реальной жизни намного хуже фермеров, инженеров, механиков и торговцев, мы позволяем за нас принимать важнейшие решения, основываясь на канувших в лету прецедентах, созданных давно их покойными коллегами по юриспруденции.
Так что в реальности главная проблема участия юристов в общественной жизни заключается в том, что большинство из них не знает, как выглядит реальность.
Cделанный мною в этой книге упор на наличие в нашей стране двух основных партий, на партийную дисциплину, и необходимость поддержки одной из партий, может привести вас к мысли, что я противник любых попыток создания других политических партий. Если вам так показалось, я бы хотел вас поправить. Постоянная поддержка своей партии и соблюдение партийной дисциплины – этичны, и с чисто прагматической точки необходимы для любой политической партии, которая собирается выполнять свои политические обещания. Особенно верен этот принцип по отношению к проигравшим праймериз кандидатам: никто не должен выдвигаться кандидатом на праймериз если не готов смириться с волей большинства членов той политической группы, которая его выдвигает. Выдвижение на праймериз – дело добровольное, так же, как и принятие условий кокуса, и оно подразумевает под собой, как права, так и обязанности. Кандидата никто не принуждает выдвигаь свою кандидатуру на праймериз. Кроме того, он всегда может баллотироваться на выборах как независимый кандидат.
В некоторых штатах, участие в праймериз обставлено некоторыми условиями: кандидат должен обязаться поддержать сформированный по их результатам партийный список кандидатов. Такое условие вполне справедливо, и может предотвратить участие в праймериз некоторых беспринципных политиков желающих всего и сразу.
Иногда возникает такая странная ситуация, как борьба двух, принципиально расходящихся во мнениях по основным вопросам, политических групп, за право носить название партии, к которой, по утверждению обеих групп, они обе принадлежат. В таких случаях, конечно же, и речи быть не может о том, что проигравшие поддержат победителей, следовательно, нельзя говорить и о постоянстве поддержки своей партии. Но гораздо чаще встречается случай, когда проигравший кандидат начинает капризничать как маленький ребенок, настаивая на том, чтобы ему позволили действовать по своим собственным правилам, иначе он тогда не играет.
Из всего этого следует одно – если вы решили переметнуться в другую политическую организацию, то делайте это по полной программе: покидайте свою партию и вступайте в другую, или даже какую-нибудь третью. Не думайте, что Республиканцы или Демократы позволят вам ими манипулировать, угрожая покинуть их партию каждый раз, когда вам приспичит.
Вопросы создания третьей партии, сейчас, или в прошлом, выходят за рамки этой книги, однако, наблюдаемые сейчас противоречия среди членов обеих основных партий приводят к тому, что правое и левое крыло каждой партии, по своим взглядам оказывается ближе к соответствующему крылу другой партии, чем к собственным коллегам по партии из другого ее крыла. В такой ситуации идеологическая перегруппировка была бы разумной, и могла бы привести к созданию третьей партии. Но практическая польза от этой затеи – а как раз это интересует нас больше всего – зависит от того, уравновешивается ли риск неудачи такого мероприятия его пользой и целями. Создание третьей партии – предприятие очень рискованное, неудачей оно заканчивается гораздо чаще, чем успехом. Но все же, в нашей истории такие прецеденты бывали, и не раз. Например, мистер Линкольн на оба своих срока был выдвинут третьей партией: в первый раз – Республиканцами, во второй раз – Объединенной партией (что является довольно малоизвестным фактом). Кроме Линкольна, в праймериз 1864 года участвовал кандидат от Республиканцев 1856 года Джон Фремонт, выдвинутый на этот раз так называемыми «Радикалами», по сути, являющимися Республиканцами, не вошедшими в Объединенную партию (которая, в свою очередь, являлась коалицией Республиканцев и Демократов).
В политике есть общеизвестное правило, гласящее: «Только одна вещь хуже коррупционеров у власти – это сменившие их реформаторы». Почему оно возникло? Ведь большинство реформаторов искренне стремятся сформировать хорошее правительство, баллотируясь на выборные посты, полны лучших намерений, и, по моему опыту, их стремления действительно искренни. Некоторые из неудач реформаторов можно отнести на счет их ужасающей наивности: занимая посты, они совершенно не готовы иметь дело с алкогольным лобби, защитниками прав женщин, инициативными группами, не готовы получать коварные удары противников из-за угла. Некоторые из реформаторов – оторванные от реальности идеалисты, неспособные удержать власть потому, что, в отличие от предшествующих им коррупционеров, не понимают, чего именно хотят от них избиратели. И, наконец, встречается такое печальное явление, как попавшие во власть реформаторы, которые, осознав недостаточность той зарплаты, которую наше общество предлагает своим государственным деятелям, поддаются окружающим их искушениям, и скатываются по наклонной плоскости взяточничества и подкупов.
Однако, лично мне кажется, что чаще всего реформаторы проигрывают из-за тщеславия и осознания своей безусловной правоты, вскружившим им голову после впечатляющей победы на выборах. Я и сам могу отнести себя к реформаторам, поэтому очень заинтересован в разгадке причин этого явления. И меня удивляет и расстраивает то, что мои коллеги-реформаторы оказываются такими слабохарактерными в тот момент, когда у них появляется шанс воплотить в жизнь свои идеалы.
Рассвет и закат политической карьеры реформатора обычно выглядит таким образом: полный энтузиазма и возмущения от происходящего вокруг, он идет в политику, давая себе клятву не иметь ничего общего с тем, что он называет политиканством. Он не собирается давать никаких сомнительных обещаний, и готов всегда быть независимым представителем интересов всех простых людей. Чуть позже он понимает, что какие-то обязательства ему все же придется давать, потому что никому ничем не обязанный человек не продвинется ни на каком поприще, и потому что общественная жизнь построена на обязательствах и соглашениях. Из-за своей неопытности, реформатор делает неверные ходы, беря на себя обязательства, выполнить которые ему будет проблематично. К тому же, его окончательно подводит голова, вскруженная нахождением у власти. Как правило, он окружен подхалимами, твердящими ему о том, какой он великий государственный деятель, ни дать, ни взять – второй Савонарола, что он слишком большая шишка, чтобы быть связанным какими-то там обязательствами, что он трудится для счастья всех людей, и поэтому может не беспокоиться о выполнении конкретных обещаний конкретным персонам, особенно, если эти обещания трудновыполнимы, как это часто и бывает.
В такой ситуации очень удобно пойти на сделку с совестью, решив, что обещания можно нарушать, во имя более высших соображений. Совесть вообще можно натренировать так, что она будет давать удобный на текущий момент, каждый день разный ответ – «Свет мой, зеркальце, скажи, кто на свете всех милее?» – конечно же, всех милее – вы сами! А после череды таких решений, вас переиграет политическая мафия, снова оказавшись у власти.
Политические профессионалы, как более-менее честные из них, так и прожженные коррупционеры, накопили целый кладезь политических знаний и опыта. Реформаторы не могут соперничать с ними, если неопытны в политике, и не готовы предложить избирателям то же, что и профессионалы, и еще немного сверх того. Два самых важных правила для политики, которым реформаторам стоит научиться у профессионалов – это то, что обещания нужно выполнять, и что голоса избирателей собираются на избирательных участках.
Зная эти два пункта, все остальное в этой книге можно не читать.
В тридцатые годы этот вопрос был любимой темой для пессимистичных раздумий. Благополучно пережив Вторую Мировую войну, наша страна на деле подтвердила эффективность демократии. Я сам когда-то был очень озабочен этим вопросом, потому что, являясь сторонником демократии, опасался, что в будущем тоталитарные строи вытеснят ее с лица Земли. Мои сомнения были полностью развеяны одним беженцем из нацистской Германии, который, живя в Берлине был преуспевающим бизнесменом, но, чтобы не вступать в ряды нацистов, предпочел бежать из страны, в конце концов оказавшись в Нью-Йорке – без работы, и без единого пенни в кармане. Я выложил ему свои сомнения, на что он мне ответил: «Не слушайте никого, кто скажет вам, что какая-то форма диктатуры может быть эффективнее демократии. Человеческое общество состоит из отдельных личностей, и обе компоненты этой системы могут ошибаться. Увидев непорядок, в свободном обществе кто-то сразу поднимет тревогу, и в конце концов ошибка будет исправлена. В диктатуре же в таком случае критиковать никто не решится, и ошибка закрепится навечно, превратясь в правило жизни. Главным отличительным свойством настоящей демократии, мой знакомый считал свободу слова. Демократия и свобода слова – как сиамские близнецы, которые не могут жить друг без друга.
Несмотря на убедительное повествование в предыдущих главах, где мистер Занятой добивается избрания своего кандидата, отстраняя от власти засидевшегося там профессионального политика, и таким образом влияя – хотя бы на какой-то период времени – на курс развития всей страны, вы вправе усомниться, типичен ли такой ход событий. В конце концов, когда я писал эту книгу, я мог что-то в ней и приврать. Однако, вы помните то, что я писал о Сюзи? Об этой грозной политической армии, состоящей всего из одной женщины? О той самой Сюзи, у которой много детей? (При этом, она так много занималась политикой, что когда Сюзи решила поехать с детьми на неделю в горы отдохнуть, ее девятилетний сын спросил «А мы точно едем отдыхать, а не на очередной партийный съезд?»).
В штате, где живет Сюзи, закон о праймериз требует, чтобы делегатов на национальный партийный съезд, на котором будут выдвигать кандидата в президенты, избирали местные сторонники партии. И чтобы члены делегации поддерживали тех кандидатов, с которыми были в одном списке на праймериз, позволяя, таким образом, простым избирателям влиять на выдвижение кандидатов в президенты. Кроме того, по закону списки делегаций на съезд должны составляться по результатам сбора подписей избирателей – сторонников партии, что практически исключает возможность махинаций с составом делегаций. Сюзи добровольно бралась организовать сбор подписей за своего кандидата, но Большой Партийный Босс посоветовали ей не утруждаться, потому что «Джо Ктототам все проконтролирует. У него есть деньги, и он собирается нанять опытных профессиональных сборщиков подписей». В его речи Сюзи уловила намек на то, что ее любительские методы слишком непрофессиональны для Большой Политики. И она промолчала, но о подписях не забыла, отслеживая в газетах публикацию объявлений о сборе подписей. Но их все не появлялось. Когда до сдачи подписей осталась всего неделя, она позвонила Партийному Боссу и спросила у него, как обстоят дела с подписями:
-«Что-что? А, подписи? Я же сказал, об этом позаботится Джо».
-«Но ведь они до сих пор не сданы в избирательную комиссию».
-«Не беспокойтесь, со дня на день они будут сданы нашим офисом на севере штата».
В пятницу, по-прежнему не видя в газетах ни одного объявления о подписях, Сюзи решила сама узнать, как с ними обстоят дела. По межгороду она позвонила в северный офис партии, спросила Джона Ктототама, и узнала от секретаря, что в офисе его нет, потому что он болеет. Подписи? Секретарь что-то про них слышала, там еще были замешаны какие-то деньги, наверное, ими занимается южный офис. Но Сюзи точно знала, что здесь, на юге, подписями не занимается никто. И она принялась действовать сама. С предыдущих выборов у нее осталась пачка бланков для сбора подписей, кроме того, у нее была ее картотека избирателей и телефон. Это была пятница, стояла прекрасная погода, и пол-города уехало на выходные на природу, включая б'oльшую половину числящихся в картотеке избирателей. Но Сюзи не опустила руки.
Для начала, она нашла несколько волонтеров, умеющих работать на печатной машинке, и усадила их печатать заголовки на бланках для подписей, которых надо было отпечатать больше тысячи. Запустив процесс, она стала обзванивать командиров участковых групп агитаторов, которых было тридцать человек, и, все они, естественно, были волонтерами. По домашнему телефону ответили только половина из этого числа. Сюзи велела им бросить все, и срочно явиться к ней. В полночь этого же дня последний из них уехал созывать своих агитаторов для обхода избирателей, унося с собой последнюю заготовленную пачку бланков. Следующее утро Сюзи провела, обзванивая командиров групп в неохваченных округах.
В субботу и воскресенье настал аврал, потому что проверка и сортировка по округам подписанных бланков должны были занять: весь понедельник, ночь понедельника, и вторник. Подписи же в избирательную комиссию надо было сдать до 4 часов дня вторника. И хотя выходные – далеко не самое удобное время для сбора подписей, оказалось, что пикники, парковые гуляния, профсоюзные выезды, и толпы идущих с церковной службы прихожан представляют прекрасные возможности для этого. Сюзи нужно было собрать 15 000 подписей, и к утру понедельника она их собрала!
В избирательную комиссию подписи были сданы за 20 минут до окончания срока, и ни одна из этих подписей не вызвала у комиссии вопросов на предмет их подлинности. Большие же Политические Боссы так и не собрали ни единой подписи. Чтобы проиллюстрировать эффективность работы собранной Сюзи «добровольной пожарной дружины», скажу только, что штат, где она живет, очень велик, и на национальный партийный съезд от него направляется делегация численностью в 50 человек.
И еще добавлю, что президентские праймериз там проходят намного раньше, чем праймериз, или партийные съезды большинства других штатов. Поэтому, если бы партийный комитет штата не поддержал этого кандидата, маловероятно, что национальный партийный съезд вообще выдвинул бы его кандидатуру в президенты. Без маленькой хрупкой Сюзи, не имеющей за спиной мощной финансовой поддержки, вооруженной только парой изящных женских ручек и картотекой избирателей, кандидат не выполнил бы требования закона, не собрал бы достаточное количество подписей избирателей. и не попал бы на съезд штата. Момент был решающий, и мог бы закончиться досадной неудачей, подобной потере мистером Вилки шанса быть избранным на выборах 1944 года – из-за проигранных им праймериз в штате Висконсин.
Поскольку я обязался в этой книге не допускать пристрастия к одной из партий, я не буду говорить, был ли кандидат, которого поддержала Сюзи выдвинут на выборы и выбран в президенты, скажу только одно – за два выходных дня Сюзи, домохозяйка из среднего класса, и мать троих детей, пользуясь своим домашним телефоном, радикально изменила ход политической жизни своего штата и своей страны, повлияв даже на мировую историю и политику в достаточной степени для того, чтобы о ней помнили будущие поколения. Однако, я не припомню, чтобы когда-нибудь видел фотографию Сюзи в прессе, хотя бы даже в местной газете. Конечно, наши видные политические деятели вершили дела в гораздо более широких масштабах. Но в тот поворотный момент именно Сюзи явилась необходимым фактором, повлиявшим на весь дальнейший ход истории – подобно легендарному мальчику-герою, заткнувшему пальцем дырку в плотине, остановив воду, которая иначе бы размыла плотину и затопила бы всю страну.
Как те сотни деталей в автомобиле, которые не замечают, пока они не поломаются, волонтеры в политике становятся заметнее всего тогда, когда они отсутствуют. Возможно, вы никогда не будете выдвигать кандидата в президенты: для вас утомительный труд управления предвыборной кампанией и без того больше того, что вы готовы на себя взвалить. Так стоит ли заниматься политикой на местном уровне? Да, стоит! – по многим причинам, из которых я упомяну лишь три.
Первая из них – это то, что волонтерам в политике доверяют. Поэтому, когда партии нужно найти группу людей, на которых можно положиться, а это бывает достаточно часто, то обращаются к волонтерам. Я помню одну кампанию, в которой почти весь комитете состоял из наемных сотрудников, и только полдюжины человек во всей организации были волонтерами. И именно им доверили зарплатный фонд размером в 15 000 долларов, для оплаты работы наемных сотрудников в день выборов. По некоторым тактическим соображениям, в том числе и из-за наличия шпионов в организации, сведения о том, что в день выборов будут нанимать работников, хранили в тайне, и эти деньги должны были распределяться в последний момент. Для удобства оплаты деньги были в мелких купюрах.
Для раздачи работникам зарплаты, волонтеры послали двух женщин, двух – потому что 15 000 долларов – довольно громоздкая ноша. Я как сейчас помню этих двух молодых и красивых домохозяек – с туго набитыми сумочками в руках, в каждой из которых лежало по 3 000 долларов, и обувной коробкой под мышкой у одной из них, где лежали остальные 9 000 долларов. Имея такую внушительную сумму при себе, они ушли с таким видом, будто идут в магазин за покупками. Вернулись они уже завтра, принеся оставшиеся 4 000 долларов, которые и не подумали прикарманить. Если бы они решили это сделать, их никто бы не смог остановить. Однако, никто не волновался, что они сбегут с деньгами в Мексику, потому что это были волонтеры с безупречной репутацией, и положиться на них было надежнее, чем полагаться на сертифицированных инкассаторов с бронированным автомобилем.
Волонтеры стремительно продвигаются в партийной иерархии, в то время, как наемные сотрудники остаются там, где были. Я помню одну женщину по имени, скажем, Хелен. Она не питала каких-то особенных политических амбиций, зато всегда была готова приехать и помочь в политической работе. Через два года после начала политической карьеры, ее назначили в партийный комитет штата, куда мы очень долго отбирали человека, который нас точно не подведет. Мы сначала даже и не подумали о Хелен, в это время она нечасто появлялась в организации: у нее только что родился ребенок. Но когда мы о ней вспомнили, то все сразу согласились, что она – самая подходящая кандидатура. Мы сейчас же ей позвонили и предложили должность. Она не очень обрадовалась предложению и объяснила, что сидит сейчас с ребенком, и не сможет много работать. Но, в конце концов, согласилась.
Два года спустя, часть женщин-волонтеров решили, что их не устраивает текущий лидер женского движения в национальном партийном комитете, и стали продвигать новую кандидатуру. Они не хотели видеть на посту типичную миссис-домохозяйку из женского клуба. И они утвердили кандидатуру Хелен, еще до того, как спросили ее собственного согласия – к ее вящему удивлению. А еще через два года, конгрессмен того округа, где Хелен зарегистрирована избирателем, собрался в отставку. Несмотря на то, что Хелен даже не жила в округе постоянно (а от конгрессмена это и не требуется), уходящий в отставку конгрессмен в качестве своего преемника предложил ее кандидатуру. Попав в Конгресс, Хелен стала там одним из известнейших и полезнейших для общества конгрессменов, и ее красота и женственность совершенно не мешали ей принимать участие в управлении государством. За всю свою политическую карьеру, она никогда не стремилась к власти, и не добивалась благ лично для себя. Ее вело только желание безвозмездно работать для достижения идеалов, в которые она верила.
Но самая важная причина, по которой волонтерская работа эффективна – это то, что в нашей стране много выборных постов и проводится много выборов разных уровней. При этом, в обществе по их поводу господствует заблуждение, строго противоположное действительности. Большинство людей считает, что единственный по-настоящему важный пост в нашей стране – это пост президента, и самые главные и важные выборы – это проходящие раз в четыре года выборы президента страны. На самом же деле, трудно придумать более далекое от действительности утверждение. В демократическом строе, самый важный пост – это пост члена городского совета, а самые важные выборы –это голосование по вопросу выдвижения кандидата на праймериз. По мере продвижения по иерархии власти вверх, на других уровнях суть остается той же, вплоть до самых «главных» постов и «главных» выборов. Все это давно известно, и совершенно не умаляет значения президента нашей страны. Большинство наших президентов излагали все это в своих речах. Чем ниже выборный пост, тем больше занимающий его влияет на нашу повседневную жизнь. Например, мостовая перед моим домом оплачена городскими долговыми обязательствами, и по слухам, включает в себя на каждый квадратный фут мостовой восемь центов отката. Потому что требования для конкурса подрядчиков на укладку мостовой были написаны таким образом, что один из подрядчиков оказался в выгодном положении, и это позволило ему получить контракт на укладку мостовой, не снижая свою цену. А сделано это было путем указания в требованиях конкретного материала для мостовой, имеющегося только у этого поставщика.
Вы спросите, почему я, так хорошо разбираясь в политике, не предотвратил эту махинацию? Дело в том, что я переехал в этот дом из другого города уже после укладки мостовой. Однако, пример с мостовой – это еще не доказательство важности местной власти: даже самые большие ее махинации мы можем пережить, и худо-бедно жить дальше. А вот переживем ли мы еще одну мировую войну? Международными отношениями в нашей стране занимается президент, и с этой точки зрения, его пост – действительно самый главный. Те, кто заседает в нашем национальном Конгрессе, имеют в этом вопросе почти такую же значимость. Но конгрессменов не находят в капусте, и их не приносит аист. Да и президента нам не ниспосылают свыше. Всех их выбирают на выборах, которые проходят не где-нибудь, а в наших с вами избирательных участках! Так что эти «второстепенные» выборы – главная часть того масштабного процесса, который каждые четыре года дает нам президента. А «главные» президентские выборы – лишь последнее звено длинной цепи предшествующих им событий. Организация, способная избрать своего кандидата в городской совет, объединяется с множеством других таких же, для того, чтобы избрать президента страны. Если граждане не участвуют во «второстепенных» выборах, то на выборах в президенты они будут выбирать между кандидатами, вроде Кокса и Хардинга (одни из самых непопулярных президентов Америки – прим. перев.), или из их последователей. Невозможно влиять на политику, ограничиваясь лишь участием в президентских выборах.
К тому же, многие участвующие во второстепенных выборах кандидаты имеют шанс когда-нибудь стать президентами. Четырнадцать наших президентов начали свою правительственную карьеру с постов законодателей штата – от Джона Адамса до Рузвельта. Хайес начинал как глава городского юридического управления, Линкольн – как главный почтальон, Кливленд и Тафт были помощниками прокурора, Кулидж – членом городского совета, Трумэн – областным судьей, Бенджамин Харрисон — помощником судьи, а Джонсон начинал городским олдерменом. Время, за которое политик может пройти путь от «второстепенного» поста до президента, совсем невелико, в среднем – двадцать пять лет. Некоторые проходят этот путь за двадцать лет. (Цифры не учитывают случаев, вроде Вильсона, Гувера, или Гранта, которые подались в политику, уже сделав карьеру на другом поприще).
Возможно, тот, кто через двадцать лет станет президентом, живет в вашем округе, и именно вы можете стать тем, кто уговорит его баллотироваться на его первый выборный пост. Даже если этого не случится, в любом случае очень велики шансы на то, что будущий президент начнет свой путь с одной из тех самых второстепенных выборных должностей, которые так презирают политические дилетанты.
Так что если вы хотите определять судьбу своей страны, начните с получения власти на своем избирательном участке, после чего, объединившись с соратниками, добейтесь влияния в своем округе, и изберите устраивающие вас местные власти.
И другого пути – нет!
-> Часть 1, где есть ссылки на все остальные части
Метки: author sunman читальный зал хайнлайн политика |
Дайджест свежих материалов из мира фронтенда за последнюю неделю №273 (24 — 30 июля 2017) |
|
Обратная сторона Spring |
Неделя Spring на Хабре, судя по всему, открыта. Хочется сказать спасибо переводчику и комментаторам статьи "Почему я ненавижу Spring", которая не смотря на сильный негативный посыл в названии вызвала ряд интересных дискуссий, а так же тем, кто отреагировал на мою прошлую статью Как писать на Spring в 2017. Во многом благодаря комментариям к прошлой статье и появилась эта.
В этот раз мы погрузимся в пучины Spring фреймворка, разоблачим его магию, посмотрим как базовое веб приложение выглядит изнутри, и разберемся, какую-же задачу и как решает Spring Boot.
В комментариях к предыдущей статье несколько человек очень справедливо указали, что пример Hello World-а на Spring все же не очень показателен. Spring, особенно с использованием Spring Boot, дает ощущение простоты и всемогущества, но непонимание основ и внутренностей фреймворка ведет к большой опасности получить стектрейсом по логу. Что ж, чтобы немного развеять ощущение полной магии происходящего, сегодня мы возьмем приложение из предыдущей статьи и разберем, как и что происходит внутри фреймворка и от каких проблем нас отгораживает Boot. Целевая аудитория все же начинающие разработчики, но с некоторым опытом и базовыми знаниями Java и Spring. Хотя, возможно, и опытным пользователям Spring будет интересно освежить знания того, что происходит под капотом.
Начнем срывать покровы с самых базовых понятий Spring. Бин (bean) — это не что иное, как самый обычный объект. Разница лишь в том, что бинами принято называть те объекты, которые управляются Spring-ом и живут внутри его DI-контейнера. Бином является почти все в Spring — сервисы, контроллеры, репозитории, по сути все приложение состоит из набора бинов. Их можно регистрировать, получать в качестве зависимостей, проксировать, мокать и т.п.
Ключевой и фундаментальный механизм Spring. Внешне очень простой, но внутри он предоставляет очень много механизмов для тонкой настройки зависимостей. По сути, любое приложение Спринг — это набор бинов, связанных вместе через DI контейнер.
Очень часто при обсуждении Spring звучит аргумент, что его можно легко заменить на любой леговесный DI контейнер (Guice, например) и получить то же самое, но легче и проще. И здесь очень важно понять — ценность Spring DI не в самом факте его наличия, а в его фундаментальности. Все библиотеки в экосистеме Spring, по сути, просто регистрируют свои бины в этом контейнере (включая и сам Spring) — и через иньекцию зависимостей разработчики приложения смогут получить нужные компоненты. Простой пример: при использовании Spring Security OAuth если сконфигурить параметры OAuth в application.properties
, то Spring Security предоставит бин OAuth2RestTemplate
который мы можем просто заинжектить в своем коде. И этот бин при обращении к внешнему API будет знать, куда и как пойти, чтобы получить OAuth токен, как его обновлять, в какое место нашего запроса его добавлять и т.п. Так вот ценность DI тут в том, что это просто механизм общения между нашим кодом и Spring Security. И простой заменой реализации DI на Guice не добиться, чтобы Spring Security тоже начал его использовать. А если в этом новом DI не будет интеграции со всеми библиотеками Spring-а, то и ценность его сильно падает.
Еще один очень важный момент, который многие упускают при обсуждении DI контейнера, это то, что использование инъекции зависимостей не подразумевает создания интерфейсов для каждого компонента. Это очень простая мысль, но я много раз видел, что из-за своей простоты она не всегда очевидна. Более того, создание интерфейса, если у него лишь одна реализация — считается плохой практикой. Т.е. классы вполне могут сами по себе быть объектами DI. Более того, отсутствие интерфейса даже не мешает их мокать в тестах, т.к. Mockito, например, вполне умеет мокать классы.
Представлен интерфейсом ApplicationContext
. По сути, представляет собой само приложение Spring. Так же контекст предоставляет возможности реагировать на различные события, которые происходят внутри приложения, управлять жизненным циклом бинов (создавать как синглтон или на каждый запрос, например).
Итак, если приложение — это набор бинов, чтобы оно заработало нам нужно этот набор описать.
Конфигурация — это просто описание доступных бинов. Spring дает несколько вариантов, как можно описать набор бинов, которые сформируют приложение. Исторический вариант — это через набор xml файлов. В наши дни ему на смену пришли Java аннотации. Spring Boot построен на аннтациях чуть более, чем полностью и большинство современных библиотек в принципе тоже можно сконфигурить через аннотации. В третьем своем поколении, конфигурация бинов пришла к подходу функциональной регистрации (functional bean registration), которая станет одной из важных новых фич готовящегося к выходу Spring 5.
Типичный класс конфигурации может, выглядеть, например так:
@Configuration
class PaymentsServiceConfiguration {
@Bean
public PaymentProvider paymentProvider() {
return new PayPalPaymentProvider();
}
@Bean
public PaymentService paymentService(PaymentProvider paymentProvider) {
return new PaymentService(paymentProvider);
}
}
Эта конфигурация определяет два бина, причем второй зависит от первого. И здесь в игру вступит Spring – когда мы просим предоставить инстанс PaymentProvider
— Spring найдет его в контексте и предоставит нам.
Конфигурацию не обязательно описывать в одном огромном файле, можно разбить на несколько и объединять их с помощью @Import
аннотаций.
Достаточно важный компонент Spring Framework, еще один подход к упрощению конфигурации приложения. Идея очень простая — если мы знаем, что наш класс MyCoolComponent
должен регистрировать бин с именем myCoolComponent
, зачем каждый раз писать @Bean MyCoolComponent myCoolComponent(dependencies...) { return new MyCoolComponent(dependencies...); }
? Почему просто не дать Spring–у автоматом зарегистрировать и создать бин на основании нужного класса? Эту задачу и решает сканирование компонентов. Т.е. если мы объявим наш класс как
@Component
class MyCoolComponent {
MyCoolComponent(dependencies...) {
}
}
и разрешим сканирование компонентов — то Spring сам создаст и зарегистрирует бин с именем myCoolComponent
, использовав конструктор класса и заинжектив туда все зависимости.
Со сканированием компонентов надо быть осторожным, т.к. по сути оно неявно меняет контекст приложения. Например, если у нас есть интерфейс и две реализации — и на каждом указан @Component
, то при попытке заинжектить зависимость на интерфейс Spring бросит исключение, что есть два бина, которые удовлетворяют запросу.
Итак, вещи которые нужно запомнить: приложение Spring, описанное интерфейсом ApplicationContext
, представляет собой набор объектов (бинов), управляемых DI контейнером. Конфигурация набора бинов осуществляется с помощью классов конфигурации (аннотация @Configuration
), которые могут быть комбинированы с помощью импортов (аннотация @Import
).
Теперь переходим к следующей части. Допустим, нам надо сконфигурить подключение к MySQL базе данных. Если мы хотим использовать Spring Data JPA с Hibernate в качестве провайдера, нам потребуется сконфигурировать несколько бинов — EntityManagerFactory
(основной класс JPA), DataSource
для подключения непосредственно к базе через JDBC драйвер и т.п. Но с другой стороны, если мы это делаем каждый раз и, по сути, делаем одно и то же — почему бы это не автоматизировать? Скажем, если мы указали строку подключения к базе и добавили зависимость на MySQL драйвер — почему бы чему-то автоматически не создать все нужные бины для работы с MySQL? Именно это и делает Spring Boot. По сути, Spring Boot это просто набор классов конфигурации, которые создают нужные бины в контексте. Точно так же их можно создать руками, просто Boot это автоматизирует.
Важное понятие Spring Boot это автоконфигурация. По сути, это просто набор конфигурационных классов, которые создают и регистрируют определенные бины в приложении. По большому счету, даже сам Embedded Servlet Container — это просто еще один бин, который можно сконфигурировать! Пара важных моментов, которые важно знать об автоконфигурации:
@EnableAutoConfiguration
application.properties
и т.п.DataSource
— автоконфигурация не будет его перекрыватьЛогика при регистрации бинов управляется набором @ConditionalOn*
аннотаций. Можно указать, чтобы бин создавался при наличии класса в classpath (@ConditionalOnClass
), наличии существующего бина (@ConditionalOnBean
), отсуствии бина (@ConditionalOnMissingBean
) и т.п.
Spring Boot активно использует эти аннотации чтобы оставаться как можно более незаметным и не перекрывать пользовательские конфигурации.
Теперь, имея в запасе базовые теоретические знания, разберем что же происходит при запуске приложения.
Итак, наше приложение включает такой код:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Давайте разберем что здесь происходит по шагам.
DemoApplication
Этот класс помечен аннотацией @SpringBootApplication
, что является мета-аннотацией, т.е. по сути, является алиасом для нескольких аннотаций:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
. Т.е. наличие @SpringBootApplication
включает сканирование компонентов, автоконфигурацию и показывает разным компонентам Spring (например, интеграционным тестам), что это Spring Boot приложение
Это просто хелпер, который делает пару вещей — используя список предоставленных конфигураций (а класс DemoApplication
сам по себе конфигурация, см. выше) создает ApplicationContext
, конфигурирует его, выводит баннер в консоли и засекает время старта приложения и т.п. Его можно заменить на ручное создание контекста: new AnnotationConfigApplicationContext(DemoApplication.class)
. Как можно понять из названия, это контекст приложения, который конфигурируется с помощью аннотаций. Однако, этот контекст не знает ничего об embedded servlet container-ах, и совершенно точно не умеет себя запускать. Его наследник, уже из Spring Boot — AnnotationConfigEmbeddedWebApplicationContext
делать это вполне умеет, и если мы в методе main
напишем просто
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext =
new AnnotationConfigEmbeddedWebApplicationContext(DemoApplication.class);
}
}
То получим точно такое же работающее приложение, т.к. класс AnnotationConfigEmbeddedWebApplicationContext
найдет в контексте бин типа EmbeddedServletContainerFactory
и через него создаст и запустит встроенный контейнер. Обратите внимание, что все это работает в рамках общего DI контейнера, то есть этот класс можно реализовать самим.
Эта аннотация включает автоконфигурацию. И здесь, пожалуй, ключевой момент в развенчании магии Spring. Вот как объявлена эта аннотация:
...
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
Т.е. это самый обычный импорт конфигурации, про который мы говорили выше. Класс же EnableAutoConfigurationImportSelector
(и его преемник в Spring Boot 1.5+ — AutoConfigurationImportSelector
) это просто конфигурация, которая добавит несколько бинов в контекст. Однако, у этого класса есть одна тонкость — он не объявляет бины сам, а использует так называемые фабрики.
Класс EnableAutoConfigurationImportSelector
смотрит в файл spring.factories
и загружает оттуда список значений, которые являются именами классов (авто)конфигураций, которые Spring Boot импортирует.
Кусочек файла spring.factories
(он находится в папке META-INF
внутри spring-boot-autoconfigure.
), который нам сейчас нужен это:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
... (100 lines)
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
Т.е. аннотация @EnableAutoConfiguration
просто импортирует все перечисленные конфигурации, чтобы предоставить нужные бины в контекст приложения.
По сути, ее можно заменить на ручной импорт нужных конфигураций:
@Import({
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration.class,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration.class,
...})
public class DemoApplication {
...
}
Однако, особенность в том, что Spring Boot пытается применить все конфигурации (а их около сотни). Я думаю, у внимательного читателя уже появилась пара вопросов, которые стоит прояснить.
"Но это же медленно!". И да, и нет — под рукой нет точных цифр, но сам по себе процесс автоконфигурации очень быстрый (порядка сотни миллисекунд на абстрактной машине в вакууме)
RabbitAutoConfiguration
) если я его не использую?". Наличие автоконфигурции не значит, что бин будет создан. Автоконфигурационные классы активно используют @ConditionalOnClass
аннотации, и в большинстве случаев конфигурация ничего делать и создавать не будет (см. выше "Условия и порядок регистрации бинов").В основе "магии" Spring Boot нет ничего магического, он использует совершенно базовые понятия из Spring Framework. В кратком виде процесс можно описать так:
@SpringBootApplication
включает сканирование компонентов и авто-конфигурацию через аннотацию @EnableAutoConfiguration
@EnableAutoConfiguration
импортирует класс EnableAutoConfigurationImportSelector
EnableAutoConfigurationImportSelector
загружает список конфигураций из файла META-INF/spring.factories
AnnotationConfigEmbeddedWebApplicationContext
ищет в том же DI контейнере фабрику для запуска embedded servlet containerЭто может выглядеть сложно, но по большей части разработчикам приложений влезать во внутренности автоконфигурации не нужно, если речь не идет о поддержке авто-конфигурации для своей библиотеке.
В случае, когда что-то идет не так, Spring Boot позволяет запустить диагностику автоконфигурации и посмотреть, какие именно бины были созданы. Чтобы увидеть эту информацию, нужно запустить приложение с ключом --debug
.
java -jar my-app.jar --debug
В ответ Spring выдаст детальный Auto-configuration report:
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
DataSourceAutoConfiguration#dataSourceInitializer matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition)
...
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
...
Строчка в Positive / Negative matches будет для каждой примененной автоконфигурации, более того, Boot сообщит, почему тот или иной бин был создан (т.е. укажет, какие из условий регистрации были выполнены).
Spring Boot Actuator это мощный инструмент диагностики работающего приложения, который умеет давать много полезной аналитики (более того, набор этих метрик можно легко расширять из приложения).
После добавления Actuator к проекту, Spring Boot опубликует список доступных бинов через URL http://localhost:8080/beans
. Этот список так же доступен через JMX (Java Management Extensions), и последняя версия Intellij IDEA умеет показывать все бины приложения прямо из окна запуска.
Spring все же остается большим и не самым простым фреймворком, но это цена высокоуровневых абстракций, которые он предоставляет. И хотя знать все тонкости работы фреймворка в ежедневной разработке не нужно, знать, как он работает изнутри, все же, полезно. Надеюсь, что эта статья помогла понять важность и ценность Spring именно как экосистемы и убрала немного "магичности" в происходящем, особенно при использовании Spring Boot. Мой совет — не бойтесь углубляться в недра фреймворка, читайте исходники и документацию, благо они у Spring-a почти эталонные, на мой взгляд.
Так же стоит отметить, что в готовящемся к выходу в сентябре Spring 5 появится несколько новых концепций, направленных на создание простых приложений, и понижение уровня "магии" (хотя, как мы выяснили, магии там особо и нет). Одна из концепций это Functional Bean Registration, которая позволяет регистрировать бины в контексте с помощью функций, или даже с помощью неплохого DSL на Kotlin (а Spring 5 добавит много хорошего для поддержки Kotlin). Следующая, но еще более важная вещь, это комбинация Functional Web Framework и WebFlux (reactive web framework), которая позволит создавать веб-приложения вообще без зависимости на Spring MVC и запускать их без сервлет контейнеров. Приложение вполне сможет работать без контекста приложений и DI, и описываться просто как набор функций request -> response
. Об этом можно чуть больше почитать здесь (на английском).
Метки: author alek_sys java spring framework spring boot |
Снапшоты GlusterFS |
Метки: author zirf настройка linux it- инфраструктура glusterfs snapshot linux |
Дайджест интересных материалов для мобильного разработчика #214 (24 — 30 июля) |
![]() |
Тестирование в Badoo «с высоты птичьего полёта» |
![]() |
TamTam: как мы делали новый мессенджер |
|
IaaS-дайджест: 30 материалов о работе с ПД, новых технологиях, ИБ и высокой производительности |
На Хабре мы рассказываем не только о собственном опыте, но и делимся межотраслевыми событиями. Здесь речь идет о новом законодательстве в сфере хранения персональных данных граждан КНР и необходимости ему соответствовать. Apple — активно инвестирует в одну из китайских провинций и выходит на «передовую» сотрудничества с местным правительством.
Дата-центр в «нескольких кубах сахара» — план Microsoft на 2020 год. Кто и как над этим работает, и чего все-таки ждать — в нашей заметке на Хабре.
Рассказываем о коллаборации IT-гигантов, которые предлагают стандартизировать подход к созданию ЦОД. Для этого они создали специальную рабочую группу.
Разбираемся с альтернативными решениями для охлаждения дата-центров, говорим о естественных формах охлаждения и вариантах с использованием искусственного интеллекта.
Немного теории по теме Tier'ов, рассказ о классификации Uptime Institute и объяснение логики выбора нужного подхода для применения на собственном дата-центре.
Гостевой материал от Stratoscale с обсуждением и сравнением моделей. Все это на основе мнений нескольких десятков экспертов, представляющих самые разные ИТ-компании.
Говорим о требованиях к ИТ-инфраструктуре, разбираемся с Business Critical Application (BCA) и соответствующих решениях от VMware (vSphere 6.5, vMotion, VMware DRS и др.).
Пишем о том, как это работает, какие есть варианты для решения различных задач, разбираем основные плюсы и минусы. Материал из нашего блога о корпоративном IaaS.
Немного о том, «с чем это едят» — на реальных примерах наших клиентов. Подробно рассказываем о составляющих услуги и возможностях для решения ваших задач.
Различные нюансы, связанные с предоставлением услуги.
Тематическая заметка в разрезе виртуальных дисков. О том, что из себя представляют политики хранилища вместе с примером использования Storage Policy.
Наш классический дайджест по теме vCloud и старта работы с IaaS.
Обсуждаем новые регламенты, которые приняли в 2016 году, и рассказываем о том, как персональные данные (ПД) переносят в облака.
Продолжение аналитического разбора ситуации с ПД, новым законодательством, соответствующими положениями «пакета Яровой» и практическими нюансами.
Дополнение к двум материалам, которые мы привели выше, рассказывающее о новых реалиях и оптимальных решениях в области работы с личной информацией в России и Европе.
Здесь мы рассматриваем уровни и классы защиты. Плюс говорим о требованиях, которым должен соответствовать облачный провайдер. Еще один материал нашего блога об IaaS.
Сразу после известных событий мы провели разбор принципа работы Petya и рассказали о том, как победить вирус и подготовить свою систему в его возможному возвращению.
Анализируем мнение о том, какие цели могли преследовать разработчики Petya-подобного шифровальщика. Эксперты предлагают подумать не о вымогательстве денежных средств, а об альтернативной версии — повреждении ИТ-систем.
Очередная подборка в формате IaaS-дайджеста, в котором найдете материалы об использовании облачных технологий в спорте, музыке, кино, автопроме, гейм-индустрии, электронной коммерции и даже в работе авиакомпаний и Формуле-1.
Немного о том, как в процессе создания 3D-моделей из нескольких изображений одного объекта, сфотографированного с разных ракурсов, можно использовать облачные технологии.
Виртуальная инфраструктура может быть применена на любом этапе проектирования, производства или обслуживания авто. Сегодня IaaS уже во всю используют в сфере «умных» автомобилей и тематических сервисах для автолюбителей.
Краткая заметка о планах компании, которая собирается открыть онлайн-доступ к своим квантовым машинам для ученых и исследователей ИИ. Говорим о том, зачем это нужно.
Немного о последователе 5-кубитного компьютера от IBM, работа с которым возможна с помощью облачной платформы IBM Cloud.
Итоги выставки Computex 2017 для Intel, представившей серию Core X.
Заметка о новинке, разработанной совместно с Samsung и GlobalFoundries.
Рассказываем о совместных разработках команды исследователей MIT и других стран.
Немного о новом заказе, который получит DARPA. Что будут делать и зачем.
Говорим о сложностях, с которыми сталкиваются руководители технической команды и их подопечные. Здесь мы обсуждаем то, как можно уничтожить любые гениальные вещи.
Мегаподборка материалов нашего блога о корпоративном IaaS. Здесь собраны руководства, практические советы по ИБ, сетям и железу. Плюс мы привели наиболее интересные кейсы в сфере взаимодействия бизнеса и IaaS-провайдера.
Почему инвесторы доверили 16 миллионов долларов Фалон Фатеми (Falon Fatemi), основателю и руководителю проекта, который намеревается стать чем-то вроде «Google для смысла».
Метки: author it_man разработка под e-commerce блог компании ит-град ит-град цод дата-центр высокая производительность |
[Из песочницы] Пишем игру змейка с помощью JavaScript + Canvas |
//Возвращает случайное число.
function rand (min, max) {k = Math.floor(Math.random() * (max - min) + min); return (Math.round( k / s) * s);}
//Функция для создания нового яблока.
function newA () {a = [rand(0, innerWidth),rand(0, innerHeight)];}
//Функция для создания тела змейки из одного элемента.
function newB () {sBody = [{x: 0,y: 0}];}
var gP = document.getElementById('gP'), //Достаем canvas.
//Получаем "контекст" (методы для рисования в canvas).
g = gP.getContext('2d'),
sBody = null, //Тело змейки, мы потом его создадим.
d = 1, //Направление змейки 1 - dправо, 2 - вниз 3 - влево, 4 - вверх.
a = null, //Яблоко, массив, 0 элемент - x, 1 элемент - y.
s = 30; newB(); newA(); //Создаем змейку.
gP.width = innerWidth; //Сохраняем четкость изображения, выставив полную ширину экрана.
gP.height = innerHeight; //То же самое, но только с высотой.
setInterval(function(){
g.clearRect(0,0,gP.width,gP.height); //Очищаем старое.
g.fillStyle = "red"; //Даем красный цвет для рисования яблока.
g.fillRect(...a, s, s); //Рисуем яблоко на холсте 30x30 с координатами a[0] и a[1].
g.fillStyle = "#000"; //А теперь черный цвет для змейки.
}, 60);
sBody.forEach(function(el, i){
//Проверка на то, что яблоко ушло за границы окна, мы его не можем увидеть.
if (a[0] + s >= gP.width || a[1] + s >= gP.height) newA();
//Проверка на столкновение.
var last = sBody.length - 1;
if ( el.x == sBody[last].x && el.y == sBody[last].y && i < last) {
sBody.splice(0,last); //Стираем тело змейки.
sBody = [{x:0,y:0}]; //Создаем его заново.
d = 1; //Меняем направление на правую сторону.
}
});
//+
// Сохраняем хвост и голову змейки.
var m = sBody[0], f = {x: m.x,y: m.y}, l = sBody[sBody.length - 1];
/*
Далее мы создаем тот самый эффект движения.
Напомню, что мы меняем координаты лишь хвоста, оставляя неподвижным
остальную часть тела.
Делается это путем проверки направления змейки (изначально - это 1, - право),
а затем уже изменяем координаты. Соответственно, комментарии все описывают.
*/
//Если направление вправо, то тогда сохраняем Y, но меняем X на + s.
if (d == 1) f.x = l.x + s, f.y = Math.round(l.y / s) * s;
// Если направление вниз, то сохраняем X, но меняем Y на + s.
if (d == 2) f.y = l.y + s, f.x = Math.round(l.x / s) * s;
//Если направление влево, то сохраняем Y, но меняем X на -s.
if (d == 3) f.x = l.x - s, f.y = Math.round(l.y / s) * s;
//Если направление вверх, то сохраняем X, Но меняем Y на -s.
if (d == 4) f.y = l.y - s, f.x = Math.round(l.x / s) * s;
sBody.push(f); //Добавляем хвост после головы с новыми координатами.
sBody.splice(0,1); //Удаляем хвост.
//Отрисовываем каждый элемент змейки.
sBody.forEach(function(pob, i){
//Если мы двигаемся вправо, то если позиция элемента по X больше, чем ширина экрана, то ее надо обнулить
if (d == 1) if (pob.x > Math.round(gP.width / s) * s) pob.x = 0;
//Если мы двигаемся вниз, то если позиция элемента по X больше, чем высота экрана, то ее надо обнулить.
if (d == 2) if (pob.y > Math.round(gP.height / s) * s) pob.y = 0;
//Если мы двигаемся влево, и позиция по X меньше нуля, то мы ставим элемент в самый конец экрана (его ширина).
if (d == 3) if (pob.x < 0) pob.x = Math.round(gP.width / s) * s;
//Если мы двигаемся вверх, и позиция по Y меньше нуля, то мы ставим элемент в самый низ экрана (его высоту).
if (d == 4) if (pob.y < 0) pob.y = Math.round(gP.height / s) * s;
//И тут же проверка на то, что змейка съела яблоко.
if (pob.x == a[0] && pob.y == a[1]) newA(), sBody.unshift({x: f.x - s, y:l.y})
//А теперь рисуем элемент змейки.
g.fillRect(pob.x, pob.y, s, s);
});
//setInerval(...);
onkeydown = function (e) {
var k = e.keyCode;
if ([38,39,40,37].indexOf(k) >= 0) e.preventDefault();
if (k == 39 && d != 3) d = 1; //Вправо
if (k == 40 && d != 4) d = 2; //Вниз
if (k == 37 && d != 1) d = 3; //Влево
if (k == 38 && d != 2) d = 4; //Вверх
};
Метки: author kinojs javascript html canvas html5 gamedev snake |
Биомеханика и искусственный интеллект в медицине. Лекция на YaC 2017 |
Метки: author Leono машинное обучение блог компании яндекс искусственный интеллект нейронные сети медицина медицина будущего спорт машинный интеллект виртуальная реальность |
Быстрые сетки для верстальщиков |
Любому верстальщику, перед которым встала очередная задача по вёрстке адаптивного макета, нужны сетки. В большинстве случаев берётся старый добрый bootstrap, и в html-ке начинают появляться div-ы с классами вида
col-xs-6 col-sm-4 col-md-3
. И вроде бы всё хорошо и быстро, но в данном подходе часто возникает множество подводных камней. В данной статье мы рассмотрим эти подводные камни, и закидаем тухлыми помидорами рассмотрим мою поделку для беспроблемных сеток.
Итак, у нашего верстальщика очень мало времени, макет горит, всё надо сделать вчера. Поэтому, он берёт для основы популярный css-фреймворк bootstrap, и начинает свою работу. И тут, в середине работы, он вдруг натыкается на блок баннеров "5 в ряд". Все, кто работал с bootstrap знает, что его сетка по умолчанию 12-кратная, поэтому 5 колонок в ряд стандартной бутстраповской сеткой ну никак не сделаешь. Да, конечно, в бутстрапе можно собрать произвольную сетку, но это время терять, качать зависимости, собирать less-ки (а мы, допустим, пишем на sass).
Может подключить какую-нибудь библиотеку для настраиваемых сеток? В целом это хороший выход, единственный минус данного подхода, что практически все из них рассчитаны либо на долгое и нудное написание @media(min-width:){}
, либо генерируют свой набор классов, с кучей, наверняка не нужных col15-xs-offset-3
, которые попадут в итоговую css-ку.
Поэтому, с большой вероятностью, верстальщик просто пропишет все стили вручную (там, в принципе, не так много писать).
Очень часто в стандартной бутстраповской сетке не хватает дополнительных брейкпоинтов, т. е. есть xs, sm, md, lg — все они до ширины 1200px. А как же большие мониторы? Какой-нибудь брейкпоинт xl на 1600px так и просится в стандартный набор. Но его опять же нет, и возникают те же варианты решения, что и в предыдущем пункте. А ведь контрольных точек может быть очень много — 320, 360, 640, 768, 992, 1200, 1600, 1900..
И тут мы плавно подходим к следующей проблеме. Представьте, что вам нужно прописать для каждой сетки свои размеры блока, тогда у вас получится что-то типа этого:
Не слишком ли много? Добавьте сюда возможные pull/push и visible/hidden и тогда можно смело начинать сходить с ума. А ведь все эти классы прописаны в css, представьте сколько нужно прописать классов в css для всех комбинаций 60-кратной сетки!
Любой верстальщик знает, что inline-стили — это плохо. Так зачем мы пишем в классы разметки то, что касается стилей? col-xs-6
, visible-sm
и не дай бог text-right
— это всё стили, и, если надо будет вносить правки в уже натянутую на вёрстку, обязательно возникнет проблема, что верстальщику придётся просить backend-щика поменять col-sm-6 на col-sm-4.
Часто css-фреймворк подключают весь только ради сеток и пары мелких функций, что вытекает впоследствии в избыточном сбросе стилей и двойном размере итогового css. Например, подключается весь bootstrap.min.css, а потом весело и задорно убираются тенюшки и закруглённые уголки у .btn, .form-control
и тому подобного, включая :hover, :focus, :first-child
. В итоге, вместо помощи, фреймворк начинает мешать. Не говоря уже о часто не нужных фичах, по типу .glyphicon
. Конечно, опять же можно собрать bootstrap из того, что нужно, но это опять время.
Допустим, верстальщик изучил БЭМ и начал его применять. Но необходимость использовать bootstrap диктует свои исключения — в нём все классы пишутся через дефис, не следуя принципам БЭМ. И тут возникает проблема выбора — либо смириться с мешаниной в названиях классов (btn-block disabled component__btn component__btn_disabled
), либо всё-таки выкинуть bootstrap.
Как известно, сетки в bootstrap 3 основаны на float-ах. Что часто вызывает проблемы, одна из наиболее частых — различная высота блоков, в результате которой красивая сетка "ломается". Хватит использовать float-ы не по назначению, уже практически вымерли все браузеры, которые не умеют flexbox!
В поиске решения всех перечисленных выше проблем, я наткнулся на замечательный сеточный фреймворк Susy!, в целом очень хороший. Но мне не хватало скорости, т. к. susy! предлагал описывать колонки для каждого брейкпоинта отдельно:
.col {
@media (min-width: 768px) {
@include gallery(4 of 12);
}
@media (min-width: 1200px) {
@include gallery(3 of 12);
}
}
То есть susy! предполагает, что брейкпоинтами вы будете заниматься самостоятельно. Кроме того, susy! сам не пишет за вас display: flex
для, строк, вам нужно их не забывать прописывать самостоятельно. Отступы между колонками в нём задаются только относительные (сделать фиксированные в пикселях не получится). Также, он совсем недавно научился flex, а до этого он строил сетки на float
и :nth-child()
. В общем, susy! это хорошо, но хотелось бы скорости и лёгкости описания сеток для всех брейкпоинтов, как это было с bootstrap.
Поиск других сеточных систем также не давал особо результата — все либо идут по пути susy!, забывая про breakpoints, либо идут по пути bootstrap, предоставляя набор сгенерированных классов для руления сетками в html.
Итак, решено было написать что-то своё, в результате родился fast-grid. Он также, как и susy, построен на sass. Какие же главные преимущества он предоставляет по сравнению с другими решениями, в частности, с susy!? В первую очередь скоростью за счёт меньшего количества кода, возьмем стандартный bootstrap пример:
1
2
С помощью fast-grid такую сетку очень легко описать:
@import "~fast-grid/fast-grid";
.row {
@include grid-row();
}
.col {
@include grid-col(6 4 3 2);
}
https://codepen.io/PaulZi/pen/EvPbWK
Давайте теперь пройдёмся по нашим недостаткам, и увидим как fast-grid решает все эти проблемы.
Легко:
@import "~fast-grid/fast-grid";
.cols {
$grid: (
gap: 5px
);
@include grid-row($grid);
&__item {
@include grid-col(12 6 null (1 of 5), $grid);
}
}
https://codepen.io/PaulZi/pen/gxPXJq
@import "~fast-grid/fast-grid";
.cols {
$grid: (
breakpoints: (
xxs: 0px,
xs: 360px,
sm: 640px,
md: 960px,
lg: 1200px,
xl: 1600px
),
columns: 60
);
@include grid-row($grid);
&__item {
@include grid-col((xxs: 60, xs: 30, sm: 20, md: 15, lg: 12), $grid);
}
}
https://codepen.io/PaulZi/pen/XaXVmg
fast-grid это сеточный фреймворк для использования в css, а не в html на основе сгенериронных наборов классов. Благодаря этому разметка становится отделена от стилей, что благотворно отражается на дальнейшей поддержке. Также благодаря этому нет необходимости генерировать кучу вспомогательных классов (.col-xs-push-4
и т. п.), которые по большей части не используются.
Так как fast-grid — это набор mixin-ов, сам он не генерирует ни одного правила в css. Поэтому тут вы не столкнётесь с тем, что фреймворк стилизует элементы так как вам не надо. Да и вообще, это только сетки, и ничего больше.
fast-grid — это mixin-ы, которые вы должны использовать внутри ваших классов, с такими наименованиями, которые вы сами предпочитаете. Любите БЭМ? Не вопрос!
По умолчанию используется flexbox, что открывает множество возможностей и решает проблемы классических float. Например, можно легко менять порядок колонок.
В примере ниже, мы выводим сайдбар ниже основного содержимого для мобильной версии, и делаем его первым блоком на больших экранах:
https://codepen.io/PaulZi/pen/yoepbg
Можно было бы конечно этого добиться с помощью pull/push для float, но это очень костыльно.
В целом, поставленная для меня задача была выполнена — теперь сетки для меня больше не вызывают никаких проблем, и вёрстка идёт быстро и легко. Больше о возможностях fast-grid вы можете почитать в репозитарии и рассмотреть на примерах:
GitHub: https://github.com/paulzi/fast-grid
Примеры: https://paulzi.github.io/fast-grid/
Вы всё ещё используете bootstrap? Тогда мы идём к вам!
Метки: author PaulZi разработка веб-сайтов css sass grid |
[Из песочницы] Фрод: что это, откуда берется и как бороться |
Фрод — язва электронной коммерции. Любая компания, которая принимает платежи на своем сайте, рано или поздно сталкивается с проблемой фрода и несет от него убытки. Чтобы оградить себя от фрода нужно постоянно держать наготове защитные механизмы и процедуры, а также регулярно проверять их эффективность. Предлагаю разобраться что к чему.
По-простому, фрод (с англ. fraud, «обман») — это когда нехороший человек оплачивает услуги ворованным платежным средством. Обычно это — кредитная карта, но иногда Фрод бывает и с PayPal.
Рассмотрим практический пример Фрода:
Степан — обычный человек. Доверчивый, немного наивный. Предложения увеличить доход на 10 сантиметров в месяц задевают Степана за больное место, и он оплачивает курс по увеличению дохода. Но он не учел, что сайт, на котором он производил оплату, — небезопасный, и данные его банковской карты перехватываются мошенником.
Мошенник ищет способы «слить» полученные деньги, находит продавца и покупает у него продукт за $100 с украденной карты. Совет 1: всегда хорошо иметь anti-fraud систему, которая определит Мошенника и не позволит ему даже совершить оплату на сайте.
Продавец — еще зеленый новичок, поэтому любая продажа для него — шампанское и овации. Он еще не верит во Фрод, поэтому идет к своему поставщику и покупает продукт за $80, который позже продает мошеннику, не имея ни малейшего понятия о том, что он на самом деле мошенник, а деньги ворованные. На первый взгляд, продавец заработал $20 и всё хорошо. Увы, ненадолго. Совет 2: без тщательной проверки платежа нельзя рассчитываться с партнерами.
Прошел месяц и Степану что-то невесело — доход не увеличился, а даже наоборот — деньги с банковской карты активно пропадают. Степан нервно смотрит выписку по счету и пытается понять, куда же деваются его кровно заработанные: «Так, это $100 за курс по увеличению дохода, это $20 за ужин в ресторане… А это еще что за $100? В это время я спал, я не мог совершить этот платеж, да и не заказывал я кроссовки на Амазоне!»
Степан в панике бежит в свой банк и слезно просит вернуть деньги.
Итоги истории:
Если бы саму карточку украли — всё было бы понятно. Но как можно украсть данные карточки, которую Степан постоянно носит в кошельке?
Вот основные способы:
Степан вводит данные своей карты на сайте с низким уровнем защиты (например, без SSL-сертификата) и их перехватывает мошенник.
Степан переходит по ссылке и логинится в свой кошелек PayPal, но не замечает, что адрес домена — pavpai.com. Благодаря фальшивой странице, мошенник получает доступ к кошельку Степана и может им распоряжаться по своему усмотрению. Такие подставные сайты называют фишинг.
Степан вставил свою карту в банкомат, который оборудован скимминговым устройством. Устройство считало данные его карты и теперь у мошенника полный доступ.
Степан не позаботился о безопасности своего кошелька и в качестве пароля от интернет-банкинга установил дату своего рождения. Так как Степан — человек публичный и информация о дате его рождения общедоступна, мошеннику было несложно подобрать пароль.
Мы не единственная компания в мире, которая страдает от Фрода и от мошенников. Это настолько большая проблема, что ей занимаются целые государственные департаменты.
В самой основе современной финансовой индустрии лежат политики противодействия мошенничеству, отмыванию денег и финансированию терроризма.
AML расшифровывается как anti-money-laundering. По-русски — противодействие отмыванию денег. Это набор процедур, законов и правил, которые нужны для того, чтобы граждане не получали доход нелегальным путем. Политики AML рекомендуют внедрять бизнесам во всем мире, как в личных интересах, так и в интересах международной борьбы с экономической преступностью.
Очень понятный и актуальный список рекомендаций придумали на съезде саммита G7 в 1989 году. Сделаю небольшую выдержку из пункта 5, которым руководствуемся мы:
В двух словах по-русски:
KYC (Know Your Customer), по-русски — знай своего клиента. Это часть процедуры CDD, которую должны выполнять финансовые учреждения и другие регулируемые компании. Она помогает -защититься от отмывания денег. Ее основные цели и функции:
В разных странах есть законодательно принятые KYC процедуры. То есть мы не просто имеем право требовать документы, а просто обязаны это делать для соблюдения закона и снижения своих финансовых рисков.
CTF (Counter-terrorist financing), по-русски — борьба с финансированием терроризма. Что это такое, думаю, и так понятно. Так как понятие терроризма в России и Украине в последнее время очень размытое и не имеет границ, жалоба может прийти буквально на любой сайт, который даже косвенно связан со терроризмом и т.п.
В случае с подобными проектами жалобы приходят сразу официальные и от правоохранительных органов нашей юрисдикции, на которые мы реагируем в соответствии с действующим законодательством.
На самом деле, в мире существует много политик и стандартов по борьбе с Фродом. В следующем разделе, я расскажу, как мы справляемся с Фродом в Unihost и какие правила мы из этой практики вывели.
Как вы уже поняли, фрод — это плохо. Давайте теперь конкретизируем это «плохо» и выделим перечень рисков, которые он несет для любой компании, а также Unihost, как для хостинг-провайдера.
Все финансовые риски за транзакцию несёт продавец, как получатель средств. А значит, ему и принимать меры для противодействия мошенничеству. И если эти меры недостаточны и продавец допустил неправомерную оплату средств, то при возврате средств банк накажет продавца штрафом в $20.
Советую ввести процедуру Customer Due Diligence для всех заказов.
На клиентов, которые используют услуги для неправомерных целей (продажа краденых кредитных карт, фишинг, DDoS-атаки и т.д.) приходят абузы. Абузы — это официальные запросы с требованием прекратить неправомерную деятельность.
Естественно, таких ненадежных клиентов нужно блокировать и возвращать им уплаченные средства. Естественно, это негативно влияет на нашу репутацию у платежного процессинга.
Наличие чарджбэков и возвратов средств плохо отражается на репутации у платежного процессинга. Кроме того, у любого процессинга существуют ограничения на объем рефандов в процентном показателе от месячного оборота и частоту рефандов. Превышение ограничений может привести к штрафным санкциям от платежного процессинга, вплоть до полного отказа сотрудничать. Советую лишний раз проверить клиента, чем потерять партнера — платежного процессера.
Правовые риски связаны с политикой противодействия отмыванию денег (AML) и несоответствия какому-либо закону или указу. Может включать в себя что угодно: начиная от штрафов, заканчивая уголовными делами.
В современном правовом поле СНГ, этот риск минимален. Но учитывать его всё равно стоит.
Чтобы минимизировать риски, внедряйте систему верификации клиента по CDD.
При обращении к нам мошенника, есть два варианта развития событий:
Приятный вариант. Запрашиваем документы у мошенника и определяем, что его карта ворованная (либо человек просто отказывается проходить верификацию или не отвечает на наше письмо). Делаем возврат средств как можно быстрее — это избавляет нас от потенциальной жалобы со стороны банка, а соответственно и от чарджбэков.
Чтобы максимально снизить риски, мы верифицируем сначала транзакцию, потом клиента, а потом его заказ. Первое защищает нас от уже известных мошенников, второе — от новоявленных, а третье — от абуз.
При новом заказе от неверифицированного клиента, мы:
Проверяем его по модулю FraudRecord. Это международная база ненадежных клиентов, мошенников и прочих нехороших.
Проверяем количество неудачных попыток оплаты. Если их менее двух — всё ОК. Если их больше — переходим к верификации клиента и ставим метку «подозрительный».
Проверяем, уникален ли IP клиента. Часто уже заблокированные из-за фрода клиенты создают новые аккаунты на другие имена.
При повторных заказах и продлениях, клиенту нужно пройти только пункт 2.
Верификация личности нужна для того, чтобы убедиться, что клиент является живым человеком и удостовериться, что платежный метод действительно принадлежит ему. Для этого мы запрашиваем у клиента документы, подтверждающие его личность.
Принимаются только документы государственного образца из следующего списка:
Мы тщательно проверяем все документы на соответствие госстандартам. Хотя зачастую подделка определяется с первого взгляда. Так, один из клиентов прислал паспорт с датой рождения «30 декабря 1792 года».
Для проверки платежного метода, мы требуем фото банковской карты (с видимой лицевой стороной, но закрытым CVV) или скриншот оплаты из PayPal, где видно, что оплата была совершена на нашем сайте. Этот пункт уже привычен многим.
Мы просим описать проект при заказе сервера или VPS. Причем простые «сайт для компании» или «сайт для клиента» мы отправляем обратно с просьбой рассказать подробнее: чем занимается клиент/компания, что будет размещено на сайте. Ведь клиентом может быть сайт детского порно, а это уже проблема.
Если проект планирует рассылать письма, мы требуем доказательства того, что база данных получателей была собрана самим клиентом, а сами получатели прошли double opt-in проверку.
Список проектов, которые мы не принимаем:
Нельзя сказать, что эти меры на 100% спасают от чарджбэков или абуз. Но они значительно снижают число мошенников, которые получают доступ к услугам. Поэтому, если ваша компани еще только на пути внедрения системы верификации клиентов и заказов, советую не экономить. Известно, что жадный платит всегда.
Я надеюсь, что однажды мы будем жить в мире, где можно будет принимать всё на веру. Но до тех пор, пока этот мир еще не наступил — верификация — единственный выход. Пускай это не самый красочный или популярный аспект деятельности сферы e-commerce, но это просто необходимо. Жаль, что честные клиенты также должны проходить проверку.
Метки: author unihost финансы в it фрод хостинг абузы abuse |
[Перевод] Пиратство и четыре валюты: Pay What You Want и Free-to-Play |
Метки: author PatientZero разработка игр пиратство pay what you want free-to-play f2p |
Google re:Work — Руководство: Постановка целей с помощью OKR (перевод) |
“Та вещь, что я видел в Google, и которую я определенно применил в Twitter, – это OKR – цели и ключевые результаты. Это отличный способ помочь всем в компании понять, что является важным и как вы собираетесь измерять это важное. Это, по сути, отличный способ коммуницировать стратегию и то, как вы собираетесь измерять стратегию. Вот так мы и используем их. Когда вы выращиваете компанию, самая сложная вещь для масштабирования это коммуникация. Это необыкновенно сложно. OKR – отличный способ убедиться, что все понимают, как вы собираетесь измерять успех и стратегию”.
Метки: author olegsergeykin управление проектами управление персоналом венчурные инвестиции agile okr продуктивность планирование google twitter intel |
Форма авторизации с отправкой зашифрованного пароля |
session_start();
//Присваиваем значение уникальный id если отсутствует
if(!isset($_SESSION['uniq'])||$_SESSION['uniq']=='')
$_SESSION['uniq']=uniqid();
//Запускаем шаблонизатор
require_once('engine.php');
$engine = new Template("tpl/");
$engine->display("header");
//Если отсутствует id сессии то показываем форму логина
if(!isset($_SESSION['id'])||$_SESSION['id']=="")
{
$engine->display('login');
}else
{
//считаем клиент уже авторизовался и отправляем его работать
$engine->display('pannel');
}
?>
require_once('libs/mysql.php');
//Проверяем введен логин или нет
if (isset($_POST['login'])&&$_POST['login']!='')
{
//Если да отправляем на проверку
$db=new Database_Module();
$db->CheckLogin($_POST['login'],$_POST['password']);
} else {
//иначе рисуем форму
//Скрипты JQuery для генерации MD5 хеша
//Функция генерации хеша
function CheckLogin($login,$md5pass)
{
try{
//Достаем хеш пароля из базы данных
$STH=$this->db->query("select password from users where email='$login'");
$STH->setFetchMode(PDO::FETCH_OBJ);
$val=$STH->fetch();
$pass=$val->password;
}
catch (PDOExeption $e){
echo $e->getMessage();
}
//Прибавляем к ней уникальный id полученный в индексе при посещении
$pass.=$_SESSION['uniq'];
//Получаем хеш этой гремучей смеси
$pass=md5($pass);
//Удаляем уникальный id чтоб в следующий раз пароли опять получились новые
unset($_SESSION['uniq']);
//Ну и сравниваем хеш
if(strcmp($md5pass,$pass)==0)
{
echo "Авторизация прошла успешно. Если вы не переместились на страницу обновите ее";
$_SESSION['id']=session_id();
}
//Обновляем страницу
echo "";
echo " ";
}
Метки: author RomanPogosyan jquery php mysql авторизация на сайт защита пароля |
[Из песочницы] Опыт разработки и продвижения игры на Android |
Метки: author SinQueen разработка мобильных приложений разработка игр google play продвижение реклама опыт ошибки |
Июльские бесплатные печеньки для дизайнеров и разработчиков |
|
Простейший генератор redux types для асинхронных запросов |
const CREATE_ITEMS = "CREATE_ITEMS";
const CREATE_ITEMS_START = "CREATE_ITEMS_START";
const CREATE_ITEMS_FINISH = "CREATE_ITEMS_FINISH";
const CREATE_ITEMS_ERROR = "CREATE_ITEMS_ERROR";
const GET_ITEMS = "GET_ITEMS";
const GET_ITEMS_START = "GET_ITEMS_START";
const GET_ITEMS_FINISH = "GET_ITEMS_FINISH";
const GET_ITEMS_ERROR = "GET_ITEMS_ERROR";
const DELETE_ITEMS = "DELETE_ITEMS";
const DELETE_ITEMS_START = "DELETE_ITEMS_START";
const DELETE_ITEMS_FINISH = "DELETE_ITEMS_FINISH";
const DELETE_ITEMS_ERROR = "DELETE_ITEMS_ERROR";
import reduxTypesCreator from "redux-types-creator";
const actionTypes = reduxTypesCreator(true) // true - object will be frozen.
('START', 'FINISH', 'ERROR') // postfix
('CREATE_ITEMS', 'GET_ITEMS', 'DELETE_ITEMS'); // types
console.log(actionTypes); // на выводе получим вот это
/*
{
CREATE_ITEMS: {
START: 'CREATE_ITEMS_START',
FINISH: 'CREATE_ITEMS_FINISH',
ERROR: 'CREATE_ITEMS_ERROR',
SELF: 'CREATE_ITEMS'
},
GET_ITEMS: {
START: 'GET_ITEMS_START',
FINISH: 'GET_ITEMS_FINISH',
ERROR: 'GET_ITEMS_ERROR',
SELF: 'GET_ITEMS'
},
DELETE_ITEMS: {
START: 'DELETE_ITEMS_START',
FINISH: 'DELETE_ITEMS_FINISH',
ERROR: 'DELETE_ITEMS_ERROR',
SELF: 'DELETE_ITEMS'
}
}
*/
// Создаем константы.
const { CREATE_ITEMS, GET_ITEMS, DELETE_ITEMS } = actionTypes;
CREATE_ITEMS.SELF // CREATE_ITEMS
CREATE_ITEMS.START // CREATE_ITEMS_START
CREATE_ITEMS.FINISH // CREATE_ITEMS_FINISH
CREATE_ITEMS.ERROR // CREATE_ITEMS_ERROR
// Пример использования в action creator
getItems = () => ({
type: CREATE_ITEMS.SELF
})
import reduxTypesCreator from "redux-types-creator";
import { takeEvery, put } from 'redux-saga/effects';
import { GET_REDDITS } from "../actions/Reddits";
const actionTypes = reduxTypesCreator(true) // true - object will be frozen.
('START', 'FINISH', 'ERROR') // postfix
('GET_REDDITS'); // types
const { GET_REDDITS } = actionTypes;
const getReddits = ({after, count } = {after: null, count: 0}) => ({
type: GET_REDDITS.SELF,
after,
count,
});
const getRedditsFetch = function* (action){
const { after, count } = action;
yield put({ type: GET_REDDITS.START });
try {
const url = `https://www.reddit.com/blablabla/.../`;
const result = yield fetch(url);
const json = yield result.json();
yield put({ type: GET_REDDITS.FINISH, data: json.data.children, after: json.data.after });
} catch (e) {
yield put({ type: GET_REDDITS.ERROR, error: e.message });
}
};
export const getRedditsSaga = function* () {
yield takeEvery(GET_REDDITS.SELF, getRedditsFetch)
};
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Метки: author ruslangavrilov reactjs javascript redux react es6 frontend frone-end ecmascript |
Doctrine Specification Pattern или ваш реюзабельный QueryBuilder |
class RegionRepository extends \Doctrine\ORM\EntityRepository
{
public function findAvailableRegions()
{
$qb = $this->createQueryBuilder('r');
return $qb
->join('r.houses', 'h')
->join('h.developer', 'd')
#Куча бесполезного дерьма start
->innerJoin('h.apartments', 'a') //Нам же только корректные дома нужны
->where('h.longitude IS NOT NULL') //и тут фильтруем
->andWhere('h.latitude IS NOT NULL') //блин, и тут
->andWhere('h.description IS NOT NULL') //бл*ть... это же регион.. нахера я думаю про дом здесь..
#Куча бесполезного дерьма end
#Куча бесполезного дерьма start
->andWhere('d.verified') //мне кажется я что-то делаю не так...
#Куча бесполезного дерьма end
->getQuery()
->getResult();
}
public function findAvailableRegionsByDeveloper(DeveloperCompany $developerCompany)
{
$qb = $this->createQueryBuilder('r');
return $qb
->join('r.houses', 'h')
->join('h.developer', 'd')
#Куча бесполезного дерьма start
->innerJoin('h.apartments', 'a') //Нам же только корректные дома нужны
->where('h.longitude IS NOT NULL') //и тут фильтруем
->andWhere('h.latitude IS NOT NULL') //блин, и тут
->andWhere('h.description IS NOT NULL') //бл*ть... это же регион.. нахера я думаю про дом здесь..
#Куча бесполезного дерьма end
->andWhere('d.id = :developer_id')
->setParameter('developer_id', $developerCompany->getId())
->getQuery()
->getResult();
}
}
class HouseRepository extends \Doctrine\ORM\EntityRepository
{
public function findAvailableHouses()
{
$qb = $this->createQueryBuilder('h');
return $qb
->join('h.developer', 'd')
->innerJoin('h.apartments', 'a') //фильтруем дома без квартир
->where('h.longitude IS NOT NULL') //без
->andWhere('h.latitude IS NOT NULL') //координат
->andWhere('h.description IS NOT NULL') //без описания
#опасна!!!
->where('d.verified') //черт, я ж в доме. нахера я думаю про застройщика тут...
->getQuery()
->getResult();
}
}
class DeveloperCompanyRepository extends \Doctrine\ORM\EntityRepository
{
public function findAvailableDevelopers()
{
return $this->createQueryBuilder('d')
->where('d.verified') //Дежавю........
->getQuery()
->getResult();
}
}
use Happyr\DoctrineSpecification\BaseSpecification;
use Happyr\DoctrineSpecification\Spec;
class CorrectDeveloperSpecification extends BaseSpecification
{
public function getSpec()
{
return Spec::eq('verified', true);
}
}
use Happyr\DoctrineSpecification\BaseSpecification;
use Happyr\DoctrineSpecification\Spec;
class CorrectHouseSpecification extends BaseSpecification
{
public function getSpec()
{
Spec::andX(
Spec::innerJoin('apartments', 'a'),
Spec::innerJoin('developer', 'd'),
Spec::isNotNull('description'),
Spec::isNotNull('longitude'),
Spec::isNotNull('latitude'),
new CorrectDeveloperSpecification('d')
);
}
}
use Happyr\DoctrineSpecification\BaseSpecification;
use Happyr\DoctrineSpecification\Spec;
class CorrectRegionSpecification extends BaseSpecification
{
public function getSpec()
{
return Spec::andX(
Spec::innerJoin('houses', 'h'),
new CorrectHouseSpecification('h')
);
}
}
use AppBundle\Entity\DeveloperCompany;
use Happyr\DoctrineSpecification\BaseSpecification;
use Happyr\DoctrineSpecification\Spec;
class CorrectOccupiedRegionByDeveloperSpecification extends BaseSpecification
{
/** @var DeveloperCompany */
private $developer;
public function __construct(DeveloperCompany $developerCompany, $dqlAlias = null)
{
parent::__construct($dqlAlias);
$this->developer = $developerCompany;
}
public function getSpec()
{
return Spec::andX(
new CorrectRegionSpecification(),
Spec::join('developer', 'd', 'h'),
Spec::eq('d.id', $this->developer->getId())
);
}
}
class RegionRepository extends EntitySpecificationRepository
{
public function findAvailableRegions()
{
return $this->match(
new CorrectRegionSpecification()
);
}
public function findAvailableRegionsByDeveloper(DeveloperCompany $developerCompany)
{
return $this->match(
new CorrectOccupiedRegionByDeveloperSpecification($developerCompany)
);
}
}
class HouseRepository extends EntitySpecificationRepository
{
public function findAvailableHouses()
{
return $this->match(
new CorrectHouseSpecification()
);
}
}
class DeveloperCompanyRepository extends EntitySpecificationRepository
{
public function findAvailableDevelopers()
{
return $this->match(
new CorrectDeveloperSpecification()
);
}
}
Метки: author php_freelancer symfony php doctrine orm doctrine design patterns |
Грант для стартаперов: онлайн-магистратура ждет лучших |
Метки: author KateVo учебный процесс в it магистратура онлайн-магистратура образование высшее образование образование 2.0 техпред стартапы; команда; опыт |