Парадигмы
программирования и
шаблоны проектирования
Или как правильно варить JS
и смотреть Игру Престолов
Зачем уметь варить JS ?!
Большие веб
приложения
Настольные
приложения
Мобильные
приложения
Jeff Atwood (2007): any application that can be written in
JavaScript, will eventually be written in JavaScript
Часть 1. Парадигмы программирования
1.Популярные парадигмы
2.Процедурный подход (ПП)
3.Функциональное программирование (ФП)
a.Функция: ФП vs ПП
b.Возможности ФП
4.Объектно ориентированный подход
a."Как это было вчера и будет завтра" –
эмуляция классов, прототипы, ES6
b."Как это можно делать сегодня"
Часть 2. Шаблоны проектирования
1.Что такое шаблон проектирования ?
2.Пространства имён
3.Классические шаблоны:
a.Порождающие - Singleton
b.Поведенческие - Observer
4.MV* шаблоны - современный подход к разработке
больших приложений
Ч1. Наиболее популярные парадигмы
• Процедурное программирование
• ООП
• Логическое программирование
• Функциональное программирование
• Параллельное программирование
• Событийно-ориентированная
Источник: Quora.com
Ч1. Процедурное программирование (ПП)
Программирование, при
котором последовательно
выполняемые операторы можно
собрать в подпрограммы
(функции, процедуры), то есть
более крупные целостные
единицы кода, с помощью
механизмов самого языка.
Ч1. ПП - Пример кода
var allowedImgSize = 3000000;
var allowedImgNumber = 10;
var fileCountReaded = 0;
var fileCountUploaded = 0;
(function($){
$(document).ready(function(){
$( "#from-date" ).datepicker({
minDate: 11,
showOn: "button",
....
Глобальные переменные –
к чему относятся, откуда
вызываются ?
Ч1. ПП - Почему этот подход плох ?!
С ростом приложений, в отсутствии жёстких
правил структурирования кода, мы получаем
большой набор плохо поддерживаемого кода
- Spaghetti code
Организация кода очень напоминает
организацию «Кхаласара» – племя
кочевников: никакой инфраструктуры, почти
нет правил, всё – общее. Также кхаласары
могут сражаться друг с другом, при этом члены
побежденного кхаласара присоединяются к
победившему.
Ч1. ПП - Проблемы Spaghetti кода
Плохо тестируемый
Плохо читаемый
Плохо расширяемый
Создаёт предпосылки для
возникновения ошибок из-за
большого взаимодействия с
внешней средой
ПП в чистом виде – это подход новичков
Ч1. ФП – Первое решение
Функциональное программирование (ФП) —
подход к программированию, в котором функции
являются главным инструментом работы: они
считают результат, они могут также передаваться
в качестве аргументов и возвращаться в качестве
результатов.
Ч1. ПП vs ФП
Функция в ПП Функция в ФП
1. Не изменяет входные данные
2. Не обладает побочными
эффектами
3. Является строго
детерминированной
4. Не осуществляет операций
ввода, вывода
1. Изменяет входные данные
2. Может изменять среду в
которой исполняется
3. Результат не всегда
предсказуем
4. Содержит alert, prompt
Чистая функция
Ч1. ФП - Возможности ФП в JS
 Фильтры и Конвейер (pipe)
 Мемоизация
 Каррирование
Ч1. ФП - Фильтры и Конвейер (pipe)
Ч1. ФП - Фильтры и Конвейер
var children = [
{ age: 21, Name: "Rob" },
{ age: 18, Name: "Sansa" },
{ age: 16, Name: "Arya" },
{ age: 15, Name: "Brandon" },
{ age: 11, Name: "Rickon" }
];
var filteredChildren = //....
console.log(filteredChildren);
console.log(children);
Ч1. ФП - Фильтры и Конвейер
Функциональный подход
var filteredChildren = children
.filter(function (x) {
return x.age % 3 == 0;
})
.map(function (x) { return x.Name;})
.sort();
Процедурный подход
var filteredChildren = [];
for (var i in children) {
if (children[i].age % 3 == 0) {
filteredChildren.
push(children[i].Name);
}
}
filteredChildren.sort();
Ч1. ФП - Фильтры и Конвейер
1. Улучшают читаемость кода
2. Уменьшают количество переменных
3. Сводят к минимуму количество условных операторов
Ч1. ФП - Мемоизация
 Мемоизация — сохранение результатов выполнения
функций для предотвращения повторных вычислений.
 Плюсы: увеличение скорости выполнения программы
 Минусы: дополнительный расход памяти
Ч1. ФП - Мемоизация
На островах Вестероса, учёные мужи – Маэстры, нашли
удивительную закономерность чисел, которая часто
встречается в природе. Она начинается с 0,1, а каждое
следующее число получается суммированием двух
предыдущих. По одним лишь им известным причинам,
зовут они их – числа Фибоначчи
Ч1. ФП - Мемоизация
«Наивный» подход
При n = 40, 331 160 281 - вызовов
function fibonacci(n) {
if (n == 0 || n == 1) {
return n;
}
return fibonacci(n-1) + fibonacci(n-2);
}
Использование мемоизации
При n = 40, 79 вызовов
var fibonacci = (function () {
var memo = {};
function f(n) {
var value;
if (n in memo) {
value = memo[n];
} else {
if (n == 0 || n == 1) value = n;
else value = f(n - 1) + f(n-2);
memo[n] = value;
}
return value;
}
return f;})();
Ч1. ФП - Каррирование
Преобразование функции от многих аргументов
в функцию, берущую свои аргументы по одному
(названо в честь Хаскелла Карри)
function sum(a, b) { }
sum(5,6)  sum(5)(6)
Ч1. ФП - Каррирование
lodash - библиотека с огромным количеством
инструментов для работы с массивами, коллекциями,
объектами, функциями.
https://lodash.com/
Ч1. ФП - Каррирование
var add = function (a, b, c, d) {
return a + b + c + d;
}
var inc = _.curry(add);
console.log(inc(6, 7, 8, 9));
console.log(inc(6)(7)(8, 9));
var inc2 = inc(6);
var inc3 = inc2(7);
var inc4 = inc3(8);
console.log(inc4(9));
Ч1. ФП - Зачем использовать ?
Функциональное П
Лёгкое и эффективное unit тестирование
Хорошо читаемый
Минимальный внешний эффект
Плохо расширяемый
Процедурное П
Плохо тестируемый
Плохо читаемый
Плохо расширяемый
Создаёт предпосылки для возникновения
ошибок из-за большого взаимодействия с
внешней средой
Ч1. ООП
Ч1. ООП - Особенности в JS (ES5)
 Нет классов
 Нет интерфейсов
 Используется функция конструктор для
инстанциирования объектов
 Наследование основано на прототипах
Как это было вчера ES5
function Warrior(strength) {
this.strength = strength;
this.say = function () {
// code
}
}
Warrior.prototype.kick=function(){
return this.strength;
}
Как это будет завтра ES6
class Warrior {
constructor(strength) {
// code
}
kick() {
console.log("My strength is: "
+ this.strength);
}
say(){}
}
Ч1. ООП – Вчера vs Завтра
var snow = new Warrior(10);
snow.say();
Как это было вчера ES5
function Knight(strength) {
this.strength = 2 * strength;
}
Knight.prototype =
Object.create(Warrior.prototype);
Knight.prototype.kick = function(){
Warrior.prototype.kick.call(this);
console.log("I am knight. I have
double strength");
}
Как это будет завтра ES6
class Knight extends Warrior {
constructor(strength) {
super(2 * strength);
}
kick() {
super.kick();
console.log("I am knight. I
have double strength");
}
}
Ч1. ООП – Вчера vs Завтра
var jaime = new Knight(10);
jaime.kick();
Ч1. ООП – Как это можно делать сегодня
TypeScript
1. Компилируется в JS ( Разные версии)
2. Схожий синтаксис с ES6
3. Строгая типизация, интерфейсы, модули
Часть 2. Шаблоны проектирования
Ч2. Шаблоны проектирования
Шаблон проектирования или паттерн (англ. design pattern)
в разработке программного обеспечения —
повторимая архитектурная конструкция, представляющая собой
решение проблемы проектирования в рамках некоторого часто
возникающего контекста.
Содержит 23 шаблона проектирования
 Порождающие – 5
 Структурные – 7
 Поведенческие – 11
Примеры написаны на С++, Smalltalk
Ч2. Пространства имён
C++ : namespace - using
PHP : namespace – use – as
Java : package - import
JS
Ч2. Пространства имён
Как известно в Вестерос входит 7
королевств, которые подчиняются
королю. Каждым королевством
управляет лорд, а само оно делится на
ещё меньшие области. Каждая
область имеет обычно главный замок
и близлежищие деревеньки, в
которых живут люди.
То есть, можно сказать, что Север
входит в Вестерос, а Винтерфелл
соотвествено в Север.
Ч2. Пространства имён - реализация
var vesteros = vesteros || {};
vesteros.namespace = function (ns_string) {
var parts = ns_string.split('.'),
parent = vesteros, i;
// отбросить начальный префикс – имя глобального
объекта
if (parts[0] === 'vesteros') {
parts = parts.slice(1);
}
for (i = 0; i < parts.length; i += 1) {
// создать свойство, если оно отсутствует
if (typeof parent[parts[i]] === 'undefined') {
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
};
объект
Ч2. Пространства имён - применение
// присваивание возвращаемое значение локальной переменной
var greenvale = vesteros.namespace('vesteros.dorn.greenvale');
greenvale === vesteros.dorn.greenvale; // true
// можно опустить начальный префикс `vesteros`
vesteros.namespace('north.winterfell');
Ч2. Порождающие шаблоны - Singleton
Шаблон проектирования, гарантирующий, что в однопоточном
приложении будет единственный экземпляр класса с глобальной
точкой доступа
Области применения: модули в Node.js, сервисы в Symfony (PHP),
Bean в Spring (Java)(По умолчанию)
Ч2. Порождающие шаблоны - Singleton
На крайнем севере Вестероса, за восемь тысяч лет до
начала войны пяти королей, в эпоху героев, была построена
огромная стена, для того, чтобы защищать Вестерос от
белых ходоков.
Java
public class Wall {
private static Wall instance;
private Wall () {}
public static Wall getInstance() {
if (instance == null) {
instance = new Wall();
}
return instance;
}
}
JS
function Wall() {
if (Wall.instance) {
return Wall.instance;
}
Wall.instance = this;
}
Wall.getInstance = function () {
return Wall.instance;
}
Ч2. Порождающие шаблоны - Singleton
Wall.instance = 5;
Ч2. Порождающие шаблоны - Singleton
var Wall = (function () {
var instance = null;
function Wall() {
if (instance){
return instance;
}
instance = this;
}
Wall.getInstance = function () {
if (instance) {
instance = new Wall();
}
return instance;
};
return Wall;
})();
Анонимная функция
Вызов
Ч2. Поведенческие шаблоны
Шаблоны проектирования, определяющие алгоритмы и способы
реализации взаимодействия различных объектов и классов.
Отлично реализуется в JS, благодаря возможности сохранять
функции в структурах данных.
Ч2. Поведенческие шаблоны - Observer
Шаблон проектирования, который помогает определить
зависимость типа «один ко многим» между объектами таким
образом, что при изменении состояния одного объекта все
зависящие от него оповещаются об этом событии
Ч2. Поведенческие шаблоны - Observer
Королевский двор Вестероса – это место изощрённых интриг и
коварства. Действующие лица очень активно используют шпионов,
причём часто, один и тот же шпион работает на нескольких
представителей двора, поэтому, как только шпион что-то узнаёт, он
должен сразу доложить всем информацию.
Ч2. Поведенческие шаблоны - Observer
var Spy = (function () {
function Spy() {
this._partiesToNotify = [];
}
Spy.prototype.subscribe = function (subscriberFn) {
this._partiesToNotify.push(subscriberFn);
};
Spy.prototype.whisper = function (event) {
for (var i = 0; i < this._partiesToNotify.length; i++) {
this._partiesToNotify[i](event);
}
};
return Spy;
})();
Хранитель подписчиков
Ч2. Поведенческие шаблоны - Observer
var Player = (function () {
function Player() {
}
Player.prototype.listen = function(info) {
//perform some action
};
return Player;
})();
var s = new Spy();
var p = new Player();
s.subscribe(p.listen); //p is now a subscriber
s.whisper(12); //s will notify all subscribers
Ч2. “Современные” шаблоны MV*
MVC MVP MVVM
Ч2. Шаблоны MV* - MVVM
Ч2. MVVM – Knockout
 Декларативное связывание
 Двунаправленная синхронизация
 Наличие шаблонов
 Free, open source
 54kb
Ч2. MVVM – Knockout, View
<form data-bind="submit: sendRequest">
<label>Castle name</label>
<input data-bind="value: castleName">
<br>
<label>Wall thickness</label>
<input data-bind="value: wallThick">
<br>
<button type="submit">Submit</button>
</form>
Ч2. MVVM – Knockout, ViewModel
var myViewModel = {
castleName: ko.observable('Dorn'),
wallThick: ko.observable(1),
sendRequest: function () {
console.log("Castle name: " +
this.castleName());
console.log("Wall thickness : " +
this.wallThick());
}
};
ko.applyBindings(myViewModel);
Резюме
1. Функциональное программирование
2. ООП
3. Пространства имён
4. Singleton
5. Observer
6. MVVM
Вывод
JS - это гибкий язык программирования, который позволяет под
нужные задачи использовать разные подходы
Способов решения задачи огромное количество, самое сложное –
выбрать правильный. Что вам и желаю !
Спасибо за внимание !
Ч1. ФП - «Ленивая» инициализация
 Приём в программировании, когда некоторая ресурсоёмкая
операция выполняется непосредственно перед тем, как будет
использован её результат. Таким образом, инициализация
выполняется «по требованию», а не заблаговременно.
 Плюсы: Инициализация выполняется только в тех случаях, когда
она действительно необходима
 Минусы: Невозможно явным образом задать порядок
инициализации объектов
Ч1. ФП - «Ленивая» инициализация
Пекарня в Вестеросе выпекает отличный хлеб. Они получают
заказы на разный вид хлеба, но сразу не пекут. Так как
создание объекта “Bread” – это дорогостоящая операция,
поэтому они стараются отложить эту работу, пока кто-нибудь
действительно не придёт за хлебом.
Ч1. ФП - «Ленивая» инициализация
var Bread = (function () {
function Bread(breadType) {
this.breadType = breadType;
//тяжёлая операция
console.log("Bread " + breadType + " created.");
}
return Bread;
})();
Ч1. ФП - «Ленивая» инициализация
Создаём объект “Bakery”. Он будет принимать заказы на разный вид хлеба.
var Bakery = (function () {
function Bakery() {
this.requiredBreads = [];
}
Bakery.prototype.orderBreadType = function (breadType) {
this.requiredBreads.push(breadType);
};
Теперь у нас есть возможность быстро принимать заказы
не тратя время на их реализацию.
Bakery.prototype.buy = function (breadType) {
// create and return
};
var bakery = new Bakery();
bakery.orderBreadType("Brioche");
bakery.orderBreadType("Anadama bread");
bakery.orderBreadType("Chapati");
bakery.orderBreadType("Focaccia");
Ч1. ФП - «Ленивая» инициализация
bakery.buy("Chapati")
;
Инициализация
Прил 1. Каррирование – имплементация
function curry(fx) {
var arity = fx.length;
return function f1() {
var args = Array.prototype.slice.call(arguments, 0);
if (args.length >= arity) {
return fx.apply(null, args);
}
else {
return function f2() {
var args2 =
Array.prototype.slice.call(arguments, 0);
return f1.apply(null, args.concat(args2));
}
}
};
}
Прил 1. ФП – Каррирование - применение
getData(r) render()
argument
Прил 1. ФП – Каррирование - применение
getData
render
2
render
1
Прил 1. ФП – Каррирование - применение
rende
r Curry renderC
render1 render2
Прил 1. ФП – Каррирование - применение
function getData(renderFn) {
// get data
var data = 5;
renderFn(data);
}
function renderComplicate(flag,
data) {
if (flag) {
console.log(2 * data);
} else {
console.log(3 * data);
}
}
var r = _.curry(renderComplicate);
var r1 = r(true);
var r2 = r(false);
getData(r1); // 10
getData(r2); // 15
Ч2. Шаблон модуль
var Dragon = (function () {
function Dragon(strength) {
this.strength = strength;
}
Dragon.prototype.burn = function () {
return "Dragon is close...";
};
return Dragon;
}());
Анонимная функция
Вызов
Ч2. Структурные шаблоны
Шаблоны проектирования, в которых рассматривается вопрос о
том, как из множества классов или множества объектов
образуются более крупные или изменённые структуры.
Ч2. Структурные шаблоны
Широко используется агрегация и
композиция
JS – язык с динамической типизацией
Удобная реализация
Ч2. Структурные шаблоны - Decorator
Структурный шаблон проектирования, предназначенный для
динамического подключения дополнительного поведения
к объекту. Шаблон Декоратор предоставляет гибкую альтернативу
практике создания подклассов с целью расширения
функциональности.
Ч2. Структурные шаблоны - Decorator
Броня, которую рыцари Вестероса носят, является очень
конфигурируемой и «настраивается» под любые нужды и размер
кошелька заказчика. Она может быть кольчужной, иметь
вплетения, сделанные из медных колец, позолоченные. Так же
могут быть разные наколенники, и разные вставки в шлем.
Вариантов очень много, особенно для кодинга !
Ч2. Структурные шаблоны - Adapter
Структурный шаблон проектирования, предназначенный для
организации использования функций объекта, недоступного для
модификации, через специально созданный интерфейс.
Ч2. Структурные шаблоны - Decorator
var BasicArmor = (function(){
function BA () {}
BA.prototype.damage=function(hit){
return hit.s / 1.5;
};
return BA;
})();
var ChainMail = (function () {
function CM(ba) {
this.bArmor = ba;
}
CM.prototype.damage=function(hit) {
hit.s *= 0.8;
return this.bArmor.damage(hit);
};
return CM;
})();
var armor = new ChainMail(new BasicArmor());
Ч2. Структурные шаблоны - Adapter
В Вестеросе очень опасно путешествовать. С лёгкостью можно попасть в руки
к разбойникам или заблудиться, поэтому часто, люди у которых есть деньги
пользуются кораблём. Однако кораблём мы управлять не умеем, в отличие от
верблюда.
interface Ship{
SetRudderAngleTo(angle);
SetSailConfiguration(configuration);
SetSailAngle(sailId, sailAngle);
GetCurrentBearing();
GetCurrentSpeedEstimate();
ShiftCrewWeightTo(weightToShift, locationId);
}
interface Camel{
TurnLeft();
TurnRight();
GoForward();
}
Ч2. Структурные шаблоны - Adapter
var Camel = (function () {
function Camel() {
this._ship = new Ship();
}
Camel.prototype.TurnLeft = function () {
this._ship.SetRudderAngleTo(-30);
this._ship.SetSailAngle(3, 12);
};
Camel.prototype.TurnRight = function () {
this._ship.SetRudderAngleTo(30);
this._ship.SetSailAngle(5, -9);
};
Camel.prototype.GoForward= function () {
//do something else to the _ship
};
return Camel;
})();
var camel = new Camel();
camel.GoForward();
camel.TurnLeft();
Dirty checking
Через каждый интервал времени,
проверяются все поля во VM, на
предмет их изменения, если они
были изменены, то обновляется
Представление. В Представлении на
всех контролах сидят слушатели.
Контейнерный объект
Пример: Библиотека - Knockout.js
function CreateCastleVModel(name) {
this.name = ko.observable(name);
}
var model = new CreateCastleVModel();
model.name("Winterfell"); //set
model.name(); //get
Ч2. MVVM – варианты реализации
Использует: Angular Использует: Backbone, Ember

парадигмы программирования и шаблоны проектирования

  • 1.
    Парадигмы программирования и шаблоны проектирования Иликак правильно варить JS и смотреть Игру Престолов
  • 2.
    Зачем уметь варитьJS ?! Большие веб приложения Настольные приложения Мобильные приложения Jeff Atwood (2007): any application that can be written in JavaScript, will eventually be written in JavaScript
  • 3.
    Часть 1. Парадигмыпрограммирования 1.Популярные парадигмы 2.Процедурный подход (ПП) 3.Функциональное программирование (ФП) a.Функция: ФП vs ПП b.Возможности ФП 4.Объектно ориентированный подход a."Как это было вчера и будет завтра" – эмуляция классов, прототипы, ES6 b."Как это можно делать сегодня"
  • 4.
    Часть 2. Шаблоныпроектирования 1.Что такое шаблон проектирования ? 2.Пространства имён 3.Классические шаблоны: a.Порождающие - Singleton b.Поведенческие - Observer 4.MV* шаблоны - современный подход к разработке больших приложений
  • 6.
    Ч1. Наиболее популярныепарадигмы • Процедурное программирование • ООП • Логическое программирование • Функциональное программирование • Параллельное программирование • Событийно-ориентированная Источник: Quora.com
  • 7.
    Ч1. Процедурное программирование(ПП) Программирование, при котором последовательно выполняемые операторы можно собрать в подпрограммы (функции, процедуры), то есть более крупные целостные единицы кода, с помощью механизмов самого языка.
  • 8.
    Ч1. ПП -Пример кода var allowedImgSize = 3000000; var allowedImgNumber = 10; var fileCountReaded = 0; var fileCountUploaded = 0; (function($){ $(document).ready(function(){ $( "#from-date" ).datepicker({ minDate: 11, showOn: "button", .... Глобальные переменные – к чему относятся, откуда вызываются ?
  • 9.
    Ч1. ПП -Почему этот подход плох ?! С ростом приложений, в отсутствии жёстких правил структурирования кода, мы получаем большой набор плохо поддерживаемого кода - Spaghetti code Организация кода очень напоминает организацию «Кхаласара» – племя кочевников: никакой инфраструктуры, почти нет правил, всё – общее. Также кхаласары могут сражаться друг с другом, при этом члены побежденного кхаласара присоединяются к победившему.
  • 10.
    Ч1. ПП -Проблемы Spaghetti кода Плохо тестируемый Плохо читаемый Плохо расширяемый Создаёт предпосылки для возникновения ошибок из-за большого взаимодействия с внешней средой ПП в чистом виде – это подход новичков
  • 11.
    Ч1. ФП –Первое решение Функциональное программирование (ФП) — подход к программированию, в котором функции являются главным инструментом работы: они считают результат, они могут также передаваться в качестве аргументов и возвращаться в качестве результатов.
  • 12.
    Ч1. ПП vsФП Функция в ПП Функция в ФП 1. Не изменяет входные данные 2. Не обладает побочными эффектами 3. Является строго детерминированной 4. Не осуществляет операций ввода, вывода 1. Изменяет входные данные 2. Может изменять среду в которой исполняется 3. Результат не всегда предсказуем 4. Содержит alert, prompt Чистая функция
  • 13.
    Ч1. ФП -Возможности ФП в JS  Фильтры и Конвейер (pipe)  Мемоизация  Каррирование
  • 14.
    Ч1. ФП -Фильтры и Конвейер (pipe)
  • 15.
    Ч1. ФП -Фильтры и Конвейер var children = [ { age: 21, Name: "Rob" }, { age: 18, Name: "Sansa" }, { age: 16, Name: "Arya" }, { age: 15, Name: "Brandon" }, { age: 11, Name: "Rickon" } ]; var filteredChildren = //.... console.log(filteredChildren); console.log(children);
  • 16.
    Ч1. ФП -Фильтры и Конвейер Функциональный подход var filteredChildren = children .filter(function (x) { return x.age % 3 == 0; }) .map(function (x) { return x.Name;}) .sort(); Процедурный подход var filteredChildren = []; for (var i in children) { if (children[i].age % 3 == 0) { filteredChildren. push(children[i].Name); } } filteredChildren.sort();
  • 17.
    Ч1. ФП -Фильтры и Конвейер 1. Улучшают читаемость кода 2. Уменьшают количество переменных 3. Сводят к минимуму количество условных операторов
  • 18.
    Ч1. ФП -Мемоизация  Мемоизация — сохранение результатов выполнения функций для предотвращения повторных вычислений.  Плюсы: увеличение скорости выполнения программы  Минусы: дополнительный расход памяти
  • 19.
    Ч1. ФП -Мемоизация На островах Вестероса, учёные мужи – Маэстры, нашли удивительную закономерность чисел, которая часто встречается в природе. Она начинается с 0,1, а каждое следующее число получается суммированием двух предыдущих. По одним лишь им известным причинам, зовут они их – числа Фибоначчи
  • 20.
    Ч1. ФП -Мемоизация «Наивный» подход При n = 40, 331 160 281 - вызовов function fibonacci(n) { if (n == 0 || n == 1) { return n; } return fibonacci(n-1) + fibonacci(n-2); } Использование мемоизации При n = 40, 79 вызовов var fibonacci = (function () { var memo = {}; function f(n) { var value; if (n in memo) { value = memo[n]; } else { if (n == 0 || n == 1) value = n; else value = f(n - 1) + f(n-2); memo[n] = value; } return value; } return f;})();
  • 21.
    Ч1. ФП -Каррирование Преобразование функции от многих аргументов в функцию, берущую свои аргументы по одному (названо в честь Хаскелла Карри) function sum(a, b) { } sum(5,6)  sum(5)(6)
  • 22.
    Ч1. ФП -Каррирование lodash - библиотека с огромным количеством инструментов для работы с массивами, коллекциями, объектами, функциями. https://lodash.com/
  • 23.
    Ч1. ФП -Каррирование var add = function (a, b, c, d) { return a + b + c + d; } var inc = _.curry(add); console.log(inc(6, 7, 8, 9)); console.log(inc(6)(7)(8, 9)); var inc2 = inc(6); var inc3 = inc2(7); var inc4 = inc3(8); console.log(inc4(9));
  • 24.
    Ч1. ФП -Зачем использовать ? Функциональное П Лёгкое и эффективное unit тестирование Хорошо читаемый Минимальный внешний эффект Плохо расширяемый Процедурное П Плохо тестируемый Плохо читаемый Плохо расширяемый Создаёт предпосылки для возникновения ошибок из-за большого взаимодействия с внешней средой
  • 25.
  • 26.
    Ч1. ООП -Особенности в JS (ES5)  Нет классов  Нет интерфейсов  Используется функция конструктор для инстанциирования объектов  Наследование основано на прототипах
  • 27.
    Как это быловчера ES5 function Warrior(strength) { this.strength = strength; this.say = function () { // code } } Warrior.prototype.kick=function(){ return this.strength; } Как это будет завтра ES6 class Warrior { constructor(strength) { // code } kick() { console.log("My strength is: " + this.strength); } say(){} } Ч1. ООП – Вчера vs Завтра var snow = new Warrior(10); snow.say();
  • 28.
    Как это быловчера ES5 function Knight(strength) { this.strength = 2 * strength; } Knight.prototype = Object.create(Warrior.prototype); Knight.prototype.kick = function(){ Warrior.prototype.kick.call(this); console.log("I am knight. I have double strength"); } Как это будет завтра ES6 class Knight extends Warrior { constructor(strength) { super(2 * strength); } kick() { super.kick(); console.log("I am knight. I have double strength"); } } Ч1. ООП – Вчера vs Завтра var jaime = new Knight(10); jaime.kick();
  • 29.
    Ч1. ООП –Как это можно делать сегодня TypeScript 1. Компилируется в JS ( Разные версии) 2. Схожий синтаксис с ES6 3. Строгая типизация, интерфейсы, модули
  • 30.
    Часть 2. Шаблоныпроектирования
  • 31.
    Ч2. Шаблоны проектирования Шаблонпроектирования или паттерн (англ. design pattern) в разработке программного обеспечения — повторимая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. Содержит 23 шаблона проектирования  Порождающие – 5  Структурные – 7  Поведенческие – 11 Примеры написаны на С++, Smalltalk
  • 32.
    Ч2. Пространства имён C++: namespace - using PHP : namespace – use – as Java : package - import JS
  • 33.
    Ч2. Пространства имён Какизвестно в Вестерос входит 7 королевств, которые подчиняются королю. Каждым королевством управляет лорд, а само оно делится на ещё меньшие области. Каждая область имеет обычно главный замок и близлежищие деревеньки, в которых живут люди. То есть, можно сказать, что Север входит в Вестерос, а Винтерфелл соотвествено в Север.
  • 34.
    Ч2. Пространства имён- реализация var vesteros = vesteros || {}; vesteros.namespace = function (ns_string) { var parts = ns_string.split('.'), parent = vesteros, i; // отбросить начальный префикс – имя глобального объекта if (parts[0] === 'vesteros') { parts = parts.slice(1); } for (i = 0; i < parts.length; i += 1) { // создать свойство, если оно отсутствует if (typeof parent[parts[i]] === 'undefined') { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; }; объект
  • 35.
    Ч2. Пространства имён- применение // присваивание возвращаемое значение локальной переменной var greenvale = vesteros.namespace('vesteros.dorn.greenvale'); greenvale === vesteros.dorn.greenvale; // true // можно опустить начальный префикс `vesteros` vesteros.namespace('north.winterfell');
  • 36.
    Ч2. Порождающие шаблоны- Singleton Шаблон проектирования, гарантирующий, что в однопоточном приложении будет единственный экземпляр класса с глобальной точкой доступа Области применения: модули в Node.js, сервисы в Symfony (PHP), Bean в Spring (Java)(По умолчанию)
  • 37.
    Ч2. Порождающие шаблоны- Singleton На крайнем севере Вестероса, за восемь тысяч лет до начала войны пяти королей, в эпоху героев, была построена огромная стена, для того, чтобы защищать Вестерос от белых ходоков.
  • 38.
    Java public class Wall{ private static Wall instance; private Wall () {} public static Wall getInstance() { if (instance == null) { instance = new Wall(); } return instance; } } JS function Wall() { if (Wall.instance) { return Wall.instance; } Wall.instance = this; } Wall.getInstance = function () { return Wall.instance; } Ч2. Порождающие шаблоны - Singleton Wall.instance = 5;
  • 39.
    Ч2. Порождающие шаблоны- Singleton var Wall = (function () { var instance = null; function Wall() { if (instance){ return instance; } instance = this; } Wall.getInstance = function () { if (instance) { instance = new Wall(); } return instance; }; return Wall; })(); Анонимная функция Вызов
  • 40.
    Ч2. Поведенческие шаблоны Шаблоныпроектирования, определяющие алгоритмы и способы реализации взаимодействия различных объектов и классов. Отлично реализуется в JS, благодаря возможности сохранять функции в структурах данных.
  • 41.
    Ч2. Поведенческие шаблоны- Observer Шаблон проектирования, который помогает определить зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии
  • 42.
    Ч2. Поведенческие шаблоны- Observer Королевский двор Вестероса – это место изощрённых интриг и коварства. Действующие лица очень активно используют шпионов, причём часто, один и тот же шпион работает на нескольких представителей двора, поэтому, как только шпион что-то узнаёт, он должен сразу доложить всем информацию.
  • 43.
    Ч2. Поведенческие шаблоны- Observer var Spy = (function () { function Spy() { this._partiesToNotify = []; } Spy.prototype.subscribe = function (subscriberFn) { this._partiesToNotify.push(subscriberFn); }; Spy.prototype.whisper = function (event) { for (var i = 0; i < this._partiesToNotify.length; i++) { this._partiesToNotify[i](event); } }; return Spy; })(); Хранитель подписчиков
  • 44.
    Ч2. Поведенческие шаблоны- Observer var Player = (function () { function Player() { } Player.prototype.listen = function(info) { //perform some action }; return Player; })(); var s = new Spy(); var p = new Player(); s.subscribe(p.listen); //p is now a subscriber s.whisper(12); //s will notify all subscribers
  • 45.
  • 46.
  • 47.
    Ч2. MVVM –Knockout  Декларативное связывание  Двунаправленная синхронизация  Наличие шаблонов  Free, open source  54kb
  • 48.
    Ч2. MVVM –Knockout, View <form data-bind="submit: sendRequest"> <label>Castle name</label> <input data-bind="value: castleName"> <br> <label>Wall thickness</label> <input data-bind="value: wallThick"> <br> <button type="submit">Submit</button> </form>
  • 49.
    Ч2. MVVM –Knockout, ViewModel var myViewModel = { castleName: ko.observable('Dorn'), wallThick: ko.observable(1), sendRequest: function () { console.log("Castle name: " + this.castleName()); console.log("Wall thickness : " + this.wallThick()); } }; ko.applyBindings(myViewModel);
  • 50.
    Резюме 1. Функциональное программирование 2.ООП 3. Пространства имён 4. Singleton 5. Observer 6. MVVM
  • 51.
    Вывод JS - этогибкий язык программирования, который позволяет под нужные задачи использовать разные подходы Способов решения задачи огромное количество, самое сложное – выбрать правильный. Что вам и желаю !
  • 52.
  • 53.
    Ч1. ФП -«Ленивая» инициализация  Приём в программировании, когда некоторая ресурсоёмкая операция выполняется непосредственно перед тем, как будет использован её результат. Таким образом, инициализация выполняется «по требованию», а не заблаговременно.  Плюсы: Инициализация выполняется только в тех случаях, когда она действительно необходима  Минусы: Невозможно явным образом задать порядок инициализации объектов
  • 54.
    Ч1. ФП -«Ленивая» инициализация Пекарня в Вестеросе выпекает отличный хлеб. Они получают заказы на разный вид хлеба, но сразу не пекут. Так как создание объекта “Bread” – это дорогостоящая операция, поэтому они стараются отложить эту работу, пока кто-нибудь действительно не придёт за хлебом.
  • 55.
    Ч1. ФП -«Ленивая» инициализация var Bread = (function () { function Bread(breadType) { this.breadType = breadType; //тяжёлая операция console.log("Bread " + breadType + " created."); } return Bread; })();
  • 56.
    Ч1. ФП -«Ленивая» инициализация Создаём объект “Bakery”. Он будет принимать заказы на разный вид хлеба. var Bakery = (function () { function Bakery() { this.requiredBreads = []; } Bakery.prototype.orderBreadType = function (breadType) { this.requiredBreads.push(breadType); }; Теперь у нас есть возможность быстро принимать заказы не тратя время на их реализацию.
  • 57.
    Bakery.prototype.buy = function(breadType) { // create and return }; var bakery = new Bakery(); bakery.orderBreadType("Brioche"); bakery.orderBreadType("Anadama bread"); bakery.orderBreadType("Chapati"); bakery.orderBreadType("Focaccia"); Ч1. ФП - «Ленивая» инициализация bakery.buy("Chapati") ; Инициализация
  • 58.
    Прил 1. Каррирование– имплементация function curry(fx) { var arity = fx.length; return function f1() { var args = Array.prototype.slice.call(arguments, 0); if (args.length >= arity) { return fx.apply(null, args); } else { return function f2() { var args2 = Array.prototype.slice.call(arguments, 0); return f1.apply(null, args.concat(args2)); } } }; }
  • 59.
    Прил 1. ФП– Каррирование - применение getData(r) render() argument
  • 60.
    Прил 1. ФП– Каррирование - применение getData render 2 render 1
  • 61.
    Прил 1. ФП– Каррирование - применение rende r Curry renderC render1 render2
  • 62.
    Прил 1. ФП– Каррирование - применение function getData(renderFn) { // get data var data = 5; renderFn(data); } function renderComplicate(flag, data) { if (flag) { console.log(2 * data); } else { console.log(3 * data); } } var r = _.curry(renderComplicate); var r1 = r(true); var r2 = r(false); getData(r1); // 10 getData(r2); // 15
  • 63.
    Ч2. Шаблон модуль varDragon = (function () { function Dragon(strength) { this.strength = strength; } Dragon.prototype.burn = function () { return "Dragon is close..."; }; return Dragon; }()); Анонимная функция Вызов
  • 64.
    Ч2. Структурные шаблоны Шаблоныпроектирования, в которых рассматривается вопрос о том, как из множества классов или множества объектов образуются более крупные или изменённые структуры.
  • 65.
    Ч2. Структурные шаблоны Широкоиспользуется агрегация и композиция JS – язык с динамической типизацией Удобная реализация
  • 66.
    Ч2. Структурные шаблоны- Decorator Структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности.
  • 67.
    Ч2. Структурные шаблоны- Decorator Броня, которую рыцари Вестероса носят, является очень конфигурируемой и «настраивается» под любые нужды и размер кошелька заказчика. Она может быть кольчужной, иметь вплетения, сделанные из медных колец, позолоченные. Так же могут быть разные наколенники, и разные вставки в шлем. Вариантов очень много, особенно для кодинга !
  • 68.
    Ч2. Структурные шаблоны- Adapter Структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.
  • 69.
    Ч2. Структурные шаблоны- Decorator var BasicArmor = (function(){ function BA () {} BA.prototype.damage=function(hit){ return hit.s / 1.5; }; return BA; })(); var ChainMail = (function () { function CM(ba) { this.bArmor = ba; } CM.prototype.damage=function(hit) { hit.s *= 0.8; return this.bArmor.damage(hit); }; return CM; })(); var armor = new ChainMail(new BasicArmor());
  • 70.
    Ч2. Структурные шаблоны- Adapter В Вестеросе очень опасно путешествовать. С лёгкостью можно попасть в руки к разбойникам или заблудиться, поэтому часто, люди у которых есть деньги пользуются кораблём. Однако кораблём мы управлять не умеем, в отличие от верблюда. interface Ship{ SetRudderAngleTo(angle); SetSailConfiguration(configuration); SetSailAngle(sailId, sailAngle); GetCurrentBearing(); GetCurrentSpeedEstimate(); ShiftCrewWeightTo(weightToShift, locationId); } interface Camel{ TurnLeft(); TurnRight(); GoForward(); }
  • 71.
    Ч2. Структурные шаблоны- Adapter var Camel = (function () { function Camel() { this._ship = new Ship(); } Camel.prototype.TurnLeft = function () { this._ship.SetRudderAngleTo(-30); this._ship.SetSailAngle(3, 12); }; Camel.prototype.TurnRight = function () { this._ship.SetRudderAngleTo(30); this._ship.SetSailAngle(5, -9); }; Camel.prototype.GoForward= function () { //do something else to the _ship }; return Camel; })(); var camel = new Camel(); camel.GoForward(); camel.TurnLeft();
  • 72.
    Dirty checking Через каждыйинтервал времени, проверяются все поля во VM, на предмет их изменения, если они были изменены, то обновляется Представление. В Представлении на всех контролах сидят слушатели. Контейнерный объект Пример: Библиотека - Knockout.js function CreateCastleVModel(name) { this.name = ko.observable(name); } var model = new CreateCastleVModel(); model.name("Winterfell"); //set model.name(); //get Ч2. MVVM – варианты реализации Использует: Angular Использует: Backbone, Ember