This tiny mistake completely ruins your code

I was coding the other day and stumbled upon something atrocious.

Do you see it?

Let’s zoom in a bit more:

This line:

Please don’t do this in any language.

Don’t await properties.

You’re destroying your code readability and ruining the whole concept of OOP.

Properties are features not actions.

They don’t do like methods. They are.

They are data holders representing states of an object.

Simple states:

JavaScript
class Person { firstName = 'Tari'; lastName = 'Ibaba'; site = 'codingbeautydev.com'; }

Derived states — what getters are meant for:

JavaScript
class Person { firstName = 'Tari'; lastName = 'Ibaba'; site = 'codingbeautydev.com'; get fullName() { return `${this.firstName} ${this.lastName}`; } } const person = new Person(); console.log(person.fullName); // Tari Ibaba

But the status property was returning a Dart Future — JavaScript’s Promise equivalent:

❌Before:

JavaScript
class Permission { get status() { return new Promise((resolve) => { // resolve(); }); } } const notifications = new Permission(); await notifications.status;

It would have been so much better to use a method:

✅ After:

JavaScript
class Permission { getStatus() { return new Promise((resolve) => { // resolve(); }); } } const notifications = new Permission(); await notifications.getStatus();

And now async/await can make things even more intuitive:

JavaScript
class Permission { async getStatus() { // } } const notifications = new Permission(); await notifications.getStatus();

But guess what happens when you try async/await with properties?

Exactly. It’s a property.

This rule doesn’t just apply to async tasks, it applies to any long-running action, synchronous or not:

❌ Before:

JavaScript
class ActionTimer { constructor(action) { this.action = action; } // ❌ Property get time() { const then = Date.now(); for (let i = 0; i < 1000000; i++) { this.action(); } const now = Date.now(); return now - then; } } const splice = () => [...Array(100)].splice(0, 10); const actionTimer = new ActionTimer(splice); console.log(`time@codingbeautydev.com: ${actionTimer.time}`);

✅ After:

Let them know that the action is expensive enough to deserve caching or variable assignment:

JavaScript
class ActionTimer { constructor(action) { this.action = action; } // ✅ Get method getTime() { const then = Date.now(); for (let i = 0; i < 1000000; i++) { this.action(); } const now = Date.now(); return now - then; } } const splice = () => [...Array(100)].splice(0, 10); const actionTimer = new ActionTimer(splice); const theTime = actionTimer.getTime(); console.log(`time@codingbeautydev.com: ${theTime}`);

But sometimes it still doesn’t deserve to be a property with this.

Check this out — do you see the issue with the level setter property?

JavaScript
class Human { site = 'codingbeautydev.com'; status = ''; _fullness = 0; timesFull = 0; set fullness(value) { this._fullness = value; if (this._fullness <= 4) { this.status = 'hungry'; } else if (this._fullness <= 7) { this.status = 'okay'; } else { this.status = 'full'; timesFull++; } } } const human = new Human(); human.fullness = 5; console.log(`I am ${human.status}`);

It doesn’t just modify the backing _fullness field — it changes multiple other fields. This doesn’t make sense as a property, as data.

It’s affecting so much aside from itself.

It has side-effects.

Setting this property multiple times modifies the object differently each time.

JavaScript
const human = new Human(); human.fullness = 8; console.log(human.timesFull); // 1 human.fullness = 9; console.log(human.timesFull); // 2 console.log(`I am ${human.status}`);

So even though it doesn’t do much, it still needs to be a method.

JavaScript
class Human { site = 'codingbeautydev.com'; status = ''; _fullness = 0; setLevel(value) { this._fullness = value; if (this._fullness <= 3) { this.status = 'hungry'; } else if (this._fullness <= 7) { this.status = 'okay'; } else { this.status = 'full'; } } } const human = new Human(); human.setLevel(5); console.log(`I am ${human.status}`);

Name them right

Natural code. Coding like natural language.

So always name the properties with nouns like we’ve been doing here.

JavaScript
class ActionTimer { constructor(action) { this.action = action; } // ✅ Noun for property get time() { // ... } }

But you see what we did when it was time to make it a property?

We made it a verb. Cause now it’s an action that does something.

JavaScript
class ActionTimer { constructor(action) { this.action = action; } // ✅ verb phrase for method getTime() { // ... } }

Nouns for entities: variables, properties, classes, objects, and more.

Not this

JavaScript
// ❌ do-examples.ts // ❌ Cryptic const f = 'Coding'; const l = 'Beauty'; // ❌ Verb const makeFullName = `${f} ${l}`; class Book { // ❌ Adjectival phrase createdAt: Date; }

But this:

JavaScript
// ✅ examples.ts // ✅ Readable const firstName = 'Coding'; const lastName = 'Beauty'; // ✅ Noun const fullName = `${firstName} ${lastName}`; class Book { // ✅ Noun phrase dateCreated: Date; }

Verbs for actions: functions and object methods.

Key points: when to use a method vs a property?

Use a property when:

  • The action modifies or returns only the backing field.
  • The action is simple and inexpensive.

Use a method when:

  • The action modifies multiple fields.
  • The action is async or expensive.

All for clean, readable, intuitive code.



Leave a Comment

Your email address will not be published. Required fields are marked *