Соглашение вместо конфигурации (также известное как кодирование по соглашению ) — это парадигма проектирования программного обеспечения , используемая программными фреймворками , которая пытается уменьшить количество решений, которые разработчик, использующий фреймворк, должен принять, не обязательно теряя при этом гибкости и принципов « не повторяйся » (DRY). [1]
Эта концепция была введена Дэвидом Хайнемайером Ханссоном для описания философии веб-фреймворка Ruby on Rails , но связана с более ранними идеями, такими как концепция «разумных значений по умолчанию » и принцип наименьшего удивления в дизайне пользовательского интерфейса .
Фраза по сути означает, что разработчику нужно указать только нестандартные аспекты приложения. Например, если в модели есть класс Sales, соответствующая таблица в базе данных по умолчанию называется "sales". Только если отклониться от этой конвенции, например, таблица "product sales", нужно написать код относительно этих имен.
Когда соглашение, реализованное инструментом, соответствует желаемому поведению, он ведет себя так, как и ожидалось, без необходимости писать файлы конфигурации. Только когда желаемое поведение отклоняется от реализованного соглашения, требуется явная конфигурация.
Использование этой фразы в Ruby on Rails в частности сосредоточено на структуре файла проекта и каталогов по умолчанию, что избавляет разработчиков от необходимости писать файлы конфигурации XML для указания того, какие модули должна загружать фреймворк, что было распространено во многих более ранних фреймворках.
Недостатки подхода «соглашение вместо конфигурации» могут возникать из-за конфликтов с другими принципами проектирования программного обеспечения, такими как принцип Zen of Python «явное лучше неявного». Программная структура, основанная на соглашении вместо конфигурации, часто включает в себя предметно-ориентированный язык с ограниченным набором конструкций или инверсию управления , в которой разработчик может влиять на поведение только с помощью ограниченного набора хуков , и оба эти фактора могут усложнить реализацию поведения, которое нелегко выразить с помощью предоставленных соглашений, по сравнению с использованием программной библиотеки , которая не пытается уменьшить количество решений, которые должны принимать разработчики, или требует инверсии управления.
Другие методы уменьшения количества решений, которые необходимо принять разработчику, включают идиомы программирования и библиотеки конфигурации с многослойной архитектурой .
Некоторым фреймворкам требуется несколько файлов конфигурации, каждый со множеством настроек. Они предоставляют информацию, специфичную для каждого проекта, начиная от URL-адресов и заканчивая сопоставлениями между классами и таблицами базы данных. Многие файлы конфигурации со множеством параметров часто трудно поддерживать.
Например, ранние версии Java persistence mapper Hibernate сопоставляли сущности и их поля с базой данных, описывая эти отношения в XML-файлах. Большая часть этой информации могла быть раскрыта путем традиционного сопоставления имен классов с идентично названными таблицами базы данных , а полей — с их столбцами соответственно. Более поздние версии отказались от XML- файла конфигурации и вместо этого использовали эти самые соглашения, отклонения от которых можно было указать с помощью аннотаций Java (см. спецификацию JavaBeans, ссылку на которую можно найти ниже).
Во многих современных фреймворках используется подход , основанный на соглашениях, а не на конфигурации .
Однако эта концепция более старая, восходит к концепции default и может быть замечена в последнее время в корнях библиотек Java . Например, спецификация JavaBeans в значительной степени опирается на нее. Процитируем спецификацию JavaBeans 1.01: [2]
«Как правило, мы не хотим изобретать огромный класс java.beans.everything, от которого людям придется наследовать. Вместо этого мы хотели бы, чтобы среды выполнения JavaBeans обеспечивали поведение по умолчанию для «нормальных» объектов, но позволяли объектам переопределять заданную часть поведения по умолчанию путем наследования от некоторого конкретного интерфейса java.beans.something».