философия-разработки-программного-обеспечения
Что он делает
Используйте при написании, изменении или проверке кода, когда изменение добавляет экспортируемое или импортируемое имя, создает модуль, класс, компонент, помощник, хук, сервис или обертку, централизует повторяющийся код или изменяет API. Правила Оустерхоута (глубокие модули, сокрытие информации, снижение сложности) плюс инвариантный тест для совместного использования кода, тест стоимости для читателя и обязательная заметка о дизайне в конце.
Установка открывает эту карточку в вашем десктопном приложении AgentsRoom. Если приложение ещё не установлено, вы попадёте на страницу загрузки.
SKILL.md
--- name: философия-разработки-программного-обеспечения description: Используйте при написании, изменении или проверке кода, когда изменение добавляет экспортируемое или импортируемое имя, создает модуль, класс, компонент, помощник, хук, сервис или обертку, централизует повторяющийся код или изменяет API. Правила Оустерхоута (глубокие модули, сокрытие информации, снижение сложности) плюс инвариантный тест для совместного использования кода, тест стоимости для читателя и обязательная заметка о дизайне в конце. --- # Философия проектирования программного обеспечения (Джон Оустерхоут) ## Когда использовать этот навык Используйте этот навык, когда вы проектируете, пишете, изменяете или проверяете код. Он применим к проектированию модулей, изменениям API, декомпозиции, рефакторингу, именам, комментариям, тестам и работе с производительностью. Используйте его также, когда изменение кажется неудобным или когда одно изменение распространяется на многие файлы. ## Смещение, которое нужно исправить Рабочий код не равен простому коду. Маленькие части, знакомые шаблоны, флаги, обертки и дополнительная документация могут усложнять дизайн. Они делают это, когда добавляют то, что читатель должен знать, или когда «протекают» знания в другие модули. ## Правила принятия решений - Оценивайте дизайн по тому, насколько он снижает сложность. Предпочитайте дизайн, который уменьшает нагрузку на читателя. Сложность проявляется в четырех признаках. Одно изменение требует правок во многих местах. Зависимости скрыты. Шаги должны выполняться в фиксированном порядке. Читатель должен держать в уме много фактов. - Рассматривайте дизайн как непрерывную работу. Первый патч, который работает, не закончен, если он усложняет последующие изменения. Для решения по интерфейсу, разделению модуля или абстракции сравнивайте два или более возможных дизайна. - Предпочитайте глубокие модули. Глубокий модуль имеет небольшой интерфейс и скрывает большое количество сложности. Отказывайтесь от проходных сервисов, тонких оберток библиотек и маленьких вспомогательных модулей. Отказывайтесь от любого выделения, которое добавляет имена, но не снижает нагрузку на читателя. - Проектируйте интерфейс вокруг того, что должен знать вызывающий, а не вокруг того, как работает реализация. Избегайте хрупких последовательностей настройки, флагов режимов, конфигурационных переключателей и аргументов, которые показывают внутренние выборы. - Скрывайте решения, которые могут измениться. Примеры: внутренние представления, форма хранения, протоколы, форматы файлов и трюки с производительностью. Ведение учета, нормализация и крайние случаи: другие примеры. Держите каждое из них внутри модуля, который владеет этими знаниями. - Переносите сложность вниз в модуль, который владеет деталями. Принимайте более сложную реализацию, если она дает вызывающим более простой контракт и убирает повторяющуюся работу с каждого места вызова. - Делайте модуль общим на правильном уровне. Не подгоняйте модуль под одного вызывающего. Не добавляйте расплывчатую абстракцию для будущих нужд. Держите редкие крайние случаи вне основного пути и помещайте особое поведение в отдельное место. - Объединяйте или разделяйте модули по общей сложности. Не объединяйте и не разделяйте их по размеру, по порядку выполнения кода, по привычке или по внешнему виду. Держите связанные состояние, поведение, правила и решения вместе. Разделяйте их только тогда, когда новая граница глубже, и читатель может понять каждую сторону отдельно. - Делайте множество исключений меньше. По возможности изменяйте интерфейс или правила так, чтобы недопустимые состояния не могли возникать. Не заставляйте каждого вызывающего повторять один и тот же защитный код. - Используйте комментарии для снижения сложности. Записывайте контракты интерфейса, правила, которые должны оставаться верными, скрытые решения дизайна и их причины. Также записывайте сложные факты, которые вызывающие не должны знать. Не повторяйте код в комментарии. Не используйте комментарий, чтобы скрыть плохое имя, плохое разделение или запутанный поток управления. - Рассматривайте имена, согласованность и ясность как информацию о дизайне. Имя сообщает читателю абстракцию, а не механизм. Связанные операции используют одни и те же соглашения. Код, который удивляет читателя, добавляет сложность, даже если он короткий. - Пишите тесты против публичных контрактов и стабильных API. Тестируйте скрытую сложность и особые случаи через эти контракты. Не позволяйте удобству теста заставлять делать поверхностный или протекающий интерфейс. - Добавляйте изменение производительности, паттерн, парадигму или фреймворк только по одной из двух причин. Это снижает сложность в этой кодовой базе или есть доказательства, что компромисс необходим. Скрывайте каждую оптимизацию за стабильным интерфейсом. ## Сигналы и реакция на каждый из них - Функция неудобна, или одно изменение распространяется по файлам, или рецензент должен искать скрытые зависимости. Реакция: ищите отсутствие сокрытия информации и мелкие модули. Также ищите шаги в фиксированном порядке и сложность, которую несут вызывающие. - Вы добавляете модуль, слой, сервис, помощник, обертку или фасад. Или добавляете паттерн, опцию, обратный вызов или аргумент. Реакция: покажите, что это скрывает больше сложности, чем добавляет. - Вы меняете API. Реакция: проверьте, что должен знать обычный вызывающий. Вызывающему не нужно знать порядок вызовов, представление или хранение. Вызывающему не нужно знать транспорт, кэш, протокол или формат файла. Вызывающему не нужно знать внутренний рабочий процесс или множество шагов настройки. - Вы добавляете особый случай, флаг, путь исключения, условие или контейнер, который видят вызывающие. Реакция: сначала спросите, что может сделать владеющий модуль вместо этого. Он может убрать недопустимое состояние, изолировать необычное поведение или дать более сильную операцию. - Вы разделяете код, выделяете функцию или добавляете переменную. Реакция: проверьте, что новая граница или имя несут смысл. Они не должны только добавлять переходы, состояние, которое проходит, или промежуточные шаги, которые видят вызывающие. - В коде есть фазы, такие как `prepare`, `process` и `finalize`, или вызывающие должны строить объекты поэтапно. Реакция: проверьте, что порядок времени: это реальная концепция. Если нет, организуйте код вокруг стабильных обязанностей. - Имя расплывчато, называет механизм, не согласовано или удивляет читателя. Реакция: подумайте снова о границе абстракции. Не принимайте имя, которое почти правильное. - Комментарий длинный, повторяет код, объясняет запутанный интерфейс или показывает внутренности для объяснения использования. Реакция: измените абстракцию или перенесите отсутствующий контракт в интерфейс. - Вы оптимизируете производительность. Реакция: сначала измерьте, затем скройте оптимизацию. Не отказывайтесь от глубины модуля или сокрытия информации без доказательств, что компромисс необходим. - Вы тестируете или проверяете. Реакция: смотрите на публичное поведение и контракты интерфейса. Также смотрите на скрытую сложность за стабильными API и на особые случаи, скрытые за абстракцией. ## Итоговый чеклист - Снижает ли изменение усилия на понимание, изменение, проверку и расширение системы? - Скрывает ли каждый элемент интерфейса, обертка, слой, помощник, опция и имя достаточно сложности, чтобы это было оправдано? - Находятся ли важные решения в одном месте? Видны ли зависимости? Записаны ли ограничения, которые должны знать вызывающие? Защищены ли внутренние части, которые могут изменяться? - Работают ли распространённые случаи без дополнительных шагов? Остаются ли редкие элементы управления, особые случаи, трюки с производительностью и детали исключений вне общего пути? - Точные и последовательные ли имена? Актуальны ли комментарии, без повторения кода? Следует ли код существующим соглашениям, если только новая информация не дала причины их изменить? ## Gate Используйте полный чеклист, когда изменение добавляет имя, которое может экспортировать или импортировать другой код. Используйте его также, когда изменение создаёт модуль, класс, компонент, помощник, хук, сервис или обертку, либо помещает повторяющийся код в одно место. Переименования, codemods, изменения конфигурации, изменения данных и однострочные исправления не требуют этого. ## Тест инварианта: делитесь только кодом, который меняется вместе - Извлекайте общий код только тогда, когда он защищает правило, которое вы можете назвать. Доказательством является совместное изменение: история показывает, что копии исправлялись или менялись вместе. Код, который только похож и меняется независимо,: это рифма. Оставляйте рифмы как дубликаты. Три похожих блока не доказывают правило. - Исправление должно устранять проблему, а не переносить её. Шесть приведений типов, объединённых в один универсальный помощник, всё равно остаются шестью приведениями. Напишите типизированный маппер, который скрывали приведения. - Если абстракция неверна, верните код обратно в линию и позвольте дублированию вернуться. Не искажайте абстракцию флагами. - Не разделяйте код только из-за его размера. Один модуль на 400 строк, скрывающий одно решение, лучше, чем четыре модуля по 100 строк, которые протекают одинаковыми соединениями. - Механическое чтение Clean Code или SOLID (очень маленькие функции, один класс на каждую ответственность) даёт поверхностные модули. Этот навык имеет приоритет над этим давлением. ## Стоимость для читателя: третий тест Тест глубины и тест инварианта решают, должна ли существовать граница. Тест стоимости для читателя решает, насколько легко менять код вокруг границы. Следующий читатель, человек или агент, платит за каждую строку, которую должен прочитать. Агент платит токенами. Агент находит код через текстовый поиск, частичное чтение, проверку типов и тесты. - **Находимость.** Используйте одно имя для каждой концепции. Пишите его одинаково везде, чтобы простой текстовый поиск находил его. Дефекты: имена, построенные из строк, проводка через побочные эффекты импорта, два имени для одной концепции. Цепочки реэкспорта, скрывающие определение, тоже дефекты. - **Раннее прекращение.** Поместите контракт в начале файла или над экспортом. Скажите, что он обещает, что скрывает и что никогда не делает. Тогда читатель может остановиться раньше. - **Проверяемость машиной.** Используйте точные типы на входе и выходе каждой границы, чтобы проверка типов заменяла чтение вызывающих. Дефекты: `any`, простые словари, булевы флаги, смысл которых только в теле. - **Видимая связность.** Два места должны меняться вместе. Обеспечьте это общим типом, тестом или одним источником. Если не можете, отметьте это в обоих местах. - **Отсутствие шума.** Удаляйте комментарии, повторяющие код, и закомментированный код. Удаляйте мёртвые ветки и комментарии с историей изменений. Удаляйте старый путь, который остаётся рядом с заменой. - **Предсказуемость.** Следуйте существующей структуре репозитория. Поместите тест там, где его ищет читатель, и сделайте так, чтобы он запускался отдельно. Размер файла в этот список не входит намеренно. Очень большой файл: повод искать второе скрытое решение. Никогда не повод резать файл. ## Безопасность Для существующего кода сначала напишите тест, который фиксирует текущее поведение. Затем сделайте модуль глубже. Для нового кода напишите тест, который определяет желаемое поведение. ## Заметка по дизайну (обязательно, когда применяется gate) Когда применяется gate, добавьте раздел с заголовком `## Design note` в описание pull request. Напишите две-четыре строки: - Каждую добавленную границу и решение, которое она скрывает. - Каждое дублирование, которое вы оставили намеренно, и причину. - Каждую поверхностную часть, которую вы приняли, и причину. Если gate не применяется, напишите `## Design note`, а затем `Gate not applicable: <причина>`. Также добавьте заметку по дизайну в резюме вашего финального шага. ## Режим ревью Используйте этот раздел, когда вы проверяете или тестируете код, написанный другим агентом или человеком. 1. Проверьте заметку по дизайну. Если применяется gate и в pull request нет раздела `## Design note`, сообщите о блокирующем замечании. Если заметка не совпадает с диффом, сообщите о блокирующем замечании. 2. Замечание по дизайну блокирующее только если выполняются оба условия: - Оно называет правило этого навыка. Правило: это правило решения, gate, тест инварианта или пункт стоимости для читателя. - Оно указывает конкретную стоимость для читателя или для следующего изменения. Примеры: «Вызывающие должны знать форму хранения.» «Одна концепция имеет два имени.» «Изменение ограничения требует правок в трёх файлах.» 3. Все остальные замечания по дизайну отмечайте как неблокирующие. Поместите их в отдельный список с заголовком «Неблокирующие заметки по дизайну». Неблокирующая заметка никогда не возвращает работу обратно разработчику. 4. Не сообщайте предпочтения как замечание. Другое имя, расположение файла или стиль: это предпочтение. Оно становится замечанием только если нарушает названное правило и имеет конкретную стоимость. 5. Если то же замечание по дизайну возвращается во втором цикле ревью, эскалируйте его. Не запрашивайте одно и то же изменение в третий раз. ## Связанные навыки (при установке) - `find-shared-code`: поиск только с отчётом по недавней истории для кода, который стоит выделить. Использует тест инварианта и тест глубины этого навыка. - `refactoring` и `working-effectively-with-legacy-code`: безопасные шаги к более глубокой архитектуре. Этот навык решает, останется ли новая граница. ## Источник и лицензия Этот навык основан на «мини»-правилах из книги A Philosophy of Software Design в репозитории ciembor/agent-rules-books на GitHub (лицензия MIT, коммит 893a88a). Ворота, тест инварианта, тест стоимости для читателя, заметка о дизайне и режим обзора являются дополнениями к этим правилам. В репозитории также содержатся полные правила из книги.
Теги
Полезные материалы
Claude Ads: навык Claude Code, который проводит аудит ваших рекламных аккаунтов
Claude Ads: открытый навык для Claude Code. Более 250 проверок в Google, Meta, LinkedIn, TikTok или Amazon Ads, оценка по 100-балльной шкале и приоритизированный план действий примерно за десять минут. Установка, команды, ограничения и как встроить его в AgentsRoom.
AGENTS.md: один файл контекста для любого агента-кодера (Codex, Antigravity, Claude)
AGENTS.md: переносимый файл инструкций, который твои агенты-кодеры читают, прежде чем трогать код. Что в него класть, чем он отличается от CLAUDE.md и как держать единый контекст для Codex, Antigravity и Claude.
Скачать AgentsRoom
Запускай всех своих ИИ-агентов во всех проектах из одного окна.
Приложение-компаньон: следите за агентами на ходу
Используйте Claude, Codex, Antigravity CLI или другого поставщика AI.
Отправляйте баги и запросы прямо в ваш публичный бэклог.