eguneys
eguneys

Reputation: 6396

How to get rid of state or dependencies to simple reason

I have a class that has internal state and public getters:

function Section() {

  let ls = ['a','b','c','d','e','f'];
  let i = 0;

  this.map = () => ls[i];

  this.changeI = () => i=(i+1)%ls.length;

}

I have a user of this class:

function Ground() {

    let section = new Section();
    let mover = new Mover(this);

    let map;

    this.map = () => map;

    this.init = () => {
        map = section.map();
    };


    this.draw = () => {
      console.log(map);
    }
}

and user of that class:

function Mover(ground) {

  let map = ground.map;


  this.dojob = () => {
    let usemap = map()

    return usemap + 'X';
  }
}

Now when I call changeI, the return of the map function changes so I need to update the variable I use to draw the map in Ground function. I can make it a getter function instead of a variable as Mover class uses, but I think there is something wrong with this approach, I mean is there a better way to do this, or can I get rid of this internal state or the nested dependencies? I need an answer as simple as few abstractions as possible.

Upvotes: 1

Views: 48

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42228

Each of these classes has an internal instance of Section or an internal instance of another class which accesses Section. So you can call .map() and always get the updated value from the Section map, regardless of i;

Note that Ground creates its own new Section() rather than taking an existing Section instance as an argument, so the only way to call changeI on this Section instance is through ground.section.changeI().

Is there a reason that you aren't using ES6 class syntax? I rewrote these as classes with a typescript annotations (but you can remove those) and some other changes which I think make it much more readable.

class Section {

    private ls = ['a', 'b', 'c', 'd', 'e', 'f'];
    private i = 0;

    public map = (): string => {
        return this.ls[this.i];
    }

    public changeI = (): void => {
        this.i = (this.i + 1) % this.ls.length;
    }

}

class Ground {

    public readonly section = new Section();

    public map = (): string => {
        return this.section.map();
    }

    public draw = (): void => {
        console.log(this.map());
    }

    public createMover = (): Mover => {
        return new Mover(this);
    }
}

class Mover {

    private readonly ground: Ground;

    constructor(ground: Ground) {
        this.ground = ground;
    }

    public dojob = (): string => {
        return this.ground.map() + 'X';
    }
}

You can test it out and see that we are properly incrementing in all places.

const ground = new Ground();
const mover = new Mover(ground);
ground.draw(); // "a"

ground.section.changeI();
ground.draw(); // "b"
console.log( mover.dojob() ); // "bX"

ground.section.changeI(); 
console.log( mover.dojob() ); // "cX"

Upvotes: 1

Related Questions