SlideShare a Scribd company logo
FRONTEND FORTHE WIN!
Антон Плешивцев, aviasales.ru
МЕТАПОИСК
МЕТАПОИСК
МЕТАПОИСК
МЕТАПОИСК
МЕТАПОИСК
Frontend for the win
Frontend for the win
LEGACY
• кастомное решение	

• 10К строк кода без тестов	

• виджет-ориентированная архитектура
ЖИДКОЕ ПРИЛОЖЕНИЕ
Поисковая
форма
Поиск
Выдача
Билеты
ФильтрыСостояние
Агенства
Фидбек
История
Календарь
INTERFACE
NEW AGE
• AngularJS	

• 3K строк кода	

• 80% покрытие тестами
СТРУКТУРА
СТРУКТУРА
Поисковая форма
Билеты Фильтры
СТРУКТУРА
Поисковая форма
Билеты Фильтры
Форма
История	

поисков
Календарь
Отели
Билеты
Цена
Время
Вылет
…
ВЗАИМОДЕЙСТВИЕ	

ЧАСТЕЙ
ВЗАИМОДЕЙСТВИЕ
Билеты
Календарь
Отели
Билеты Фильтры
Цена
Время
Вылет
…
?
ВЗАИМОДЕЙСТВИЕ
Билеты
Календарь
Отели
Билеты Фильтры
Цена
Время
Вылет
…
service
ВЗАИМОДЕЙСТВИЕ
Билеты Фильтры
Календарь
Отели
Билеты
Цена
Время
Вылет
…
«Выдача с фильтрами»
МОДУЛИ
MODULE PATTERN
var testModule = (function () {
!
var counter = 0;
!
return {
!
incrementCounter: function () {
return counter++;
},
!
resetCounter: function () {
console.log( "counter value prior to reset: " + counter );
counter = 0;
}
};
!
})();
AMD MODULE
//Calling define with a dependency array and a factory function
define(['dep1', 'dep2'], function (dep1, dep2) {
!
//Define the module value by returning a value.
return function () {};
});
DEPENDENCY INJECTION
function MyController($scope, greeter) {
!
$scope.test = true;
!
$scope.check = function(){
greeter.check($scope.test);
};
!
}
Ядро
Ядро
Форма
поиска
Выдача
Ядро
Форма
поиска
Выдача
Форма История Билеты Фильтры
Ядро
Форма
поиска
Выдача
Форма История Билеты Фильтры
Поиск
Календарь Отели Выдача
Цена Время
Ядро
Форма
поиска
Выдача
Форма История Билеты Фильтры
Поиск
Календарь Отели Выдача
Цена Время
Ядро
Форма
поиска
Выдача
Форма История Билеты Фильтры
Поиск
Календарь Отели Выдача
Цена Время
у
Выдача
Билеты Фильтры
{
filters: {}
tickets: []
}
{
tickets: []
filters: {}
sort: function(){…}
}
{
reset: function(){…}
filters: {}
tickets: []
}
Выдача Цена
{
sorting: ‘price’
tickets: []
filters: {}
sort: function(){…}
}
{
visible: [1000, 10 000]
reset: function(){}
filters: {}
tickets: []
}
Выдача
Билеты Фильтры
{
filters: {}
tickets: []
}
{
tickets: []
filters: {}
sort: function(){…}
}
{
reset: function(){…}
filters: {}
tickets: []
}
Выдача Цена
{
sorting: ‘price’
tickets: []
filters: {}
sort: function(){…}
}
{
visible: [1000, 10 000]
reset: function(){}
filters: {}
tickets: []
}
Выдача
Билеты Фильтры
Выдача Цена
$scope.filters.price = [1000, 15000]
Выдача
Билеты Фильтры
Выдача Цена
$scope.filters.price = [1000, 15000]
$scope.filters.price = [1000, 15000]
Выдача
Билеты Фильтры
Выдача Цена
$scope.filters.price = [1000, 15000]
$scope.filters.price = [1000, 15000]
onchange(‘filters.price’, function(){
update_tickets();
})
PITFALL
PITFALL
Выдача
Фильтры
Цена
$scope.filters = {
price: [100, 10000],
duration: [3600, 84600],
…
}
BEFORE
Выдача
Фильтры
Цена $scope.filters
$scope.filters
$scope.filters
AFTER
Выдача
Фильтры
Цена $scope.filters
$scope.filters
$scope.filters
TEMPLATES
UNOBTRUSIVE
NANO("templates.searches.tickets.widgets.proposals", function(NANO){
return NANO.templates(‘ticket.html’, {
"@data-ticket-id": "ticket.id",
"@data-source": "source",
".ticket_proposal": {
"gate<-proposals": {
".gate_name": "gate.name",
".gate_select_button a@href": "gate.url",
".gate_select_button a@data-gate": "gate.id",
".gate_price": "gate.price",
".gate_payment_methods .payment_method": {
"method<-gate.payment_methods": {
"@class+": " #{method}"
}
}
}
}
});
});
DECLARATIVE
<li class="proposal-carousel"
ng-repeat="proposal in ticket.proposals_for_carousel()">
<a class="agency_offer"
ng-click="buy_ticket(ticket, proposal)"></a>
<span>{{ proposal.name() | cut:15 }}</span>
<span class="price">
<span>{{ proposal.price() | current_price:search.currency }}</span>
</span>
</li>
UNOBTRUSIVE
layout.find(".yes").bind("click", function(){
self.toggle(layout, "yes");
});
layout.find(".no").bind("click", function(){
self.toggle(layout, "no");
});
layout.find("#new_feedback").submit(function(){
return self._submit();
});
<form class="feedback">
<div class="yes">Да</div>
<div class="no">Нет</div>
...
</form>
+
DECLARATIVE
<form class="feedback" ng-submit="submit()">
<div class="yes" ng-click='success(true)'>Да</div>
<div class="no" ng-click='success(false)'>Нет</div>
...
</form>
ИТОГИ
COMPOSITE ARCHITECTURE
IS POWERFUL
PROTOTYPE INHERITANCE IS
GOOD
DECLARATIVE ALWAYS
BETTERTHEN IMPERATIVE
ANGULARJS IS BETTERTHAN
ANYTHING ELSE
ABOUT
АНТОН ПЛЕШИВЦЕВ	

!
twitter.com/allaud
github.com/allaud
https://www.facebook.com/ant.pl.3
!
aviasales.ru

More Related Content

PDF
как мы сделали поисковой движок
PDF
Happydev presentation soa
PPT
интерфейсы3 ppt
PDF
Iwiss network tools
PDF
Ez series hydraulic-tools
как мы сделали поисковой движок
Happydev presentation soa
интерфейсы3 ppt
Iwiss network tools
Ez series hydraulic-tools

Viewers also liked (6)

PDF
Happydev presentation angular
PPTX
Հովհաննես Թումանյան բալադներ
PDF
Повышение конверсии через оптимизацию JS
PDF
ARC 90 For Small Businesses
PDF
How to create modern web application (about Virool mobile player)
PDF
CodeFest dirty facts about AngularJS
Happydev presentation angular
Հովհաննես Թումանյան բալադներ
Повышение конверсии через оптимизацию JS
ARC 90 For Small Businesses
How to create modern web application (about Virool mobile player)
CodeFest dirty facts about AngularJS
Ad

Frontend for the win