Injecting a service into a domain model

308 views
Skip to first unread message

Supun Budhajeewa

unread,
Jul 8, 2016, 11:36:57 PM7/8/16
to AngularJS
I've a question about injecting a service into a domain model, in a way that it'd allow me to instantiate (`new`) that domain model.

Imagine I have a domain model called `Book`. I need to inject a service called `Books` into this domain model, so that I can call the `Books.create()` method from the `Book.create()` method.

If I inject the service dependency in the domain model's constructor, I am not able to `new` that domain model, unless I pass an instance of the service into the domain model.

Domain model:

~~~
class Book {
    id: number;
    name: string;

    constructor (
        private Books: Books
    ){}

    create (){
        this.Books.create(//pass data here);
    }
}
~~~

Component:

~~~
class BooksCreateComponent {
    create(){
        let book = new Book(); //This fails unless I pass in an instance of Books service. 

        boook.id = 149;
        book.name = 'TMA - 1';

        book.create();
    }
}
~~~

Any idea how I should proceed?

Steven Luke

unread,
Jul 9, 2016, 9:51:44 AM7/9/16
to AngularJS
Dependency Injection is like a virus, once you start to use it, it spreads until it is the only way to make objects...

The Books service is now a method parameter to the Book.  You need to pass it in.  If you can't new a Books instance (which you shouldn't) then you should inject it into the BooksCreateComponent:

class BooksCreateComponent {
    constructor
(books : Books) {}


    create
(){
        let book
= new Book(this.books);



        boook
.id = 149;
        book
.name = 'TMA - 1';


        book
.create();
   
}
}


That is the easiest/shortest route, but my suggestion would be to avoid newing the Book if you can.  I realize you have params to send to the Books create() method, but do you need to use an instance of Book to store/send those parameters to Books?  How about:


class BooksCreateComponent {
    constructor
(books : Books) {}

    create
(){
        let bookConfig
= {
            name
: "TMA - 1" as string,
            id: 149 as number,
           
...
       
};

        let book
= this.books.createBook(bookConfig);
   
}
}


You use an Object Literal to create the data to pass to the books service, it is just a data transport object, not really part of your model.  Then you rely on your service to create the model, so it can sync with storage and the server, or whatever is needed.  And you never new the model, because that could lead to desync and a 2 step creation process.

Supun Budhajeewa

unread,
Jul 9, 2016, 10:35:11 AM7/9/16
to AngularJS
Hi Steven, your reply is very insightful. Kudos!

The perception I have about domain models is that a domain model class like Book should have methods like update, delete, etc. The idea is that the Book model should take care of itself. I've coded in C#/.NET and PHP/Laravel, and we have coded relatively fatter models in both those frameworks.

I guess that should not be the case in Angular2. Domain Models are just a data structure and all manipulation should be done in appropriate service. Isn't it so?

I've changed my original plans. I now use the domain models to define the data structure. I call the service to create objects of those models and manipulate them,

Model:

class Book {
id: number;
isbn: string;
name: string;
}

Component:

class BooksCreateComponent {
book: Book;

constructor(
private Books: Books
) {
this.book = new Book();
}

save() {
this
.Books
.create(this.book);
}
}

Values are assigned to the book property of the component from the view.
Reply all
Reply to author
Forward
0 new messages