Where should I create data models?

I won’t say it that strongly, but it’s a pattern I’ve decided to avoid, although perhaps primarily for a reason that may not strictly be relevant in your case: reducing bugs related to serialization and deserialization of objects. If we put the “intelligence” (i.e. “methods”) into the data-bearing object, then every time it goes or comes from JSON (most frequently, being dropped from heaven over the network), I have to remember to sprinkle magic pixie dust on it, and if I forget, I get an object that sort-of-looks-ok-but-doesn’t-actually-do-everything-it’s-supposed-to, which can make for some hard-to-diagnose and frustrating bugs. However, there’s another huge benefit of this that you’ll see in a minute.

So the rule I use is “never manually instantiate any objects that I define”. There are largely unavoidable times where you have to new a Something object defined by an external library, but I don’t new anything that I make. Either I let Angular’s DI manage it and inject when needed, or I make it an interface so that I can just assign {foo: "bar", baz: 42} to it.

A truly OO language would not allow you to make half-assed objects that have all their data members but not their function members, and this is how I choose to keep myself from stepping on that particular rake. I don’t know if it is now a concern about passing objects with prototypes through NavParams, but if they are going into URLs you get the exact same serialization worrries, because that’s how things get stuffed into query strings. I wouldn’t do it.

A slightly separate concern I have is with rename and readdress. You have to decide if, from the POV of a Server user, the name and address are intended to be exposed or encapsulated. My instinct says to encapsulate it, in which case rename and readdress shouldn’t be public.

So what I would do is put all the other methods you currently have on ServerObject into a DI-managed ServerService, and give them an explicit Server parameter indicating the data-bearing PODO they are to work on.

export interface Server {
  name: string;
  ip: string;
}

@Injectable()
export class ServerService {
  constructor(tcp: TCPservices) { 
    // previously mentioned "huge benefit"
    // woo hoo no problem injecting tcp here
  }

  watchStatus(server: Server): Observable<ServerStatus> { ... }
}
1 Like