2

Consider the following JavaScript code:

class MyClass {
   #myPrivateField;
   constructor() {
      #myPrivateField = new AnotherClass();
      this.theGetter.method1(); // or: this.#myPrivateField.method1(); 
      this.theGetter.method2(); // or: this.#myPrivateField.method2();
   }
   get theGetter() {
      return this.#myPrivateField;
   }
}

Obviously, invoking the "getter" method of theGetter causes some negligible overhead, or probably gets inlined. Inside of the class, the getter could've perfectly been alternated with a "direct access" notation (i.e, through this.#myPrivateField.method1(), for example).

Regardless of the performance penalty, in a software engineering perspective, why should or shouldn't I stick to one notation over the other inside the context of the class and what is the best practice in this regard?

goodUser
  • 129
  • 3
  • Not exactly sure what it is that you are asking here. The vibe I get is that this a stylistic question. But if you are talking about communicating intent. Then always pick the usage that is clearest to your reader. Generally calling you own public interface is not very clear (though there are exceptions) – Kain0_0 Mar 23 '20 at 07:14
  • 1
    @Kain0_0 Thanks for the response; It's more than a "stylistic" question: take for granted that the advocates of the "getter" usage may rationally argue that not only changing the "foundations" (i.e. the very private fields) would be trivial, but also it utilizes the the expressive public interface that improves readability; in this sense, what would the critics may validly argue? – goodUser Mar 23 '20 at 07:47
  • 1
    I think the question you are asking is actually just [Why use getters and setters/accessors?](https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors). Anyways, I'm not sure if those principles apply well in JavaScript context. – akuzminykh Mar 23 '20 at 07:57
  • 1
    @akuzminykh Thanks for the response; The concepts do apply as JavaScript is an object oriented language and the same features are provided. Also, my question is more specific than: _"whether or not to use the accessors (getters and setters) in general"_, but rather: _"whether or not to utilize the getter notation inside the context of the class, and why?"_ – goodUser Mar 23 '20 at 08:18
  • @akuzminykh not *exactly* applicable currently, as you need some workarounds for private fields. Still, getters and setters are there and you *can* hide data to make it sort of private. However soon when actual private fields are possible with the class syntax, then it'd be even more applicable. The [proposal is currently at Stage 3](https://github.com/tc39/proposal-class-fields) which is one step before the release stage. – VLAZ Mar 23 '20 at 08:19
  • 1
    @VLAZ While the "private fields" are not yet in the "formal standard", but the support is getting widespread; Nevertheless, it's more of a _Software Engineering_ question than a _JavaScript-specific_ one! – goodUser Mar 23 '20 at 08:28
  • @goodUser *"whether or not to utilize the getter notation inside the context of the class, and why?"*, this should be done when the getter/setter does more than just getting/setting the field. When this is not the case, you should just access the field directly. An interesting thing to ask yourself is: *"What to do if the getter/setter potentially has additional functionality in the future?"*. This is something that has to be evaluated from case to case and thus is not answerable in a generalized way. If you are not sure what to do, just do the most readable. You can refactor later anyways ... – akuzminykh Mar 23 '20 at 08:49
  • @goodUser I was adding some context for akuzminykh to assure that the question does make sense. However, they are also correct in that being a cross-site dupe for [Why use getters and setters/accessors?](https://stackoverflow.com/q/1568091). – VLAZ Mar 23 '20 at 09:28
  • What is the significance of the # symbol used here? – candied_orange Mar 23 '20 at 10:32
  • 1
    @candied_orange The symbol of `#` indicates a [private field](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_fields#Private_instance_fields) in JavaScript. – goodUser Mar 23 '20 at 11:00

2 Answers2

3

Besides the general principles of Why use getters and setters/accessors? I try to answer that with an example, and focus on the usage class-internally as this is your question.


One thing for clarification: In Java there are two classes to represent a point in time regarding Coordinated Universal Time (UTC) where both have a method to get their value, which is in milliseconds, i.e. Date#getTime and Instant#toEpochMilli.


Imagine a class in two versions using Java:

class Data {
    private Date date;

    public Date getDate() {
        return date;
    }

    public long getMillis() {
        return date.getTime();
    }
}
class Data {
    private Date date;

    public Date getDate() {
        return date;
    }

    public long getMillis() {
        return getDate().getTime();
    }
}

Note that the first version uses the field directly while the second version uses the getter.

Now imagine I want to change the type of date to Instant thus I have to change the versions as follows. I will do minimal effort in changing. The first thing to change is obviously the field itself.

    private Instant date;

The second thing to change is the getter. But how? Do we change it to return the new type or do we a conversion?

    public Instant getDate() {
        return date;
    }
    public Date getDate() {
        return Date.fromInstant(date);
    }

Depending on how we changed the getter the method that uses the getter changes as follows.

    public long getMillis() {
        return getDate().toEpochMilli();
    }
    public long getMillis() {
        return getDate().getTime();
    }

As you can see, when we change the getter to convert from the previous type to the new type, we don't have to change the using method at all.

The version of the method that accesses the field directly has to be changed as follows.

    public long getMillis() {
        return date.toEpochMilli();
    }

Now I hope this clarifies the benefit of using the getter inside the class itself. You will have less effort to put in when refactoring the code. But is it worth it?

Maybe you don't want to use the previous type anymore at all. Maybe the trouble to refactor the class is minimal. Maybe the factor readability comes into place. How will the class potentially change, may there be a functionality in the getter in the future? Are there conventions in my company?

All those questions' answers depend on the specific use case thus there is no generalized answer.

Anyways, I suggest to use the fields directly as (from my experience) the refactoring doesn't hurt and brings more benefits most of the time. You will have cleaner code and no strange mixtures of concepts. If you are not sure, just do the most simple and readable solution.


The answer disregards the case where the getter/setter does more than just getting/setting the field. In that case you obviously always want to use the getter/setter.

akuzminykh
  • 429
  • 4
  • 12
  • 1
    +1: I do appropriate the efforts to convey your idea, thank you. I'm looking for a more engineering analytics and comparisons. However the "getter" approach does really seem to fit more appropriately in this regard as it's capable of returning _dynamically computed value_ and perfectly reflects the status of an internal variable in a _readonly_ manner; Additionally, in my specific case in JavaScript, unlike Java, the getter methods are invoked merely by their name, without the invocation-parenthesis: `()`, as though they're "properties", which adds to _elegance_ and _readability_ even further. – goodUser Mar 23 '20 at 11:38
1

Check the semantics first. Someone might subclass your class and (mis-)override the getter to not to return the instance variable. In this sense, utilizing the getter instead of the instance variable is wrong, even in the base class itself.

On the other hand, you might not allow subclassing.

someOne
  • 103
  • 4
gnasher729
  • 42,090
  • 4
  • 59
  • 119