Шаблон для владения и ссылок между несколькими контроллерами и полу-общими объектами? - PullRequest
1 голос
/ 11 февраля 2010

Например, у меня есть окно (бездокументарная модель) - с ним связан контроллер. В этом окне у меня есть список и кнопка add . Щелчок по кнопке add вызывает другое окно / диалоговое окно «подробности» (со связанным контроллером), которое позволяет пользователю вводить подробную информацию, нажимать «ОК» и затем распространять элемент обратно в список исходного окна. , Очевидно, у меня был бы базовый объект модели, который содержит коллекцию этих сущностей (давайте назовем единственную сущность Entity для справки).

Возможно, у меня есть только одно главное окно, поэтому у меня, вероятно, будет только одна коллекция сущностей. Я мог бы спрятать его в контроллере главного окна - но тогда как мне передать его в детальное окно? Я имею в виду, я, вероятно, не хочу передавать эту коллекцию - трудно читать / поддерживать / многопоточность. Я мог бы передать ссылку на родительский контроллер и использовать ее для доступа к коллекции, но это, кажется, тоже пахнет. Я мог бы спрятать его в appDelegate и затем обращаться к нему как к «глобальной» переменной через [[NSApplication sharedApplication] делегат] - что кажется немного чрезмерным, учитывая, что делегат приложения на самом деле не имеет ничего общего с моделью. В качестве опции можно использовать другой стиль глобальной переменной - я мог бы сделать так, чтобы класс Entity имел одноэлементную фабрику для доступа к коллекции и методы класса. Это похоже на большее злоупотребление, чем appDelegate - особенно учитывая объект Entity и набор упомянутых объектов - две отдельные проблемы. Я мог бы создать класс EntityCollection, который имеет метод фабрики-одиночки, а затем методы объекта для взаимодействия с коллекцией (или разделить на настоящий класс фабрики и класс коллекции для немного большего совершенства ОО и легкой замены тестовых объектов). Если бы я использовал модель NSDocument, я бы мог спрятать ее там, но это не сильно отличается от сохранения в делегате приложения (хотя сам NSDocument, по-видимому, представляет модель в некотором роде).

В последнее время я довольно много времени проводил на стороне сервера, поэтому мне не приходилось много заниматься клиентской стороной, а когда я это делал, я просто грубо заставлял решение. В конце концов, есть миллиард способов убрать с лица кожи эту кошку, и кажется, что ни один из них не является ужасно чистым или красивым. Каков общепринятый способ программиста Какао сделать это? Или, что еще лучше, каков оптимальный способ сделать это?

Ответы [ 4 ]

7 голосов
/ 11 февраля 2010

Я думаю, что ваша концептуальная проблема заключается в том, что вы думаете об интерфейсе как о ядре приложения, а модель данных - как о чем-то, что вам нужно где-то найти.

Это назад. Модель данных является ядром программы, а все остальное прививается в модель данных. Модель должна инкапсулировать все логические операции, которые могут быть выполнены с данными. Интерфейс, GUI или другой, просто отправляет сообщения в модель данных, запрашивающие определенные действия.

Исходя из этой концепции, легко заметить, что универсальная доступность модели данных не является небрежным дизайном. Поскольку модель содержит всю логику для изменения данных, вы можете иметь произвольно большое количество интерфейсов, обращающихся к ней, без запутывания данных или усложнения кода, поскольку модель изменяет данные только в соответствии со своими внутренними правилами.

Лучший способ обеспечить универсальный доступ - создать класс, создающий одиночный код, а затем поместить заголовок для класса в заголовки префикса приложения. Таким образом, любой объект в приложении может получить доступ к модели данных.

Edit01:

Позвольте мне прояснить важное различие между голой глобальной переменной и глобально доступной моделью инкапсулированных классов.

Исторически мы рассматривали глобальные переменные как плохой дизайн, потому что они были просто необработанными переменными. Любая часть кода может изменить их по желанию. Эта нагота привела к очевидным проблемам: вам приходилось постоянно защищаться от какого-то случайного фрагмента кода, который изменял глобальный код и затем выводил приложение из строя.

Однако в глобальном классе на основе класса глобальная переменная инкапсулирована и защищена логикой, реализованной инкапсулирующим классом. Эта инкапсуляция означает, что, хотя любой случайный фрагмент кода может пытаться изменить глобальную переменную внутри класса, он может сделать это только в том случае, если инкапсулирующий класс разрешает изменение. Автоматическая проверка уменьшает сложность кода, поскольку вся логика проверки находится в одном классе, а не распространяется по всему приложению в любом случайном месте, где можно манипулировать данными.

Вместо создания слабого места, как в случае открытой глобальной переменной, вы создаете строгую и универсальную проверку данных и управление ими. Если вы обнаружите проблему с управлением данными, вам нужно будет исправить ее только в одном месте. Если у вас есть правильно настроенная модель данных, остальная часть приложения становится смехотворно легкой для написания.

2 голосов
/ 11 февраля 2010

Моей первоначальной реакцией было бы использование «модального делегата», очень похоже на NSAlert s. Вы создаете свое окно сведений, передавая ссылку на делегат, который будет отображаться в окне сведений, когда он завершит создание объекта. Затем делегат, который, вероятно, будет контроллером для главного окна, может обработать сообщение «Закончено редактирование» и добавить объект в коллекцию. Я бы не хотел передавать коллекцию напрямую.

0 голосов
/ 11 февраля 2010

Я использую метод singleton, где сам класс управляет своими собственными коллекциями, настройками и разборками. Я считаю, что это отделяет функциональность базы данных / хранилища от контроллеров и поддерживает чистоту. Приятно и просто позвонить [Object objects] и вернуть ссылку на мой список объектов.

0 голосов
/ 11 февраля 2010

Я поддерживаю класс EntityCollection. На мой взгляд, если у вас есть список объектов, этим списком нужно управлять за пределами определенного контроллера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...