Здравствуйте, vdimas, Вы писали:
V>Если речь об IDL, то проблемно-ориентированное кодирование всей твоей матрешки идёт вот так:
V>V>enum ClanUpdate { NoUpdate, EnterClan, ExitClan };
V>union ClanEvent switch (ClanUpdate) {
V> case NoUpdate: ;
V> case EnterClan: int ClanId;
V> case ExitClan: ;
V>};
V>
Сразу вопросы:
1) А для обязательных полей ты тоже рекомендуешь объявлять enum и union? Или мы обязательные поля обновляем одним способом, а опциональные другим? Если так, то разве это — не проблема сопровождения? (Для меня одно из базовых требований при выборе паттерна — то, что придет новый человек и сможет сходу решать любую простую задачу "по аналогии".)
2) Вот эти 6 лишних строк и один-два типа на ровном месте
для каждого поля — вот ради чего это? При том, что использоваться в пользовательском коде это богатство и не будет.
V>Итого, для случая выхода из клана тоже достаточно одного байта, а не два, как у тебя сейчас.
У меня сейчас 1 бит в хедере + 1 байт для поля. Свести к двум битам — не проблема, только вот единственным наблюдаемым эффектом будет усложнение документации по бинарному протоколу.
V>Но можно еще проще.
V>Считаем, что "игрок больше не состоит в клане" — это тоже клан такой. Эдакий клан бесклановых игроков.
V>Выдели для него некий отдельный ID.
Это хуже по следующим причинам:
1) Игрок больше не состоит в клане — это не тоже клан такой. Из него выйти нельзя, он в UI не отображается, у него нет ни одного атрибута клана. Я считаю, что если это различие можно выразить в системе типов, то его нужно выразить.
2)
public class Player
{
// 1
public int ClanID { get; private set; }
// 2
public int? ClanID { get; private set; }
}
Нужно проверить, состоит ли игрок в клане. В каком из случаев очевидно, как это сделать, а в каком остается чесать репу?
3) Теперь для каждого случая обновления опционального по своей природе поля мы будем придумывать новый хак?
На самом деле это мы как раз пробовали в первую очередь. Люди плевались и просили Optional<Optional<>>.
V>И далее можно унифицировано обновлять поля в плоском сообщении без геммороя со вложенными Nullable в другие Nullable.
Вот это называется унифицированно? Когда на каждый чих нужно придумывать клан который не клан?
V>Ты в сетку как передаёшь?
V>По байту на признак наличия каждого поля? Если брать IDL, то меньше байта не выйдет, верно?
По биту.
V>В общем, использовать IDL в 2017-м (CORBA IDL небось?) — это вообще признак оторванности от реальности.
А как в 2017 нужно описывать сетевой протокол с поддержкой сериализации для разных языков и форматов и возможностью генерации схемы?
IDL внутренней разработки.
V>И ты на каждое обновление пробегаешься по всем 30-ти полям, что ле, вот в этой манере:
V>V>void Update(XxxUpdate update)
V>{
V> if (update.Field1.HasValue)
V> this.Field1 = update.Field1.Value;
V> if (update.Field2.HasValue)
V> this.Field2 = update.Field2.Value;
V>...
V>
Да. А что именно смущает? Я уже писал, этот код можно сгенерировать.
V>Когда полей посылается много, то можно вначале прогнать битовую маску.
Для дельта-рекордов мы так и делаем.
V>Ну или можно взять какой-нить ASN.1 с хорошим профилём упаковки.
Нельзя. У ASN.1 крайне неудобный язык и нет возможности удобно контролировать кодогенерацию через атрибуты. С сериализацией в JSON или XML тоже беда. А упаковка у нас компактнее и быстрее.
V>А еще лучше самому набросать утилиту генерации сериализатора по метаинформации, раз уж речь о дотнете, благо по состоянию на 2017-й год инфраструктура развита сильно (можно брать BLToolkit как маппер), там трудоемкости, скорее всего, будет меньше, чем возни с сопряжением c каким-нить IDL-фреймворком.
Я писал, что сервер у нас на Эрланге. И вообще, дотнет-клиент (на самом деле Unity3d, у которого до сих пор рантайм 2.0) — лишь один из, кроме него есть большой набор приложений, работающих с данными IDL. Поэтому внешний IDL — это обязательное требование.
Возни с ним нет. Это отработано годами.
V>Через BLToolkit можно сделать так, чтобы код обновления полей вообще ручками писать не надо было.
Так и приведенный код обновления полей я могу сгенерировать скриптом расширения к нашему кодогенератору строк так на восемь. Но хватает и тонкостей, например с обновлением коллекций (а там пока каждый второй случай — частный), поэтому проще в итоге писать руками.
Резюмируя: я просил привести альтернативы и описать проблемы с текущим решением. Две альтернативы ты привел, одна из них очень многословная и спорная (а компенсирующих преимуществ я пока не вижу). Вторая — грязноватый хак, уже опробованный на практике с негативным эффектом. А вот в чем проблема с текущим решением и его якобы тяжелой поддержкой ты так и не объяснил.