Why do people hide all class variables behind getters?

1. To keep data valid. Or, in jargony speak, to maintain an invariant. Let's look at two implementations that contain, for example, a number 0-11 to represent a month.

class C {
    constructor(month) {
        this.month = month;
    }
}

const o = new C(13); // bad; invalid object
o.month = 42; // also bad; invalid object

class C {
    constructor(month) {
        this.setMonth(month);
    }

    setMonth(month) {
        if (month < 0 || month > 11) {
            throw new Error();
        }

        this._month = month;
    }

    getMonth() {
        return this._month;
    }
}

const o = new C(13); // bad but safeguarded; throws an error
o.setMonth(42); // also bad but safeguarded; throws an error

By controlling direct access to data, by keeping it private and encapsulated, we can ensure the data, and thus the object itself, remains valid.

2. This next part is a touch controversial, but we sometimes use getters and setters even if -- for now -- we don't need to maintain an invariant. The cat's name property, for example, has no invariant. Any name is a good name. But... what if sometime in the future, as our requirements change, suddenly we do have an invariant to enforce? Except now we can't because our API already exposes the cat's name publicly.

The most important thing to get right is the interface. Everything else can be fixed later. The more users there are that depend on an interface, the more difficult it is to ever change the interface. Get the interface wrong, and you might never be allowed to fix it.

/r/node Thread