官术网_书友最值得收藏!

Making Invalid States Impossible

Let's say that we'd like to add a field to seat to hold the date a seat was purchased:

type seat = {
section,
price: int,
person: option(person),
dateSold: option(string)
};

Now, we've introduced the possibility of an invalid state in our code. Here's an example of such a state:

let seat = {
section: Pit,
price: 42,
person: None,
dateSold: Some("2018-07-16")
};

In theory, the dateSold field should only hold a date when the person field holds a ticket holder. The ticket has a sold date, but no owner. We could look through our imaginary implementation to verify that this state would never happen, but there would still be the possibility that we missed something, or that some minor refactor introduced a bug that was overlooked.

Since we now have the power of Reason's type system at our disposal, let's offload this work to the compiler. We are going to use the type system to enforce invariants in our code. If our code breaks these rules, it won't compile.

One giveaway that this invalid state could exist is the use of option types within our record field. In these cases, there may be a way to use a variant instead such that each constructor only holds the relevant data. In our case, our sold-date and ticket-holder data should only exist when the seat has been sold:

type person = {
age: int,
name: string,
};

type date = string;

type section =
| Pit
| Floor
| Mezzanine
| Balcony;

type status =
| Available
| Sold(date, person);

type seat = {
section,
price: int,
status
};

let getSeatPrice = (seat) => seat.price;

let isAvailable = (seat) =>
switch (seat.status) {
| Available => true
| Sold(_) => false
};

Check out our new status type. The Available constructor holds no data, and Sold holds the sold date as well as the ticket holder.

With this seat type, there's no way to represent the previous invalid state of having a sold date without a ticket holder. It's also a good sign that our seat type no longer includes option types.

主站蜘蛛池模板: 兴仁县| 融水| 都兰县| 芜湖县| 正安县| 新建县| 镇坪县| 永济市| 青岛市| 弥渡县| 塘沽区| 海盐县| 小金县| 柏乡县| 宜春市| 梅州市| 宝兴县| 高阳县| 宁武县| 双城市| 灌云县| 金湖县| 古交市| 梨树县| 祁阳县| 忻城县| 竹山县| 连城县| 浦江县| 仙游县| 新民市| 繁峙县| 渭南市| 山东省| 杭锦旗| 班玛县| 胶南市| 惠水县| 襄城县| 太谷县| 博爱县|