Что такое лсп тестирование
Влияние протокола языкового сервера (LSP) на будущее IDE
С момента своего появления Visual Studio Code в одиночку так сильно повлиял на экосистему разработчиков, что возврата назад уже не будет. Это общедоступный бесплатный инструмент с открытым исходным кодом и это очень мощный инструмент.
Что такое Протокол языкового сервера?
Это взаимодействие происходит с помощью набора правил, заданных протоколом. Протокол языкового сервера можно рассматривать как урезанную модификацию HTTP взаимодействующую только по JSON-RPC протоколу.
Зачем нужен LSP?
Вы заметили, что в VSCode постоянно появляются изобретательные сообщения об ошибках и предложения автоподстановок? И как же легко, просто установив расширение из магазина VSCode, вы получаете всю мощь IntelliSense для совершенно разных языков, таких как C, Python, Java и т.д.? Все это происходит благодаря LSP.
Поддержка автозавершения и IntelliSense для HTML/CSS/JavaScript идет сразу вместе с VSCode (так же, как PyCharm идет сразу с поддержкой Python). Однако такая же поддержка других языков может быть реализована с помощью протокола LSP для этих языков.
Что такое JSON-RPC?
Это простой пример для JSON-RPC:
В этом примере мы посылаем запрос в кодировке JSON в соответствии со спецификацией RPC. Если сервер настроен на корректную работу с JSON-RPC, то он выполнит метод runThisFunction с переданными параметрами и вернет результат в том виде, как показано выше.
LSP + JSON-RPC
LSP использует JSON-RPC для связи с удаленным сервером. Для этого используется следующий формат:
Почему все это так важно?
С введением формального протокола LSP, Microsoft свела знаменитую проблему M x N к проблеме M + N.
M = Различные языки (C, C++, PHP, Python, Node, Swift, Go и т.д.).
N = Различные редакторы кода (VSCode, Eclipse, Notepad++, Sublime Text и т.д.).
Раньше для того, чтобы M редакторов поддерживали N языков, вам нужно было иметь M*N решений. То есть каждый редактор кода должен был реализовать поддержку каждого языка самостоятельно.
С появлением LSP в редактор оставалось лишь внедрить поддержку протокола языкового сервера. После этого любой, кто делает языковой сервер (следуя стандартам LSP), может легко интегрироваться в редактор кода, при этом редактор никогда не будет «знать», с каким языком он работает!
Будущее IDE
По мере того, как языковые сервера реализуются для различных языков программирования, у разработчиков появляется возможность выбирать редактор на свой вкус. Без привязки к конкретному языку. Нет больше необходимости ограничивать себя, например только XCode для разработки на Swift или PyCharm для Python. И не только это, LSP можно внедрить прямо в JavaScript для поддержки IntelliSense в браузере! Настало потрясающее время для программистов!
Компьютерные сети
You are here
Тестирование путей LSP
В протоколе LSP Ping для тестирования состояния LSP применяется техника, близкая к механизму работы утилиты ping протокола IP. Она заключается в том, что протокол LSP Ping отправляет вдоль тестируемого пути LSP сообщение Echo Request. Если такое сообщение доходит до устройства LER, которое является конечным узлом тестируемого пути LSP, оно отвечает сообщением Echo Replay. Получение исходным узлом такого сообщения означает, что путь LSP работоспособен.
Описанная схема работы аналогична схеме работы утилиты ping протокола IP, однако она имеет свои особенности, которые мы поясним на примере сети, изображенной на рис. 1.
Наши партнеры:
— Возможно эта информация Вас заинтересует:
— Посмотрите интересные ссылочки вот тут:
Рис. 1. Тестирование LSP с помощью протокола LSP Ping
В этом примере устройство LSR1 тестирует состояние пути LSP1, который заканчивается на устройстве LSR8 (для этого пути оно является устройством LER).
Для тестирования пути LSP1 устройство LSR1 отправляет MPLS-пакет с меткой 105 — эта метка соответствует пути LSP1 на линии между устройствами LSR1 и LSR4. Сообщение Echo Request вкладывается в UDP-сообщение, которое, в свою очередь, вкладывается в IP-пакет. На рис. 20.12 показаны только значимые для изучения протокола LSP Ping поля: метка MPLS-кадра, IP-адрес источника (SA), IP-адрес назначения (DA), а также поле FEC, которое идентифицирует тестируемый путь LSP. В нашем примере это IP-адрес сети 105.0.0.0, к которой ведет путь LSP1.
Адрес назначения в IP-пакете, который переносит сообщение Echo Request, равен 127.0.0.1, то есть является адресом обратной петли стека протоколов IP каждого узла. О причине использования такого необычного адреса назначения (а не, скажем, IP-адреса интерфейса конечного узла тестируемого пути LSP) мы расскажем позже, а пока заметим, что адрес 127.0.0.1 должен работать правильно, так как в процессе передачи запроса по сети для его продвижения используются MPLS-метки, а не IP-адрес назначения. При приходе на конечный узел IP-пакет освобождается от заголовка MPLS (это также может произойти на предыдущем хопе, если применяется техника PHP) и обрабатывается на основе IP-адреса. Так как адрес 127.0.0.1 указывает на собственный узел, то пакет передается собственному стеку TCP/IP, где он распознается как UDP-пакет протокола LSP Ping и обрабатывается соответственно.
Поле FEC посылается в запросе Echo Request для того, чтобы конечный узел пути мог сравнить указанное в пакете значение FEC со значением из его собственной базы данных для пути, по которому пришел кадр запроса. Такой механизм позволяет отслеживать ситуации, когда запрос вследствие каких-то ошибок приходит не по тому пути, который тестируется.
В том случае, когда запрос благополучно доходит до конечного узла пути, и тот убеждается, что полученный запрос пришел по нужному пути (то есть полученное значение FEC совпадает со значением FEC из базы данных конечного узла), он отправляет ответ Echo Replay узлу, выполнившему запрос. В нашем случае узел LSR8 отправляет ответ Echo Replay узлу LSR1. Сообщение Echo Replay посылается уже не по пути LSP, а как обычное UDP-сообщение, вложенное в IP-пакет. Если вспомнить, что пути LSP являются однонаправленными, станет понятно, что это единственное гарантированное решение, так как обратного пути от LSR8 к LSR1 может и не существовать.
Теперь посмотрим, что происходит в том случае, когда по какой-то причине путь LSP поврежден. На рис. 2 представлен именно такой случай, когда путь поврежден на последнем своем участке (между устройствами LSR7 и LSR8).
Рис. 1. Тестирование неисправного пути LSPc помощью протокола LSP Ping
В этой ситуации LSR7 не может отправить MPLS-кадр по назначению, как того требует метка 177, а отбрасывает заголовок MPLS и старается обработать кадр как IP-пакет. Как и в случае исправного пути, адрес 127.0.0.1 требует передачи пакета локальному стеку TCP/IP. Именно этого эффекта и добивались разработчики протокола LSP Ping, выбирая в качестве адреса назначения этот специальный адрес. Узел LSR7 обрабатывает сообщение Echo Request и отправляет сообщение Echo Replay узлу LSR1 с информацией об обнаруженной ошибке.
7 шагов к отличному результату – пользовательское тестирование
Главная идея тестирования состоит в том, чтобы показать проект пользователю на раннем этапе. Это позволит оценить будущие итерации и проверить предположения.
Что такое пользовательское тестирование
Пользовательское тестирование (или тестирование юзабилити) является процессом, который идентифицирует проблемы продукта. Вы находите реальных пользователей, желательно из вашей целевой аудитории, и просите их попробовать ваше детище. История этого вида тестирования началась во время второй мировой войны, когда тестировали удобство использования военной техники.
Стив Круг в книге «Не заставляйте меня думать» популяризировал юзабилити тестирование. В наше время методы тестирования стали общедоступны, выйдя за рамки военных исследований и научных лабораторий.
Зачем нужно ранее тестирование
Намного дешевле найти потенциальные проблемы на ранних этапах жизненного цикла нового продукта. Технические компании, как правило, следуют за производственным процессом, который выглядит примерно так:
Этот график представляет, как проект передается через команды по всей компании. Менеджеры по продукции определяют требования к продукту и передают их команде UX. После окончания проектирования продукт перемещается к разработчикам. Этот цикл повторяется итеративным способом, пока конечный продукт не завершен.
Разработчики, которые полагаются на интуицию и одни только предположения, должны ждать выпуска каждого цикла, чтобы измерить обратную связь, потенциально тратя впустую много ресурсов. Как только создан образец продукта, нужно получить доказательства плохого юзабилити и изменять проект. Это оказывается слишком дорого и неэффективно.
«Если вы думаете, что хороший дизайн дорого стоит, посмотрите счет за плохой» Ralf Speth
Тестирование юзабилити на прототипах было разработано как быстрое и недорогое решение для снижения некоторых из этих рисков. Вы можете проверить предположения, регулировать разработку продукта и определить направление его развития. Скрытые проблемы продукта раскрываются с использованием фактических отзывов пользователей. Тестирование юзабилити может ограничиваться искусственной тестовой средой и небольшой выборкой, но это никогда не даст тех же результатов, какие дает обратная связь с массовым пользователем. От них мы получаем реальные данные.
Используйте бесплатные инструменты
Разрабатываем программу тестирования
Шаг 1 — Определите цели тестирования
Самое важное – определить на какие вопросы вы должны получить ответы в ходе тестирования. Ищите слабые места вашего продукта, тестируйте сложные действия пользователя и другие идеи, которые могут оказаться критичными. Наличие таких вопросов поможет подобрать наиболее подходящий метод тестирования и создать план. При недостатке средств можно использовать метод тестирования под названием «Мысли вслух».
«В тесте «Мысли вслух», вы просите участников непрерывно размышлять вслух, просто выражая словами их мысли, когда они пользуются интерфейсом» — Jakob Nielsen
Шаг 2 — Создайте сценарий
Здравствуйте! Меня зовут Алексей, и я буду сопровождать ваше тестирование. Спасибо за то, что нашли время поучаствовать в тестировании, Ваш отзыв очень ценен. Прежде чем мы начнем, я хотел бы прояснить несколько пунктов.
После идентификации целей исследования, определенных на предыдущем этапе, я проведу обсуждение некоторых вопросов по темам:
Фон/Контекст — «Как обычно вы создаете сайты? Вы используете приложения или сервисы?»
Ожидания — «Прежде, чем нажать кнопку поиска, чего вы ожидаете, что должно произойти?»
Юзабилити — «Как эту область лучше всего использовать?»
Шкала оценки — «Как сложно(1) или легко(5) создать форму в редакторе?»
Если ваш продукт сложен, расставьте приоритеты в вопросах и проведите многократные сеансы тестирования. Рассчитывайте, что для сеанса 20–30 минут используется 1–2 вопроса и 3–5 задач. Обращайте внимание на формулировки и избегайте наводящих вопросов, чтобы исключить влияние на поведение пользователя. Например, «Как вы прокручиваете страницу, чтобы видеть больше контента?» предполагает, что можно прокрутить. Лучше спросить «На странице есть еще контент? Как его можно увидеть?»
Шаг 3 — Создайте каркас и прототип
Каркас должен фокусироваться в меньшей степени на зрительном ряде и в большей на расположении элементов. Если вы используете программу для создания прототипа на основании визуальных каркасов, используйте их. С помощью платформы PIXLI можно пропустить этот шаг и сразу создать интерактивный прототип с визуализацией элементов. Общее правило состоит в том, чтобы создать высокоточные мокапы после проверки корректности основных пользовательских потоков, а не до них.
На этом этапе ваш прототип должен соответствовать вопросам, которые вы поставили. Если первая задача звучит как «Как вы авторизуетесь в системе?», то прототип должен демонстрировать доступ к форме и саму форму авторизации.
Если вторая задача – «Как вы создаете сайт на основании шаблона в редакторе», то где-то должен присутствовать переход к созданию сайта на основе шаблонов и возможность их выбора. Обратите внимание, где пользователи ищут путь решения задачи. Это и есть цель тестирования.
Шаг 4 — Поиск пользователей
Определитесь с целевой аудиторией. Если на тестирование выделили бюджет, обеспечьте стимулы для пользователей. Например, Google или Airbnb обычно стимулируют пользователей, предлагают подарочную карту. Если бюджет отсутствует, воспользуйтесь следующими подсказками.
Если у вас уже есть пользователи
Идентифицируйте людей, которые активно используют ваш продукт и отправьте сообщение по электронной почте. Предложите им поучаствовать с целью дальнейшего развития продукта. Сообщите, что будете учитывать все мнения и результаты тестирования. Легкий подхалимаж не помешает. Пользователь даст обратную связь, если он лично заинтересован в вашем продукте – ваш успех это его успех. Если пользователь не заинтересован, объясните, какую продукт приносит пользу или как решает его проблему.
Если у вас нет пользователей
Найдите места, где собирается ваша целевая аудитория лично или онлайн. Ищите форумы, группы в соцсетях, клубы и т.д. И отправьте сообщение, например:
«Здравствуйте, Андрей! Я разработчик платформы для web-дизайна PIXLI. По сообщениям на форуме я обратил внимание, что вы активно используете конструкторы для создания сайтов. Не могли бы Вы уделить полчаса на тестирование нашего продукта? Если да, то сообщите о наиболее удобном для Вас времени».
Если это не работает, расширьте зону поиска пользователей или обеспечьте маленькие стимулы. Например, можно предложить увеличить тестовый период пользования платформой, или расширить бесплатный функционал. Искать пользователей для тестирования трудно, если бюджет отсутствует.
Сколько пользователей должны участвовать в тестировании?
3–5 пользователей за один сеанс достаточно, чтобы увидеть большинство проблем. Если вам необходимо большее число пользователей, увеличьте количество сеансов.
Шаг 5 — Создайте подходящую обстановку для тестирования
Личные сеансы тестирования лучше проводить в тишине. Например, выделите комнату в своем офисе. Кафе тоже является неплохим вариантом, но там может быть шумно – это мешает. Следите за отсутствием отвлекающих факторов. Или постарайтесь их минимизировать. Если вы назначили встречу в кафе, лучше выбрать время, когда там не собирается полсотни служащих соседнего офисного центра на обед.
Удаленные сеансы проще организовать – пользователь находится в комфортной и привычной обстановке. Однако могут происходить технические сбои и надо иметь запасные возможности. Например, быстро сменить клиента для связи.
Всегда проводите пробный прогон!
Как следует проверьте свой прототип, доступ к нему. Прогоните сначала свой сценарий сами, чтобы еще раз все детализировать и уточнить.
Шаг 6 — Подготовка сеанса
Электронные письма-напоминания полезны, чтобы уменьшить неявки. Сообщите, в течение какого времени вы будете ожидать пользователя.
Записывайте высказывания пользователя на аудио, а потом их анализируйте. Видео и аудио позволят увидеть все действия и услышать «мысли вслух» по поводу их выполнения. Особенно те, которые отклоняются от заданного поведения. Обязательно предупредите пользователя, что его действия будут фиксироваться.
Шаг 7 — Анализируйте ключевые результаты
Пересмотрите, протестируйте, повторитесь
Пользовательское тестирование даст вам направление для движения дальше. Продукт запускается в разработку, когда решены проблемы юзабилити и общая обратная связь положительна. Если обратная связь нейтральна или отрицательна, или УТП для пользователя не определено четко, следует пересмотреть прототип и выполнить тестирование еще раз.
____________________ __________ __________ __________ __________ __________
Материал создан агентством контент-маркетинга Текстотека.
Хотите самостоятельно внедрить контент-маркетинг в свой бизнес? Подписывайтесь на наше сообщество ВКонтакте, там много бесплатного обучающего материала.
Как тестировать сайты
Допустим, вы сделали сайт, но у вас нет тестировщика, который может всё проверить. Вот короткая инструкция, на что смотреть, чтобы с большой вероятностью после запуска всё было в порядке.
Когда тестирование полезно
В больших компаниях каждым пунктом из этой статьи могут заниматься целые отделы, сотрудники которых досконально проверяют каждую мелочь — руками или автоматически. Но представим, что сейчас под рукой нет IT-департамента. Что можно сделать самостоятельно и быстро, чтобы проверить, что всё работает как задумано.
Предупреждение: статья не претендует на академическую полноту, но точно поможет что-нибудь не упустить.
Всё посмотреть и прокликать
Сначала нужно проверить, что всё выглядит, как задумано заказчиком — сайт совпадает с макетом, кнопки работают и ссылки ведут, куда нужно.
Что проверять:
Иногда используют автоматические тесты, которые сравниваются отрендеренный результат кода аля интерфейс с рендер-версией приложения. Фактически, это сравнение скриншотов. Конечно, автотесты можно подготовить и для тестирования интерактивных элементов.
Фрагмент реального сайта о том, что тестирование полезно
Инструменты:
Ошибки JavaScript
Если в коде есть ошибки, их будет видно в консоли разработчика. Также там можно обратить внимание на запросы (время и коды ответов) и посмотреть размер загружаемых файлов. И если размер большой, обсудить с разработчиками оптимизацию кода на JavaScript, шрифтов и изображений.
Валидность кода
Нужно убедиться, что код удовлетворяет стандартам HTML/CSS, для этого есть специальные валидаторы. Узнайте, как проверить валидность HTML.
Веб-формы
Формы — кладезь пользовательских данных и одновременно потенциальный источник уязвимостей. Формы должны быть удобными для пользователя и безопасными для сайта.
Что проверять:
Неправильные ссылки
Проверьте, что все ссылки ведут на настоящие сайты и не ведут на 404. Для этого тоже есть несколько инструментов. На главной не должно быть ссылки на главную.
Уберите ссылку на главную с главной
Локализация
Если пользователи сайта говорят на разных языках, сайт локализуют — готовят тексты на разных языках и добавляют переключалку с флагами.
Но недостаточно проверить перевод текстов в интерфейсе, ошибок и документации — есть ещё ряд нюансов. Например, нужно проверить представление дат и времени, поддерживает ли шрифт локальные символы, и есть ли режим RTL для стран, где текст читается справа налево.
Производительность сайта
Пользователи уходят, если сайт грузится медленно. Поэтому нужно проверить, что ваш сайт не такой.
Что проверять
Иногда скорость загрузки зависит от контента, который используется на странице. Вот советы, как его оптимизировать.
Критерии качества
На курсах HTML Academy сайты верстают и готовят к публикации на основе критериев качества — длинного списка правил, который нужен, чтобы делать сразу хорошо. Критерии включают не только то, что написано в этой статье — там гораздо больше мелочей, которые должен знать хороший фронтенд-разработчик.
Делать сразу хорошие сайты
Всё, что нужно фронтендеру — на курсах HTML Academy. Научитесь всему, чтобы у тестировщиков закончилась работа.
Мифология и реальные методы прагматичного программирования
В разработке цветет культ Карго. Многие полагаются на слова, которые сказал уважаемый автор десятки лет назад. Продолжают разрабатывать код, опираясь на подходы, которые либо не актуальны, либо сам автор поменял свою точку зрения. И сегодня мы поговорим о некоторых распространенных принципах программирования, которые не так однозначны как может показаться.
Меня зовут Кирилл Мокевнин и я — сооснователь школы программирования Хекслет. За последние пару лет я провел собеседования с более чем 400 человек, потенциальными наставниками по совершенно разным направлениям в разработке. В результате у меня собралась большая выборка наблюдений, которые мы разберем ниже.
Редакторы
Для развития экосистемы не очень круто, что каждая IDE сама реализует все фичи под каждый язык. Вендоры не хотят делиться этим с сообществом и разрабатывают механизмы для анализа и работы с кодом внутри себя. И если кто-то делает свой собственный редактор, то для поддержки языков ему приходится писать всё практически с нуля, особенно тяжелые фичи.
Не все знают, что недавно в мире редакторов произошла революция. Раньше было четкое разделение на IDE (которые дают рефакторинг, autocomplete, подсказки, документацию и запуск кода) и обычные редакторы, которые дают подсветку и небольшой набор базовых возможностей, типа перехода по файлам. Но какое-то время назад всё изменилось.
LSP (Language Server Protocol)
По-другому, это, как ни странно, реализовала Microsoft. Хотя миф, что Microsoft — ребята не очень, существует до сих пор. Но с точки зрения Open Source они — номер один в мире по количеству продуктов. Я уж не говорю о том, что им принадлежит GitHub.
Microsoft сделала LSP — спецификацию, про которую знает пока не так много людей. Понятно, зачем в Microsoft это сделали — они хотят, чтобы их среда и технологии распространялись, поэтому им выгодно делать это бесплатно. И тем не менее.
LSP — это стандарт, который определяет, как должен быть написан сервер, отвечающий за анализ и изменение кода. Такой сервер не связан с редактором, он пишется независимо. Единственное, что требуется от редакторов — встроить возможность общаться с таким сервером.
Если раньше поддержку языков писали под каждый редактор, то сейчас на GitHub есть открытые имплементации LSP и они работают абсолютно со всеми редакторами. На самом деле это серьезная вещь и она полностью изменила ландшафт. Например, теперь очень просто создать собственный редактор с сумасшедшими возможностями.
Более того, для современных языков (Rust, Swift, TypeScript) уже не делают специализированных IDE и даже плагинов к существующим. На том же GitHub разработчики этих языков сразу декларируют, что будут делать реализацию LSP, чтобы вы сами могли подключить поддержку языка в ваш любимый редактор.
Это уже поддерживают Apple, Microsoft и Mozilla — и рано или поздно мы получим все возможности IDE в любом редакторе. Для примера — мой редактор Vim.
Видно, что здесь есть умный autocomplete: он знает не только про класс и стандартную Java, но и Lombok. Сверху есть аннотации, Vim всё подсказывает и подсвечивает. Кроме того, есть еще рефакторинг, организация импортов, проваливание, дизассемблирование и много других вещей. Может быть, это не так симпатично, как в IDE, но очень эффективно. А достигается всё это благодаря LSP.
Благодаря этому сейчас начинается узкоспециализированный бум: на GitHub можно увидеть множество новых редакторов, потому что они из коробки получают поддержку всех популярных языков.
Разработка
В разработке существуют не то чтобы мифы, но многие думают, что можно делать только так, а не по-другому.
Ритуалы
Я специально назвал это ритуалами — люди часто что-то выполняют, не задумываясь, потому что другого просто не видели. Например, синхронные митинги, когда надо всем в одно и то же время созвониться и рассказать, кто и что сделал. Подобные митинги часто превращаются в обычную отчетность.
То же самое происходит со спринтами и деплоями. Например, я знаю людей, у которых спринт идет две недели, и деплой почему-то тоже раз в две недели. При этом в скраме нет требования привязывать деплой к концу спринта. В идеале, нужно деплоиться каждый день, независимо ни от чего, потому что с точки зрения бизнеса Time To Market — это самая главная вещь. Когда вы выкатываете сразу множество фич, сложно оценить, что на что повлияло и к чему все это приведет. При этом всем очень важно считать — все хотят понять, что происходит и оценивают, оценивают и оценивают.
Все подобные ритуалы приводят к проблемам, которых без них бы не было. Укладываться в спринтах в срок не то чтобы невозможно, а чаще всего не нужно. Это выдуманная проблема, которая не только приводит разработчиков к стрессу, но даже разборки после спринта провоцирует. «Почему мы не успеваем, давайте на 3,14 умножать! У нас есть коэффициенты? А, их же нельзя, персональной ответственности нет — мы, как команда, зафейлили…»
Но всё возможно совсем по-другому:
Деплой в любой момент, хоть 5 раз в день;
Задачи по мере поступления;
Всё это применяется и у нас в Хекслете. При этом сейчас мы стали использовать множество ботов для тех же дейли.
Код ревью и фича-ветки
Все сталкиваются с долгими фича-ветками и блокирующими код ревью. Все не упускают случая пожаловаться, что фича-ветку ребейзят и мержат в мастер пять дней и всей командой, а на код ревью надо пятерых уговаривать, и у них все равно нет времени.
Хотя на самом деле возможно по-другому:
Прямо в мастер (хотя сейчас уже надо говорить main).
Делать неблокирующее ревью через маленькие изменения позволяет подход Trunk-based Development. Многие программисты не всегда осознают, что изменения могут быть небольшими — они уверены, что их фича не бьется. Но если проверить, то почти всегда это возможно: ведь глобальные изменения, которые затрагивают всё, и их нельзя поэтапно накатывать, бывают достаточно редко.
Благодаря маленьким изменениям практически всё можно делать сразу в main. При таком подходе даже если вы что-то напишете не так, то быстро и легко сможете это поправить.
Есть еще дополнительный бонус от такого подхода. Когда программист что-то долго пишет и где-то в начале уходит не туда, он может идти не туда целую неделю и даже больше. В результате накопленный негативный эффект будет слишком большой. Но если бы он вливал в main очень маленькими кусочками, то вы бы намного раньше увидели, что он пошел не в ту сторону, и поправили это.
Понятно, что это работает не везде, и что это связано с культурой компании. Но у нас это работает — и мы требуем ветки только от новичков.
Качество
В некоторых командах количество тестировщиков зашкаливает: их больше, чем программистов. Есть компании у которых по 5 стейджингов, и иногда это действительно бывает оправдано. Но на самом деле в современном мире может быть по-другому:
От стейджинга отказываются из-за того, что существуют флаги включения фич, канареечные релизы и другие подходы, которые позволяют минимизировать ошибки и сделать так, чтобы они проявлялись на небольшом количестве людей, либо только внутри продукта. Года 2-3 назад было много статей на тему, как большие компании типа Airbnb и Spotify отказались от стейджингов и почему.
В Booking работают несколько тысяч разработчиков и у них вообще нет отдела тестирования. Да, они используют жесткие маркетинговые приемы, можно их за это не любить. Но с точки зрения инженерной культуры они довольно продвинутые ребята. Например, они очень хорошо считают деньги и, если у них появляются баги, то они сразу же понимаю, сколько теряют.
Если мы делаем баги, то в нормальной разработке это означает, что мы на что-то не обращаем внимания, зато двигаемся и развиваемся очень быстро. Если у нас багов нет, то почти всегда это связано с консервативным подходом к разработке — то есть она очень длительная.
В Booking поменяли негатив на позитив. Подход интересный, и, с моей точки зрения, за ним скрывается очень важная вещь: самое главное — это мониторинг. Ведь вы никогда в жизни не добьетесь того, чтобы у вас совсем не было ошибок. Но если у вас отличный мониторинг, разделение и все эти подходы, о которых я говорю, то не принципиально, как и что вы делаете. Вы всегда можете откатиться, поправить всё, и продолжить двигаться с высокой скоростью.
Пирамида тестирования
Это моя любимая тема. Все знают про пирамиду тестирования Фаулера: если спросить про тесты, большинство сразу говорит, что пишут юнит-тесты.
Это очень фанатическая история, относящаяся к тому, что надо писать. Особенно часто я это встречаю, когда собеседую Java-разработчиков. В книгах, в документации Spring, в статьях, везде — только и разговоров, что о unit-тестах.
Я сам в тестировании много чего повидал и много как тестировал. Но вы же знаете, что мир меняется? Например, в 2008 году Kent Beck сказал: «I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence. ». В 2019 году он же написал про принципы тестирования, но многие люди, которые высказываются за юнит-тесты, до сих пор на него ссылаются. Хотя он уже давно переосмыслил tdd, и даже написал в Фейсбуке, что попробовал Haskell и изменил своё отношение к тестам.
Бережливое тестирование
К счастью, подходы все-таки меняются, это хорошо видно во фронтенде. Например, появилось новое веяние — бережливое тестирование.
Основная цель тестов — сделать так, чтобы наше приложение работало, а не заниматься тестами. В этом я абсолютно солидарен с Кентом Беком 2019 года, который предложил писать как можно меньше тестов, но так, чтобы мы покрывали как можно больше функциональности.
Понятно, что E2E тесты всё это могут, но они сложные и дорогие в написании. Это не ежедневные тесты, которые надо писать разработчикам. Их чаще пишут тестировщики — и это правильно.
Но если посмотреть на фронтенд, теперь всё крутится вокруг интеграционных тестов. Благодаря Kent C. Dodds и Guillermo Rauch появилась концепция «Testing Trophy», в которой этот факт подчеркивается. Тот же React Testing Library придерживается жесткой позиции, что хватит уже лазить внутрь, всё должно работать независимо от того, React у вас или нет.
Понятно, что иногда нужны юнит-тесты, а иногда — какие-то другие тесты. Но идеальный тест — если функционально ваш код не поменялся, то и тест не сломается. Если тесты ломаются — значит вы увлекаетесь мокингом или слишком глубоко лезете в кишки. Я много раз видел, как люди сначала всё покрывали юнит-тестами, а когда начинался рефакторинг — выкидывали их, потому что эти тесты ничем не могли им помочь.
С бэкендом похожая история. Тестируем интеграцию, а детали реализации сейчас мало кого волнуют. Главное чтобы у вас системы друг с другом работали.
В заключение темы разработки я задам короткий вопрос: «Замедляют ли тесты разработку?». Я даже провел небольшой опрос в Твиттере — половина опрошенных ответили, что нет, а в комментариях объяснили, что тесты наоборот, разработку ускоряют.
Все зависит от того, про какие тесты мы говорим. Чаще всего это упирается в умение писать тесты, а, как ни странно, их умеют писать далеко не все. Например, все ли понимают хотя бы разницу между моками и стабами, если моками называют то, что ими не является, или их пишут там, где не надо? Посмотрите на моем канале видео, я там рассказывал про эту тему.
Это отдельная большая тема, поэтому сегодня остановимся только на некоторых интересных особенностях.
Полиморфизм
Когда я разговариваю с людьми об этом, то очень многие удивляются, что существует несколько видов полиморфизма (а их вообще много). Во-вторых, когда начинаешь копать, то выясняется, что все хорошо знают определение, но довольно слабо понимают, где это можно и нужно использовать, почему это надо и какие проблемы решает.
Я провел еще один опрос в Твиттере:
Только половина ответила правильно. Это грустно, потому что полиморфизм в ООП наиболее сильно влияет на структуру кода (Бенджамин Пирс в ТАПЛ выделяет полиморфизм подтипов как основную фишку современного мейнстримового ООП).
Если взять навскидку несколько паттернов — Null Object, Strategy, Adapter, Decorator, Composite, Proxy, State — все это просто разновидности применения полиморфизма. Но если вы знаете полиморфизм и понимаете его, вам эти паттерны и знать не надо. Вы и так будете понимать, в какой момент и как их можно применить.
Принципы SOLID
Еще одна прекрасная вещь в ООП — SOLID. Тут вообще надо знать историю, откуда SOLID взялся и почему эти принципы так получились.
Самый забавный принцип здесь — Liskov. Как часто в жизни вы про него вспоминаете? Как он вообще на архитектуру вашего кода влияет? Этот принцип абсолютно правильный, но он нужен для редких кейсов, я бы даже сказал — для специфических языков. Но армия программистов следует за Робертом Мартином, который не только сейчас на Clojure пишет, но и давным-давно отдал предпочтение динамической типизации, пересмотрев свое отношение к возможностям языков. Почитайте его блог. Он писал на Ruby, перешел на Clojure, и вообще на днях написал, что это будет его последний язык.
Про Лисков. В своей статье про SOLID он сказал: «People (including me) have made the mistake that this is about inheritance. It is not. It is about sub-typing». В принципе в Liskov нет ни слова про классы или наследование, там всё связано с типами, которые обычно выражаются интерфейсами.
Если вы действительно хотите узнать про архитектуру, то послушайте Андрея Аксенова, который сделал Sphinx. «Снесите это немедленно», — один из лучших докладов про архитектуру. Кроме всего прочего, он говорит, что принцип Liskov понадобился ему только один раз — на собеседовании.
На самом деле есть гораздо более важные принципы. Например, Single level of abstraction и вообще барьер абстракции — это одна из ключевых частей разработки. А с Command-Query Separation мы вообще сталкиваемся каждый день. Law of Demeter — попроще, но он встречается гораздо чаще, чем принцип Liskov.
Микросервисы
Я прекрасно понимаю джавистов, когда на собеседовании они начинают со слова «микросервис». Но мне не очень понятно, когда об этом говорят ребята из других языков, особенно когда в их команде разработки три человека.
Например, человек мне рассказывал, что они переходят на микросервисы, потому что у них тормозит ORM в Django. И что у Django плохая ORM, потому что там нельзя писать рекурсивные запросы. Я решил докопаться до сути и начал его расспрашивать.
Выяснилось, что у ребят древовидный каталог, они пишут рекурсивные запросы прямо на SQL, и они тормозят. Как это матчится на микросервисы, не очень понятно, но суть оказалась в другом. Человек просто не знал, как хранить деревья в базе, потому что когда они делали каталог, то не посмотрели, какие есть способы хранения, кроме adjust set. Когда я рассказал ему про материализованный путь, он ушел исправлять проект. Такое у нас было собеседование.
Другая история связана с Python. Парень сказал, что он реализовал микросервисы именно потому, что у него было много зависимостей в одном проекте, и они долго устанавливались. Я попытался поговорить с ним, что это не совсем связанные вещи, но он был твердо уверен, что всё сделал правильно.
О чем я хочу сказать. Микросервисы, безусловно, решают проблемы, и есть проекты, в которых они нужны. Но существует миф, что если где бы то ни было внедрить микросервисы, то станет лучше. Часто говорят: у нас код так себе, поддерживать невозможно, а вот если мы его сейчас разделим на микросервисы, то он сразу станет классным.
Но вообще-то микросервисы сложнее, потому что логика никуда не денется — система останется такой же сложной, но при этом станет еще и распределенной.
С микросервисами вы сразу упираетесь в:
То есть микросервисы не спасают от плохого кода — при разделении он станет еще хуже, потому что в том месте, в котором он все равно собирается, вместо синхронных вызовов будут асинхронные вызовы, и т.д. Я уж не говорю про логирование и всякие другие штуки. Плохой код в тысячу раз проще сделать хорошим в рамках системы, где вы работаете. А микросервисы нужны для другого и решают другие проблемы.
Расскажу историю. В одной компании пишут на Java, и у них всё в микросервисах. При этом их архитектор не любит Spring, и они реализовали пять разных алгоритмов в одном зашифрованном файле. И чтобы достать из этого файла алгоритм, у них реализовано семь микросервисов: один берет данные, другой складывает в базу, плюс под каждый алгоритм написан свой собственный микросервис (еще пять штук).
Все микросервисы одновременно берут этот файл, потому что они одновременно срабатывают. Внутри каждого есть проверка на свой файл. Сам алгоритм на 200 строк, и еще обвязка на пару тысяч, чтобы все это запускалось. Это явный перебор, но так работают многие компании, особенно в аутсорсе. Хотя, на самом деле, это решается классическим паттерном — обычной стратегией, которая делается с помощью простого свитча.
Если вы хотите по-настоящему знать всё про микросервисы, рекомендую доклад Валентина Гогичашвили «События, шины и интеграция данных в непростом мире микросервисов». Он рассказывает, как в Заландо пришли к этому решению и с чем столкнулись по дороге.
Это прекраснейший доклад. В нем помимо практики есть и философия — от просмотра оторваться нельзя, как от хорошей книжки.
Заключение
Есть фундаментальные правила проектирования кода:
Менеджмент состояния. Как только у нас появляется shared state, то возникает определенный класс проблем, и это нужно понимать. Это связано с concurrency и распределенными системами.
Изоляция побочных эффектов. Если вы писали или будете писать на функциональных языках, вы это хорошо поймете, потому что они к этому приучают.
Семантическое именование имеет невероятно важное значение, потому что именовать все равно никто не умеет.
Что делать?
Читайте книги! Есть огромное количество книг, в которых давно написана вся правда. А читая про ОС, вы поймете, как работает все остальное — в операционках много готовых архитектурных решений.
Если вы не писали на языках с совершенно другой парадигмой, то потратьте время на них. У меня есть набор языков, которые я всегда рекомендую, чтобы захватить как можно большее количество разных парадигм и подходов:
Clojure, и вообще любой Lisp в принципе.
Kotlin из языков уровня C#, Java и подобных.
Ruby, Python, JS — не сильно принципиально какой, любой из них.
И последнее: работайте среди тех, кто сильнее вас.
Видео моего выступления на эту тему на конференции TechLead Conf 2021:
В 2022 году конференция TechLead пройдет на одной площадке с конференцией DevOps Conf 2022 — 9 и 10 июня в Москве, в Крокус-Экспо. Подать заявку на выступление для техлидов вы можете здесь, а для devops-коммьюнити — здесь.
Если у вас есть идеи и мысли по выступлению, но есть и много вопросов, то можно встретиться в прямом эфире с Программным комитетом и расспросить их обо всем. На сайтах обеих конференций смотрите информацию о встречах.