Laravel 4. Отличия и сравнения

image

Относительно не давно была выпущена первая Beta фреймворка «Laravel». Товарищ rsvasilyev начал публикацию статей о разработке на 4-й версии, я в свою очередь хочу описать новые преимущества и сравнить с его предыдущей версией.

Если вы заинтересованы в этом, прошу под кат.

Изменений произошло много, но начну я пожалуй с моего любимого изменения, которое избавило от велосипедов.
Раньше мы могли применять всего 2 статически-регулярных выражений для URL вида /user/{значение}.

Первое — Последовательность цифр:

Route::get('user/(:num)', function  ($id) {     return $id; }); 

Второе — Буквенно-цифровое:

Route::get('user/(:any)', function  ($name) {     return $name; }); 

В новой версии ситуация изменилась и теперь мы сами можем назначать регулярное выражение на каждое значение.
Делается это довольно просто, одним движением пальцев:

Route::get('news/{habr}', function($habr) {     return $habr; }) ->where('habr', '[A-Za-z]+'); 

или

Route::get('news/fullnews/{idNews}', function($idNews) {     return $idNews; }) ->where('idNews', '[0-9]+'); 

Еще стоит уточнить некоторую особенность: Если вы заменим {idNews} на {idNews?} и добавим в параметр значение function($idNews = ‘4’), то по обращению на /news/fullnews, мы получим новость с ID = 4.

Легко, не правда ли? Поехали дальше.

Добавлена возможность использовать не только группу для фильтров, но и к определенным URL:

Route::filter('blacklist, function() {    return 'Привет, Habrahabr.'; });  Route::when('chat/*', 'blacklist); 

Тем самым на все URL вида: chat/*, будет применяться фильтр blacklist.

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

Маршруты

  • Добавлена возможность применять модели к параметрам.
  • Теперь мы свободно можем описывать фильтры в классах.
  • Применение маршрутов к поддоменам.
  • Использование префиксов в группах.
Новые функции

  • Добавлены функции для работы с почтой.
  • Добавлены функции для работы с Composer, в особенности для Artisan.
  • Добавлены очереди и большой пакет функциональности работы с ними.

Если вы дочитали мою первую статью до конца, то я испытаю чуточку удовольствия.

ссылка на оригинал статьи http://habrahabr.ru/post/170771/

Цена бесплатного: на прохождение Real Racing 3 нужно потратить более $500

С момента выпуска EA гонок Real Racing 3 прошло уже достаточно много времени, но споры вокруг игры и решения издателя сделать ее бесплатной продолжаются.

Сайт 148Apps.com подсчитал, сколько на самом деле нужно денег игрокам потратить на встроенные покупки, если они хотят приобрести все машины.

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

Цифра на самом деле поражает – для прохождения «бесплатной» игры может потребоваться более 500 долларов.

«Мы подсчитали, что для заработка необходимой суммы требуется 472 часа игры», — говорит основатель 148Apps.com Джеф Скотт.

«Или, на покупку всех машин через внутриигровые покупки, $503.22 при самой выгодной цене».

Скотт подсчитал, что без вливания реальных денег играющему понадобится закончить 6801 гонку со средним временем 4 минуты 10 секунд каждая и прибылью 3 700 игровых кредитов.

На это потребуется 472 часа – почти 20 дней непрерывной игры – и в результате у водителя получится более 25 миллионов, на которые и надо будет покупать все 46 машин. И это без учета восстановления или апгрейдов.

Естественно, оплата покупкой реальными деньгами, возможна лишь для части машин, так как суть самой игры все-таки гонки, а они по умолчанию дают прибыль. Однако для остальных «бесплатная» игра – вопрос целого состояния.

Скотт легко вывел, что за $503.22 можно купить Xbox 360, Forza Horizon и всеми DLC на 127 машин, 22-дюймовый LED TV и еще останется $17.22.

«Игрокам, которые хотят всю игру, стоит держаться подальше от Real Racing 3», — делает вывод Скотт «Она хочет слишком много времени, или денег».

ссылка на оригинал статьи http://habrahabr.ru/company/apps4all/blog/170773/

Nokia 105 за 15 евро с фонариком и аккумулятором на месяц

На выставке MWC 2013 Nokia представила два новых телефона: Nokia 301 и Nokia 105


Nokia 301 (слева), Nokia 105 (справа)

Nokia 301

  • Цена ~65 евро
  • 2,4” дисплей
  • 3,2-Мп камеру
  • Два слота для SIM-карт
  • Поддержка сетей 3,5G

Nokia 105

  • Цена ~15 евро
  • Цветным экраной
  • FM–радио
  • Фонарик
  • Повышенная устойчивость к воздействию влаги и пыли
  • Цвет корпуса: черный, голубой
  • Продолжительность автономной работы в режиме ожидания составляет около 35 дней

Подробнее можно прочитать на 3dnews

Я считаю это то, чего ждал мир 🙂 Лично я — точно.

ссылка на оригинал статьи http://habrahabr.ru/post/170769/

Больше, чем plain vanilla scrum. Общепринятые практики работы с требованиями

Недавно, на Скрам портале была опубликована статья Майка Кона об Общепринятых практиках в Скраме — практиках, которые довольно часто встречаются в Скрам-проектах, но не являются базовыми правилами Скрам.

Скрам поощряет подобные добавления и специально построен минималистично, дабы команды могли добавить то, что им по вкусу. Не стоит путать подобные улучшения процесса с печально известным Скрам-ном. В отличие от последнего, добавленные практики улучшают процесс, повышая эффективность выпуска продуктов и выравнивая поток работ.

Сегодня я хочу поделиться множеством таких практик, собранных вокруг работы с требованиями. За последние несколько лет перечисленные практики мне не раз довелось наблюдать за кулисами у успешных команд в роли agile-коуча и рассказывать о них на тренингах Certified ScrumMaster в роли скрам-тренера.

Я ни в коем случае не претендую на полноту практик и буду рад услышать дополнения. Некоторые из перечисленных практик заслуживают отдельных статей — это work in progress.


Итак:

Общепринятые практики работы с требованиями в Скрам

Структурированные карты требований

Видение проекта и высокоуровневые требования хранить в виде беклога неудобно. Это не одномерные списки. Идеи — это списки со сложными связями. Для работы с идеями проекта современные Владельцы Продуктов и аналитики используют специализированные техники и форматы. Двумя популярными специализированными техниками являются карты пользовательских историй (user story mapping) и карты влияния (impact mapping) — специализированные mind-мепы.

В настоящее время не так много электронных инструментов поддерживают создание подобных карт. Но Google docs для story mapping и обычный mind-mapping тул для карт влияния неплохо справляются с этими задачами.

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

Команда Владельца Продукта

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

Такие группы сейчас принято называть Командой Владельца Продукта.

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

Сессии груминга беклога

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

Вместо этого, частой практикой является проводить во время спринтов запланированные встречи по проработке беклога. В иностранной литературе используется термин backlog grooming (буквально — «ухаживать»). В течение этих сессий участники:

  • составляют пользовательские истории (на основании карт требований и текущих нужд)
  • декомпозируют крупные истории на мелкие
  • оценивают сложность работы
  • детализируют истории скетчами дизайна и взаимодействия пользователей, тест-кейсами и примерами
  • обсуждают способы реализации
  • выполняют и анализируют быстрые прототипы

Доски процесса анализа

По мере работы Команды Владельца Продукта и их груминг сессий возникает немало артефактов и требований на разных фазах анализа. Для удобства управления потоком этой работы используются Канбан-доски.

Пример состояний такой доски:

Новые идеи
(5)
Детализация
(3)
Готово для груминга с командой
(3)
Прототипирование
(3)
Проработка интерфейсов
(3)
Готово для планирования в спринт
(10)

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

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

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

ссылка на оригинал статьи http://habrahabr.ru/company/scrumguides/blog/170767/

Orchard CMS: программное наполнение сайта контентом

Представим ситуацию: необходимо перенести на сайт, сделанный на Orchard, большой объем каких-то данных. Например, это может быть интернет-магазин, сайт-каталог и т.д.

Допустим, нам надо создать сайт — каталог автомобилей. Для примера условимся, что для каждого автомобиля нужно хранить название модели, цену, год выпуска и количество имеющихся в наличии автомобилей. Используя исходники Orchard и немалое количество статей на тему написания модулей, создадим свой ContentType.

Model — класс Car со свойствами Model, Price, Year, Quantity:

    public class CarPartRecord : ContentPartRecord     {         public virtual string Model { get; set; }         public virtual decimal Price { get; set; }         public virtual int Year { get; set; }         public virtual int Quantity { get; set; }     }      public class CarPart : ContentPart<CarPartRecord>     {         public string Model         {             get { return Record.Model; }             set { Record.Model = value; }         }         public decimal Price         {             get { return Record.Price; }             set { Record.Price = value; }         }         public int Year         {             get { return Record.Year; }             set { Record.Year = value; }         }         public int Quantity         {             get { return Record.Quantity; }             set { Record.Quantity= value; }     } 

View:

    @T("Model: ") @Model.Model<br />     @T("Price: ") @Model.Price<br />     @T("Year: ") @Model.Year<br />     @T("Quantity: ") @Model.Quantity<br /> 

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

Очевидно, что при объеме данных свыше 50 записей уже хотелось бы программно добавлять их в CMS. В Orchard для того, чтобы записать данные через БД, необходимо для каждого элемента добавить записи в 5 связанных таблиц:

  • ИмяМодуля_CarPartRecord
  • Common_CommonPartRecord
  • Common_CommonPartVersionRecord
  • Orchard_Framework_ContentItemRecord
  • Orchard_Framework_ContentItemVersionRecord

Дальше возможно два варианта: использовать или SQL-скрипты, или LINQtoSQL. Лично у меня, когда я проверял первый вариант, не получилось обойтись без конструкции вида

insert ... select ...

что при большом количестве записей (проверял на 3000+) приводит к совершенно неприемлемому времени работы (порядка нескольких часов).

Поэтому остановимся на втором варианте: напишем простое WinForms приложение, которое и будем производить импорт данных.

При запуске импорта должно последовательно вызываться 5 функций, добавляющих записи в каждую из вышеперечисленных таблиц, например:

private CarPartRecord create(/* строка из CSV-файла, XMLNode или любой другой формат исходных данных */)         {             CarPartRecord record = new CarPartRecord();             record.Model =    //             record.Price =      //заполнение полей созданного ContentPart             record.Year =       //соответствующими данными             record.Quantity = //              return record;         }  private Orchard_Framework_ContentItemRecord related1_create()          {             Orchard_Framework_ContentItemRecord record = new Orchard_Framework_ContentItemRecord();             record.ContentType_id = 9;         // по умолчанию в "чистой" CMS есть 8 разных ContentType, поэтому наш идет девятым             return record;         }          private Orchard_Framework_ContentItemVersionRecord related2_create(CarPartRecord item)         {             Orchard_Framework_ContentItemVersionRecord record = new Orchard_Framework_ContentItemVersionRecord();             record.Number = 1;             record.Latest = true;             record.Published = true;             record.ContentItemRecord_id = item.Id;             return record;         }          private Common_CommonPartRecord related3_create(int id)         // передаем ID созданного CarPartRecord         {             Common_CommonPartRecord record = new Common_CommonPartRecord();             record.CreatedUtc = DateTime.Now;             record.ModifiedUtc = DateTime.Now;             record.PublishedUtc = DateTime.Now;             record.OwnerId = 2;             record.Id = id;             return record;         }          private Common_CommonPartVersionRecord related4_create(int id)   //   передаем ID созданного CarPartRecord         {             Common_CommonPartVersionRecord record = new Common_CommonPartVersionRecord();             record.CreatedUtc = DateTime.Now;             record.ModifiedUtc = DateTime.Now;             record.PublishedUtc = DateTime.Now;             record.ContentItemRecord_id = id;             record.Id = id;             return record;         } 

И, соответственно, в main:

CarPartRecord record = create(/* наши параметры */); context.CarPartRecords.InsertOnSubmit(record);                                                          //создадим запись в основной таблице context.SubmitChanges();  Orchard_Framework_ContentItemRecord tmp1 = related1_create();                //и в остальных, используя для связи ID созданной CarPartRecord. context.Orchard_Framework_ContentItemRecords.InsertOnSubmit(tmp1);  Orchard_Framework_ContentItemVersionRecord tmp2 = related2_create(record); context.Orchard_Framework_ContentItemVersionRecords.InsertOnSubmit(tmp2);  Common_CommonPartRecord tmp3 = related3_create(record.Id); context.Common_CommonPartRecords.InsertOnSubmit(tmp3);  Common_CommonPartVersionRecord tmp4 = related4_create(record.Id); context.Common_CommonPartVersionRecords.InsertOnSubmit(tmp4); context.SubmitChanges(); 

В результате импорт 3000+ записей будет длиться около 100 секунд на машине средней конфигурации. Профит.

ссылка на оригинал статьи http://habrahabr.ru/post/170759/