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

15

Поэтому мой учитель говорит мне, что очень важно не инкапсулировать программный код и код графического интерфейса в одних и тех же классах, а сохранять их полностью независимыми. Сейчас я пишу игру для iPhone с сеткой. для меня гораздо больше смысла создавать как графическую сетку, так и технический код в одном классе "Grid". Другой программист не одобрит это? Действительно ли очень важно сохранить графический интерфейс и код независимыми. Какие проблемы возникнут, если я не буду?

Спасибо!

РЕДАКТИРОВАТЬ: спасибо, ребята! Будет ли хорошо для меня сначала написать проект, а затем скопировать код, чтобы сформировать разделение задач проекта. Я знаю, что это может полностью победить цель, но так же, как на практике ... Так что в следующий раз я смогу применить этот шаблон проектирования с самого начала?

Джон
источник

Ответы:

17

Концепция, на которую ссылается ваш учитель, называется разделением интересов.

Чтобы проиллюстрировать это в своем контексте, если вы завершили свою программу, а затем решили, что хотите перенести ее на Android; вам придется переписать намного больше кода, чем если бы вы хранили отдельную логику сетки.

Управление интерфейсом должно касаться только рисования того, что ему говорят, логика сетки должна касаться только того, что находится в сетке, а не того, как ее рисовать.

Это помогает?

Расс Кларк
источник
Спасибо, это помогло. Дело в том, что мне намного проще визуализировать мой конечный продукт, когда я инкапсулирую оба в классе. Является ли это уважительной причиной для меня не следовать «разделению интересов»? Или это абсолютно необходимо, и я не могу назвать себя настоящим программистом: p?
Положительный эффект этого разделения состоит в том, что вам не нужно переписывать свою игровую логику, если вы решите, например, заменить свой графический интерфейс
@John - Напишите документ спецификации, если вам нужно визуализировать свой дизайн. Если вы можете описать это, вы можете начать отделять код графического интерфейса от самой логики игры.
Ramhound
3
Это также облегчает тестирование кода сетки. Тестирование графического интерфейса пользователя является болезненным (из-за возможных проблем со средами), поэтому получение такого интерфейса, который представляет собой тонкий «очевидно правильный» слой над чем-то, что можно тестировать, является огромной победой. (Опять же, это разделение проблем.)
Донал Стипендиаты
1
@ Джон: Некоторые из нас учатся лучше всего, делая. Предполагая, что этот проект не такой большой, попробуйте написать его как отдельный класс и заставить его работать на iPhone. Теперь перенесите его на Android, отслеживая ваши «болевые точки». Наконец, перепишите его, как предложил Русс Си. Я думаю, вы поймете, почему разделение логики и представления - это путь.
Питер Роуэлл
4

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

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

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

Карра
источник
3

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

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

Джонатан Вуд
источник
1

Когда разделение проблем применяется к структуре приложения, результатом является многоуровневая архитектура (или архитектура N-уровня) http://en.wikipedia.org/wiki/Multitier_architecture .

StuperUser
источник
0

Чтобы опираться на другие ответы и дать вам пример, вы должны как-то позволить себе вводить свою логику / данные в свою таблицу или наоборот.

Ваш элемент управления сеткой может предоставлять Renderметод или DataBindметод.

class GridControl
{
    public Render(GridData data) { ... }
}

или

class GridControl
{
    public DataBind(GridData data) { ... }
}

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

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

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

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

Raynos
источник
0

Я настоятельно рекомендую вам взглянуть на архитектуру MVC .

Это уточнение упомянутой вами концепции (разделение программного кода и графического интерфейса). MVC расшифровывается как Model-View-Controller. Здесь Модель - это данные, View - код графического интерфейса, а COntroller - код, который обрабатывает данные.

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

DPD
источник
0

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

Где MVC выигрывает, если изменения ограничены V-частью, или «View».

По моему опыту, гораздо более вероятно, что изменения затрагивают все три части, поэтому лучше, если они не разделены. Чтобы показать, что я имею в виду, я долгое время использовал разработанную мною технику, называемую « Динамические диалоги» , в которой новое требование, такое как «разрешить пользователю редактировать имя и по завершении делать XYZ», вводится в исходный код в виде единого блока. текст:

if(deTextEdit(&sName)){
  // do XYZ
}

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

Если вы перейдете по этой ссылке, вы увидите более сложный пример.

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

Это не бесплатно. Он вводит единовременную кривую обучения для программиста.

Майк Данлавей
источник
0

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

Гас
источник