...

суббота, 18 октября 2014 г.

[Перевод] Выразительный JavaScript: Структуры данных: объекты и массивы

Содержание


Два раза меня спрашивали: «Скажите, м-р Бэббидж, а если вы введёте в машину неправильные данные, получится ли правильный ответ?». Непостижима та путаница в головах, которая приводит к таким вопросам.


Чарльз Бэббидж, «Отрывки из жизни философа» (1864)


Числа, булевские значения и строки – кирпичики, из которых строятся структуры данных. Но нельзя сделать дом из одного кирпича. Объекты позволяют нам группировать значения (в том числе и другие объекты) вместе – и строить более сложные структуры.


Написание программ, которым мы до сего момента занимались, сильно затруднял тот факт, что они работали только с простыми данными. Эта глава добавит вам в инструментарий понимание структур данных. К её концу вы будете знать достаточно для того, чтобы начать писать полезные программы.


Глава пройдётся по более-менее реалистичному примеру программирования, вводя понятия по мере необходимости. Код примеров будет строиться из функций и переменных, которые мы определяли ранее.



Белка-оборотень




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

С одной стороны, Жак рад, что он не превращается в классического волка. Превращение в белку влечёт меньше проблем. Вместо того, чтобы волноваться о том, не съешь ли ты соседа (это было бы неловко), он волнуется, как бы его не съел соседский кот. После того, как он дважды просыпался на очень тонкой ветке в кроне дуба, голый и дезориентированный, он приучился запирать окна и двери в своей комнате на ночь, и класть несколько орешков на пол, чтобы чем-то занять себя.


Так решаются проблемы с котом и дубом. Но Жак всё ещё страдает от своего заболевания. Нерегулярные обращения наводят его на мысль, что они должны быть чем-то вызваны. Сначала он думал, что это происходит только в те дни, когда он прикасался к деревьям. Он перестал это делать, и даже стал избегать подходить к ним. Но проблема не исчезла.


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


Сперва он решил разработать структуру данных для хранения этой информации.


Наборы данных



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

2, 3, 5, 7, 11


Можно поиграть со строками – строки могут быть любой длины, в них можно поместить много данных, и использовать для представления этого набора «2 3 5 7 11». Но это неудобно. Нам нужно будет как-то вынимать оттуда числа или вставлять новые в строку.


К счастью, JavaScript предлагает тип данных специально для хранения последовательностей чисел. Он называется массивом (array), и записывается, как список значений в квадратных скобках, разделённых запятыми:



var listOfNumbers = [2, 3, 5, 7, 11];
console.log(listOfNumbers[1]);
// → 3
console.log(listOfNumbers[1 - 1]);
// → 2


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


Номер первого элемента – ноль, а не один. Поэтому первый элемент можно получить так: listOfNumbers[0]. Если вы раньше не программировали, придётся привыкнуть к такой нумерации. Но она имеет давнюю традицию, и всё время, пока её последовательно соблюдают, она прекрасно работает.


Свойства



Мы видели много подозрительных выражений вроде myString.length (получение длины строки) и Math.max (получение максимума) в ранних примерах. Эти выражения используют свойства величин. В первом случае, мы получаем доступ к свойству length (длина) переменной myString. Во втором — доступ к свойству max объекта Math (который является набором функций и переменных, связанных с математикой).

Почти у всех переменных в JavaScript есть свойства. Исключения — null и undefined. Если вы попробуете получить доступ к несуществующим свойствам этих не-величин, получите ошибку:



null.length;
// → TypeError: Cannot read property 'length' of null


Два основных способа доступа к свойствам – точка и квадратные скобки. value.x и values[x] получают доступ к свойству value – но не обязательно к одному и тому же. Разница в том, как интерпретируется x. При использовании точки запись после точки должна быть именем существующей переменной, и она таким образом напрямую вызывает свойство по имени. При использовании квадратных скобок выражение в скобках вычисляется для получения имени свойства. value.x вызывает свойство под именем “x”, а value[x] вычисляет выражение x и использует результат в качестве имени свойства.


Если вы знаете, что интересующее вас свойство называется “length”, вы пишете value.length. Если вы хотите извлечь имя свойства из переменной i, вы пишете value[i]. А поскольку свойство может иметь любое имя, для доступа к свойству по имени “2” или “Jon Doe” вам придётся использовать квадратные скобки: value[2] или value[«John Doe»]. Это необходимо даже когда вы знаете точное имя свойства, потому что “2” или «John Doe» не являются допустимыми именами переменных, поэтому к ним нельзя обратиться при помощи записи через точку.


Элементы массива хранятся в свойствах. Так как имена этих свойств – числа, и нам часто приходится получать их имена из значений переменных, нужно использовать квадратные скобки для доступа к ним. Свойство length массива говорит о том, сколько в нём элементов. Имя этого свойства – допустимое имя переменной, и мы его знаем заранее, поэтому обычно мы пишем array.length, потому, что это проще, чем писать array[“length”].


Методы



Объекты string и array содержат, в дополнение к свойству length, несколько свойств, ссылающихся на функции.

var doh = "Дык";
console.log(typeof doh.toUpperCase);
// → function
console.log(doh.toUpperCase());
// → ДЫК


У каждой строки есть свойство toUpperCase. При вызове оно возвращает копию строки, в которой все буквы заменены на прописные. Есть также и toLowerCase – можете догадаться, что оно делает.


Что интересно, хотя вызов toUpperCase не передаёт никаких аргументов, функция каким-то образом получает доступ к строчке “Дык”, свойство которой мы вызывали. Как это работает, описано в главе 6.


Свойства, содержащие функции, обычно называют методами той переменной, которой они принадлежат. То есть, toUpperCase – это метод строки.


В следующем примере демонстрируются некоторые методы, имеющиеся у массивов:



var mack = [];
mack.push("Трест,");
mack.push("который", "лопнул");
console.log(mack);
// → ["Трест,", "который", "лопнул"]
console.log(mack.join(" "));
// → Трест, который лопнул
console.log(mack.pop());
// → лопнул
console.log(mack);
// → ["Трест,", "который"]


Метод push используется для добавления значений в конец массива. pop делает обратное: удаляет значение из конца массива и возвращает его. Массив строк можно сплющить в одну строку при помощи метода join. В качестве аргумента join передают строку, которая будет вставлена между элементами массива.


Объекты



Вернёмся к нашей белке. Набор журнальных записей можно представить в виде массива. Но записи не состоят только лишь из номеров или строк – каждая должна хранить список того, что сделал наш герой, и булевское значение, показывающее, превратился ли Жак в белку. В идеале нам бы хотелось группировать каждую из записей в какую-то одну переменную, и потом добавлять их в массив.

Переменные типа object (объект) – коллекции произвольных свойств, и мы можем добавлять и удалять свойства объекта по желанию. Один из способов создать объект – использовать фигурные скобки:



var day1 = {
squirrel: false,
events: ["работа", "тронул дерево", "пицца", "пробежка", "телевизор"]
};
console.log(day1.squirrel);
// → false
console.log(day1.wolf);
// → undefined
day1.wolf = false;
console.log(day1.wolf);
// → false


В скобках мы можем задать список свойств, разделённых запятыми. Записывается каждое свойство как имя, после которого идёт двоеточие, затем идёт выражение, которое и является значением свойства. Пробелы и переносы строк не учитываются. Разбивая запись свойств объекта на несколько строк, вы улучшаете читаемость кода. Если имя свойства не является допустимым именем переменной, его нужно заключать в кавычки:



var descriptions = {
work: "Пошёл на работу",
"тронул дерево": "Дотронулся до дерева"
};


Получается, у фигурных скобок в JavaScript два значения. Употреблённые в начале инструкции, они начинают новый блок инструкций. В любом другом месте они описывают объект. Обычно нет смысла начинать инструкцию с описания объекта, и поэтому в программах обычно нет двусмысленностей по поводу этих двух применений фигурных скобок.


Если вы попытаетесь прочесть значение несуществующего свойства, вы получите undefined – как в примере, когда мы первый раз попробовали прочесть свойство wolf.


Свойству можно назначать значение через оператор =. Если у него ранее было значение, оно будет заменено. Если свойство отсутствовало, оно будет создано.


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


Оператор delete отрезает щупальце. Это унарный оператор, применяемый к выражению доступа к свойству. Это делается редко, но вполне возможно.



var anObject = {left: 1, right: 2};
console.log(anObject.left);
// → 1
delete anObject.left;
console.log(anObject.left);
// → undefined
console.log("left" in anObject);
// → false
console.log("right" in anObject);
// → true


Бинарный оператор in принимает строку и им объекта, и возвращает булевское значение, показывающее, есть ли у объекта свойство с таким именем. Есть разница между установкой значения свойства в undefined и удалением свойства. В первом случае свойство сохраняется у объекта, просто оно пустое. Во втором – свойства больше нет, и тогда in возвращает false.


Получается, что массивы – это разновидность объектов, которые специализируются на хранении последовательностей. Выражение typeof [1, 2] вернёт “object”. Их можно рассматривать как длинных плоских осьминогов, у которых все щупальца расположены ровным рядом и размечены номерами.



Поэтому журнал Жака можно представить в виде массива объектов:



var journal = [
{events: ["работа", "тронул дерево", "пицца", "пробежка", "телевизор"],
squirrel: false},
{events: ["работа ", "мороженое", "цветная капуста", "лазанья", " тронул дерево ", "почистил зубы"],
squirrel: false},
{events: ["выходной", "велик", "перерыв", "арахис", "пивасик"],
squirrel: true},
/* and so on... */
];


Изменчивость (Mutability)

Скоро мы уже и до программирования доберёмся. А пока нам нужно понять последнюю часть теории.


Мы увидели, что значения объекта можно менять. Типы значений, которые мы рассматривали ранее,– числа, строки, булевские значения,- неизменяемы. Нельзя поменять существующее значение заданного типа. Их можно комбинировать и выводить из них новые значения, но когда вы работаете с некоторым значением строки, это значение остаётся постоянным. Текст внутри строки нельзя поменять. Если у вас есть ссылка на строку «кошка», в коде нельзя поменять в ней символ, чтобы получилось «мошка».


А вот у объектов содержимое можно менять, изменяя значения их свойств.


Если у нас есть два числа, 120 и 120, мы можем рассматривать их как одно и тоже, независимо от того, хранятся ли они в памяти в одном и том же месте. Но когда мы имеем дело с объектами, есть разница, есть ли у нас две ссылки на один объект или же у нас есть два разных объекта, содержащих одинаковые свойства. Рассмотрим пример:



var object1 = {value: 10};
var object2 = object1;
var object3 = {value: 10};

console.log(object1 == object2);
// → true
console.log(object1 == object3);
// → false

object1.value = 15;
console.log(object2.value);
// → 15
console.log(object3.value);
// → 10


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


Оператор == при сравнении объектов возвращает true только, если сравниваемые объекты – это одна и та же переменная. Сравнение разных объектов вернёт false, даже если у них идентичное содержимое. Оператора «глубокого» сравнения, который бы сравнивал содержимое объектов, в JavaScript не предусмотрено, но его возможно сделать самостоятельно (это будет одним из упражнений в конце главы).


Журнал оборотня




Итак, Жак запускает свой любимый интерпретатор JavaScript и создаёт окружение, необходимое для хранения журнала.

var journal = [];

function addEntry(events, didITurnIntoASquirrel) {
journal.push({
events: events,
squirrel: didITurnIntoASquirrel
});
}


Каждый вечер, часов в десять,– а иногда и назавтра утром, спускаясь с верхней полки шкафа,- он записывает свой день.



addEntry(["работа", "тронул дерево", "пицца", "пробежка", "телевизор"], false);
addEntry(["работа ", "мороженое", "цветная капуста", "лазанья", " тронул дерево ", "почистил зубы"], false);
addEntry(["выходной", "велик", "перерыв", "арахис", "пивасик"], true);


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


Корреляция – это мера зависимости между переменными величинами (переменными в статистическом смысле, а не в смысле JavaScript). Она обычно выражается в виде коэффициента, принимающего значения от -1 до 1. Нулевая корреляция обозначает, что переменные вообще не связаны, а корреляция 1 означает, что они полностью связаны – если вы знаете одну, вы автоматически знаете другую. Минус один также означает прочную связь переменных, но и их противоположность – когда одна true, вторая всегда false.


Для измерения корреляции булевских переменных хорошо подходит коэффициент фи (ϕ), к тому же, его сравнительно легко подсчитать. Для этого нам нужна таблица, содержащая количество раз, когда наблюдались различные комбинации двух переменных. К примеру, мы можем взять события «поел пиццы» и «обращение» и представить их в следующей таблице:


ϕ можно вычислить по следующей формуле, где n относится к ячейкам таблицы:


n01 обозначает количество измерений, когда первое событие (пицца) false (0), а второе событие (обращение) true (1). В нашем примере n01 = 4.


Запись n1• обозначает сумму всех измерений, где первое событие было true, что для нашего примера равно 10. Соответственно, n•0 – сумма всех измерений, где событие «обращение» было false.


Значит, для таблицы с пиццей числитель формулы будет 1×76 — 9×4 = 40, а знаменатель – корень из 10×80×5×85, или √340000. Получается, что ϕ ≈ 0.069, что довольно мало. Непохоже, чтобы пицца влияла на обращения в белку.


Вычисляем корреляцию



Таблицу 2х2 можно представить массивом из четырёх элементов ([76, 9, 4, 1]), массивом из двух элементов, каждый из которых является также двухэлементным массивом ([76, 9], [4, 1]]), или же объектом со свойствами под именами “11” или “01”. Но для нас одномерный массив проще и выражение для доступа к нему будет короче. Мы будем обрабатывать индексы массива как двузначные двоичные числа, где левый знак обозначает переменную оборачиваемости, а правый – события. К примеру, 10 обозначает случай, когда Жак обратился в белку, но событие (к примеру, «пицца») не имело места. Так случилось 4 раза. И поскольку двоичное 10 – это десятичное 2, мы будем хранить это в массиве по индексу 2.

Функция, вычисляющая коэффициент ϕ из такого массива:



function phi(table) {
return (table[3] * table[0] - table[2] * table[1]) /
Math.sqrt((table[2] + table[3]) *
(table[0] + table[1]) *
(table[1] + table[3]) *
(table[0] + table[2]));
}

console.log(phi([76, 9, 4, 1]));
// → 0.068599434


Это просто прямая реализация формулы ϕ на языке JavaScript. Math.sqrt – это функция извлечения квадратного корня объекта Math из стандартного окружения JavaScript. Нам нужно сложить два поля таблицы для получения полей типа n1•, потому что мы не храним в явном виде суммы столбцов или строк.


Жак вёл журнал три месяца. Результат доступен на сайте книги

http://ift.tt/1qzavUE


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



function hasEvent(event, entry) {
return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal) {
var table = [0, 0, 0, 0];
for (var i = 0; i < journal.length; i++) {
var entry = journal[i], index = 0;
if (hasEvent(event, entry)) index += 1;
if (entry.squirrel) index += 2;
table[index] += 1;
}
return table;
}

console.log(tableFor("pizza", JOURNAL));
// → [76, 9, 4, 1]


Функция hasEvent проверяет, содержит ли запись нужный элемент. У массивов есть метод indexOf, который ищет заданное значение (в нашем случае – имя события) в массиве. и возвращает индекс его положения в массиве (-1, если его в массиве нет). Значит, если вызов indexOf не вернул -1, то событие в записи есть.


Тело цикла в tableFor рассчитывает, в какую ячейку таблицы попадает каждая из журнальных записей. Она смотрит, содержит ли запись нужное событие, и связано ли оно с обращением в белку. Затем цикл увеличивает на единицу элемент массива, соответствующий нужной ячейке.


Теперь у нас есть все инструменты для подсчёта корреляций. Осталось только подсчитать корреляции для каждого из событий, и посмотреть, не выдаётся ли что из списка. Но как хранить эти корреляции?


Объекты как карты (map)



Один из способов – хранить корреляции в массиве, используя объекты со свойствами name и value. Однако поиск корреляций в массиве будет довольно громоздким: нужно будет пройтись по всему массиву, чтобы найти объект с нужным именем. Можно было бы обернуть этот процесс в функцию, но код пришлось бы писать всё равно, и компьютер выполнял бы больше работы, чем необходимо.

Способ лучше – использовать свойства объектов с именами событий. Мы можем использовать квадратные скобки для создания и чтения свойств и оператор in для проверки существования свойства.



var map = {};
function storePhi(event, phi) {
map[event] = phi;
}

storePhi("пицца", 0.069);
storePhi("тронул дерево", -0.081);
console.log("пицца" in map);
// → true
console.log(map["тронул дерево"]);
// → -0.081


Карта (map) – способ связать значения из одной области (в данном случае – названия событий) со значениями в другой (в нашем случае – коэффициенты ϕ).


С таким использованием объектов есть пара проблем – мы обсудим их в главе 6, но пока волноваться не будем.


Что, если нам надо собрать все события, для которых сохранены коэффициенты? Они не создают предсказуемую последовательность, как было бы в массиве, поэтому цикл for использовать не получится. JavaScript предлагает конструкцию цикла специально для обхода всех свойств объекта. Она похожа на цикл for, но использует команду in.



for (var event in map)
console.log("The correlation for '" + event +
"' is " + map[event]);
// → The correlation for 'пицца' is 0.069
// → The correlation for 'тронул дерево' is -0.081


Итоговый анализ




Чтобы найти все типы событий, представленных в наборе данных, мы обрабатываем каждое вхождение по очереди, и затем создаём цикл по всем событиям вхождения. Мы храним объект phis, в котором содержатся корреляционные коэффициенты для всех типов событий, которые мы уже нашли. Если мы встречаем новый тип, которого ещё не было в phis, мы подсчитываем его корреляцию и добавляем её в объект.

function gatherCorrelations(journal) {
var phis = {};
for (var entry = 0; entry < journal.length; entry++) {
var events = journal[entry].events;
for (var i = 0; i < events.length; i++) {
var event = events[i];
if (!(event in phis))
phis[event] = phi(tableFor(event, journal));
}
}
return phis;
}

var correlations = gatherCorrelations(JOURNAL);
console.log(correlations.pizza);
// → 0.068599434


Смотрим. что получилось:



for (var event in correlations)
console.log(event + ": " + correlations[event]);
// → морковка: 0.0140970969
// → упражнения: 0.0685994341
// → выходной: 0.1371988681
// → хлеб: -0.0757554019
// → пудинг: -0.0648203724
// и так далее...


Большинство корреляций лежат близко к нулю. Морковки, хлеб и пудинг, очевидно, не связаны с обращением в белку. Но оно вроде бы более часто происходит на выходных. Давайте отфильтруем результаты, чтобы выводить только корреляции больше 0.1 или меньше -0.1



for (var event in correlations) {
var correlation = correlations[event];
if (correlation > 0.1 || correlation < -0.1)
console.log(event + ": " + correlation);
}
// → выходной: 0.1371988681
// → чистил зубы: -0.3805211953
// → конфета: 0.1296407447
// → работа: -0.1371988681
// → спагетти: 0.2425356250
// → читал: 0.1106828054
// → арахис: 0.5902679812


Ага! У двух факторов корреляции заметно больше остальных. Арахис сильно влияет на вероятность превращения в белку, тогда как чистка зубов наоборот, препятствует этому.


Интересно. Попробуем вот что:



for (var i = 0; i < JOURNAL.length; i++) {
var entry = JOURNAL[i];
if (hasEvent("арахис", entry) &&
!hasEvent("чистка зубов", entry))
entry.events.push("арахис зубы");
}
console.log(phi(tableFor("арахис зубы ", JOURNAL)));
// → 1


Ошибки быть не может! Феномен случается именно тогда, когда Жак есть арахис и не чистит зубы. Если б он только не был таким неряхой относительно оральной гигиены, он бы вообще не заметил своего несчастья.


Зная это, Жак просто перестаёт есть арахис и обнаруживает, что трансформации прекратились.


У Жака какое-то время всё хорошо. Но через несколько лет он теряет работу, и в конце концов ему приходится наняться в цирк, где он выступает как Удивительный Человек-белка, набирая полный рот арахисового масла перед шоу. Однажды, устав от столь жалкого существования, Жак не обращается обратно в человека, пробирается через дыру в цирковом тенте и исчезает в лесу. Больше его никто не видел.


Дальнейшая массивология




В конце главы хочу познакомить вас ещё с несколькими концепциями, относящимися к объектам. Начнём с полезных методов, имеющихся у массивов.

Мы видели методы push и pop, которые добавляют и отнимают элементы в конце массива. Соответствующие методы для начала массива называются unshift и shift



var todoList = [];
function rememberTo(task) {
todoList.push(task);
}
function whatIsNext() {
return todoList.shift();
}
function urgentlyRememberTo(task) {
todoList.unshift(task);
}


Данная программа управляет списком дел. Вы добавляете дела в конец списка, вызывая rememberTo(«поесть»), а когда вы готовы заняться чем-то, вызываете whatIsNext(), чтобы получить (и удалить) первый элемент списка. Функция urgentlyRememberTo тоже добавляет задачу, но только в начало списка.


У метода indexOf есть родственник по имени lastIndexof, который начинает поиск элемента в массиве с конца:



console.log([1, 2, 3, 2, 1].indexOf(2));
// → 1
console.log([1, 2, 3, 2, 1].lastIndexOf(2));
// → 3


Оба метода, indexOf и lastIndexOf, принимают необязательный второй аргумент, который задаёт начальную позицию поиска.


Ещё один важный метод – slice, который принимает номера начального (start) и конечного (end) элементов, и возвращает массив, состоящий только из элементов, попадающих в этот промежуток. Включая тот, что находится по индексу start, но исключая тот, что по индексу end.



console.log([0, 1, 2, 3, 4].slice(2, 4));
// → [2, 3]
console.log([0, 1, 2, 3, 4].slice(2));
// → [2, 3, 4]


Когда индекс end не задан, slice выбирает все элементы после индекса start. У строк есть схожий метод, который работает так же.


Метод concat используется для склейки массивов, примерно как оператор + склеивает строки. В примере показаны методы concat и slice в деле. Функция принимает массив array и индекс index, и возвращает новый массив, который является копией предыдущего, за исключением удалённого элемента, находившегося по индексу index.



function remove(array, index) {
return array.slice(0, index).concat(array.slice(index + 1));
}
console.log(remove(["a", "b", "c", "d", "e"], 2));
// → ["a", "b", "d", "e"]


Строки и их свойства




Мы можем получать значения свойств строк, например length и toUpperCase. Но попытка добавить новое свойство ни к чему не приведёт:

var myString = "Шарик";
myString.myProperty = "значение";
console.log(myString.myProperty);
// → undefined


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


Но у них есть свои встроенные свойства. У каждой строки есть набор методов. Самые полезные, пожалуй – slice и indexOf, напоминающие те же методы у массивов.



console.log("кокосы".slice(3, 6));
// → осы
console.log("кокос".indexOf("с"));
// → 4


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



console.log("раз два три".indexOf("ва"));
// → 5


Метод trim удаляет пробелы (а также переводы строк, табуляцию и прочие подобные символы) с обоих концов строки.



console.log(" ладно \n ".trim());
// → ладно


Мы уже сталкивались со свойством строки length. Доступ к отдельным символам строчки можно получить через метод charAt, а также просто через нумерацию позиций, как в массиве:



var string = "abc";
console.log(string.length);
// → 3
console.log(string.charAt(0));
// → a
console.log(string[1]);
// → b


Объект arguments




Когда вызывается функция, к окружению исполняемого тела функции добавляется особая переменная под названием arguments. Она указывает на объект, содержащий все аргументы, переданные функции. Помните, что в JavaScript вы можете передавать функции больше или меньше аргументов, чем объявлено при помощи параметров.

function noArguments() {}
noArguments(1, 2, 3); // Пойдёт
function threeArguments(a, b, c) {}
threeArguments(); // И так можно


У объекта arguments есть свойство length, которое содержит реальное количество переданных функции аргументов. Также у него есть свойства для каждого аргумента под именами 0, 1, 2 и т.д.


Если вам кажется, что это очень похоже на массив – вы правы. Это очень похоже на массив. К сожалению, у этого объекта нет методов типа slice или indexOf, что делает доступ к нему труднее.



function argumentCounter() {
console.log("Ты дал мне", arguments.length, "аргумента.");
}
argumentCounter("Дядя", "Стёпа", "Милиционер");
// → Ты дал мне 3 аргумента.


Некоторые функции рассчитаны на любое количество аргументов, как console.log. Они обычно проходят циклом по свойствам объекта arguments. Это можно использовать для создания удобных интерфейсов. К примеру, вспомните, как мы создавали записи для журнала Жака:



addEntry(["работа", "тронул дерево", "пицца", "пробежка", "телевизор"], false);


Так как мы часто вызываем эту функцию, мы можем сделать альтернативу, которую проще вызывать:



function addEntry(squirrel) {
var entry = {events: [], squirrel: squirrel};
for (var i = 1; i < arguments.length; i++)
entry.events.push(arguments[i]);
journal.push(entry);
}
addEntry(true, "работа", "тронул дерево", "пицца", "пробежка", "телевизор");


Эта версия читает первый аргумент как обычно, а по остальным проходит в цикле (начиная с индекса 1, пропуская первый аргумент) и собирает их в массив.


Объект Math




Мы уже видели, что Math – набор инструментов для работы с числами, такими, как Math.max (максимум), Math.min (минимум), and Math.sqrt (квадратный корень).

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


Слишком большое число глобальных переменных «загрязняет» пространство имён. Чем больше имён занято, тем больше вероятность случайно использовать одно из них в качестве переменной. К примеру, весьма вероятно, что вы захотите использовать имя max для чего-то в своей программе. Поскольку встроенная в JavaScript функция max безопасно упакована в объект Math, нам не нужно волноваться по поводу того, что мы её перезапишем.


Многие языки остановят вас, или хотя бы предупредят, когда вы будете определять переменную с именем, которое уже занято. JavaScript не будет этого делать, поэтому будьте осторожны.


Возвращаясь к объекту Math. Если вам нужна тригонометрия, он вам поможет. У него есть cos (косинус), sin (синус), and tan (тангенс), их обратные функции — acos, asin, и atan. Число π (pi) – или, по крайней мере, его близкая аппроксимация, помещающаяся в число JavaScript,- также доступна как Math.PI. (Есть такая старая традиция в программировании — записывать имена констант в верхнем регистре).



function randomPointOnCircle(radius) {
var angle = Math.random() * 2 * Math.PI;
return {x: radius * Math.cos(angle),
y: radius * Math.sin(angle)};
}
console.log(randomPointOnCircle(2));
// → {x: 0.3667, y: 1.966}


Если вы незнакомы с синусами и косинусами – не отчаивайтесь. Мы их будем использовать в 13 главе, и тогда я их объясню.


В предыдущем примере используется Math.random. Это функция, возвращающая при каждом вызове новое псевдослучайное число между нулём и единицей (включая ноль).



console.log(Math.random());
// → 0.36993729369714856
console.log(Math.random());
// → 0.727367032552138
console.log(Math.random());
// → 0.40180766698904335


Хотя компьютеры – машины детерминистские (они всегда реагируют одинаково на одни и те же входные данные), возможно заставить их выдавать кажущиеся случайными номера. Для этого машина хранит у себя во внутреннем состоянии несколько номеров. Каждый раз, когда идёт запрос на случайный номер, она выполняет разные сложные детерминистские вычисления и возвращает часть результата вычислений. Этот результат она использует для того, чтобы изменить своё внутреннее состояние, поэтому следующий «случайный» номер получается другим.


Если вам нужно целое случайное число, а не дробь, вы можете использовать Math.floor (округляет число вниз до ближайшего целого) на результате Math.random.



console.log(Math.floor(Math.random() * 10));
// → 2


Умножая случайное число на 10, получаем номер от нуля до 10 (включая ноль). Так как Math.floor округляет вниз, мы получим число от 0 до 9 включительно.


Есть также функция Math.ceil («ceiling” – потолок), которая округляет вверх до ближайшего целого) и Math.round (округляет до ближайшего целого).


Объект global




К глобальной области видимости, где живут глобальные переменные, vожно получить доступ так же, как к объекту. Каждая глобальная переменная является свойством этого объекта. В браузерах глобальная область видимости хранится в переменной window.

var myVar = 10;
console.log("myVar" in window);
// → true
console.log(window.myVar);
// → 10


Итог




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

У большинства величин в JavaScript есть свойства, за исключением null и undefined. Мы получаем доступ к ним через value.propName или value[»propName"]. Объекты используют имена для хранения свойств и хранят более-менее фиксированное их количество. Массивы обычно содержат переменное количество сходных по типу величин, и используют числа (начиная с нуля) в качестве имён этих величин.


Также в массивах есть именованные свойства, такие как length, и несколько методов. Методы – это функции, живущие среди свойств и (обычно) работающие над той величиной, чьим свойством они являются.


Объекты также могут работать как карты, ассоциируя значения с именами. Оператор in используется для выяснения того, содержит ли объект свойство с данным именем. Это же ключевое слово используется в цикле for (for (var name in object)) для перебора всех свойств объекта.


Упражнения




Сумма диапазона



Во введении был упомянут удобный способ подсчёта сумм диапазонов чисел:

console.log(sum(range(1, 10)));


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


Затем напишите функцию sum, принимающую массив чисел и возвращающую их сумму. Запустите указанную выше инструкцию и убедитесь, что она возвращает 55.


В качестве бонуса дополните функцию range, чтобы она могла принимать необязательный третий аргумент – шаг для построения массива. Если он не задан, шаг равен единице. Вызов функции range(1, 10, 2) должен будет вернуть [1, 3, 5, 7, 9]. Убедитесь, что она работает с отрицательным шагом так, что вызов range(5, 2, -1) возвращает [5, 4, 3, 2].



console.log(sum(range(1, 10)));
// → 55
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]


Обращаем вспять массив



У массивов есть метод reverse, меняющий порядок элементов в массиве на обратный. В качестве упражнения напишите две функции, reverseArray и reverseArrayInPlace. Первая получает массив как аргумент и выдаёт новый массив, с обратным порядком элементов. Вторая работает как оригинальный метод reverse – она меняет порядок элементов на обратный в том массиве, который был ей передан в качестве аргумента. Не используйте стандартный метод reverse.

Если иметь в виду побочные эффекты и чистые функции из предыдущей главы, какой из вариантов вам кажется более полезным? Какой более эффективным?



console.log(reverseArray(["A", "B", "C"]));
// → ["C", "B", "A"];
var arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log(arrayValue);
// → [5, 4, 3, 2, 1]


Список



Объекты могут быть использованы для построения различных структур данных. Часто встречающаяся структура – список (не путайте с массивом). Список – связанный набор объектов, где первый объект содержит ссылку на второй, второй – на третий, и т.п.

var list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};


В результате объекты формируют цепочку:


Списки удобны тем, что они могут делиться частью своей структуры. Например, можно сделать два списка, {value: 0, rest: list} и {value: -1, rest: list}, где list – это ссылка на ранее объявленную переменную. Это два независимых списка, при этом у них есть общая структура list, которая включает три последних элемента каждого из них. Кроме того, оригинальный список также сохраняет свои свойства как отдельный список из трёх элементов.


Напишите функцию arrayToList, которая строит такую структуру, получая в качестве аргумента [1, 2, 3], а также функцию listToArray, которая создаёт массив из списка. Также напишите вспомогательную функцию prepend, которая получает элемент и создаёт новый список, где этот элемент добавлен спереди к первоначальному списку, и функцию nth, которая в качестве аргументов принимает список и число, а возвращает элемент на заданной позиции в списке, или же undefined в случае отсутствия такого элемента.


Если ваша версия nth не рекурсивна, тогда напишите её рекурсивную версию.



console.log(arrayToList([10, 20]));
// → {value: 10, rest: {value: 20, rest: null}}
console.log(listToArray(arrayToList([10, 20, 30])));
// → [10, 20, 30]
console.log(prepend(10, prepend(20, null)));
// → {value: 10, rest: {value: 20, rest: null}}
console.log(nth(arrayToList([10, 20, 30]), 1));
// → 20


Глубокое сравнение



Оператор == сравнивает объекты на идентичность. Но иногда полезно было бы сравнить их по содержимому.

Напишите функцию deepEqual, которая принимает два значения и возвращает true, только если это два одинаковых значения или это объекты, свойства которых имеют одинаковые значения, если их сравнивать рекурсивным вызовом deepEqual.


Чтобы узнать, когда сравнивать величины через ===, а когда – объекты по содержимому, используйте оператор typeof. Если он выдаёт “object” для обеих величин, значит нужно делать глубокое сравнение. Не забудьте об одном дурацком исключении, случившемся из-за исторических причин: “typeof null” тоже возвращает “object”.



var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Старая псина учит новые трюки: Code Kata с использованием QuickCheck

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


Баги в некоторых программах остаются незамеченными годами. Другие тихо исправляются. Но встречаются баги, которые становятся объектом всеобщего внимания и даже судебного разбирательства. Именно такая история произошла с ошибкой в игровом автомате Game King Multi-Game. Обнаруживший её игрок не сообщил разработчикам о найденной уязвимости, а начал снимать джекпоты в разных казино. Расследование ФБР показало, что он снял из игровых автоматов более $500 тыс.



Первые автоматы для видеопокера появились в американских казино в 70-е годы и их сразу ждал большой успех. Игрокам нравилось, что они могут влиять на результат (выбирать карты), а не тупо крутить барабан. Владелец патента International Game Technology провела IPO и вышла на бижу в 1981 году.


Главным козырем IGT было использование компьютерных технологий в игровых автоматах. Компания добилась идеальной формулы в 1996 году, с выпуском модели Game King Multi-Game, которая предлагала несколько вариантов покера. Казино закупили эти автоматы, а производитель продавал им новые прошивки с новыми играми. 25 сентября 2002 года вышла пятая версия прошивки — Game King 5.0.


Как выяснилось, в код Game King 5.0 закралась ошибка. Точнее, ряд небольших багов в программе под номером G0001640. Им удалось избежать обнаружения во время тестирования.


Баг оставался незамеченным в течение следующих 7 лет, переходя в каждую новую версию прошивки. В результате копирования кода он проник в 99 разных программ на тысячах игровых автоматов IGT. Насколько известно, никто не воспользовался им до апреля 2009 года, когда его случайно обнаружил Джон Кейн (на фото).


Баг проявился случайно. Джон Кейн проводил за игрой огромное количество времени. Однажды в одном из игровых автоматов возле китайской закусочной на окраине Лас-Вегаса он пробовал разные варианты покера, но потом решил заказать кэшаут и поискать удачи в другом автомате. Как только он нажал кнопку “Cash Out”, экран неожиданно заблокировался, автомат заморгал, зазвенел и сообщил о джекпоте более чем на $1000. Джон даже не начинал играть новую руку. Он сообщил подошедшему сотруднику о глюке, но тот посчитал это шуткой и выдал выигрыш.


Джон Кейн позвонил другу Андре Нестору (Andre Nestor), они вместе засели за автоматы и начали проводить тестирование игровой системы, пробуя разные игры, лимиты и последовательность действий.


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


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


К сожалению, по какой-то причине баг проявлял себя только в автоматах Game King, установленных в одном маленьком районе Лас-Вегаса — во Фремонте. Тем не менее, за 5 недель упорного труда Кейн сумел снять в этом районе более $100 тыс.


Менеджеры заметили неладное и отключили на проигрышных банкоматах функцию удвоения ставки “Double Up”, после чего всё перестало работать. И тут на «хакеров» снизошло озарение: ведь эта функция отключена по умолчанию во всех автоматах, на которых они пробовали её в прошлый раз. Таким образом, они могли зайти в любое казино, попросить включить функцию — и получить джекпот. Друзья договорились не снимать с казино более $20 тыс. в день.


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


После очередного джекпота игровые автоматы опечатали и отправили на экспертизу в технический отдел Агентства по регулированию деятельности казино в Неваде. Расследование поручили 25-летнему Джону Ластуски (John Lastusky), недавнему выпускнику факультета информатики университета Южной Каролины. Тот изучил логи, затем скопировал содержимое EPROM и не нашёл признаков внешнего вмешательства и бэкдоров. Тем не менее, повторяя выигрышные действия, через несколько дней Ластуски всё-таки смог воспроизвести нужную последовательность. Он сообщил о находке руководству, и вскоре функцию “Double Up” деактивировали на всех игровых автоматах.


Прокуратура предъявила Андре Нестору обвинение по 698 пунктам, от воровства до преступного сговора. В 2011 году дело передали в министерство юстиции, и обвиняемым выдвинули обвинение по новой статье о компьютерном взломе (закон Computer Fraud and Abuse Act). Но закончилось всё хэппи-эндом. Друзья отказались давать показания друг против друга, и министерство юстиции было вынуждено снять обвинения, а в марте 2014 года дело закрыли.


Нестор потратил все деньги на адвоката, а вот Кейн сохранил выигрыши. Судя по судебным записям, они не были конфискованы, так что бывший пианист сейчас ведёт тихую спокойную жизнь, нигде не работая.


Андре Нестору запретили вход во все казино Пенсильвании, и он теперь тратит время, играя в Candy Crush на Android-планшете. За два месяца Нестор прошёл 515 уровней, используя чит, найденный в интернете.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Multiboot, UEFI, NTFS или почти рецепт счастья

Пост написан по мотивам публикации Живительная флешка .





Предисловие




Доброго времени суток, Хабр. Совсем недавно, читая Хабр, наткнулся на статью Живительная флешка, где был описан способ создания мультизагрузочной флешки с набором полезных утилит, разнообразных систем и т.д. И все бы ничего, да вот и тут зарыта собака — обратим внимание на эту ветку комментариев, в которой обсуждается работоспособность мультизагрузки в системах с UEFI. Таким образом я начал собственное расследование искать универсальный способ решения этой проблемы.



Далеко ходить не пришлось — еще со времен безумной популярности сборки Windows XP Zver Edition ее разработчики использовали набор утилит под названием RMPrepUSB для записи сборки на USB-накопитель. Сборка ушла из памяти людей, ну а сам проект пакета утилит продолжает развиваться и крепнуть. Ну а сама основа — проект Easy2Boot. Изучая их сайт я нашел универсальный способ создания мультизагрузочной флешки, которая может содержать в себе любой дистрибутив, LiveCD или образы дискет, которые Вы только захотите добавить. Итак, приступим к созданию такой чудо-флешки.

Начинаем




Идем на сайт и качаем последний архив с Install_RMPrepUSB_Full в названии. Распаковываем и устанавливаем.

Внимание: для любителей переносимости — можно открыть установочник в 7-zip (к примеру) и распаковать его в папку без установки.

Далее идем на сайт Easy2Boot и качаем архив с самим E2B, распаковываем в любую папку на ПК.

Подготовка флешки




Заходим в папку с E2B и запускаем файл _ISO\docs\Make_E2B_USB_Drive.cmd.

Внимание: если Вы не устанавливали, а распаковывали RMPrepUSB, то на первом же этапе Вас попросят указать путь в папке RMPrepUSB.

Нас попросят указать номер накопителя из приведенного списка, спросят, действительно ли мы хотим форматировать накопитель и попросят выбрать ФС.

И вот тут внимание! Выбираем FAT32 — грузимся в UEFI без проблем, но нет поддержки файлов >4 Гб, и наоборот — NTFS без UEFI, но с поддержкой больших файлов. Если Ваши образы весять меньше 4 Гб каждый, то смело выбирайте FAT32. С NTFS немного сложнее, а именно — флешка в UEFI не загрузится, но если загрузить ее на обычном биосе, а потом выбрать образ для UEFI (об этом ниже), то Easy2Boot перепишет MBR флешки и она будет загружаться в UEFI, при условии, что в том образе есть его поддержка (наличие файлов efi\bootia32.efi и efi\boot\bootx64.efi)

Идем по сложному пути — пишем N (то есть форматируем в NTFS), вылезет окошко с подтверждением, жмем ОК и ждем. После форматирования будут скопированы файлы E2B и на зеленом фоне появится надпись «Нажмите любую клавишу».


Скриншоты





Структура папок или куда же класть образы?




Заходим на накопитель, видим файлы и папку _ISO. Кратко опишу структуру (подробности есть на сайте):


  • ANTIVIRUS — закидываем образы антивирусных LIveCD (Kaspersky, Dr.Web и иже с ними)

  • AUTO — кидаем любой образ в подпапку с нужным названием (к примеру, по пути Ubuntu\My_Ubuntu_Distro.iso)

  • LINUX — соответственно любой Лунксовый образ закидываем в эту папку.

  • MAINMENU — закидываем образ в эту папку и он появится в главном меню Grub4DOS при загрузке (не в подменю, об этом позже)

  • UTILITIES — образы дискет кидаем сюда

  • UTILITIES_MEMTEST — то же самое, но, увы, точнее сказать не могу

  • WIN — сюда мы будем складывать образы, подготовленные для загрузки в UEFI. Об этом позже

  • WINDOWS — по структуре подпапок несложно понять, что для каждого семейства Windows нужно положить образ в соответствующую ему подпапку.


Далее запускаем RMPrepUSB, выбираем накопитель в списке и жмем Ctrl+F2, соглашаемся и ждем пару секунд. Программа пошаманит с файлами и можно грузиться с флешки.


Постой, а как же UEFI?




Ах, ну да. То, ради чего мы здесь и собрались. Для подготовки образа к загрузке в UEFI, скачаем архив, распакуем его. Устанавливаем файл ImDisk\imdiskinst.exe из папки, после чего перетаскиваем файл образа на скрипт MakePartImage_AutoRun_FAT32.cmd в основной папке. Данный скрипт переделает образ в формат .imgPTN, при монтировании которого E2B будет переписывать MBR и монтировать образ как раздел FAT32. Подробнее Вы можете прочитать тут.

Как все это выглядит?




Рабочий пример — накидал разных образов на накопитель, структура такова:


  • _ISO\LINUX\linuxmint-17-xfce-dvd-64bit.iso

  • _ISO\WIN\ru-en_win7_sp1_x86-x64_18in1_activated_v2.imgPTN

  • _ISO\WIN\Boot_USB_Sergei_Strelec_2014_v.6.9.imgPTN

  • _ISO\WIN\ru_windows_8_1_pro_vl_x86_dvd_LITE_3.iso




Скриншоты



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

Внимание! Если Вы загружались с образов, подготовленных для UEFI, то Вы заметите, что при следующей загрузке с накопителя будет меню загрузки с того самого образа. А где же все те, что мы набросали на флешку? Да и файлы на флешке не те… Тут два варианта — из загрузчика выбрать верхний пункт EASY2BOOT или в ОС запустить с флешки скрипт e2b\RestoreE2B (run as admin).cmd.


В сухом остатке




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

Информация с сайта разработчиков




This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Русский перевод Apple iPhone Developer Program License Agreement + Schedule 2 v19

Всем привет!

На прошлой неделе появилась необходимость предоставить в банк договор, по которому были получены деньги из App Store. Если перевод оригинального iPhone Developer Program License Agreement нашелся в сети довольно быстро, то перевода последней версии Schedule 2 (на текущий момент v19) нигде не было. Мы доперевели разницу и готовы поделиться этими документами.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Веб-приложение — ну почти без бек-энда: Flask, Redis, API через JSONP, JSFiddle.net

Данная статья — так называемый «proof-of-concept» создания фронт-енд приложения, работающего с API посредством JSONP, то есть, как говорят, «cross-origin». Также описана организация данных в Redis.

Например, можно с легкостью разместить на jsfiddle.net некое приложение, бек-энд которого будет находится на другом домене.


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



Цель статьи — поделится своим сегодняшним опытом с двух сторон:



  • Имплементацией JSONP + Long Polling

  • Работой с замечательной Redis


Кое-чем подобным занимаются ребята из BackendLess.


Что у нас есть




Итак, у нас есть:


  • Некий собственный сервер с Python 2.x на борту

  • Браузер и доступ к JSFiddle.net

  • Желание построить API-over-JSONP


Что я использовал


JSONP



Думаю, читатель не нуждается в объяснении, что это такое. А насчёт имплементации — тут всё делает один декоратор:

def jsonp(fn):
def wrapper(*args, **kwargs):
callback = request.args.get('callback', None)
if not callback:
raise BadRequest('Missing callback argument.')
return '{callback}({data});'.format(
callback=callback,
data=dumps(fn(*args, **kwargs))
)
wrapper.__name__ = fn.__name__
return wrapper


Redis



Есть такая замечательная вещь — Redis. Как говорят о ней разработчики,


Redis is an open source, BSD licensed, advanced key-value cache and store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets, sorted sets, bitmaps and hyperloglogs.





Или в двух словах:


Redis — это мощная система хранения и кеширования данных в формате «ключ-значение.»



Немного про Redis



Если вы не знакомы с Redis, советую почитать о нём на оф. сайте, поскольку ниже будут описаны не все тонкости работы с ним.

Собственно, сам Redis работает как отдельный демон, а из Python-скрипта мы обращаемся к нему через довольно простой одноимённый модуль-коннектор.

Мы можем создать некий ключ и присвоить ему:


  • Скалярное значение (на самом деле — строку)

  • Список

  • Массив

  • Множество

  • Отсорированное множество




Но! Мы не можем сделать массив из массивов, например. Поэтому в данном случае придется делать ключ со списком индексов и по ключу на каждый индекс. Также ввиду отсутствия выборки по значениям (а-ля WHERE в SQL) иногда приходится делать списки с обратным «маппингом», например, для поиска ID юзера по никнейму и для поиска никнейма юзера по его ID.

Грубо говоря: то, что в SQL является таблицей, в Redis'е будет списком индексов и набором массивов. Также принято разделять части ключа двоеточием.

Пример в SQL: 1 таблица — с полями user_id, user_name, user_email и 5-мя записями.

Аналогия в Redis: 1 список и 5 массивов — список users с данными [1, 2, 3, 4, 5] и 5 массивов с названиями (ключами) вида user: с данными {id: , name: , email: }, а также несколько массивов с обратной связкой, например, nicknames со значениями {andrew: 1, john: 2, mike: 3, ...}


Почему Redis?




  • В Redis не нужно задавать структуры данных: достаточно просто положить их туда.

  • Мы можем делать CRUD (Create-Read-Update-Delete) с данными, находящимися в базе Redis, а также использовать встроенный механизм блокировки — он, кстати, очень упрощает имплементацию механизма long polling.

  • Никаких JOIN или WHERE Redis не умеет, да и не должен — он всего лишь хранит примитивы, максимум списки или ассоциативные массивы из примитивов. Но это не минус, а дополнительная свобода действий и стимул для расширения мышления, отличного от паттернов SQL- и NoSQL-СУБД.


Структура БД системы хранения ключей-значений



Вот так выглядят данные в нашей Redis в момент, когда Andrew написал сообщение и John написал сообщение, но первое прочитали все, кроме майка, а второе — лишь сам Джон. Но за несколько моментов все user:X:messages очистятся, т.к. наступит таймаут полинга и данные уедут на клиенты. Т.е. user:X:messages — это такой себе контейнер для еще не полученных сообщений некоего юзера.


Long polling




Средствами Redis можна легко реализовать long polling. Примерный алгоритм таков:


  • Запрашиваем в Redis (командой LLEN), есть ли прямо сейчас в списке сообщений для клиента сообщения, если есть — возвращаем сообщения и чистим список через DEL

  • Если сообщений нет, запрашиваем их опять, но на сей раз команой BLPOP, которая заблокирует активный поток, пока не появлятся данные либо не истечет таймаут. По разблокировке возвращаем клиенту результат от Redis, в котором будет либо только что пришедшее сообщение, либо ничего.


«Боевая команда, вперёд!»




Фронт-энд для тестирования: http://ift.tt/11HfjTp

Исходный код бек-энда: http://ift.tt/11HfhLo

Post Scriptum


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

Надеюсь, хабраэффект не сильно заденет мой маленький VPS.

Спасибо за внимание!


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Архитектура KodiCMS

Введение




Всем привет, в этой статье я постараюсь кратко рассказать о компонентах, которые составляют архитектуру CMS, их много (думаю все они не поместятся в статью), контроллерах, модулях, плагинах и организации подключения css, js файлов.

Основой KodiCMS является Kohana framework версии 3.3.2. Ядром системы является модуль “kodicms”, который содержит основную логику работы и расширяется с помощью наблюдателей (Observers) через модули и плагины.


Cписок модулей, которые были разработаны для CMS:




  • API — Работа с AJAX запросами, поддерживает типы запросов GET, POST, PUT, DELETE. Ответ в формате json, либо HTML

  • Behavior — расширение поведения Frontend страниц

  • Dashboard — рабочий стол и все что с ним связано

  • Datasource — основа для создания разделов данных (с помощью него созданы разделы Гибридные данные , Категории , Рейтинг документов ), отключаемый

  • elFinder — файловый менеджер, отключаемый

  • Email, Email _Queue — отправка почты, массовая рассылка почты, разделы Email в Backend и tasks для менеджера задач, отключаемый

  • FileSystem — классы для работы с ФС

  • Installer — Инсталлятор системы

  • KodiCMS — Ядро системы

  • Navigation — Навигация в Backend

  • Page_Parts — Части страниц (Связан со модулем Pages через Observer), отключаемый

  • Pages — модуль страниц сайта, теоретически отключаемый

  • Plugins — модуль плагинов, организует расширение системы плагинами, отключаемый

  • Reflinks — помощник генерации временных ссылок, например Вспомнить пароль или Подтверждение регистрации

  • Scheduler — Календарь для Backend, а также менеджер задач Cron, отключаемый

  • Search — поиск по сайту, содержит драйвер полнотекстового поиска, список можно дополнять собственными драйверами

  • Sidebar, отключаемый

  • Snippet — модуль организации кусков кода, которые можно вставлять в шаблон, также используется модулем “Widget” для шаблонов видежтов, отключаемый

  • Tags — организация тегов в модуле страницы и Гибридных данных, отключаемый

  • Update — модуль обновления системы, отключаемый

  • Users — пользователи системы, ACL

  • Widget — Виджеты, блоки помещаемые на страницы сайта, выводят какую либо информацию, отключаемый


*отключаемый — возможно отключение в application/init.php


В системе помимо разработанных мной модулей есть стандартные модули и сторонние разработки




  • Assets — для организации CSS, JavaScript

  • Breadcrumbs — генерация хлебных крошек, используется виджетом “Хлебные крошки”

  • Captcha

  • Minion — используется менеджером задач для запуска запланированных задач (tasks )

  • Pagination


Модуль KodiCMS




Основной модуль CMS, именно в нем происходит расширение стандартного функционала Kohana, содержаться базовые контроллеры для работы с Backend, конфиги, хелперы и т.д.

Настройки




В системе существует несколько типов хранения настроек:


  • Файловые конфиги

  • Таблица в БД, для переопределения файловых конфигов (Кешируется)

  • Отдельная таблица для хранения информации плагинов (Кешируется)

  • Хранение пользовательской информации User_Meta (Например, набор и расположение виджетов на рабочем столе), как в Wordpress и Bitrix, SugarCRM и т.д. (Кешируется)


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



  • построения sitemap админ панели — sitemap.php

  • указания возможных типов страниц — behaviors.php

  • списка прав доступа к контроллерам админ панели — permissions.php

  • списка разделов данных — datasources.php

  • списка доступных виджетов — widgets.php

  • списка драйверов для модуля поиска — search.php

  • списка доступных задач для менеджера задач Cron — jobs.php

  • списка типов полей для раздела “Гибридные данные” — fields.php




Т.е. при создании плагина, если необходимо добавить пункт меню (sitemap.php), новый раздел в backend (datasources.php), расширить права доступа к новым контроллерам (permissions.php) или добавить новую задачу в планировщик (jobs.php) в нем создается конфиг файл.

Контроллеры




Контроллер системы имеет несколько уровней абстракции


  1. Пустой контроллер System_Controller

  2. Security контроллер проверки прав доступа System_Security < System_Controller

  3. Template контроллер отвечающий за шаблоны страниц System_Template < System_Security

  4. Backend контроллер System_Backend < System_Template, от которого наследуются все контроллеры для доступа к которым необходима авторизация. В этом контроллере происходит подключение всех необходимых css, javascript и т.д.

  5. Frontend контроллер System_Frontend < System_Template, от которого наследуются все контроллеры для доступа к которым не нужна авторизация. (Авторизация, Вспомнить пароль, Страница ошибки)

  6. Media контроллер для поиска media файлов (сss, js и т.д.) во всех модулях и плагинах в папке media, т.е. если в плагине создать папку media/css и положить в нее css файл (test.css), то к нему можно будет обратиться как cms/media/css/test.css

  7. API контроллер System_API < System_Ajax используется в основном для ajax (GET, POST, PUT, DELETE) запросов, причем экшены в контроллере бывают также нескольких типов get_…, post_…, put_…, delete_…, в зависимости от того какого типа приходит запрос.

  8. Front контроллер для Frontend страниц.


Давным-давно я рассказывал о такой структуре на оф. форуме kohana, возможно этот пост кому-нибудь покажется полезным.


Frontend контроллер




Роут для этого контроллера стоит последним в списке. При вызове контроллера происходит поиск страницы по URL (запросы кешируются), далее проверка типа страницы, проверка доступа к странице, через обсерверы подключение виджетов, частей страницы и других расширений, для админа подключение профайлера в HTML шаблон (+ на будущее добавлена возможность создания тулбара через View, как в модных CMS типа Bitrix, Wordpress и т.д.), кеширование на стороне браузера и указания типа страницы (в slug поле в настройках страницы можно указать расширение, например, rss.xml и вывод будет с соответствующим Content-Type).

Я нарисовал схему пути, который проходит запрос при вызове frontend контроллера, схема немного запутанная и главное не запутаться в стрелках и найти Request.



Организация media (css, js, less, image) файлов




Основные media файлы системы находятся в папке cms/media.

Основной файл стилей css/common.css компилируется из LESS файлов и сторонних библиотек, среди которых Twitter Bootstrap, Font-Awesome и др., перекомпиляция происходит при включении плагина Less и внесении изменений в файл less/common.less, он же является основным.

Главный JavaScript файл — js/backend.js (возможно будет описан в одной из будущих статей)


Для подключения css и js в шаблонах используется модуль Assets, который был немного доработан, а именно, написан менеджер пакетов Assets_Package, который позволят группировать media файлы в пакеты. Он же может использоваться во frontend для быстрого подключения библиотек, а также в виджетах.



// Пример использования пакетов во Frontend шаблоне
Meta::factory($page)->package(array('jquery', 'bootstrap', 'holder', 'fontawesome', 'demo-assets'));


Каждый модуль и плагин в системе также может иметь папку media с аналогичной структурой и подключаться в контроллере как cms/media/…. без указания названия модуля, поиск файлов осуществляется через Kohana::find_file и поэтому пути нахождения файлов кешируются.


Также при запросе backend контроллера происходит поиск для него javascript файла cms/media/js/controller/controller_name.js


Модули и Плагины




Помимо стандартных возможностей модулей (и плагинов в том числе) в них была добавлена поддержка инсталляции.

В момент запуска инсталлятора происходит поиск и вызов в каждом модуле файла install/observers.php, в момент инсталляции системы инсталлятор проходится по всем модулям и смотрит наличие файлов install/schema.sql, а затем install/dump.sql а после уже запуск install/install.php


Т.к. в плагинах есть возможность активации и деакцивации, то для них также добавлены install.php, uninstall.php, install/drop.sql, а также в файлы frontend.php и backend.php, которые работают аналогично init.php, но подключаются во Frontend/Backend.

В остальном работа плагинов не отличается от стандартных модулей Kohana.


P.S

В предыдущей статье я забыл упомянуть о том, что для KodiCMS существует репозиторий плагинов: github.com/KodiCMS, его же можно увидеть в backend.


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

В общем если вам интересно что-либо узнать, пишите, постараюсь рассказать.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


[Из песочницы] Классификация видов тестирования

Учил студентов предмету «Тестирование и отладка программного обеспечения» в ИжГТУ. Структуру курса обучения построил на основе классификации видов тестирования.

Виды тестирования



Карту можно скачать тут.





Повторение — мать учения.





Пословица разных народов мира.

Виды тестирования сгруппированы на mind-карте по:



  • целям;

  • хронологии выполнения;

  • формальности;

  • позитивности;

  • ...


Каждое занятие выбирали:



  • Тестируемое приложение или сервис: почтовый клиент, видео-хостинг, ...

  • Опорный вид тестирования, например, основное функциональное ручное позитивное … тестирование

  • Несколько видов тестирования для сравнения с опорным: повторное, автоматическое, негативное




Начинали выполнять тестовые работы в рамках выбранного опорного вида тестирования.

Состав тестовых работ выбирался из опорного списка:



  1. Планирование.

  2. Подготовка сценариев.

  3. Подготовка тестового окружения.

  4. Выполнение тестов.

  5. Анализ результатов тестирования.

  6. Отчёты.

  7. Отслеживание дефектов.


Каждый раз для выбора вида тестирования использовалась карта. Каждый раз использовался опорный список видов работ.





Всё познаётся только в правильно выполненном сравнении.





Автор мне неизвестен, возможно, Фридрих Ницше или Рене Декарт.

На конкретных примерах рассматривали, какая техника тест-дизайна при подготовке сценариев более применима к функциональному тестированию, а какая к конфигурационному. Разбирали в чём отличия выполнения тестов для основного функционального исследовательского тестирования, от основного функционального тестирования по тестам. Чем будут отличаться планы тестирования. Как при этом, выглядят проекты тестов (чеклист или mind-карта, против инструкций с порядком действий и ожидаемым результатом). Что является общим — процесс отслеживания дефектов.


Рассматривали, чем отличаются отчёты по конфигурационному тестированию и тестрованию масшабируемости, или отчёты по нагрузочному и объёмному.



Приносил примеры отчётов, несекретных и старых, сокращал их до 3-х страниц, удалив конфиденциальную информацию. Разбирали, что в отчётах общего (структура: цели, основа, краткие результаты, детали). В чём отличия. Как их читать. Как составлять. Как формировать автоматически.


Так, перебирая попарно виды тестирования формировал представление о выборе инструментов, подходов, целей и задач изучаемой деятельности.


Список работ по тестированию взял из SWEBOK (v3), глава 4 «Software Testing», раздел «Test Process», подраздел «Test Activities».

image


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





Нам не дано предугадать, как слово наше отзовется ...





Фёдор Иванович Тютчев, 27 февраля 1869.

Карта является опорным конспектом для преподавателя. Напоминает о чём, надо успеть сказать. Помогает не сказать лишнего. Ведь времени так мало, а рассказать надо так много.


Ранее преподавал в учебном классе, где были только парты доска и мел. На занятия приходил точно к началу, доску не готовил. Стоять спиной и рисовать изучаемую предметную область во время занятий не хотел. Объяснить взаимосвязи на схемах удобно. Поэтому для каждой темы делал mind-карту. Распечатывал в нескольких экземплярах, раздавал студентам на занятии. Доску и мел использовал для изображения примеров. Рисовали как байтики движутся по схеме системы и приводят к SQL-инъекции, или как работает горизонтальное масшабирование. Так сформировалась привычка готовить mind-карты.


Карта позволяет:



  • запоминать материал быстрее;

  • экономить время при начале занятия;

  • использовать официально разрешенную шпаргалку как для преподавателя так и для студента.




Ведя занятие, читаешь по бумаге, но чтение между строк допустимо.

Студенты, имея перед глазами карту, имеют больший выбор:



  • просто слушать;

  • коспектировать;

  • рисовать.




Больше думают, легче находят аналогии, увереннее отвечают на вопросы. Готовишь карту к каждому занятию, студенты начинают ждать очередной материал. И если, вдруг, не подготовить схему, то занятие начнётся с вопроса: «А что, принтер сломался?», — смеются, уже хорошо.

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

image


Есть ограничения использования mind-карт в подготовке темы занятия. При большом количестве узлов, карта плохо читается на формате альбомного листа. И тогда лучше использовать доску и мел — дублировать части схемы на доске.


О доске и меле




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



Потом стал стараться писать и рисовать, как в начальных классах. Ровно, красиво, чётко («как слоги в пионерской речёвке»). Студенты стали задавать больше вопросов. Стало понятнее, что занятия стали понятнее.

Готовился основательно. Случались технические сбои и заминки, не всё удавалось показать и объяснить. О каждом случае можно отдельную историю рассказать. Так подготовка лабораторных работ по тестированию — дорога на Эверест, уложенная граблями. Отладить работу автоматического теста в идеальном окружении, бывает, непросто. А если окружение неидеальное, на каждом учебном компьютере оно своё, и тест написан студентом на скорую руку, то лишь телепатия и «эффект разработчика», в которого ты перевоплощаешься, могут помочь.

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

Стоит попробовать.


















































Классификацию видов тестирования составила Юлия Григорьева, на сколько мне известно (если авторов было несколько, сообщите пожалуйста). Получился набор статей на wiki-узле отдела тестирования.
При составлении статей использовались различные источники:


  • Стандартный глоссарий терминов, используемых в тестировании программного обеспечения

  • Книга «Гибкое тестирование...» (Криспин и др.)

  • Книга «Тестирование программного обеспечения» (Канер и др.)

  • Книга «Верификация программного обеспечения» (Синицын и др.)

  • Книга «Usability Engineering» (Nielsen)

  • Глоссарий NIAG

  • Сайт «Про Тестинг»

  • Глоссарий НПО Компьютер




Полувшийся набор статей оформил в виде карты. Термины могут быть уточнены, поэтому разместил файл на github, для поддержки версионности. Картинки пока размещены в Яндекс.Фото, надо бы положить их вместе с картой и зафиксировать в разделе releases.TypesOfTesting
Для составления карты использовал FreeMind 0.9.0. Также можно использовать xMind и другие инструменты, поддерживающие формат с расширением «mm».FreeMind — free mind mapping software
SWEBOK 3 изначально был каркасом курса обучения. В описании специальности было написано, что студенты обучаются программной инженерии. Когда спросил опытного преподавателя, что взять за основу курса, он сказал, что программная инженерия — это SWEBOK.Software Engineering Body of Knowledge (SWEBOK) Home
Учебный курс «Тестировние и отладка программного обеспечения» тестировался в 2014 году на студентах кафедры «Програмное обеспечение»: Надежда, Олег, Рамиль, Дмитрий, Анатолий, Артур, Юрий.
Аудиторию и оборудование предоставил Ижевский государственный технический университет имени М. Т. Калашникова.www.istu.ru
В статье использован кадр из фильма Назад в будующее 2, где Док объясняет, как Биф создал версию будующего, в котором сейчас находятся герои.Photos with Christopher Lloyd
В статье использованы пословицы, стихи и фразы, которые стараниями разных людей засели в голове. И иконки из темы Faenza.Faenza

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


пятница, 17 октября 2014 г.

mod_proctitle — модуль Apache для отображения запросов и краткой статистики в имени программы (вывод top и ps)

Часто возникает ситуация, когда надо быстро оценить, чем занимается ваш веб-сервер. Иногда для успокоения «вроде не он». Когда на сервере один апач, один сайт, нагрузка небольшая — проблем нет. Зашел, top посмотрел. /server-status посмотрел, tail -f на логи сделал, помедитировал — и обычно всё понятно. Однако бывает ситуация, когда сайтов много, много самих apache (почти все ОС сейчас из коробки умеют подымать несколько веб-серверов apache, но этим редко пользуются почему-то). Бывает ситуация, когда apache уже и ответить не может. Как было бы хорошо, хотя бы примерно прикинуть, что делают (или уже делали) воркеры апача. Представьте — делаете вы ps -aux, а у вас там — кто какие URL запрашивает, какой ширины канал занят, какова скорость работы — ня!

Я достаточно давно использую патч для apache, который после разбора строки запроса пишет в имя программы IP, откуда был запрос, то, что пришло в заголовке Host и саму строку запроса. Но этот двухстрочный патч был написан 12 лет назад для Apache версии 1.3. А потом руки не доходили. Тем более, с того времени появилось множество (я за пять минут нашел как минимум два) разновидностей модулей для тех целей, для более новых версий Apache. Однако, со временем мне стало маловато просто строк запросов. И… я написал свой модуль.



Доктор, откуда у Вас такие картинки?




Вначале я намучился с отсутствием документации для разработчиков у Apache. Нужные hook'и пришлось искать методом перечитывания всего исходного кода. Не, когда вы уже 10-ой модуль пишете, оно может и отлично, а когда первый и может быть последний — проблема.

Когда мне удалось найти хук ap_hook_monitor(), который вызывается из рутового процесса apache каждые 20 запросов или каждую 1 секунду, мною овладела жажда запихать в строку как можно больше крутой статистики. Я пробовал всякие статусы, количества, загрузку за 10 секунд, 1 минуту, 5 минут, аптайм… Но посмотрев на результат, я понял, что эта мишура только мешает и оставил только битрейт и запросы в секунду.


Самым главным новшеством модуля являются значения Complete и Incomplete Listen Queue Lenght. Это когда в httpd.conf пишем BackLog чтототам, то запросы, которые сервер не успевает принять, копятся в этой очереди. А когда очередь заполняется — начинают отбрасываться. Обычно такое происходит при хабраэффекте например, или если сайт обращается к стороннему ресурсу, а тот «лежит» или заблокирован (как например недавно github). И вот тут нашему глазу очень поможе цифра в listen queue и цифра qps.


Как всё плохо в этих ваших линуксах




Внезапно оказалось, что малыми жертвами модуль можно написать только под FreeBSD. Для изменения имени программы там есть функция setproctitle(), а посмотреть Complete и Incomplete Listen Queue Lenght можно через вызов getsockopt() с параметром SO_LISTENQLEN и SO_LISTENINCQLEN.

Для Linux всё сложнее. Требуется взять имя исполняемого файла и отдельно всегда его дописывать (FreeBSD делает это автоматически). Это нужно помому, что подавляющее большинство rc-скриптов используют имя, которое светится в ps в целях запуска/перезапуска.


Для Linux оказалось непросто и значения Listen Queue найти. Пока что мне видится вариант работы с netlink(7). Но детали ускользают.


Вливайся




Для FreeBSD + Apache 2.4 модуль абсолютно работоспособен. Можно попробовать его на других версиях Apache. Можно и нужно помочь портировать его на Linux.

Модуль распространяется в исходных кодах и вы можете сделать с ним всё, что захотите:

http://ift.tt/1qK3nGe


P.S. Некстати, хочу дополнить его функцией периодического сброса статистики по UDP куда-нибудь. Чуть более полной.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


OpenSSL закрыл четыре опасные уязвимости

OpenSSL Project выпустил патч своего пакета для шифрования с открытым исходным кодом с целью исправления недавно обнаруженной уязвимости POODLE SSL и других. Обновления доступны для OpenSSL 0.9.8zc, 1.0.0o и 1.0.1j.


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


Две были связаны с POODLE (Padding Oracle On Downgraded Legacy Encryption), позволявшей получить данные, такие как куки-файлы через безопасное соединение. Еще две иниицировали утечки памяти и открывали возможность для DoS-атаки.


Как сообщается в научно-исследовательской работе, опубликованной во вторник экспертами по безопасности Google Бодо Моллером, Таем Дуоном и Кшиштофом Котовичем, POODLE стал результатом проблемы в 15-летней версии 3.0 протокола SSL. Хотя многие сайты перешли на использование Transport Layer Security (TLS) -протокола, основные веб-браузеры, чреди которых Chrome и Firefox, по-прежнему обеспечивают поддержку SSL 3.0 в случаях, когда они не могут подключиться к серверу с использованием более современного протокола.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Facebook удвоила антихакерскую премию

Компания Facebook увеличила вдвое награду для разработчиков и экспертов по информационной безопасности за обнаружение уязвимостей в коде рекламной системы своей сети. До настоящего времени средняя премия за обнаружение бага составляла $500, теперь выплата увеличивается до $1000.


Решение выделить больше денег в призовой фонд для поощрения Белых шляп», последовало после ряда проверок, проведенных экспертами Facebook по безопасности.


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

Вместе с этим компания опубликовала 4 части инструкции для «Белых хакеров», которое поможет им быстрее и проще сообщать о найденных уязвимостях и, соответственно, получать свое вознаграждение.


Специалист отдела безопасности Facebook Колин Грин в своем блоге написал, что минимальный «двойной тариф» будет действовать до конца 2014 года.


Программа для хакеров-волонтеров Bounty была учреждена в 2011 году. С тех пор, в виде вознаграждения «Белым шляпам» по ней были выплачено более $3 млн.


В качестве рекламных инструментов Facebook использует менеджер рекламы, рекламный API и realtime-систему статистики Insights.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


VexorCI — свежий взгляд на continuous integration

Привет, Хабр.

Меня зовут Олег Балбеков, я хочу рассказать вам о нашем новом проекте Vexor CI.

image


Vexor CI – облачный continuous integration сервис для разработчиков, позволяющий эффективно тестировать проекты.


Ежедневно разработчики используют CI-сервисы, однако большинство из них дорогие, медленные, неэффективные и накладывают большие ограничения на использование.


Vexor:



  • для тех, кому надоело тратить время и деньги на поддержание тестовой инфраструктуры;

  • для тех, кому давно не хватает ресурсов локального сервера;

  • для тех, кто не решается на облачный CI потому, что дорого;

  • для тех, кто устал ждать очереди на просчёт тестов в обычном облачном CI;

  • для тех, кому действительно важна скорость.




У нас справедливая цена (поминутная оплата) и безлимитные мощности для каждого. Всем подключившимся мы дарим $10 и не берём оплату, пока вы настраиваете сервис. У нас самая дружественная русскоязычная поддержка (в моём лице). Подключайтесь!



Теперь обо всём и по порядку.



Continuous integration – это практика разработки программного обеспечения, которая заключается в выполнении частых автоматизированных сборок проекта для скорейшего выявления и решения интеграционных проблем. Обычно это автоматический запуск тестов после каждого вашего коммита.





Вы справедливо возразите: ведь в данный момент существует много решений для непрерывной интеграции, зачем нужно было делать ещё одно? Давайте поговорим о них.

Итак,


Зачем мне Vexor, если я уже гоняю мои тесты на своём ноутбуке?




Большинство разработчиков пишут тесты (юнит-тесты или интеграционные тесты) и запускают их локально на своём компьютере, но в этом подходе есть несколько проблем. Во-первых, ресурсы самого компьютера ограничены, а значит тесты начнут тормозить по мере увеличения их количества. Во-вторых, в какой-то момент можно просто забыть о тестах и перестать их запускать, особенно если тесты проходят более чем за 10 минут.

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


Да, но...


У меня уже есть open-source решение, установленное на нашем сервере




Хорошо, давайте порассуждаем и посчитаем.

Итак, для open-source решения, установленного на вашем оборудовании, вам необходим хороший сервер. Также сервер нужно администрировать и тратить на это время ваших разработчиков или нанять системного администратора.


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


Кроме того, вы потратите достаточно много времени на установку решения. Если, в случае с Vexor, вам лишь нужно настроить ваш проект под CI, то в других случаях вам нужно будет настроить не только ваш проект, но и сам CI.


Далее...


Open-source решение, установленное на вашем оборудовании, нужно обслуживать. Раз в месяц оно будет падать, а вы столкнётесь с отсутствием поддержки. Вы вынуждены будете тратить в месяц минимум 2 – 4 часа времени разработчика на обслуживание. Как только вашу команду покинет человек, который раньше занимался обслуживанием, его работу станет некому делать. Обычно с open-source решениями руководитель получает головную боль и лишние затраты.


А что с финансами?


Почему-то так получается, что за все Continuous integration сервисы нужно платить, даже если вы ими не пользовались.


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


Даже если вы были в отпуске и ничего не коммитили – вы платите за месяц, причем платите за оборудование круглосуточно. Задумайтесь, разве вы работаете по ночам? А по выходным? Но вы платите за сервер или ресурсы, на котором будет «крутиться» ваш CI.


Vexor ­– это поминутная оплата за реальное использование ресурсов. У нас вы платите только за те минуты, которые мы используем для прогона ваших тестов. Не было коммитов в течение месяца – счёт равен нулю. Информация по среднему чеку есть у нас на сайте (Average monthly cost).


Ну и наконец...


Вы всегда ограничены мощностью вашего локального сервера, и в какой-то момент вам начинает не хватать скорости.


Мы – облачный сервис, который умеет одновременно выделять вам столько мощности, сколько нужно. В случае, когда вы сделаете 10 коммитов подряд, ваш open-source CI будет выполнять их последовательно. Vexor же моментально выделит вам 10 серверов и сделает всё параллельно. При этом вы платите только за минуты, которые мы действительно потратили на работу с вашими тестами.


Хорошо, но...


Я уже использую облачный CI-сервис!




Как я уже писал, скорее всего вы:

— ограничены в ресурсах;

— испытываете проблемы со скоростью;

— оплачиваете подписку и платите за простой, даже если не используете сервис;

— платите банально дорого, даже если ваш проект ещё на стадии роста.

Друзья, подключайтесь к Vexor и избавьтесь от этих ограничений и несправедливой стоимости.

Вы можете попробовать Vexor совершенно бесплатно. Мы дарим всем подключившимся пользователям $10 на счёт и не берём оплату до тех пор, пока вы не настроите свой проект.




Мы будем рады любому отзыву, совету или вашим идеям.

Пишите мне на oleg@vexor.io и следите за нами в твиттере.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.