Как правильно организовать DRY архитектуру для REST back-end'a?

Возникла необходимость написать клиент на AngularJS для взаимодействия с REST API на Django (Django Rest Framework). В качестве фреймворка для AngularJS был выбран Restangular. Для каждого endpoint'а есть свой сервис и по 2 контроллера (ObjectNameListController и ObjectNameDetailController). Все дело в том, что сервисы и контроллеры имеют идентичную структуру и я хотел это вынести весь общий код в родительские сервисы и контроллеры. Но до сих пор не могу придумать наиболее выгодный путь.

Я попробовал вынести в директивы (у директивы есть свой контроллер в который передается сервис через аттрибут):

function RESTSupportDirective() {
    return {
        restrict: 'E',
        controller: function($scope, $injector) {
            var self = $scope;

            self.objects = [];

            self.activate = function (serviceName) {
                self.service = $injector.get(serviceName);
            };

            self.list = function () {
                self.service.list().then(function (response) {
                    self.objects = response;
                }, function (error) {

                });
            };

            self.create = function (newObject) {
                self.service.create(newObject).then(function (response) {

                }, function (error) {

                });
            };
        },
        link: function (scope, element, attrs) {
            scope.activate(attrs.serviceName);
        }
    };
}


Но при таком подходе я не вижу способа использовать роутинг (resolve).

Вторая реализация заключается в том, чтобы инициализировать контроллер непосредственно в роутинге, используя resolve:

function getService(serviceName) {
    return {
        service: [serviceName, function (serviceName) {
            return serviceName;
        }]
    };
}
// Routing
$routeProvider.when('/object', {
    templateUrl: '',
    controller: 'RESTListController',
    controllerAs: 'objectController',
    resolve: getService('ObjectService')
})

// Controller
function RESTListController(Service) {
    var self = this;

    self.objects =  [];

    self.list = function () {
        console.log(Service);
        Service.list().then(function (response) {
            self.objects = response;
        }, function (error) {

        });
    };

    self.create = function (newObject) {
        Service.create(newObject).then(function (response) {

        }, function (error) {

        });
    };
}

Тут возникает вопрос - как передавать service, если не использовать routing с resolve?

В общем случае, сервис и контроллер имеет набор методов list(), one(), create() и remove(). Есть идеи, как это вынести в родительскую функцию "правильно"?

PS. Я рассматривал примеры с наследованием, но почему-то ничего не заводилось.

PPS. Я не использую $scope, только "this" approach.

Спасибо.
  • Вопрос задан
  • 2533 просмотра
Пригласить эксперта
Ответы на вопрос 1
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Я как-то эксперементировал с наследованием контроллеров и пришел к выводу что если у вас есть дублирование кода в контроллере, которое красиво решается наследованием... значит что-то пошло не так и это дело надо вынести в сервисы.

Далее имеет смысл воспользоваться UI-Router что бы разделить скрины на отдельные состояния. Общие вещи можно так выносить в базовые состояния и добиться большей гибкости...

Так же я делаю ресолвы как-то так:
$stateProvider.state({
    resolve: {
       list: function (service) {
            return service.list();
       }
    },
    controller: function (list) {
       this.list = list;
    }
});


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

Как-то сумбурно... и мне так же было бы любопытно взглянуть на подходы других людей.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы