Pull to refresh

Comments 5

То есть, у нас тут есть static-объект, являющийся шиной, к которой прикрепляются все-все объекты приложения. Так, что каждый объект связан с каждым. Вложения для сообщений не типизированы, поэтому постоянно выполняются касты в object и обратно.

Если поле состоит из 10000 ячеек, и ячейка 15 отправляет сообщение ячейке 19, то остальное 9998 ячеек тоже получат это сообщение, разберут его, достанут guid получателя, поймут, что это не для них, и ничего не сделают.

Как-то всё получается хрупко (из-за кастов) и слишком зависимо от качества компонент. Чуть-чуть плохо оптимизированный компонент может тормозить всю систему даже тогда, когда к нему и не обращаются.
Спасибо за комментарий говорящий о внимательном прочтении.

Написав комментарий, понял что он получился довольно большим, поэтому небольшой анонс:

  • рассмотрим утверждение по поводу того, что «каждый объект связан с каждым».
  • подробно разберёмся с 10000ми ячеек

По поводу связей объектов.

Прежде чем решить, связаны ли объекты в Red Architecture, давайте сначала в общих чертах вспомним о связях объектов в терминах какой-нибудь другой популярной архитектуры, например Clean Architecture. Напомню, там есть вложенные друг в друга слои. Вунтреннему слою ничего не разрешается «знать» про внешний слой. Для решения «развязки» внутреннего слоя с внешним предлагается паттерн, в котором внутренний слой определяет интерфейс, который имплементирует внешний слой. На самом деле, развязка в этом случае получилась не очень, потому что: 1) Компонент 1, объявивший интерфейс обязан быть в системе — его удаление влечёт за собой удаление имплементации и вероятный рефакторинг в компоненте 2, реализовавшем интерфейс компонента 1. 2) В рантайме компонент 1, объявивший интерфейс, обязан следить за жизненным циклом компонентов 2, реализовавших данный интерфейс, чтобы случайно не вызвать метод интерфейса у одного из уже удалённых к моменту вызова компонентов.

Таких ограничений нет в Red Architecture — оба взаимодействующих объекта могут быть независимо друг от друга удалены из системы, и не обязаны объявлять/имплементировать никакие интерфейсы для взаимного взаимодействия и вообще — ничего друг о друге «не знают».
Та же связь, которая есть между объектами в Red Architecture — не видна взаимодействующим программным объектам, она видна разработчику. Это полезная связь, которая помогает разработчику быстро найти конкретную логическую цепочку по ключу в перечислении k.

По поводу 10000 ячеек.

В клиентских приложениях нужно не забывать об их назначении и их отличии от серверных программ. Дело в том, что с клиентским приложением почти всегда работает 1 пользователь, 1 человек, в то время как серверная программа обслуживает сотни тысяч или даже миллионов пользователей. Нужно помнить, что человек в каждый момент времени может увидеть и «обработать» относительно небольшой объём данных. Red Architecture выстраивает взаимодействие между объектами, обрабатывающими и отображающими данные пользователю, а не между объектами, представляющими единицы самих данных (например, семплами в аудио или пикселами в изображениях). Исходя из этого, наличие в памяти 10000 экземпляров какого-либо класса, обрабатывающего или отображающего данные — уже выглядит сомнительным архитектурным решением. Во всяком случае, мне сходу не приходит в голову пример, в котором такое количество объектов одного класса в памяти было бы необходимо для предоставления какой-либо функции одному единственному пользователю.

Допустим, мы скроллим список с 10000 элементов вплоть до последнего. Но у нас есть соглашение, что мы не дублируем статические состояния в памяти, это означает, что этот список в конце скролла у нас будет представлен в памяти 10000ми гуидов (строк), по каждому из которых мы будем «вытаскивать» данные из базы каждый раз, когда соответствующий элемент списка покажется на экране пользователя. На самом деле, процесс «вытаскивания» данных из БД можно оптимизировать не нарушая соглашений Red Architecture, но об этом потом. Таким образом, количество объектов, принимающих и отправляющих данные по паттерну Red Architecutre для всего десятитысячного списка будет ограничено количеством переиспользуемых графических элементов списка (cells), которые отображают данные пользователю по мере скролла. Их (переиспользуемых ячеек), система вряд ли создаст больше пары-тройки десятков. И в этом случае, даже если компонент, как вы правильно заметили, может быть чуть-чуть плохо оптимизированный, вряд ли это вызовет заметные проблемы.

Более того, допустим, у вас есть пример где действительно для приемлемой работы клиентского приложения вам нужно «раздуть» 10000 объектов ячейки в памяти. И вам нужно передать сообщение от ячейки 15 к ячейке 19, в этом случае вам в любом случае нужно найти 19 ячейку среди этих 10000. В самом простом случае вы сможете это сделать вот так cells[19].sendMessage(message);. Но если вы можете это сделать так просто, то вам вообще не нужны никакие архитектурные паттерны. Статья же про сложные и запутанные программы, в которых не всё так очевидно. И в этом случае Red Architecture будет точкой входа в понятную логику приложения. Позже вы можете оптимизировать какие-то операции, если понадобится. Но с Red Architecture вы сразу получаете прозрачные, понятные цепочки логики.
«Связь» в моём комментарии — это не зависимость кода компонентов, а связь по шине, т.е. доставка сообщений между объектами.

С точки зрения проектирования компоненты, конечно, независимы.

Как вариант архитектуры имеет право на жизнь, но в best practices я бы не стал его записывать.
Слишком много способов сделать неправильно и неоптимально. А архитектура должна направлять разработчика, не давать ему накосячить.

Выглядит похоже на однопоточную Akka, только упрощенную технологически и более сложную для взаимодействия. Однопоточность предполагаю из var newItem = (KeyValuePair<k, object>)e.NewItems[0] и отсутствия какой-либо видимой синхронизации вокруг.

Решение проблем многопоточности мы рассмотрим в следующих постах.
Only those users with full accounts are able to leave comments. Log in, please.