В начале прошлого года мне пришла в голову идея написать собственный язык интерфейсов (IDL), который был бы похож на Protobuf или Thrift, но предназначался бы для веба. Я надеялся закончить его где-нибудь месяца за три. До первой стабильной версии прошло чуть больше года.
Pdef (пидеф, protocol definition language) — это статически типизированный язык описания интерфейсов, который поддерживает JSON и HTTP RPC. Он позволяет один раз описать интерфейсы и структуры данных, а потом сгенерировать код для конкретных языков программирования. Пидеф подходит для публичных апи, внутренних сервисов, распределенных систем, конфигурационных файлов, как формат для хранения данных, кеша и очередей сообщений.
Основная функциональность:
- Развитая система пакетов, модулей и пространств имен.
- Поддержка циклических импортов и зависимостей типов (с некоторыми ограничениями).
- Простая система типов, основанная на четком разделении интерфейсов и структур данных.
- Наследование сообщений (аналог struct'ов) и интерфейсов.
- Поддержка цепочек вызовов, например,
github.user(1).repos().all()
. - JSON как формат данных и HTTP RPC для передачи данных.
- Возможность использовать другие форматы и RPC.
- Подключаемые кодогенераторы (официально поддерживаются Java, Python и Objective-C).
- Опциональность кодогенерации, т.е. Пидеф позволяет сериализовать данные и отправлять запросы руками.
Зачем нужен Пидеф? В первую очередь для повышения производительности труда и упрощения разработки и поддержки клиент-серверного, сервисно-ориентированного и распределенного кода. Но он также объединяет документацию и описание апи и позволяет строить вертикально-интегрированные системы, в которых снижены накладные расходы на взаимодествие отдельных компонентов.
Пример описания сообщения:
message Human {
id int64;
name string;
birthday datetime;
sex Sex;
continent ContinentName;
}
Примеры использования (примеры сгенерированного кода):
{
"id": 1,
"name": "Ivan Korobkov",
"birthday": "1987-08-07T00:00Z",
"sex": "male",
"continent": "europe"
}
Human human = new Human()
.setId(1)
.setName("John")
.setSex(Sex.MALE)
.setContinent(ContinentName.ASIA)
String json = human.toJson();
Human another = Human.fromJson(json);
human = Human(id=1, name="John")
human.birthday = datetime.datetime(1900, 1, 2)
s = human.to_json()
another = Human.from_json(s)
Human *human = [[Human alloc]init];
human.id = 1;
human.name = @"John";
human.sex = Sex_MALE;
human.continent = ContinentName_EUROPE;
NSError *error = nil;
NSData *data = [human toJsonError:&error];
Human *another = [Human messageWithData:data error:&error];