F
F
FFEK2022-04-21 11:35:42
JavaScript
FFEK, 2022-04-21 11:35:42

I'm making an SDK. How to explain to the user whether the getter is immutable or mutable?

I apologize for being stubborn. Both the concepts implemented in my SDK and the question itself.

Here is

class Cat {
...
}


And there is one feature. This class has a method clone!

That is, you can do this
var cat = new Cat();
cat.color = Colors.BLACK;
var cat2 = cat.clone();
cat2.color = Colors.RED;

And it turns out really 2 cats of 2 different colors.
Cool idea, right?

I think that although it is debatable (to drag approaches from one language to another), it is convenient.

And now about the problem.
There is a class CatPairin it 2 fieldsCat
var catPair = new CatPair();
catPair.male.color = Colors.BLACK;

What do you think will happen? Well, according to the canons of JS, the color of one of the cats in the pair should really change here. So far, everything is OK.

But you also need to make a class CatValue. In which there will also be a field\property Cat. And here it should work differently.
The task of the class CatValueis:
1. Give the user the opportunity to fill in the form fields to create a cat. CatValueat the same time, it will lie in the React state and store the state of the form fields. And when the fields are changed, it will try to form a cat, and if this does not work out, then it will return errors, which will also be placed in the state in order to immediately display them to the user.
2. After everything is filled out correctly and the submit form is done, CatValueit should return a cat, that is, an instance of the classCat, and further work will be with him.

In general, it CatValueis stored in the state and therefore must be immutable.
This means that you can't do this:
const { catValue } = this.state
catValue.cat.colors = Color.BLACK

But just something like this:
const { catValue } = this.state
const newValue = catValue.changeColor(e.target.value)
setState({ catValue: newValue })

How to do it? Since normal readonly fields were not delivered to JS, you probably just need to:
class CatValue{
...
get cat() {
return this._cat.clone()
}
...
}


OK, but the user doesn't know what cloning is. (It's written in the doc, but he didn't read it.) And we need to do something so that the user understands that it doesn't work that way, that you shouldn't try to mutate it!

Therefore, I think that in this case it is necessary to make not a getter, but a method, and name it so that an attempt to mutate looks strange. For example:
catValue.buildCat().color = Colors.BLACK;
But there is a problem. That it's a lie. The method does not build a cat. It just clones. OK, let's call it:
catValue.cloneCat().color = Colors.BLACK;
Now it's normal. But it’s not the norm with the m / s that, with the normal receipt of a knocked down cat, it is not clear why it should be cloned. And how then to name a method?

And is this normal, given that everything else in the project is done on the basis of properties, not methods?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sergey Sokolov, 2022-04-21
@sergiks

The cat object is not aware of the state's immutability requirements. Therefore, it is better to postpone these dances to the same place where immutability is required.
Alternatively, use immer to change deep properties without worrying about immutability:

import produce from "immer"

const nextState = produce(this.state, draft => {
  // тут можно всё менять, не беспокоясь об иммутабельности
  const { catValue } = draft;
  catValue.cat.colors = Color.BLACK;
});

this.setState(nextState);
or not the whole state
import produce from "immer"

const { catValue } = this.state;
const nextCatValue = produce(catValue, draft => {
  // тут можно всё менять, не беспокоясь об иммутабельности
  catValue.cat.colors = Color.BLACK;
});

this.setState({ catValue: nextCatValue });

A
Anton Shamanov, 2022-04-21
@SilenceOfWinter

Since normal readonly fields were not delivered to JS,

https://jsdoc.app/tags-readonly.html
On the side of the read-only language, fields are obtained using getters i.e.
class Cat
{
    constructor(color) {
         this._color = color;
   }
    get color() {
         return this._color;
   }
}

const cat = new Cat('white');
console.log(cat.color)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question