コードの臭い | ショットガン・サージェリー
こんにちは。コードの臭いリファクタリングシリーズに再び戻ってきました。今回はショットガン・サージェリー
というコードの臭いについて話します。この臭いは、変更を加えるたびにその変更をコードの別々の場所に反映させなければならない場合に検出できます。
原因
単一の責任が多数の場所に分散されている場合に発生します。これは、Divergent Changeの行き過ぎた適用後に起こる可能性があります。
例
最小残高チェックが両方のメソッドで重複しているのがわかります。
class Account {
private amount: number;
constructor(amount: number) {
this.amount = amount;
//...
}
debit(debitAmount: number): void {
if (this.amount <= 1000) {
throw new Error('Minimum balance should be over 1000');
}
//...
}
transfer(from: Account, to: Account, transferAmount: number): void {
if (from.amount <= 1000) {
throw new Error('Minimum balance should be over 1000');
}
//...
}
}
解決策
最小残高チェックをメソッドに抽出して、クラスの別々のメソッドでも再利用できるようにします。
class Account {
private amount: number;
constructor(amount: number) {
this.amount = amount;
//...
}
assertMinimumBalance(amount: number): void {
const MINIMUM_AMOUNT = 1000;
if (amount <= MINIMUM_AMOUNT) {
throw new Error(`Minimum balance should be over ${MINIMUM_AMOUNT}`);
}
}
debit(debitAmount: number): void {
this.assertMinimumBalance(this.amount);
//...
}
transfer(from: Account, to: Account, transferAmount: number): void {
this.assertMinimumBalance(from.amount);
//...
}
}
ボーナストラック
CSSでのショットガン・サージェリー? 🤔
ええ、次の例を見てください。
.button-primary {
background-color: #ec407a;
}
.button-secondary {
background-color: #b4004e;
}
.navbar-primary {
background-color: #ec407a;
}
.navbar-secondary {
background-color: #b4004e;
}
もし今、プライマリカラーを別の色に変更するように頼まれたら、どうするか?全てのCSSでグローバルに検索して置き換える?ダメです!! ⛔️
解決策はCSS変数の使用です:
:root
の疑似クラスでCSS変数をグローバルに宣言し、CSSのどの部分でも使用できるようにします。この方法では、変更可能な部分を変数に集約し、色の値を一つ一つ置換する必要を避けることができます。
:root {
--primary-background: #ec407a;
--secondary-background: #b4004e;
}
.button-primary {
background-color: var(--primary-background);
}
.button-secondary {
background-color: var(--secondary-background);
}
.navbar-primary {
background-color: var(--primary-background);
}
.navbar-secondary {
background-color: var(--secondary-background);
}
読んでくれてありがとう 😊
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/producthackers/code-smell-shotgun-surgery-2k30