Re[5]: Опциональные типы
От: meadow_meal  
Дата: 23.02.17 09:49
Оценка: +1
Здравствуйте, 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 можно сделать так, чтобы код обновления полей вообще ручками писать не надо было.


Так и приведенный код обновления полей я могу сгенерировать скриптом расширения к нашему кодогенератору строк так на восемь. Но хватает и тонкостей, например с обновлением коллекций (а там пока каждый второй случай — частный), поэтому проще в итоге писать руками.

Резюмируя: я просил привести альтернативы и описать проблемы с текущим решением. Две альтернативы ты привел, одна из них очень многословная и спорная (а компенсирующих преимуществ я пока не вижу). Вторая — грязноватый хак, уже опробованный на практике с негативным эффектом. А вот в чем проблема с текущим решением и его якобы тяжелой поддержкой ты так и не объяснил.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.