TL;DR: автор проработал в компании с открытой политикой разработки около 11 лет и с чем-то согласен, с чем-то нет. Не то чтобы я был евангелистом или автором этих правил (за мной там только незначительная редактура), но если я буду выстраивать где-то разработку в будущем, я во многом буду полагаться на них, с изменениями не более 30-40%.

Человеческие природа, ограничения и восприятие

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

Даже если надменно свести это к “считай ближнего своего тупее себя”, можно сделать из этого вывод - “подумай о том, чтобы даже он понял, что ты сделал и не приходил к тебе с вопросами”. Можно и эгоистичный вариант отсюда вывести, если заменить “ближнего своего” на “будущего себя”.

Это касается комментариев к коммитам - я стараюсь сгружать в них контекст, ответы на вопросы “почему” и “зачем”. Увы, иногда забываю отредактировать дефолтное сообщение git merge –squash и вся эта информация из сквашенных коммитов теряется. В целом цель такого подхода - “подстелить соломку” будущим разработчикам, которые будут работать с моим кодом и задаваться вопросами “какого чёрта”.

Приоритеты: Люди, Разработчики, Машины

Приоритет при выборе решений:

  1. Сначала удобство для пользователей
  2. Потом удобство для программистов
  3. И только в крайнем случае приоритет оптимизации для компьютера.

Олег 2017

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

Олег 2022

Еее, никакого больше программирования в контексте ядра, kernel panic и починок зависающих при старте серверов через IP-KVM.

На самом деле надёжность уровня 99.99% нужна в 1% случаев. В остальных случаях она обеспечивается выбором максимально стандартных инструментов, а не усилиями разработчиков прикладного кода и это хорошо. Это как надёжность для ракет (сложно и приходится возиться, а если что-то пошло не так все охреневают) и надёжность продукции АвтоВАЗ - да, иногда ломается, но ремонтопригодно. Если дополнить это с помощью костылей инструментами статистического анализа и исчерпывающими автотестами итд - жизнь просто сказка.

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

Человеческая природа важнее математической гармонии

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

Олег 2017

Математика = логика, логичное = продуманное, продуманное как правило = короткое. Короткое = читаемое. Я не видел нечитаемых математически стройных программ, но видел много непродуманного нечитаемого ада, куда тяп ляп было налеплено сбоку куча всего.

Олег 2022

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

Касательно же математической стройности принцип очень близок к этому куску python zen:

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

И я даже нашёл пример. Иногда развернуть цикл из 3-5 элементов, который отлично лёг бы в list comprehension с какой-нибудь строковой операцией - лучше для читателя, пусть даже код занимается тупым перекладыванием из пустого в порожнее:

params = {
    host: config.SOME_HOST,
    user: config.SOME_USER,
    password: config.SOME_PASSWORD
}

Код выше - лучше, чем:

params = {key: getattr(config, 'SOME_' + key for key in ['host', 'user', 'password']}

Математически может быть и стройно, DRY сияет, но KISS страдает.

Compatibility with low skills, low barrier to entry

и процесс и архитектура и код должны быть простые и понятные даже новичку студенту или школьнику.

Олег 2017

Вопрос что делать с incompatibility with high skills в таком случае. С кодом проще - можно использовать автоматические тулзы shellcheck/clang-checker/pylint + pre_commit для того, чтобы вовремя получать напоминания о том, что городишь сложную херню, поглядывать на размер файлов и всё такое.

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

  • мы начали продумывать архитектуру
  • у нас уже есть рабочий код средней запущенности и мы хотим стать понятны школьнику
  • у нас уже есть рабочий код сильной запущенности и мы хотим стать понятны школьнику

были бы в этой доке очень даже в тему.

Олег 2022

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

Время жизни ПО и технологий ограниченно

разрабатывать 5 лет, чтобы потом 1 год использовать - это глупость, соотношение должно быть 1 год к 5 минимум.

Олег 2017

К несчастью, в своей жизни не видел примеров жизни ПО (принесения выгоды) после прекращения разработки.

Олег 2022

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

Достаточно 80% качества, 100% это зло и потеря времени

20 и 80 процентов качества легко перепутать, как и любое другое значение ниже 99%.

Принципы и правила, вытекающие из аксиом

Об оптимизациях

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

Олег 2017

В принципе всё верно, но меня вот рынок сейчас заставил :)

Олег 2022

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

В случае разработки бэкенда внутренних сервисов ответить на этот вопрос значительно легче. Когда дело касается коробочного ПО, если за оборудование платит клиент - всё усложняется, но об этом хотя бы думают. Когда дело касается SaaS и того, насколько ПО нагружает клиентский браузер - всё ещё сложнее, но об этом думают редко.

Кирпичики

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

Для меня “кирпичик” = минимальный отлаживаемый по отдельности элемент, строчка или языковая конструкция, если угодно. Непроверенный кирпичик может обрушить всё здание. Этот не означает что нужно проводить аудит сверху донизу каждой используемой библиотеки, но библиотеки и модули - тоже в каком-то роде кирпичики.

Чуть более хардкорная версия принципа

Написал строчку кода проверь, не проверил - пишешь объяснительную.

Это не про покрытие тестами в 100%, но про разумный компромисс в виде “хотя бы раз руками запусти строчку и убедись, что код в неё вообще попадает”.

Ошибкоустойчивость

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

Шо поделать с SEGFAULT в ядре или set -eu?:) Но вообще да, пытаться работать до последнего, не получилось так, попробуем сяк - относительно адекватный режим для продакшна.

Отказоустойчивость

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

Главное не забыть, что ошибок может быть много и это может забить диск и привести к ещё большим проблемам. Ротация ошибок - один из вариантов (keep first 10000 and last 10000 errors например).

Plaintext

Все должно быть максимально текстовое и человекочитаемое. Протоколы, команды, конфиги, отладка и логи.

Олег 2017

Но структура этих данных должна быть хоть как-то типизирована, потому что иначе это PHP и vTiger и ад, что будет приводить к переименованию переменных между уровнями и всё такое.

Олег 2022

__repr__ делает br-r-r и никаких противоречий со структурированием.

UUID

У меня в голове не до конца сформулирован подход к использованию UUID объектов в качестве основного идентификатора объектов в базах данных. В случае если присутствует человекочитаемый уникальный идентификатор в виде имени объекта, данного ему человеком - нужен ли UUID? UUID’ы портят человеко-ориентированность, но заданные пользователем идентификаторы тяготеют к тому, чтобы быть изменяемыми. Изменять идентификатор объекта плохо, потому что будет тяжело отследить его историю. Возможно автоинкрементируемый неизменяемый числовой идентификатор, который наглядно присутствует в интерфейсе - лучшее, что придумало человечество.

“Громкость” программы

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

Олег 2017

Вываливать в логи питоновые трэйсбэки на каждый чих?

Олег 2022

ДА, ТЫСЯЧУ РАЗ ДА.

Не разобрано

Все строить не из принципа красиво и логично, в из принципа понятно для человека и удобно.

Опять не вижу противоречия между этими двумя вариантами.

Живые легкие простые программы. Непрерывная разработка, микроитерации. Подробные стандартизированные логи, особенно при сбоях, возможность легкого дебага и отладки. Простота доработки и разработки в тч на лету Гибкость все можно переопределять через хуки и тп НЕ экономим память и процессор скорость и простота разработки важнее оптимальности работы программ.

Стандартизированные логи - вот за это бы на практике взяться и как-то забороть всю эту кашу.

Социальные приоритеты. (Комфорт для программистов и для пользователей. Agile в разработке и бизнесе)

Тут всё ок, да.

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

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

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

Тут всё ок, да. Только как-то мимо меня прошло :D

Учитываем что программирование это 10-15% времени, остальное отладка, тестирование и поиск багов.

Дай бог 5%. Ещё проблемы клиентов вообще не связанные с кодом продукта есть.

Автотесты и тесты обязательны.

Gitlab CI мне запилил бы кто ещё, а то куча тестов есть, а нормально гонять её не выходит.

Взаимный кодревью обязателен.

Тут всё ок, да.

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

Угу, в итоге пишем свой ansible в биллинге :)

Безопасность на этапе проектирования ДА, на этапе разработки только в крайних случаях и разумных пределах. Лучше использовать готовые проверенные средства безопасности, чем придумывать свои. Безопасность. Многоуровневая безопасность. Взлом одной части не должен давать полный доступ. Превентивная безопасность, предполагать что взлом будет одного из уровней и делать защиту для тех дыр которых еще нет. Понимать, что общая безопасность равна безопасности самого слабого звена.

Тут у меня небольшая бомбёжка:

#linux #selinux ### отключить selinux
#linux #selinux echo 0 > /selinux/enforce
#linux #selinux vi /etc/selinux/config
#linux #selinux SELINUX=disabled
#linux #selinux SELINUXTYPE=targeted
#linux #selinux SETLOCALDEFS=0

Конфиги и данные и задачи важнее, чем алгоритмы. Алгоритмы можно потом заменить.

Тут всё верно. Но вот с тулингом у наших конфигов - грустновато.

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

У гугла в srebook описывается похожий подход, что мне очень даже нравится. Они называют это автономными системами (а не автоматизированными).

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

Документация должна быть в коде

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

В каком случае делать рефакторинг и улучшения программы: только если она будет использоваться еще 3 года.

Ок.

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

Ещё бы учитывать суммарное время, отнимаемое разными рутинами у человека.

Автоматизация процесса разработки важна в первую очередь для освобождения мозга программиста и только во вторую для экономии времени. Цикл от строчки кода до отладки и теста не должен быть больше 1-3 секунд, от кода до чистового тестирования дистрибутива не более 1-10 минут. Поэтому разрабатывать лучше с rsync на рабочую среду и тестировать сразу и все это скриптануть. Не нужно собирать весь дистрибутив для теста одной программки.

Разумно. Ещё бы все эти “скриптануть” было запроектировано как делать, где хранить и всё такое (в репе, не в репе, как менеджить куда rsync, ip, ssh-ключи), а ещё лучше было бы более менее универсально расписано. В голову лезут хуки сборки, приведённые к тупо конфигам, но это маловероятно в реальном мире.

Тестирование и отладка максимально близко к среде использования и данным использования и объему использования.

Четыре чая этому господину. Однако не стоит забывать, что чем ближе исполнение кода к десктопу разработчика, тем быстрее разработка. А на десктопе абсолютно аналогичную среду не получить. + лично меня корёжит сложность разработки вдали от офиса и без интернета (без виртуалки никак, а крутить виртуалку на ноутбуке - боль).

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

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

Тесты должны тестировать в тч время и ресурсы и если они утекли тест файлед.

У меня были не совсем тесты, а сбор статистики по времени работы. В принципе к ним прикрутить алертер можно было, но тут всё надо правильно запускать, обновлять и правильно запускать (многие вещи зависят друг от друга). В принципе если выделить время и обновить gitlab, чтобы всем этим рулил CI - могу запилить.

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

@ chroot’ы в PL5

Контроль версий и сборка их исходников, TDD

Ок

Проект должен быть международным, желательно комменты писать на русском и английском

Проект должен быть международным, желательно комменты писать на русском

Проект должен быть, желательно комменты писать на русском

Проект должен быть, желательно комменты писать

Проект должен быть, желательно писать

Проект должен быть

Шутка с долей правды. Энивэй, писать комменты на двух языках - зло, либо английский, либо русский, либо оба варианта в доке, но не в коде.

На этапе разработки и первого года внедрения, технологичность и динамика развития важнее, чем стабильность и надежность, даже в ущерб количеству клиентов

Разумно.

TODO

Описать unix style, new unixstyle git, примеры и почему это правильно

Описать почему зло создавать лишние уровни абстракций

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

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

Глобальные переменные и глобальные конфиги и готу иногда зло это хорошо

Единственные три места, где глобальные переменные хорошо - то, где они:

  1. readonly
  2. счётчики в С
  3. что угодно в bash-скрипте на меньше, чем 20 строчек.

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

Про GOTO в качестве средства для попадания в очистку ресурсов при нормально и аварийном сценарии - на ура рефакторится и становится ненужным в 95% случаев с помощью разбиения кода на относительно “чистые” функции меньшего размера.

От простого к простому, чтоб реализовать сложное

А как иначе?