Проблема в том, что здравый смысл диктует, что сущность совершает действия, а не наоборот
Поскольку я не знаю, что такое "сущности", мой здравый смысл говоритЯ ничего не знаю о том, что сущности делают действия, или действия потребляют сущности.
И "сущность", и "действие" являются существительными в этой ситуации, поэтому я не вижу причин, по которым они не должны быть классами.
Какая практика кодирования лучше для чего-либокак это?Я признаю, что мой первоначальный подход функционально хорош, но он выглядит вдвое хуже, чем при использовании gotos.
Не беспокойтесь о том, что является наиболее «чистым ООП» решением, особенно если это означает сделать странным,неэффективный или неэффективный код.Вера в то, что ООП является самоцелью, даже если она делает кодирование более дорогим и трудным, я называю «болезнью объектного счастья».Написание кода ООП не должно радовать вас;Эффективное использование ООП для снижения затрат и улучшения качества должно вас радовать.Если ООП не является подходящим инструментом, а функциональное программирование - функциональным.
Вместо этого беспокойтесь о о том, как вы ожидаете, что код будет выглядеть со стороны вызывающей стороны .API - это машина, которую используют другие разработчики, поэтому убедитесь, что ваш API разработан с их мыслями, чувствами и потребностями и потребностями в центре вашего внимания, а не с тем, что является «большинством ООП». Какой код вы хотели бы, чтобы ваши абоненты написали ?Всегда начинайте с этого.
Говоря о функциональном программировании, вы можете рассмотреть один из подходов - полностью перейти на функционал и представить дискретные распределения вероятностей в виде монады.
Подумайте о некоторыхдругие монады.IEnumerable<T>
- это просто последовательность, возможно, пустая из T. A Nullable<T>
логически совпадает с последовательностью, ограниченной ровно одним или нулем элементов.IObservable<T>
- это последовательность Т, которая скорее отталкивается от вас, чем от нее.Task<T>
логически является наблюдаемой, которая имеет ровно одно значение.
Не каждая монада логически является последовательностью, но вероятностные распределения .Распределение вероятностей Distribution<T>
представляет собой бесконечную случайную последовательность T, выходные данные которой соответствуют определенному распределению .
Если вы пойдете по этому пути, вы обнаружите, что очень много операций естественно выпадают из операторов последовательности.Условные распределения (например, «бросьте два кубика, но отбросьте двойные») составляют всего Where
.P (A | B) (вероятность A для данного B) равна Func<B, Probability<A>>
, что означает, что мы можем применить оператор монадического связывания к условным вероятностям , чтобы связать условные вероятности вместе, и, таким образом, логика Байсастановится просто .И так далее.Это простая, но чрезвычайно мощная техника.
Попробуйте написать несколько реализаций
interface IDistribution<T>
{
T Sample();
IDistribution<U> Bind<U>(Func<T, IDistribution<U>> f);
// f is probability of U given a T
}
и посмотрите, к чему это приведет.