Разработка и эксплуатация
last update: 20-03-2022, 00:05 UTC
Ресурсы
- Практические аспекты Kubernetes в Azure Cloud (Олександр Грабко, 2020). Планирование, управление, квоты ресурсов, жизненный цикл кластера, Docker в подсистеме Kubernetes, интеграция с CI/CD, MongoDB в Kubernetes кластере, общий обзор мониторинга. Обзор реальных проблем и воркэраундов для их разрешения.
- BackEnd: Чистая архитектура на практике. О чем не сказал Дядя Боб? (Денис Цветцих, 2020). Начало выступления по теме с 04:00.
- Шаблоны проектирования
- Тайм-менеджмент для разработчика
- Библиотека быстрого поиска путей на графе. В библиотеке используется мало-известный вариант A* поиска, который называется NBA*.
Интерфейсы
Что такое "devops"
DevOps = красивое название для ПРОЦЕССОВ активного взаимодействия разработчиков с администраторами (БД и систем) и автоматизаторами тестирования
, которые (процессы) максимально стандартизированы с помощью договорённостей в командах и обеспеченностью сред для разработки
и автоматизированы за счёт использования специальных инструментов поставки, прогона тестов, развёртывания.
В общем случае, счастье достигается за счёт:
-
ускорения и упрощения оргпроцедур по получению техники для разработчика с уже установленной или быстро устанавливаемой/обновляемой IDE и другого необходимого инструментария, а также по получению необходимых сетевых доступов с рабочих станций.
-
упрощения и ускорения процедур по выделению и масштабированию мощностей для стендов, необходимых для развёртывания ПО и его тестирования
, обычно за счёт использования локальных или глобальных облачных решений (Amazon AWS, Google Cloud, Microsoft Azure, SberCloud, Yandex.Cloud)
-
использования средств автоматизации операций для всего процесса поставки (Jenkins, TeamCity, рукописные скрипты)
-
использования средств виртуализации и контейнеризации (Docker, Kubernetes)
- внедрения практики CI/CD/CDP и неизбежно с ней связанной автоматизацией тестов (unit, API, web-API, regress)
- внедрения решений по мониторингу как целых стендов, так и отдельных хостов, ВМ, веб-сервисов и приложений
- перехода на микросервисную архитектуру и service mesh и с тестирование контрактов многочисленных API (если используется модный сейчас gRPC, например)
N.B. В повседневности словом devops чаще обозначают РОЛЬ администратора, который помимо стандартных обязанностей, занимается как раз управлением всеми этими средствами автоматизации поставки CI/CD/CDP (см. ниже), являясь ещё и своего рода support'ом для разработчиков и тестировщиков на допродовских стендах.
Суть CI/CD/CDP
скачать схему в формате diagrams.net (бывший draw.io)
Основная идея CI/CDL/CDP -- создание автоматизированного конвейера поставки продукта заказчику/потребителю за счёт автоматизации:
- чекина изменений в репозиторий
- статического анализа кода: на уязвимости, на соответствие требованиям/стандартам
- компиляции и формирования билда (сборки)
- всех необходимых тестов (unit, smoke, acceptance, regression, integration, end-to-end)
- заведения в СУП issue в случае ошибок
- обратной связи об успехе/неудаче в виде отчётов о билде и уведомлений по выбранным каналам
- слияния изменений с основной веткой в случае "зелёных" тестов
- деплоя на dev/test/staging/prod
Continuous integration, CI = автоматизированная интеграция программного кода в существующий проект в репозитории с последующей компиляцией, формированием сборки и прогоном базовых автотестов.
Считается, что должно занимать <= 10 минут.
Сontinuous delivery, CD = CI + автоматизированная поставка готовой сборки ПО с изменениями на сервера разработки и тестирования с прогоном автотестов.
Сontinuous deployment, CDP = CD + автоматизированное развёртывание изменений в Пром.
Всё это счастье достигается посредством использования таких инструментов как, например, GitLab CI, BitBucket Pipelines, AWS CodeBuild, Bamboo, TeamCity, Jenkins и сильно облегчающей деплои контейнеризации (Docker).
Зачем всё это может быть нужно одиночке?
Один раз помучаться, сделав правильный контейнер и настроив GitLab CI/CD, а потом пушить в нужную ветку, и у тебя через 5 минут все обновилось на рабочих серверах.
Второй проект — чуть меняются скрипты и всё.
Потом вот пример: есть небольшой проект, надо добавить одну мелочь в дороге, ноута с собой нет. Зашел через веб-интерфейс в Gitlab с телефона, поправил, сохранил -- а дальше само всё обновилось!
(c)
комментарий на habr.
VM и Docker
Суть
Контейнер = набор процессов, изолированный от остальной ОС, и запускаемый с отдельного образа, который содержит все файлы, необходимые для их работы (runtime & supporting files). Образ содержит все зависимости приложения и поэтому может легко переноситься из среды разработки в среду тестирования, а затем в промышленную среду.
А разве это не просто виртуализация?
Не вполне:
- Виртуализация обеспечивает одновременную работу нескольких операционных систем на одном компьютере;
- Контейнеры используют одно и то же ядро операционной системы и изолируют процессы приложения от остальной системы.
Разница между Виртуальной машиной и Контейнером
скачать схему в формате diagrams.net (бывший draw.io)
Примеры решений контейнеризации
- Облачные решения:
- Amazon AWS ECS
- Azure Container Service (ACS)
- On-premise решения:
- Оркестрация:
- Docker Engine API
- Kubernetes
- Azure Service Fabric
- Какое-то самописное решение: API-контейнеризация + ручная автоматизация
Контракты API
API = application programming interface = опубликованный программный интерфейс компонента/системы, позволяющий другим компонентам/системам получать доступ к какой-либо функции.
Контракт API = зафиксированная и документированная ответственность поставщика и ожидания потребителя.
Включает в себя две составляющие:
-
Функциональная (сигнатура и семантика):
- Название API
- Входные данные / параметры вызова (протокол, URI)
- Возвращаемые данные
- Семантика (описание функциональности)
- Шаблон интеграционного взаимодействия
- Потребитель
-
Нефункциональная (SLA):
- Доступность (availability, %)
- Время ответа (latency, ms) = время, необходимое приложению, чтобы ответить на запрос
- Пропускная способность (throughput, transactions per second, tps) = количество транзакций (запросов), которое приложение может обработать в течение секунды
- Какие-либо ограничения (по размеру сообщения, безопасности и т.п.)
Обычно контракты API ведут как в Confluence, так и в специальных системах -- реестр API.
CDC (Consumer Driven Contract)
CDC (Consumer Driven Contract) = контракт потребителя сервиса.
Представляет из себя соглашение между сервисом-поставщиком и сервисом-потребителем в том, что
сервис-поставщик обязуется уметь принимать на вход от сервиса-потребителя определённую структуру данных определённых типов, сериализованную JSON/XML/binary/...
и гарантирует возвращать в ответ определённую структуру данных определённых типов, также сериализованную.
скачать схему в формате diagrams.net (бывший draw.io)
CDC фокусируется на поведении и данных, которые важны Потребителю, т.е. требования исходят от Потребителя: мне нужно вот это.
Сам контракт в явном виде описывается с помощью некоторого IDL (interface desciption language), например:
Этот подход когда-то реализован в виде WSDL/WADL-сервисов
, развивался для REST HTTP в виде, например, OpenAPI с его .yaml-файлами контрактов (Contract-First API Development with OpenAPI Generator and Connexion)
, а сейчас его популярность сильно возросла в связи с активным продвижением gRPC и его .proto-файлами контрактов (статьи GRPC сервис на примере генератора паролей и gRPC — фреймворк от Google для удалённого вызова процедур)
Оценка "величины" задачи
Метод трёх точек (3-point estimation)
Метод для расчёта временных затрат в проектах с уникальными задачами в условиях неопределённости и при наличии нескольких типов рисков. Используется в IT достаточно широко.
Для того, чтобы начать применять этот метод, нужно проанализировать предмет доработки и описание реализации. Попытаться провести аналогии с ранее выполненными задачами с похожим скоупом. Определить риски и описать мероприятия по устранению этих рисков (что делаем, если сработал тот или иной риск).
WM = (O + 4*BG + P) / 6
О (opitimistic) - оптимистичное время выполнения задачи, если все пойдет хорошо, т.е. если не наступит ни один из выявленных и зафиксированных рисков.
BG (best guess) - наиболее вероятное время, или средняя продолжительность выполнения аналогичной задачи, при условии выполняли её уже много раз.
Р (pessimistic) - пессимистичное время выполнения задачи, если сработали все выявленные риски.
WM (weighted mean) - взвешенное значение с учетом рисков и последствий воздействия негативных и позитивных факторов.
SD (standard deviation) - стандартное отклонение, используемое для расчета вероятностей.
Как видим, суть метода сводится к тому, что мы предполагаем, что с вероятностью 0.8 всё пойдёт так, как было и ранее в подобных случаях.
Чего позволяет добиться метод трёх точек:
- Точности (используется 3 оценки вместо одной)
- Повышения ответственности членов команды за оценку, поскольку они должны учитывать риски
- Получить описание рисков в каждой задаче
Кастомный метод для T-Shape оценки "размера" задачи
Связан с
методологией Kanban.
Набросокъ:
"Размер" задачи |
Затрагиваемые Бизнес-процессы |
Потребность в степени вовлечения Заказчика и сторонних стейкхолдеров |
Объект доработки - тип компонента ПО |
L |
(список наиболее суровых развестистых бизнес-процессов) |
высокая (почти ничего не известно, размытые бизнес-требования, требуется информация от контрагентов) |
- Интерфейсы (интеграция с новыми Системами)
|
M |
(список бизнес-процессов "средней руки") |
средняя (уже есть вопросы, чуются подводные камни в бизнес-требованиях, нет чётких кейсов воспроизведения ошибки) |
- данные (в БД, файлах)
- формы GUI
- интерфейсы (интеграция с другими Системами)
- периодические задания (SSIS-пакеты, job'ы, cron'ы)
- вспомогательные (плагины, хранимые процедуры SQL)
|
S |
(список коротких прямолинейных бизнес-процессов) |
минимальная (уже всё понятно, и нам сообщено, есть чёткий кейс воспроизведения ошибки) |
- сообытийные процедуры для форм GUI
- те или иные отчёты
- подсистема управления правами
|
Размер задачи оценивать в максимальный из получившихся оценённых параметров, например:
У нас есть
- предполагаются изменения в БП = Регистрация Клиента (S)
- но потребность в вовлечении заказчика = средняя (M)
- и объект доработки = форма GUI, событийные процедуры для форм GUI, данные (M)
, значит оцениваем задачу как М.
Что делаем: оцениваем задачи таким образом, некоторое время накапливаем статистику по времени выполнения оценённых таким образом задач, а далее при планировании мы уже на этапе такой оценки будем знать, что задача L скорее всего будет выполняться за X дней и т.п.
Потенциал для совершенствования: если суммируются несколько признаков одного уровня (например, объекты доработки), то оценка по этому признаку уходит на уровень выше.
Во фронт или в бэк?
Проверка введённых значений на соответствие логическим критериям, а не формальным — это занятие для бэка.
Пример:
- (валидация) проверка что в форму для числа введено число, а не срока — это чистый фронт;
- (верификация) проверка по КЛАДР -однозначный бэк;
И не надо тиражировать единый алгоритм проверки в нескольких местах.
Уровень квалификации
Junior -- тот, кого нельзя оставить без присмотра. Задачу надо разжевать, код придирчиво отревьюить, время от времени узнавать, как дела и поправлять на ходу. Выхлопа от работы джуна ожидать не стоит (т.е. времени он не сэкономит, скорее потратит), но на него можно сгрузить рутину и через некоторое время он подтянется и выхлоп будет.
Middle -- работает работу сам. В задачах тоже разбирается сам, где не может, сам задаёт релевантные вопросы. Кроме ревью кода пригляда за ним не требуется, но и помощи в определении курса тоже не ожидается.
Senior -- автономная боевая единица. Если в него кинуть размытой формулировкой проекта, то он её сам уточнит, ещё и укажет на слабые места и покритикует, подберёт рабочий стек технологий (без оглядки на хайп) и сам в одиночку всё запрограммирует (и за джунами присмотрит). Ещё и заказчика пнёт (возможно, через прокладку-менеджера, если таковая зачем-то есть), что тот ему ещё вчера обещал уточнения к ТЗ прислать.
OOP - базис
Объектно-ориентиированное программирование (ООП) = методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования/
Инкапсуляция = свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. Некоторые языки (например, С++) отождествляют инкапсуляцию с Сокрытием, но большинство (Smalltalk, Eiffel, OCaml) различают эти понятия.
Инкапсуляция обеспечивается следующими средствами:
- Контроль доступа. Поскольку методы класса могут быть как чисто внутренними, обеспечивающими логику функционирования объекта, так и внешними, с помощью которых взаимодействуют объекты, необходимо обеспечить скрытость первых при доступности извне вторых. Для этого в языки вводятся специальные синтаксические конструкции, явно задающие область видимости каждого члена класса. Традиционно это модификаторы public, protected и private, обозначающие, соответственно, открытые члены класса, члены класса, доступные внутри класса и из классов-потомков, и скрытые, доступные только внутри класса. Конкретная номенклатура модификаторов и их точный смысл различаются в разных языках.
- Методы доступа. Поля класса в общем случае не должны быть доступны извне, поскольку такой доступ позволил бы произвольным образом менять внутреннее состояние объектов. Поэтому поля обычно объявляются скрытыми (либо язык в принципе не позволяет обращаться к полям класса извне), а для доступа к находящимся в полях данным используются специальные методы, называемые методами доступа. Такие методы либо возвращают значение того или иного поля, либо производят запись в это поле нового значения. При записи метод доступа может проконтролировать допустимость записываемого значения и, при необходимости, произвести другие манипуляции с данными объекта, чтобы они остались корректными (внутренне согласованными). Методы доступа называют ещё аксессорами (от англ. access - доступ), а по отдельности - геттерами (англ. get - чтение) и сеттерами (англ. set - запись)
Наследование = свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс - потомком, наследником, дочерним или производным классом.
Полиморфизм подтипов (иногда просто - "полиморфизм") = свойство системы, позволяющее использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
Класс - универсальный, комплексный (составной) тип данных, состоящий из тематически единого набора:
- "полей" - переменных более элементарных типов;
- "методов" - процедуров и функций, связанных с классом, для работы с его полями. Они определяют действия, которые можно выполнять над объектом такого типа, и которые сам объект может выполнять. То есть он является моделью информационной сущности с внутренним и внешним интерфейсами для оперирования своим содержимым (значениями полей).
Объект - cущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса.
Взаимодействие объектов в абсолютном большинстве случаев обеспечивается вызовом ими методов друг друга.
Распространённые ошибки
- неосмысленные имена переменных;
- проверка наиболее возможной ситуации находится в конце списка проверок;
- отсутствие проверки "если ничего из указанного";
- отсутствие валидации параметров метода в самом начале метода;
- отсутствие валидации данных до выполнения операции с данными в БД типа update/insert (не отлавливаются пустые значения,..);
- обращение в БД с запросами вида "select * from A" (возвращает очень много данных);
- неоправданное и неаргументированное время жизни при использовании кэшей;
- ошибки с правами доступа (пароли лежат где-то в открытом виде,..);
- глобальные константы в коде классов;
- куча одинаковых(очень похожих) кусков кода не вынесены в функции;
- использование функции, когда не полностью известно(понятно) её предназначение и принцип работы (например, использование функции округления, не интересуясь в какую сторону она округлит);
- отсутствие комментариев на сложных участках;
- подключать/использовать библиотеки/функции дублирующие функциональность друг друга, когда можно было бы обойтись чем-то одним из арсенала;
- оставлять в коммите код, использовавшийся для дебага (может тормозить систему, заполняет логи лишней информацией);
- размещение сложных условий в одну строку (нечитабельно, например t = y && p &&!q&&(!!l)?k?m:n :0);
Никогда не пишите длинных if-ов
- при переборе массивов, особенно двумерных, каждый раз использовать обращение к элементу массива, а не присвоить его значение какой-нибудь переменной и работать с ней в пределах, даёт существенный прирост скорости в часто выполняемых операциях в том числе с клиентской стороны при обхода DOM-дерева, иначе каждый раз у элемента верхнего будет искаться наследник и так далее.
Технологический налог