Вариант использования чистой архитектуры для определения разделов домашней страницы - ОБНОВЛЕНО - PullRequest
0 голосов
/ 16 января 2020

Я экспериментирую с Робертом "Дядя Боб" Мартина Чистая архитектура, чтобы использовать его в будущем проекте. Это веб-приложение на основе Spring MVC.

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

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

Я пытаюсь также следовать принципу единой ответственности, поэтому я создал абстрактный ViewHomePageUseCase, который имеет дело с общими разделами на домашней странице каждого пользователя. , У меня также есть ViewUserType1HomePageUseCase, et c., Для определенных c пользовательских типов, которые расширяют базовый класс.

Хотя в настоящее время в моем Spring @Controller у меня есть что-то вроде этого:

@RequestMapping(value = {"/home"}, method = RequestMethod.GET)
public String getHomePage(Model model) {

    ViewHomePageResponseModel response;
    String userId = "test";

    int userType = this.getUserProfileUseCase.getUserType(userId);
    switch(s) {
    case 1:
        response = useCaseFactory.viewUserType1_HomePageUseCase().getHomePage(userId);
        break;
    case 2:
        response = useCaseFactory.viewUserType2_HomePageUseCase().getHomePage(userId);
        break;
    default:
        response = useCaseFactory.viewSimpleHomePageUseCase().getHomePage(userId);
    }

    HomePageViewModel viewModel = presenter.presentHomePage(response);

    model.addAttribute("viewModel", viewModel);

    return "home";
}

хотя мне и не нравится этот контроллер, так как в нем есть бизнес-логика c.

В более ранней версии моего прототипа я пытался поставить «определить тип пользователя» функция в самом сценарии использования, затем делегирование в правильный вариант использования. Хотя это сработало, мне это тоже не понравилось.

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

Надеюсь, у меня все понятно!

Любая помощь приветствуется!

Крис

ОБНОВЛЕНИЕ -

В конечном итоге я создал отдельные варианты использования для каждой домашней страницы, а также вариант использования для определения, какая домашняя страница необходима. Я также использую фабрику для создания экземпляра сценария использования. Каждый вариант использования домашней страницы просто получает данные, которые нужны конкретной домашней странице. Тогда Spring Controller упрощается:

@Controller
public class HomeController {

    private IUseCaseFactory useCaseFactory;

    @Autowired
    public HomeController(IUseCaseFactory useCaseFactory) {
        this.useCaseFactory = useCaseFactory;
    }

    @RequestMapping(value = {"/home"}, method = RequestMethod.GET)
    public String getHomePage(Model model) {

    String userId = "steven"; // User Type 2
    // hardcoded userId's are used in the GetHomePageUseCase class.

    IHomePagePresenter presenter = this.useCaseFactory.getHomePageUseCase().getHomePage(userId);
    HomePageViewModel viewModel = presenter.presentHomePage();

    model.addAttribute("viewModel", viewModel);
    return "home";
    }
}

Мой GetHomePageUseCase, который решает, какая домашняя страница необходима, выглядит примерно так:

public class GetHomePageUseCase implements IViewHomePageUseCase {

    private IUseCaseFactory useCaseFactory;

    public GetHomePageUseCase(IUseCaseFactory useCaseFactory) {
        this.useCaseFactory = useCaseFactory;
    }

    @Override
    public IHomePagePresenter getHomePage(String userId) {
        IHomePagePresenter presenter;

        //temporary
        //TODO - once users are in place, rewrite this function.
        String userRole;
        switch(userId) {
            case "chris":
                userRole = "UserType1";
                break;
            case "steven":
                userRole = "UserType2";
                break;
            default:
                userRole = "Public";
                break;
         }

         switch(userRole) {
         case "UserType1":
             presenter = useCaseFactory.viewUserType1HomePageUseCase().getHomePage(userId);
                break;
         case "UserType2":
            presenter = useCaseFactory.viewUserType2HomePageUseCase().getHomePage(userId);
            break;
        default:
            presenter = useCaseFactory.viewPublicHomePageUseCase().getHomePage(userId);
            break;          
        }

        return presenter;
    }

}

Я до сих пор не уверен в этом подходе , Хотя он чище, чем в первой версии, я не совсем доволен им.

Более общий вопрос: когда у вас есть веб-страница (в данном случае), ее функции зависят от какой-либо роли пользователя или разрешений Как я могу включить эти права пользователей в подход чистой архитектуры? Например, на другой странице (моя страница просмотра) отображаемые основные данные c одинаковы для всех пользователей, но в зависимости от роли / разрешений пользователя пользователь может редактировать, удалять и т. Д. c. в противном случае эти кнопки даже не отображаются. В этом случае (для моей страницы просмотра) у меня есть логические флаги, такие как showEditButton, которые будут установлены с помощью варианта использования, а сам код страницы просмотра просто проверяет флаг, чтобы показать или скрыть кнопку. Это правильный способ сделать это в чистой архитектуре?

Еще раз спасибо !!

Крис

1 Ответ

0 голосов
/ 27 января 2020

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

Глава 22 - Варианты использования

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

Martin, Robert C .. Чистая архитектура: Руководство мастера по структуре и дизайну программного обеспечения (Robert C. Martin Series) Pearson Education.

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

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

Даже если ViewHomePageUseCase следует SRP (принципу единой ответственности), ваш контроллер этого не делает. Каждый раз, когда добавляется новый тип пользователя, вы должны изменить оператор switch контроллера. Поэтому я бы перенаправил на контроллер, который может обрабатывать пользовательский тип.

String redirect = MessageFormat.format("redirect:/home/{0}?userId={1}", userType, userId);
return new ModelAndView(redirect);

Затем можно добавить поддержку новых типов пользователей, создав новый класс контроллера, например,

@Controller
@RequestMapping("home")
public class UserType3HomePageController {

    @Autowired
    private UserType3InfoUseCase useCase;

    @GetMapping("/{userType}")
    public ModelAndView getHomePage(@PathVariable int userType, @RequestParam userId) {
        UserType3Info userInfo = useCase.getUserInfo(userId);
        ModelAndView modelAndView = new ModelAndView("userType3Home");
        modelAndView.addObject("userInfo ", userInfo);
        return modelAndView;
    }

}

Тогда у вас также есть разделение задач в контроллерах. Это также имеет смысл, поскольку на разных домашних страницах обычно отображаются разные пользовательские данные. Таким образом, имеет смысл создать представление для каждого типа. В противном случае вы можете получить операторы switch (или if / else) в представлении.

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