2008-10-20 5 views
1

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

В настоящее время я работаю над диалоговым окном MFC, но этот вопрос может быть применен к любому приложению, управляемому пользовательским интерфейсом. У меня есть отдельные классы, которые обрабатывают состояния машин, чтение/запись файлов и аппаратное сопряжение. Для всех этих объектов потребуется некоторый тип управления пользовательским интерфейсом или отображение/редактирование свойств. В диалоговых приложениях MFC диалоговое окно является программой, поэтому оно должно существовать до закрытия программы. Обычно я просто помещал объекты в основной класс диалога для приложения и имел класс диалога, обслуживающий двойную обязанность; как основной пользовательский интерфейс, так и дом для всех других объектов приложения. В других приложениях я создал эти объекты по всему миру и ссылался на них там, где они были нужны. Ни один из этих способов не кажется правильным. Первый вариант разбивает один класс, одно правило задачи, а второе полагается на глобальные переменные, а также создает скрытые зависимости. Я мог бы ввести какой-то тип инъекции зависимостей, но где бы все эти переменные, которые я бы вводил, проживали?

Мне просто интересно, что делают другие, чтобы организовать свои программы, не нарушая правил?

ответ

0

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

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

+0

Для переходных диалогов я согласен. Тем не менее, приложения, управляемые диалоговым окном MFC, имеют диалог, присутствующий на весь срок службы приложения. Поэтому я не могу уничтожить диалог до выхода программы. – bsruth 2008-10-20 21:55:42

2

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

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

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

Нужно использовать один синглтон, который уже определен для вас, - объект приложения, который всегда называется App, специализацией CWinApp. Если вы помещаете свои синглоты в качестве публичных данных, то любой код может легко получить доступ к ним.

Предположим, что вы назвали свое приложение «решателем». Мастер создания диалогового приложения создаст класс CsolverApp. Теперь предположим, что у вас есть singleton, называемый 'theData', экземпляр класса 'cData'.

Поместите синглтон в theApp

class CsolverApp : public CWinApp 
{ 
public: 

cData theData; 

… 

Теперь получить доступ к этому в любом месте вашего кода

#include “solver.h” 

theApp.theData.somepublicmethod(); 
1

Это имеет смысл смотреть на это с MVC (Model - View - Controller) смотровая площадка. (То, что именование MFC - дань уважения MVC, - это еще одна больная шутка от Microsoft, трудно и неинтуитивно (но отнюдь не невозможно) управлять типами абстракций, которые необходимы в «истинном» MVC в MFC.)

В частности, похоже, что вы продумали основу для дизайна MVC; у вас есть классы, которые выполняют основную бизнес-логику (Модель), и вы знаете, что они должны быть отделены от компонентов пользовательского интерфейса (вид). Проблема, которая приходит сейчас, - третья часть троицы MVC; Контроллер.

MFC делает этот материал жестким, целенаправленно запутывая процесс MVC, заставляя вас начать с диалога. В вашем случае диалоговое окно, в котором MFC запускает вас, должно быть контроллером, а НЕ - представлением. Что ваш Dialog (Controller) делает для вас, это управление компонентами пользовательского интерфейса (View) и позволяет им взаимодействовать с вашими «рабочими» классами (Model). Что еще больше осложняет ситуацию, так это то, что компоненты вашего интерфейса, чтобы быть видимыми, скорее всего, должны быть прикреплены к вашему диалогу, чтобы быть видимым.

Чтобы получить такое право, вы действительно должны в основном реализовать свой контроллер как объект высокого уровня, который создается из вашего диалога; ваш диалог содержит исходный поток управления, ваш контроллер получает поток управления, а оттуда он должен рассматривать Диалог как еще один компонент пользовательского интерфейса (хотя и со специальным статусом).

Это позволяет вам иметь надлежащий уровень инкапсуляции; ваш контроллер вызывает классы бизнес-логики (модели), которые могут взаимодействовать друг с другом или с контроллером, если это необходимо; они отделяются от представления на контроллере, а не внедряются в компоненты пользовательского интерфейса и (вероятно) берут «простой способ» чрезмерно привилегированного доступа к элементам пользовательского интерфейса («Хм, мне нужен этот объект, чтобы получить некоторый вклад от пользователь, я мог бы реорганизовать, но гораздо проще просто добавить диалоговое окно, так как у меня есть дескриптор окна верхнего уровня ... »).

Как только ваш объект Controller является домом для всех объектов бизнес-логики, все становится проще; вы можете использовать контроллер для обеспечения доступа к перекрестным объектам для любых объектов, которым нужны другие объекты. Подумайте, какие классы должны быть Singletons, и использовать их экономно. Ресурсы, требующие управления конфликтами (например, аппаратные ресурсы), являются прекрасными примерами «естественных синглетонов»; вещи, которые поддаются одноэлементному подходу. Вы также можете сделать свой контроллер одиночным; в зависимости от требований к доступу к нему. В частности, в сценарии «Впрыскивание зависимостей» Контроллер представляет собой экземпляр объектов и управление зависимостями.

Это основной подход MVC; но, как я уже сказал, MFC делает его необычайно трудным и неинтуитивным из-за фундаментального дизайна MFC. Я узнал БОЛЬШЕ больше о MVC ПОСЛЕ начального ОЧЕНЬ отрицательное впечатление об этом из-за MFC; если можно, я рекомендую посмотреть, какие реалии MVC выглядят на других языках.

Удачи вам!