Extracting an Attributes Class - ldco2016/microurb_web_framework GitHub Wiki

This is the last extraction of logic out of the class of User.

Screen Shot 2020-12-01 at 10 34 12 AM

So I am going to create a new attributes property on class User and thats going to point at some object of type Attributes and the goal is to store some information tied to a user like name, age and so forth.

This extraction is probably going to be the easiest, because essentially all I am talking about doing here is copy/pasting the remaining constructor() and get() and set() methods out of the User.

export class User {
  public events: Eventing = new Eventing();
  public sync: Sync<UserProps> = new Sync<UserProps>(rootUrl);

  constructor(private data: UserProps) {}

  get(propName: string): number | string {
    return this.data[propName];
  }

  set(update: UserProps): void {
    Object.assign(this.data, update);
  }
}

The constructor(), get() and set() is all about handling User information. I am now saying I want to extract all that into this separate submodule or composition style class like so:

export class Attributes {
  constructor(private data: UserProps) {}

  get(propName: string): number | string {
    return this.data[propName];
  }

  set(update: UserProps): void {
    Object.assign(this.data, update);
  }
}

A couple of changes will be made such as the reference to UserProps. I need to turn Attributes into a generic class so that this thing will not have any reference to UserProps. If Attributes has a reference to UserProps then its only going to be good for working with my User model and eventually I want to have a very re-usable model so I can represent different types of data such as a blogpost, images, comments and so on.

So I don't want an Attributes class that is custom-tailored to working with UserProps.

To fix that, I will add in a generic type right after Attributes like so:

export class Attributes<T> {
  constructor(private data: UserProps) {}

  get(propName: string): number | string {
    return this.data[propName];
  }

  set(update: UserProps): void {
    Object.assign(this.data, update);
  }
}

So now the constructor() can take in some object that is going to satisfy the T type and the same thing for update as well like so:

export class Attributes<T> {
  constructor(private data: T) {}

  get(propName: string): number | string {
    return this.data[propName];
  }

  set(update: T): void {
    Object.assign(this.data, update);
  }
}

On the get() method I never really referred to UserProps, but I said I am only going to either refer to a number or a string. Chances are that is only going to be good for my UserProps interface. I might have other types of data inside my application that might have boolean values on them or maybe some kind of nested object or something like that. So saying that get() is only ever going to return number | string is no longer appropriate, despite the fact I never got an error message around it.

⚠️ **GitHub.com Fallback** ⚠️