"Нужно ли выражать в коде его проектные требования (контракты) и
как лучше всего это делать ?"
Ответ на вопрос кажется очевидным — нужно.
Например, для примитивов синхронизации, таких как критические секции,
делаются вещи вроде scoped_guard, заставляющие клиента автоматически
соблюдать соответствующие принципы захвата-освобождения (RAII).
А как быть, когда классы имеют нетривиальную семантику использования,
когда имеют зависимости от результатов работы других классов или
когда их корректное применение вообще допустимо в некотором сильно
ограниченном диапазоне сценариев ?
Приведу реальный пример.
У меня есть набор классов для обработки некоторой базы данных, причем эти
классы спроектированы с расчетом на использование в многопроцессорных системах.
Каждый поток выполняет свою ветку обработки, выбирая задания из специального
кругового буфера, один раз за круг потоки синхронизируются барьером и
происходит общая обработка информации, либо выход из цикла.
Несмотря на то, что программный интерфейс отдельно взятого класса простой,
на их совместное использование налагается много неочевидных ограничений — в
круговом буфере должно быть столько же задач-барьеров, сколько рабочих потоков,
доступ к общим данным можно делать только из callback-обработчика, который
срабатывает каждый раз при наполнении барьера потоками, и так далее.
Как наилучшим образом выразить данные требования в коде, сохраняя ясность и
не теряя в эффективности ?
Здравствуйте, okman, Вы писали: O>Как наилучшим образом выразить данные требования в коде, сохраняя ясность и O>не теряя в эффективности ?
разьяснить эти правила всей команде и бить линейкой по рукам всем кто будет их нарушать.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, okman, Вы писали:
O>>Как наилучшим образом выразить данные требования в коде, сохраняя ясность и O>>не теряя в эффективности ?
S>В принципе тут только 1 вариант — вынести всю логику по управлению классами в отдельный диспатчер и покрыть его тестами/ассертами.
Довольно интересно.
Это, как я понял, логически эквивалентно тому, как если бы написать отдельный класс для проверки
соблюдений требований, через который проходили бы все остальные классы при конструировании
системы обработки и который при некорректном применении выбрасывал бы исключение, например ?
Здравствуйте, __kot2, Вы писали:
__>Здравствуйте, okman, Вы писали: O>>Как наилучшим образом выразить данные требования в коде, сохраняя ясность и O>>не теряя в эффективности ? __>разьяснить эти правила всей команде и бить линейкой по рукам всем кто будет их нарушать.
А чем тогда бить клиентов кода, расположенных удаленно ?
Здравствуйте, okman, Вы писали:
O>Это, как я понял, логически эквивалентно тому, как если бы написать отдельный класс для проверки O>соблюдений требований, через который проходили бы все остальные классы при конструировании O>системы обработки и который при некорректном применении выбрасывал бы исключение, например ?
Да. Правда, я подразумевал сценарий, когда все рабочие классы полностью пассивны и отдельный класс несёт ответственность ещё и за порядок обработки. Тогда можно будет разделить основную логику и контроль за потокобезопасностью. Но это всё гадание на пальцах, в зависимости от задачи может выиграть любой подход
1) Debug asserts. Я стараюсь использовать ассерты по мере возможности, чтобы ограничить неправильное использование класса и методов (в.т.ч. проверка параметров). В release соответственно, ассерты будут исключены.
2) Комментарии. Они также могут помочь в правильном использовании кода
3) жесткие и логичные интерфейсы, видимость классов и интерфейсов. Я видел системы, где во всех сборках (.Net) все классы public. Вообще не понятно откуда их можно вызывать, а откуда нет.
4) как уже сказали, тесты. Юнит и интеграционные
5) инспекция кода перед чекином
И вообще, мое мнение такое, что код должен сам помогать его использовать и ограничивать некорректное использование.
Здравствуйте, okman, Вы писали: O>А чем тогда бить клиентов кода, расположенных удаленно ?
ну, можно придумать некий usb-девайс, чтобы их током бить удаленно.
Здравствуйте, __kot2, Вы писали:
__>Здравствуйте, okman, Вы писали: O>>А чем тогда бить клиентов кода, расположенных удаленно ? __>ну, можно придумать некий usb-девайс, чтобы их током бить удаленно.
Сначала нужно написать драйвер, который будет управлять этим девайсом.
Для этого придется собирать другую команду, которую тоже нужно бить по рукам линейкой,
причем некоторые члены команды снова-таки окажутся удаленными.
Здравствуйте, okman, Вы писали:
O>"Нужно ли выражать в коде его проектные требования (контракты) и O>как лучше всего это делать ?"
Нужно ДСЛить.
O>Приведу реальный пример. O>У меня есть набор классов для обработки некоторой базы данных, причем эти O>классы спроектированы с расчетом на использование в многопроцессорных системах. O>Каждый поток выполняет свою ветку обработки, выбирая задания из специального O>кругового буфера, один раз за круг потоки синхронизируются барьером и O>происходит общая обработка информации, либо выход из цикла.
А Rx не спасет отца русской демократии? http://rxwiki.wikidot.com/101samples
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн