背景
「良いコード悪いコードで学ぶ設計入門」の復習の為です。TypeScriptで記述します。
今回は「プリミティブ型執着」についてです。
プリミティブ型とは
プリミティブ (primitive、プリミティブ値、プリミティブデータ型) はオブジェクトでなく、メソッドを持たないデータのことです
number型、string型、boolean型等です。
プリミティブ型執着とは
プリミティブ型を乱用したコードのことを言います。
以下の記事での定義も引用させて頂きます。
ドメインの概念を表すのに基本データ型を用いること
例
- メッセージを表すのに文字列を使う
- 金額を表すのに整数を使う
今回の例では郵便番号と住所を扱います。
Address.ts
const fetchZipcodeByGoogleMapLink = async (googleMapLink:string,address:string) => {}
const validateAddressForZipcode = (address:string)=> {}
const fetchZipcodeByOriginalApi = async (address:string) => {}
const formatZipcode = (zipcode:string) => {}
const formatAddress = (address:string) => {}
プリミティブ型執着によって起こる問題
-
同じ処理を複数箇所で記述
Address.tsconst formatZipcode = (zipcode:string) => {}
別のファイルで同じ処理を記述してしまいます。
b.tsconst formattedZipCode = (zipCode:string) => {}
-
可読性の低下
Address.tsファイル内で修正、機能追加をすると住所、郵便番号の処理が複雑化していきます。
意味のあるクラスを作る
AddressクラスとZipCodeクラスを作ります。
各クラスそれぞれに関連のあるロジックを凝集させることができます。
Address.ts
class Address {
private address:string;
constructor(address:string){
if(!address) throw new Error('住所が空で渡されました')
this.address = address;
}
private validateAddressForZipcode(){
this.address = ~~~
}
private reshapeKyotoAddress(){}
getAddress(){
~~~~~~~~
return this.address();
}
}
ZipCode.ts
class ZipCode {
private zipcode:string|null = null;
async getZipcode(address:Address){
await setZipcode(address:Address);
this.formatZipcode();
return this.zipcode
}
private async setZipcode(address:Address){
const reshapedAddress = address.getAddress();
this.zipcode = await this.fetchZipcode(reshapedAddress);
}
private async fetchZipcode(address:string){
const promiseArray = [this.fetchZipcodeByOriginalApi(address),this.fetchZipcodeByGoogleMap(address)];
resultList = await Promise.allSettled(promiseArray);
~~~~~~~~~~~
}
private async fetchZipcodeByOriginalApi(address:string){}
private async fetchZipcodeByGoogleMapLink(address:string){}
private createGoogleMapLink(address:string){}
private formatZipcode(){
this.zipcode = ~~~~;
}
}
call.ts
const address = new Address('広島県広島市南区段原1丁目1-1');
const zipcode = new ZipCode().getZipCode(address);
その他
プリミティブ型の引数が多い時にも、その引数をインスタンス変数に持つ意味のあるクラスでまとめられると可読性が改善できます。
最後に
- データはプリミティブ型だけで実装はできますが、データとそのロジックを一つのクラスで管理するのはバグも起きづらく、可読性も上がるので有効だなと思いました
- プリミティブ型執着を回避するのを業務のコードにも使う場面があれば導入したいと思います
- 無理にこのプリミティブ型執着を回避するのではなく、本当に概念としてクラス化できるか考えた上で行いたいです
- オブジェクトでまとめたことはありますが、ロジックは別で書いていたことがあるのでそこをクラス化して改善したいです