Используя руководство по стилю John Papa AngularJS, как правильно объявлять объекты данных?

Скажем, что у меня есть служба данных AngularJS, которая делает вызов на сервер и возвращает объект, который может быть расширен с помощью дополнительных методов. Например, предположим, что следующая функция является частью службы AngularJS для чего-то вроде NerdDinner.

function getDinner(dinnerId) {
   return $http.get('api/dinner/' + dinnerId)
      .then(loadDinnerComplete)
      .catch(loadDinnerFailed);

   function loadDinnerComplete(response) {
      return new Dinner(response.data);
   }
}

Какая лучшая практика для места, чтобы определить класс Ужин? Это factory в отдельном файле? Определить ли это в службе NerdDinner? Или я определяю это в классе GetDinner (предполагая, что единственный метод, который может создавать обеды)?

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

Edit Я в конечном итоге решил принять Jeroen answer, потому что он наиболее соответствовал моим потребностям в довольно простом случае использования. Тем не менее, Даниэль отвечает, является чистым золотом, и его не следует упускать из виду. Если бы я решил расширить функциональность моего DTO с помощью простых CRUD или дополнительных операций на сервере, ресурс $- отличный подход.

Ответ 1

Где разместить бизнес-единицы (например, ужин) не упоминается в руководстве по стилю Джона Папа (afaik).

Если вы хотите пройти этот маршрут (используя бизнес-сущности и логику размещения там), я должен предоставить каждой организации свой собственный factory:

(function() {
  'use strict';

  angular
    .module('myDinner')
    .factory('Dinner', DinnerFactory);

  function DinnerFactory() {

    Dinner.prototype.eat = eat;
    Dinner.prototype.cancel = cancel;

    return Dinner;

    // Constructor

    function Dinner (data) {
        // this is just an example:
        this.time = data.time;
        this.location = data.location;
    }

    // Methods

    function eat() {
      // ...
    }

    function cancel() {
      // ...
    }

  }

})();

Затем вы можете ввести их в свой контроллер или, возможно, другие объекты службы, просто используя Dinner и создать новый объект Dinner, используя new Dinner(data).

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

Ответ 2

ИМО, что вы делаете, уже сделано в $resource и restacular. Вы говорите об "определении объектов данных" (или моделей в типичном языке). Тем не менее, определение каждого "объекта данных", поскольку его собственный factory - это способ сделать это, согласно совету Джона Папа относительно одиночных проблем.

Джон Папа рассказывает об этом в разделе .

Если вы хотите это сделать вручную, IMO вы можете определить свои модели и добавить методы для каждого из них, которые будут представлять собой различные операции crud. Это шаблон $resource и рестанглярный (вид).

//Dinner model as angular factory, each of these methods returns a promise

function Dinner($http) {
    return {
        create: function(route, body) { /** http.post */ },
        get: function(route) { /** http.get */ },
        update: function(route, body) { /** http.put */ },
        destroy: function(route) { /** http.delete */ }
    };
}

теперь ваша модель Dinner имеет удобные методы crud, встроенные, чтобы вы могли сделать

var dinner = new Dinner;
dinner.get("/api/dinner/1").then() //get dinner with id of 1
dinner.update("/api/dinner/1", {name: "burger"}).then() //update dinner with id of 1

Edit:

Итак, если вы хотите создать объект, который не связан с получением данных, IMO вы должны создать еще один factory, который требует вашей модели. Это отделяет ваши данные от манипуляций с данными. В оригинальном примере OPs поиск и обработка данных тесно связаны.

function Meal(dinner) {
    //this.meal is the specified dinner
    this.meal = new Dinner().get("/api/dinner" + dinner);

    //some random build-in data manipulation methods
    return {
        getCalories: function() { return this.meal * 400; },
        getPrice: function() { return (this.meal * 100) + "$"; }
    };
}

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

var mcdonalds = new Meal(/** specify which dinner */)
mcdonalds.getPrice() //$4.56
mcdonalds.getCalores() //9999

Ответ 3

Лично я использовал Services и Factories для создания объектов. Однако из руководства по стилю Джона Папа:

Службы создаются с помощью ключевого слова new, используйте this для общедоступных методов и переменных. Так как они настолько похожи на фабрики, используйте factory вместо этого для согласованности.

Следуя SRP, вы должны поместить его в новый Service или Factory не часть другого.