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

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.

主站蜘蛛池模板: 建平县| 渭南市| 郸城县| 科技| 库伦旗| 凯里市| 垦利县| 富源县| 纳雍县| 左权县| 淮南市| 济宁市| 余干县| 延庆县| 保康县| 鹿泉市| 铜鼓县| 隆德县| 临朐县| 什邡市| 呼和浩特市| 康马县| 牙克石市| 淮阳县| 静乐县| 望谟县| 阿拉善右旗| 嘉峪关市| 南昌县| 许昌县| 监利县| 梓潼县| 凤阳县| 平遥县| 香格里拉县| 霍山县| 苍山县| 乡宁县| 黄冈市| 池州市| 巴彦淖尔市|