Ответственность за право собственности и возможность повторного использования - PullRequest
0 голосов
/ 27 апреля 2019

У меня была дискуссия с коллегой о подходах к этим темам в нашем проекте. Я делаю Progress System, короче говоря, класс ProgressMonitor и класс Task, ProgressMonitor обрабатывает множество задач. Все довольно простые вещи. Но когда дело дошло до задач UI, у нас были мнения. Каждое задание имеет свой собственный интерфейс. Мы согласны, что у нас должен быть класс HUD для обработки пользовательского интерфейса. Разница во мнении состоит в том, что он хочет, чтобы HUD обрабатывал пользовательский интерфейс каждой конкретной задачи, и поэтому класс HUD станет достаточно большим, и задача не будет иметь почти никакой логики в отношении его пользовательского интерфейса. Мое мнение, HUD будет обрабатывать только логику, которая одинакова для всех вещей в нашем проекте, которые требуют пользовательского интерфейса, и вся конкретная логика обрабатывается объектами, которые нуждаются в пользовательском интерфейсе. Преимущество его в некоторой собственности (объекты, которые должны получить доступ к некоторой пользовательской информации, могут легко получить это от HUD) Мои преимущества, HUD - легкая чистота и возможность многократного использования.

Что было бы правильнее по ООП?

1 Ответ

2 голосов
/ 27 апреля 2019

Я начну с вопросов, которые повлияют на реализацию:

  • Вопрос 1: Является ли задача тесно связанной с ее пользовательским интерфейсом?

  • Вопрос 2: Является ли пользовательский интерфейс для всех задач одинаковым или имеет незначительные различия?

  • Вопрос 3: Нужно ли показывать разные интерфейсы для каждой задачи в зависимости от конкретной задачи?

Если ответ на Вопрос 1 равен Да , и разделение двух областей ответственности затруднительно, добавление логики пользовательского интерфейса в Task может многое сделать.

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

Вы можете иметь класс TasksHUD , который будет отвечать за обработку списка класса TaskUI . Каждый класс TaskUI будет иметь Task , связанный с ним, и обрабатывать рендеринг пользовательского интерфейса и логику представления для этой конкретной задачи.

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

Задача будет только отвечать за выполнение, изменение своего статуса и другие вещи, которые задача должна делать в вашем приложении (если вы предоставите более подробную информацию, я смогу дать более подробное и, возможно, более точное описание) в то время как ответственность за представление задачи будет передана TaskUI .

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

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

Если вам нужно изменить класс Task , вам может понадобиться или не потребоваться изменить класс TaskUI , так как зависимость меняется с TaskUI на Task . Некоторые изменения повлияют на пользовательский интерфейс, некоторые - нет.

Если ответ на Вопрос 3 равен Да , тогда:

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

Событие. В этом случае вы можете отделить Task от его пользовательского интерфейса в двух классах Task и TaskUI , но вам потребуется механизм, который будет связать определенный класс Task с его TaskUI class. Это может привести к большему количеству классов и сложности, с которыми, возможно, не справиться. В долгосрочной перспективе это может сэкономить ваше время (в основном, от появления ошибок).

Вот пример псевдокода:

interface TaskObserver {
  void onTaskChanged(t);
}

interface TaskUI {
  void render();
}

interface TaskUIFactory {

  register(TaskUIFactoryRegistry registry);

  TaskUI create(Task task);
}

interface Task {

  TaskStatus status;

  execute();

  addEventListener(TaskObserver o);
}

class TaskA : Task {
  // implementation.....
}

class TaskA_UI : TaskUI, TaskObserver {

  TaskA mTask;

  TaskA_UI(TaskA task) {

    mTask = task;
    mTask.addEventListener(this);
  }

  render() {
    // rendering goes here
  }

  onTaskChanged(t) {
    // raise an event or signal to the TaskHUD that a refresh is needed
  }
}

class TaskA_UIFactory : TaskUIFactory {

  void register(TaskUIFactoryRegistry registry) {
    registry.Register(typeof(TaskA), this);
  }

  TaskUI createUI(Task task) { 
      return new TaskA_UI((TaskA)task);
    }
  }

Когда задача добавлена, ваш TasksHUD может использовать TaskUIFactoryRegistry, чтобы получить TaskUIFactory, которая будет создавать TaskUI.

Вот некоторые ресурсы, которые вы можете проверить, чтобы обсудить подобные вопросы:

...