Пишу свои мысли о web-разработке и о жизни. Работаю в веб-студии Феникс — phoenix-cg.ru Связаться со мной можно по почте viktor@koreysha.ru

Later Ctrl + ↑

Почему на ноль на самом деле нельзя делить

На днях посмотрел ролик Почему на ноль делить нельзя. Тезисно логика автора такая:

  1. Чем меньше делитель, чем больше результат.
  2. Ноль минимальный из возможных делителей.
  3. Результат — самое большое число.
  4. Самое большое число — бесконечность.
  5. Бесконечность — не число.
  6. На ноль делить нельзя по тому, что в результате мы получим не число, хотя планировали получить число.

Если бы мне задали этот вопрос в 10ом классе, я, наверное, так же бы ответил. Но я бы не стал снимать по этому поводу видеоролик и позиционировать себя, как эксперт. Не стал бы кричать «Лож» и сам при этом врать зрителям в лицо.

При чем тут программирование?

Но самое обидное, что так думает не только автор ролика. Но и, например, создатели джаваскрипта. Попробуйте написать alert(1/0); Мы получим: Infinity . Давайте разберемся, что тут не так.

Для начала разберемся с Infinity. В джаваскрипте есть определение и оно очень похоже на определение бесконечности автором ролика. Это некое число, которое больше, чем любое число. Поскольку компьютеры под каждую переменную вынуждены отводить память у этого числа даже есть конкретное значение. Оно больше, чем любое другое число, то есть Number.MAX_VALUE + 1 или 1.7976931348623157e+308 + 1. Нюанс заключается в том, что компилятор не даст нам прибавить к этому числу единицу (просто оставит число таким же) или вычесть единицу из Infinity (опять же останется «бесконечность»). Из-за это особенности авторы языка притворяются, что это действительно бесконечность, а не «то, что вы подумали».
С какой-то версии, правда, ввели еще одну особенность — Infinity>Infinity это true. Так как по логике авторов Infinity — число, которое больше любого числа. Справа — число. Слева то, что всегда больше числа. Понятно. что результат TRUE.

Что делать?

Какой же ответ должен быть с точки зрения математики на пример 1/0? Конечно NaN! NaN — аббревиатура, полная версия это Not a Number, то есть «Не Число». Значение NaN не равно никакому другому числу, включая само NaN. Очевидно, что именно такое «не число» мы и получаем при попытке делить на ноль, а совсем никакую не бесконечность.

В математике есть такой метод, если решение сразу найти не удается, попробуй близкую задачу, которую решить гораздо проще. А потом учти разницу. Например, если меня попросят разделить 100 на 17, то я не смогу того сделать сразу. Мне надо будет сначала решить похожую задачу — разделить 100 на 20. Получится 5. А дальше «учесть ошибку». Ошибка тут это по 3 с каждого вхождения 17 в 100. 3*5 = 15. Итого 100/17 = 5 целых и 15/17. Надеюсь, я смог пояснить метод.

Тут так же. Попробуем взять 1 и поделить на 1. Получится, очевидно 1. Теперь поделим на 0.5. Будет 2. И таким образом мы покажем, что чем меньше число на которое делим, тем больше результат. Тут легко сказать «ну значит ответ бесконечность» и успокоится. Но надо вспомнить, что к нулю можно «подходить» с разных сторон. Если попробовать идти от отрицательных чисел, то будет: 1/(-1) = -1, 1/(-0.5) = -2 .... И так мы получим минус бесконечность. Это можно проиллюстрировать графиком.

Обратите внимание, что решения вблизи нуля «разлетаются» в разные стороны. Одно вверх, другое вниз. Говоря математическим языком можно это выразить, как «Левый и правый предел расходятся». Мало того, что это разрыв второго рода, так он еще и в разные стороны.

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

Вместо вывода

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

 No comments    26   2015   мысли

Новогодний снежок на сайт

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

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

В общем, не хочу больше затягивать, я за пол часика собрал наше «легкое» исполнение. Идею подсмотрел, но убрал все лишнее и сделал под себя. Хочу им поделится с читателями. Почитать будет полезно тем, кто только изучает джаваскрипт. А итог могут использовать на своих проектах все желающие. Так же буду рад критике коллег.

Результат

Процесс

Эта часть для тех, кто только изучает джаваскрипт. Всем остальным, думаю, будет не очень интересно.
Все, что нам понадобится в HTML, это canvas с идентефикатором snow. И я запустил скрипт по событию на BODY onload=“init()”. Это не лучшее решение, но оно за рамками самого «снега», так что оставлю его на совесть того, кто будет код использовать.
Весь наш код состоит из четырех функций.
function init() — тут мы делаем подготовку к запуску и запускаем. В этой функции должны быть все операции, которые нужно произвести до основного кода.
function draw() — отвечает за отрисовку текущего состояния снега.
function update() — отвечает за установку нового состояния. Оно будет отрисовано на следующем шаге.
function mousemove(event) — отвечает за отслеживание положения мыши. Эту функцию я добавил по тому, что захотелось какого-то интерактива. Снег не должен всегда падать только вниз, в жизни его сдувает ветром то туда, то сюда. Я решил, что за ветер будет отвечать курсор. Чем дальше он от центра экрана (горизонтално), тем сильнее ветер в эту сторону. Если интерактив не нужен, то от этой части можно отказаться.

Подробнее

Начну разбор с инициализации. Для начала я накидал что-то подобное:

function init() {
  //Canvas init
  var canvas = document.getElementById(‘snow’);

  //Canvas resize
  var W = window.innerWidth;
  var H = window.innerHeight;
  canvas.width = W;
  canvas.height = H;

  //Get context
  var ctx = canvas.getContext(‘2d’);
  ctx.strokeStyle = ‘white’;

  //Prepare array of particles
  var mp = 100;
  var particles = [];
  for (var i = 0; i < mp; i++) {
    particles.push({
      x: Math.random() * W,
      y: Math.random() * H,
      r: Math.random() * 3 + 1
    })
  }
}

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

В последнем блоке создаем массив, который будет отвечать за снежинки. Particles — массив снежинок. А каждая снежинка это объект, который «помнит» о своих координатах и диаметре. Для каждой снежинки задаем её начальное состояние: она должна быть где-то на нашем канвасе (случайным образом) и должна получить диаметр от 1 до 4 пикселей.

После этого переходим к отрисовке текущего состояния нашего снега.

function draw(W, H, particles, mp, ctx) {
  //Clearing
  ctx.clearRect(0, 0, W, H);

  //Set white whith opacity 0.8
  ctx.fillStyle = “rgba(255, 255, 255, 0.8)”;

  //Drowing
  ctx.beginPath();
  for (var i = 0; i < mp; i++) {
    var p = particles[i];
    ctx.moveTo(p.x, p.y);
    ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
  }
  ctx.fill();
}

Тут то же все просто. Чистим поле и заново рисуем каждую снежинку на её координатах и с её диаметром. Для новичков хочу обратить нимание, что мы сначала «накидываем» все в контакст. И только один раз отрисовываем с помощью ctx.fill();

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

function update(W, H, particles, mp, ctx) {
  for (var i = 0; i < mp; i++) {
    var p = particles[i];
    p.y += 1 + p.r/2;

    if (p.y > H) {
      particles[i] = {
        x: Math.random() * W,
        y: -10,
        r: p.r
      };
    }
  }
}

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

Когда мы все это подготовили нам осталось запустить отрисовку по таймеру. Для этого добавляем в init:

setInterval(function() {
    draw(W, H, particles, mp, ctx);
  }, 50);

И после отрисовки сразу общитывать новое состояние. Для этого вызываем update в конце draw:

update(W, H, particles, mp, ctx);

Интерактивчик

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

document.body.myData = {
    x: 0,
    y: 0
  };
  document.onmousemove = mousemove;

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

function mousemove(event) {
var mouse_x = mouse_y = 0;
if (document.attachEvent != null) {
mouse_x = window.event.clientX;
mouse_y = window.event.clientY;
} else if (!document.attachEvent && document.addEventListener) {
mouse_x = event.clientX;
mouse_y = event.clientY;
}
document.body.myData.x = mouse_x;
document.body.myData.y = mouse_y;
}

Отследить то мы отследили. Осталось добавить скорость вдоль горизонтальной оси Ox:

var speed_x = (document.body.myData.x – (W / 2)) / W;

Смотрим в какой половине мышь: в правой или левой. И как далеко она от центра. Чем дальше, тем «сильнее ветер».

И осталось добавить сдвиг по Ox:

p.x += speed_x * 10;

Вместо послесловия

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

Прошел месяц. Итоги.

Предупреждение. В этой заметке не будет ничего программистского и управленческого.
Ровно месяц назад я возобновил свой блог. В прошлый раз было буквально 2-3 серьезные заметки, из них в новом блоге я оставил только одну, так как считаю, что она может быть полезна мне в будущем. в остальном мое мировоззрение полностью перевернулось и старые темы мне стали неинтересны. Некоторых старых материалов я даже немного стыжусь, по тому, что считаю их совсем «зелеными».

За месяц я написал 11 материалов. Но так получилось, что вначале накопленных мыслей и энтузиазма было больше. Последнее время перешел на режим 2 заметки в неделю: одна в будни, другая в выходные. Такой режим не дает совсем уж расслабится, но и не давит жесткими сроками. Постараюсь придерживаться его и дальше.

Статистика

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

В среднем за этот месяц я выкладывал заметки 9 раз. 9 дней из 30 это ровно 30%. Притом, в эти дни по данным метрики у меня побывало 34% посетителей. Тенденция за 30 процентов времени 34 процента посетителей далеко не очевидно говорит о увеличении интереса к блогу в дни выхода заметок. А потом я вспомнил, что в эти дни сам несколько раз заходил (что бы написать материал и посмотреть, как он выглядит). Вычел себя и получилось 28 процентов визитов за 30 процентов времени. Это показалось мне забавным.
Всего я получил два комментария от одного и того же человека. Это говорит о том, что темы, которые я выбираю мало кого задевают. Постараюсь хоть иногда делать что-то более злободневное.

Немного лирики

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

На вопрос «Зачем?» я смог для себя ответить. Пока я пишу какой-то материал, обязательно сморю что-то по теме. Мысли других людей по какому-либо поводу. Я считаю, что это еще один вектор развития. Пока ты пишешь код, ты не понимаешь растут твои навыки или ты не успеваешь за бегущим вниз эскалатором. Кажется, что ты используешь одни и те же известные приемы и нет никакого способа попробовать что-то принципиально новое — на домашние проекты банально не хватает времени (мелкие делать не хочется, нужен масштаб), а в рабочих проектах велик шанс не уложиться, не успеть и не заработать, а потерять.
Есть у меня и еще один ответ. С тех пор, как небезызвестное дизайн бюро объявило о создании и первом наборе в свою школу стажеров, я мечтал туда попасть. Многие дисциплины мне крайне интересны. Проблема была в том, что я ни разу не дизайнер. Мой первый и единственный опыт дизайна оказался не особо удачным и я пока не готов продолжать попытки.
Но через год примерно появилась робкая надежда. Школа не только для дизайнеров, но и для редакторов. Редактор/писатель/журналист из меня так себе, но я, по крайней мере, вижу в себе силы научится. Начать решил с преодоления боязни письма, чем в данный момент и занимаюсь.
Следующий шаг — научится грамотности. С этим, боюсь, будет куда сложнее.

 No comments    14   2015   мысли

Шаблонная система

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

После того, как фронтенд-разработчики выдали готовую верстку, а бекэнд-разработчики построили систему взаимодействия с базой данных, наступает момент, когда необходимо указать системе какую информацию она должна брать и куда вставлять. Эту операцию иногда называют «повесить на админку». Конечно, я утрирую, и далеко не всегда это делается после всех остальных работ, а не вперемешку с ними. Но для нас сейчас это не важно. А важно то, что такая операция существует и её цель построить однозначные связи между информацией полученной или сгенерированной бекэндом и отображением для пользователя.

PHP, как шаблонная система

На заре развития веб технологий, примерно для этой цели и создали PHP. Это можно понять и из современной расшифровки акронима — «препроцессор гипертекста», а гипертекст это HTML, конечно. Ну а согласно вики начиналось все вообще с «интерпретатора форм для персональной домашней страницы», то есть фактически PHP когда-то был всего лишь шаблонной системой к конкретному сайту.

Этот позорный факт часто ставят в укор PHP-разработчикам, которых итак не особо жалуют в «продвинутом» IT собществе. Но об этом поговорим как-нибудь в другой раз. Сегодня нас интересует другое. А именно то мнение, что раз этот язык изначально задумывался, как шаблонная система, то зачем «городить огород» из разных технолгий. Давайте писать шаблоны, вставляя «php-врезки» в верстку сайта.

Такого метода придерживаются многие популярные CMS системы — WordPress, 1C-Bitrix, NetCat (частично) и другие.

Что в этом методе хорошего?

  • Не надо обучать разработчиков отдельно шаблонной системе. Они уже знают php и смогут быстро включится в проект.
  • Разработчик всегда может найти в коде конкретную переменную или функцию и посмотреть откуда она берется или что делает.
  • Это быстрее работает, т.к. нет лишнего звена между интерпретатором языка и шаблоном.

Что тут не так?

  • Велик соблазн вставить кусок логики в шаблон. Такие действия не пресекаются на уровне системы.
  • Больше мусора. Как минимум открывающий и закрывающий теги его создают.
  • Вывод в шаблон привязан к особенностям системы. Если мы поменяем функцию, то нам придется менять её и в шаблоне. Мы открываем свой «внутренний мир» тому, кто привязывает шаблон к бекэнду.
  • Если ошибка произойдет прямо в шаблоне то нам сложно будет её найти и разобрать. Это связано с тем, что часть страницы на тот момент уже выведется и мы можем на понять, что ошибка произошла перед каким-нибудь закрывающим тегом из-за чего у нас полная каша.

Отдельная шаблонная система

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

%title%

до блоков типа:

{foreach from=$myArray item=foo}
{$foo}
{/foreach}

При определенном идет таких договоренностей верстальщик может сразу сделать из HTML-верстки нужный шаблон для внедрения. Ну или по крайней мере подготовить его к этому. Это экономически целесообразно, хотя на практике целиком такое получается крайне редко. Такого подхода придерживатся: Umi.cms , Drupal(опционально), Symfony framework и многие другие проекты.

Что в этом методе хорошего?

  • Пропадает необходимость контролировать разработчиков по разделению логики представления от бизнес-логики. Используя «шаблонизатор» мы точно уверены, что никакая часть бизнес-логики не «просочится» в шаблон.
  • Шаблон в итоге выглядит чище. Это не абсолютное правило, но тенденция.
  • Мы можем разделить права. К примеру дать кому-то права изменять только шаблоны и мы будем уверены, что он не «докопается» до базы данных, например.

Что тут не так?

  • Меньше скорость работы. Однако, при использовании кеширования этот минут сходит на нет.
  • Требует отдельного изучения. Правда, как правило, структура шаблона достаточно простая для понимания разработчиками.

Вывод

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

Маленький компонент в большом проекте

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

Проект представляет из себя интернет-магазин, в котором, по предварительным нашим прикидкам должно получится около 100 групп товаров, распределенных, в среднем, по трем уровням вложенности. Товаров в каждой группе, так же предполагается существенное количество.
На этапе проектирования мы прописали несколько основных сценариев, как пользователь сможет найти нужный ему товар. Вместе с заказчиками мы описали основной сценарий: пользователи будут находить нужную группу товаров, а дальше искать товар, который их интересует по ряду параметров. В зависимости от того, какая это группа, а так же задач пользователя, его будут интересовать разные параметры. Кого-то размеры: ширина, высота, объем; кого-то цвет и фактура; а кого-то цена и бренд. Все варианты перечислить очень трудно, а учесть в техническом задании и подавно.
Параметры, по которым можно будет искать товар мы назовем свойства или характеристики. О них и пойдет речь.

Начинаем работу

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

  1. У каждого товара может быть мало (3-4) или много (10-15) различных характеристик.
  2. Характеристики почти полностью повторяются внутри группы товаров. То есть, если у одного “метиза” есть диаметр, длинна и шаг резьбы, то у другого, скорее всего, то же. Группа верхнего уровня может включать или не включать эти характеристики.
  3. У разных групп товаров свойства могут быть совсем разные. Однако, часто можно выделить блоки характеристик. Такие блоки полностью повторяются у одних групп товаров и отсутствуют у других. Большинство блоков “наследуются” в дочерних группах, но иногда появляются только в конечной группе. Например блок, который можно назвать “размеры” (ширина, высота, длинна) есть и у москитных сеток и у дюбелей, но совершенно не важен для монтажной пены или клея.

С другой стороны

Одновременно с работой проектировщика, свою работу над характеристиками начала дизайнер проекта. Она изучила множество отечественных и зарубежных интернет магазинов, а так же ассортимент нашего заказчика. Выяснила, что пользователю, как правило, удобно выбирать из представленных вариантов (белый, черный или коричневый цвет), либо указывать диапазон значений (цена от 100 до 300 рублей). Другие варианты подбора по параметрам в этой отрасли встречаются реже. Из этого понимания появился дизайн-макет фильтров на странице группы товаров.
Заказчик согласует дизайн-макет и таким образом “бетонирует” решения дизайнера. Дальше от них отступать нельзя.

Пишем ТЗ

С оглядкой на дизайн-макет, проектировщик принимается, за написания технического задания. Ему нужно понять, в каком виде можно хранить информацию. “Любое свойство продукта состоит из пары ключ-значение.” – решает проектировщик, для начала. Название у характеристики есть всегда, а вот со значением несколько хитрее.
По некоторым характеристикам нужно сделать возможность выбора диапазона – от максимального значения, до минимального. Такие свойства нужно явно задать числовыми, иначе мы не сможем проводить с ними математические операции, если пользователь введет что-то не числовое. Программисты попросили так же для увеличения производительности поделить числовые свойства на целые числа и дробные. А еще стало очевидно, что у числовых свойств будут еще единицы измерения. Так появились первые два типа характеристик.
Потом проектировщик стал обдумывать фильтры по таким свойствам, как цвет или тип крепления. Понятно, что можно дать администратору сайта вводить эти значения вручную, а пользователю потом предлагать выбрать из многих вариантов. Проектировщик уже имел опыт с таким решением и знал, что в этом случае скорее всего появятся такие варианты, как “Белый”, “белый‘, ‘светлый’, ‘белесый’, ‘white’. Все они, возможно, различаются для заполняющих сайт. но никак не различаются для пользователя. По этому нужно администратора ограничить. Пусть главный администратор вводит варианты цветов, а все остальные только выбирают из предложенного. Так мы избежим этой путаницы. Программисты так же отметили, что это целых два типа характеристик описано: в первом у товара есть только один вариант у списка(цвет только один), а во втором может быть несколько вариантов одновременно (сразу несколько вариантов креплений).
Изучая другие магазины подобной тематики, проектировщик отметил, что есть свойства, у которых может быть только два значения: есть или нету. эти свойства он вынес в отдельный тип.
Ну а все характеристики, которые нельзя будет отнести к этим типам оставим в виде текстового названия и текстового значения.

Итого, оказывается, что всё многообразие свойств можно разделить 6 типов характеристик. Решено, что администратор сайта будет создавать список характеристик и задавать их тип. Для некоторых вводить так же единицы измерения и возможные значения.
Это решение оценено в 25 часов работ программистов и верстальщиков. Руководитель проекта имеет немалый опыт и предлагает еще раз посмотреть на характеристики со всех сторон.

Смотрим со всех сторон

Начнем оценку нашего решения со стороны разработчика. Давайте представим, что мы приступили к написанию поиска по характеристикам. Тут то и становится понятно, что всего в проекте предполагаются десятки тысяч характеристик и десятки тысяч товаров. А это значит, что при поиске по одной характеристики серверу предстоит обработать около ста миллионов операций сравнения. Кроме того, стоит учитывать, что пользователь может задать одновременно фильтр по многим характеристикам. А пользователей, надеемся, будет много. Выдержит ли сервер такие нагрузки? Предварительное нагрузочное тестирование показывает, что нет.
Зовем программистов на совет. Цель: не меняя дизайн макет и внешнюю структуру сайта что-то придумать с производительностью. Вместе они еще раз открывают список, составленный проектировщиком в самом начале и решают, что каждую характеристику можно отнести не ко всему интернет-магазину сразу, а только к конкретной группе товаров. Таким образом количество характеристик уменьшится до сотен и товары, среди которых стоит искать так же ограничатся одной группой, то есть то же порядок ‘сотни’. Так мы снизим количество операций с сотен миллионов до десятков тысяч. Правда, при таком решении предполагаемый срок разработки увеличился до 40 часов.

Теперь давайте посмотрим на наш план глазами администратора сайта. Руководитель проекта шутит, что через месяц заполнения сайта администратор придет к нам в офис с бейсбольной битой. ‘Почему? Да потому, что администратор сайта чекнется вносить длину, ширину и высоту, для нескольких десятков групп товаров. А цвет и бренд для всех почти.’ – говорит он. ‘И это еще пол беды. Допустим, есть две похожие группы ‘метизы’ и ‘дюбели’, в обеих есть длинна. Клиент хочет подобрать и то и другое под диаметр. Получается, вы его заставите сначала в одной группе фильтры забивать, потом в другой. Как ваша интеллектуальная система длину оттуда с длинной отсюда сопоставлять будет? ’.
Мысль здравая. После тщательного обдумывания всех нюансов, принято решение разбить характеристики на блоки. А потом добавить возможность прикреплять эти блоки к разным группам товаров. Важно так же учесть, что у одной группы может быть любое число таких блоков. Оценка работ увеличилась до 60 часов.

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

Новые фичи

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

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

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

И что будем делать?

Что ж, проект все равно делать надо. Проектировщик вместе с программистами придумывают «интеллектуальный» алгоритм, который пытается сам определить тип характеристики. Так же сам пытается отделить значение от единицы измерения или записать варианты значений. Реализация такого алгоритма увеличивает оценку до 100 часов.
Такое увеличение уже не взять на себя без потерь качества или диких срывов сроков и руководитель проекта это понимает. Теперь приходится вести переговоры с клиентом о том, что бы урезать какой-то менее важный компонент на первом этапе или увеличить общий бюджет этапа. Но это уже другая история.

Вместо итога

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

  1. Всегда прежде чем называть сроки/стоимости клиенту возьмите паузу и еще раз взгляните на компоненты проекты со всех точек зрения. В нашем случае, это сторона программистов, сторона администратора сайта, сторона конечного пользователя-покупателя и сторона бизнеса, конечно. Не сделав этого, мы могли ошибиться в 4 раза.
  2. При ведении переговоров с клиентами старайтесь охватить все аспекты. Конечно, что-то учесть не удастся, но чем четче были обозначены ранее принятые решения, тем проще будет договариваться дальше.
  3. Старайтесь составить четкий чек лист, что бы клиент мог в любой момент видеть входит в данный этап, что что в последующие. В этом проекте мы этого не сделали и еще больше запутали клиента, когда брали на себя дополнительные обязательства по этапу. В дальнейшем постараемся прописывать и проговаривать все более четко.
Earlier Ctrl + ↓