Обновить

Комментарии 9

Идея создания нового языка пришла мне в голову, когда я получил задачу описать ТЗ для подрядчика на разработку API. Передо мной встал вопрос: как легко и понятно описать требования к контрактам?

OpenAPI прекрасно читается и некоторые даже код по нему генерят

Если говорить именно о моей задаче описания ТЗ, то да, OpenApi вполне подходил. В том случае я не стал его использовать из-за моего личного к нему отношения. Я не считаю его читабельным.

Если говорить в общем о сравнении OpenApi и Scedel, то:

  • OpenApi протоколо-центричный. Это прекрасно для описания REST-апи, однако ограничивает его использование;

  • OpenApi использует YAML, что с одной стороны хорошо, так как YAML - это устоявшийся формат, с которым умеют работать все системы. С другой стороны, из-за подчинения синтаксису YAML, OpenApi становится очень объемным в описании сложных схем (такая же проблема, как и в JSON Schema)

Зачем разделение на типы и валидаторы? Как из нескольких валидаторов собрать один? Почему параметры валидаторов то в квадратных то в круглых скобках?

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

Несколько валидаторов в один сами по себе не собираются. Валидатор присоединяется к типу как констрейнт. Можно сказать, что пользовательский тип - это базовый тип + констрейнты. На тип можно навесить несколько констрейнтов:

validator String(alphaOnly) = this matches /[a-zA-z]+/
type Username = String(alphaOnly, min:3, max:10)

Здесь я навесил на тип три констрейнта (один пользовательский и два встроенных), и, для удобства использования, дал этому сложному типу алиас

Как к этому алиасу добавить еще один констрейнт?

Это хороший вопрос, спасибо!

Изначально я планировал, что создавать валидаторы можно только для базовых простых скалярных типов.

Теоретически, можно было бы сделать так:

Username(anotherConstraint)

Но не уверен, как сейчас отреагируют на такое библиотеки, и это не описано в RFC.

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

Констрейнты в квадратных скобках - специфичные для массивов ограничения

Email(domain:'gmail.com')[min:1]

Здесь описан массив, состоящий из элементов типа Email(domain:'gmail.com'), в котором должен быть минимум один элемент. Можно написать чуть по-другому, так будет нагляднее

type GmailEmail = Email(domain:'gmail.com')
type User = {
  emailsList: GmailEmail[min:1]
}

Первым делом я подумал о JSON Schema, однако из-за её многословности я решил отказаться от неё, на мой взгляд, она недостаточно человекочитаема.

Интересный проект. Однако я год назад подумывал создать свой DSL, и проблема таких кастомных решений - это сложность их последующего расширения если вдруг понадобится использовать его для более широких целей, и такие языки к сожалению, становятся заложниками узких кейсов применения. Что касается JSON Schema то она и не призвана быть малословной, а скорее наоборот, многословность обусловлена высоким охватом практически любого кейса. И я не знаю какой кейс JSON Schema неспособна покрыть при должном знании спецификации. Разве что GraphQL и gRPC (но это отдельная история). Для удобства чтения - есть Swagger UI который идеально подходит для чтения.

Но, тем не менее, желаю успехов!

Спасибо!

Отмечу, что JSON Schema и Scedel не совсем конкуренты.

JSON Schema - это, в первую очередь, язык описания правил валидации.

Scedel - это язык для моделирования типов и контрактов, а валидация - это побочное свойство.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации