Где разместить диспетчерскую таблицу в MVC? - PullRequest
2 голосов
/ 08 октября 2019

Таблица диспетчеризации (или метод диспетчеризации) - это и таблица (модель), и маршрутизатор / контроллер.

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

my $tabs = {
  Home => {
    action => \&HomeController::dashboard,
    displayName => ‘Home’,
    ...
  },
  About => {
    action => \&AboutController::info,
    displayName => ‘About Us’,
    ...
  },
  ...
};

Изначально у меня были TabController и TabView. Внутри контроллера находилась диспетчерская таблица;однако, похоже, что оно не соответствует MVC. Это было нормально, когда было только 3 вкладки, но отличалось, когда оно росло, особенно потому, что требовалось подрезать безопасность или фильтровать представления.

Имеет смысл перенести его в модель, так как он рассматривается скорее какТаблица данных. Однако, поскольку это Perl (и таблица диспетчеризации), все соответствующие пакеты также должны быть загружены. Таким образом, эта TabModel загружает много контроллеров (и в некоторых случаях представления). Я не особенно люблю загружать / ссылаться на какие-либо контроллеры в модели, поэтому загрузка мульти ощущается еще хуже.

Есть ли передовая практика или пример для этого сценария?


Приложение

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

index.pl -- entrance
Controllers/
  -- Dashboard.pm
  -- Home.pm
  -- About.pm
Models/
  -- Tabs.pm
  -- Users.pm
Views/
  -- Dashboard.pm
  -- Home.pm
  -- About.pm
  -- Error.pm

Я не буду разбирать index.pl, но он по сути разбирает параметры и направляет их в DashboardController :: dashboard.

DashboardController

package Controllers::Dashboard;

sub dashboard{
   my $users = Models::Users::get_all();           # Users Model
   my $tabs = Models::Tabs::get_permitted(         # Tabs Model
     $users->{CURRENT_USER}{permissions}
   );
   print Views::Page::render($users,$tabs);        # Page View
}

AboutController

package Controllers::About;

sub info {
  # No models necessary
  print Views::About::render();
}

TabsModel

package Models::Tabs;

use Controllers::Home;
use Controllers::About;

sub get_all {
  my $tabs =  {
    Home => {
      action => \&Controllers::Dashboard::dashboard,
      displayName => ‘Home’,
      ...
    },
    About => {
      action => \&Controllers::About::info,
      displayName => ‘About Us’,
      ...
    },
    ...
  };

  return $tabs;
}

sub get_permitted {
  my $user_permissions = shift;
  my $tabs = get_all();
  if (defined $user_permissions){
    foreach my $tab (keys %$tabs){
      delete $tabs->{$tab} unless $user_permissions->{"can_access_$tab"};
    }
  } 
}

DashboardView

package Views::Dashboard;

sub render {
  my ($users,$tabs) = @_;


  my $html_tabs = '<ul>';
  foreach my $tab (values %$tabs){
    $html_tabs .= "$tab->{displayName}";
  }
  $html_tabs .= '</ul>;

  my $html = <<"END";

  $html_tabs 
  <!-- dashboard content -->

END

  return $html;
}
...