Try   HackMD

Introduce Parameter Object

練習用的 REPL

const station = { name: "ZB1", readings: [ {temp: 47, time: "2016-11-10 09:10"}, {temp: 53, time: "2016-11-10 09:20"}, {temp: 58, time: "2016-11-10 09:30"}, {temp: 53, time: "2016-11-10 09:40"}, {temp: 51, time: "2016-11-10 09:50"}, ] }; function readingsOutsideRange(station, min, max) { return station.readings .filter(r => r.temp < min || r.temp > max); } // 某個呼叫端可能會這樣呼叫 alerts = readingsOutsideRange(station, operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling);

min、max 是一組的,做成 Parameter Object。

class NumberRange { // Parameter Object,常常是 Value Object constructor(min, max) { this._data = {min: min, max: max}; } get min() {return this._data.min;} get max() {return this._data.max;} } function readingsOutsideRange(station, min, max, range) { return station.readings .filter(r => r.temp < min || r.temp > max); } alerts = readingsOutsideRange(station, operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling, null); // 多加上 null,在 JavaScript 內,呼叫端應該不會受影響(但不總是 100% 安全,得跑測試) // 在使用 Parameter Object 後,可以傳入 const range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling); alerts = readingsOutsideRange(station, operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling, range);
function readingsOutsideRange(station, min, range) { // 先移除參數 max return station.readings .filter(r => r.temp < min || r.temp > range.max); } const range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling); alerts = readingsOutsideRange(station, operatingPlan.temperatureFloor, range); function readingsOutsideRange(station, range) { // 再移除參數 min return station.readings .filter(r => r.temp < range.min || r.temp > range.max); } const range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling); alerts = readingsOutsideRange(station, range);

把判斷是否在區間內的行為,搬回 Parameter Object 內。

function readingsOutsideRange(station, range) { return station.readings .filter(r => r.temp < range.min || r.temp > range.max); } class NumberRange { constructor(min, max) { this._data = {min: min, max: max}; } get min() {return this._data.min;} get max() {return this._data.max;} contains(arg) {return (arg >= this.min && arg <= this.max);} // 將 filter 內容抽成 contains } function readingsOutsideRange(station, range) { return station.readings .filter(r => !range.contains(r.temp)); // 使用 method 加強語意 }