デザインパターンの不条理
先週は更新が滞ってしまい申し訳ありませんでした。週末に「重慶」に行ってしまい、慌てて更新しました。
重慶は私にとって馴染みのあるようでない街です。ここ数年で少し変わりましたが、相変わらず美しく、人々が行き交い賑やかで、ただ少し商業的になり、海外からの観光客が絶え間なくやってきます。
なぜ旅行?食べ物や景色を楽しむ人もいれば、その土地の風習を楽しむ人もいます。新しい人に会いたい人もいれば、旧友に会いたい人もいます。過去の自分を見つけたい人もいれば、新しい自分を見つけたい人もいます。そう、旅のポイントは、自分の求めるものを見つけること、違う計画を立てること、違う感覚を味わうこと。
今回は重慶に戻り、友人たちと会ってお茶を飲みながら昔話に花を咲かせ、若くて軽薄だったあの頃に戻った気分。わずか数時間ですが、また、多くのことを話し、常に無限の話題があり、常にさよならを言う時間があります。
そしていつものように、なぜこの記事を書いたかについて少し。
まず1つ目は、人々がデザインパターンに興味を持つようになったこと、そしてすべてのプログラマーが習得すべき思考法でありツールであることです。
第二は、デザインパターンを使用して、本当に使用される通常の作業であるだけでなく、あなたのプログラムをより堅牢にすることができ、保守性が向上し、主なものは、それが強制的に高く見えるということです!
3つ目は、デザインパターンが簡単ではないということです。 私自身、初めてデザインパターンを学んだとき、いつも「ちょっと複雑だな、覚えられないものが多いな」と感じていました。あるいは、「そのときは理解できたような気がするけど、忘れてしまい、いざ使おうとすると、また混乱して、どのデザインパターンを使えばいいのかわからない」。冗談ではなく、あなたもこのように感じたことがあるのではないでしょうか。
デザインパターンに関する本はたくさんありますし、ネット上のブログもたくさんあります。では、デザインパターンについて記事を書くとして、それが読者にもたらす価値はどこにあるのだろうかと考えます。デザインパターンを機械的に紹介するだけでは、あまり意味がありません。今日は、デザインパターンをどのように認識し、どのように学ぶか、そして、デザインパターンをプログラミングのツールとしてどのように活用し、茨の道を切り開くかについて、より詳しくお話したいと思います。
デザインパターンについての質問
まずはじめに、デザインパターンに関するいくつかの疑問について、皆さんと議論したいと思います。これらは、この記事を書こうと思ったときに私の頭に浮かんだ疑問のいくつかであり、私自身もいくつかの答えを出してみました。
1 デザインパターンが解決する問題とは?
ソフトウエアは工学の一分野であり、機能を実装するのは簡単ですが、機能を実装した上で、より「拡張しやすく、変化に対応しやすい」ものにするのがソフトウエアの技術です。
ほとんどの場合、ゼロからコードを書いているのではなく、「コードを変更している」ことに気づくでしょう。よく設計されたコードであれば、小さな場所を変更するだけで、あるいは変更しなくても、新しい機能を実現することができます。一方、設計の悪いコードは、地雷のラインのように変更させる、大きな赤の変更、これはプログラムがあまりにも結合されています。
あらゆるソフトウェア方法論を見てみると、その大半が結合の問題に取り組んでおり、プログラムを高度に凝集させ、結合を低くすることに最善を尽くそうとしていることがわかります。
"デザインパターンは、オブジェクト指向の使用によってもたらされるソフトウェアの複雑さ、特に変化に直面したときに対処するもの"です。コードを書く一番最初の段階で、後に起こるかもしれない変更を考慮し、少しでも良いプログラムになるように、そして後の変更にかかるコストができるだけ小さくなるように設計できればと思います。
2 デザインパターンの6つの原則とは?
デザインパターンに関する本や一連の記事を読むと、基本的にデザインパターンの6つの原則の紹介から始まります。
ソフトウェアの複雑さを解決するために上記のデザインパターンは、実際にはオブジェクト指向の使用であり、その具体的な解決方法は?実際には、前の世代によって要約されたこれらの原則に依存しています。
「なぜなら、特定のデザインパターンは「テクニック」であるのに対し、6つの原則は「道」だからです。どのようなデザインパターンも、この6つの原則の1つ以上に従っていることがわかります。
"このうち、開閉の原理はやや特殊です。最も "仮想的 "なものであり、他の原理は開閉原理を実現したものと見ることができます。
"
あなたがプログラムを書く場合は、既知のデザインパターンを使用していない場合でも、あなたがプログラムを書き出すように、6つの原則に従うようにしようとすると、基本的に "高結合、低結合 "の特性を持って、あまりにも悪くなることはありません。
もちろん、原理原則というものは、時には違反することもあり得るということです。ただ、違反することのコストと、それがもたらす利益を天秤にかけて、それに見合う価値があるかどうかを判断しなければなりません。
3 なぜ23のデザインパターンがよく言われるのですか?
というのも、「デザイン・パターン」という言葉は、「最もよく使われるデザイン・パターン」とも呼ばれる23のデザイン・パターンをまとめた『デザイン・パターン』という本の中で、Gang of Fourによって紹介されたものだからです。
ですから、実際には23以上のデザインパターンがあります。ただ、これらの23はより一般的に使われているデザインパターンであり、異なるシナリオに適用できますが、ソフトウェア設計シナリオの大部分もカバーしています。これらの23のデザインパターンは、前世代の「経験」や「ルールセット」に過ぎず、時には経験がまだかなり重要で、これらの経験を使用すると、多くの回り道を減らすことができます。
時にはデザインパターンの様々な互いに組み合わせて使用することができます、またはいくつかの変更の上に既存の23のデザインパターンでも、いくつかの新しい "ルーチン "をまとめ、既存の23のデザインパターンを解決するために使用される問題を解決することはできませんが、正常です。デザインパターンは、静的死んでいない、それは柔軟である必要があります。
4 デザインパターンをマスターするには?
デザインパターンには非常に多くの種類があり、しかも柔軟性が高いので、どうすればデザインパターンという野生馬をうまく飼いならすことができるのでしょうか?
最初のステップは、6つの設計原則を理解すること、それらを食べ尽くすこと、なぜそこにあるのか、それに従わないとどうなるのかを理解することです。6つの設計原則を理解することは、具体的な設計パターンの理解を深めることにつながります。
デザインパターンを学ぶ際に重要なのは、「そのデザインパターンがどのような問題を解決するのか?そのデザイン・パターンを使わないと、どんなデメリットがあるのか?次に同じような問題に直面したときに、その問題を解決するデザインパターンがあることを思い出せるようにするためです。
それから、このデザイン・パターンがどのように機能するのか、できれば例を使って、より生き生きとした感触を得るために、自分でコードを書くことができます。それから、オープンソースのコードを見て、神々がこのデザインパターンをどのように使っているかを見てください。
デザインパターンを学ぶには?
デザインパターンは一種の「ルーティン」なので、デザインパターンを学ぶこともルーティンになります。任意のデザインパターンを選び、それを適用します。例えば、テンプレート・メソッド・パターン。
どのような問題が解決されたのですか?
親クラスに複数のサブクラスがあり、「すべてのサブクラスに共通」なロジックがあるとします。例えば、固定フローや固定分岐ロジックなどです。
使わなかったらどうなりますか?
テンプレートメソッドパターンを使用せず、各サブクラスが独自に実装している場合、多くの「重複コード」を作成することになり、この共有ロジックを変更したい場合は、各サブクラスを変更する必要があります。
どのような原則に従ったのですか?
- リヒターの置換原則。テンプレート・メソッドに共通するロジックが親クラスで定義され、抽象でない場合、サブクラスはそのメソッドをオーバーライドすべきではありません。サブクラスで実装する必要があるメソッドは抽象として定義され、サブクラスで実装する必要があります。
- 依存関係の逆転、インターフェイス、抽象クラス指向プログラミングの原則。クライアントが依存する必要があるのは親クラスだけで、サブクラスには依存しません。
サンプルコード?
登録のようなテンプレート的なアプローチに適した例を見てみましょう。登録のプロセスは比較的決まっていますが、Eメール登録や携帯電話登録など、さまざまな登録方法が考えられます。
まずは登録からCAPTCHA送信までのフローを定義してみましょう:
- ユーザー名を入力
- ユーザー名が正しい形式であることを確認してください。
- フォーマットが正しくない場合は例外がスローされ、フォーマットが正しい場合は登録が成功し、検証コードが送信されます。
最初に抽象親クラスを定義します:
public abstract class SignUpTemplate {
public final void signUp(String username, String password) {
if (!isValidUserName(username)) {
throw new RuntimeException("ユーザー名の書式が正しくありません");
}
save(username, password);
sendCode(generateCode());
}
protected abstract boolean isValidUserName(String username);
protected abstract void sendCode(String code);
private String generateCode() {
return "ランダムな6桁のCAPTCHAを生成する ";
}
private void save(String username, String password) {
// 二次暗号化、ドロップ・ライブラリ、その他の操作
}
}
その後、サブクラスの実装は個別に定義されます:
// emailサブクラスを登録する
public class EmailSignUp extends SignUpTemplate {
@Override
protected boolean isValidUserName(String username) {
// Eメールのフォーマットが満たされているか確認する
return false;
}
@Override
protected void sendCode(String code) {
// コードをメールで送る
}
}
// 携帯電話番号登録サブクラス
public class PhoneSignUp extends SignUpTemplate {
@Override
protected boolean isValidUserName(String username) {
// 携帯電話番号の形式と一致しているか確認する
return false;
}
@Override
protected void sendCode(String code) {
// コードを携帯に送る
}
}
クライアントはおそらくこんな感じでしょう:
SignUpTemplate signUp = context.getSignUp();
signUp.signUp(context.getUsername, context.getPassword);
このモデルのオープンソースコードを使用
SpringのAbstractApplicationContextクラスのリフレッシュメソッドは、テンプレートメソッドパターンの典型的なアプリケーションです。Springのソースコードを知っている友人なら、このコードを見たことがあるはずです。
上記の "ルーチン "をマインドマップにまとめると、ひょうたんの例に従って、他のデザインパターンもこのルーチンを使ってみて、デザインパターンを素早く理解できるかどうかを確認することができます。
最も重要なことのひとつは、最初のステップである「どのような問題を解決するか」を明確にすることです。また、覚えておくことが最も重要です。思い出せなくなるのが怖ければ、ドキュメントや表を使って記録しておけば、コードを書くときに漠然とあるデザインパターンを使う必要性を感じて、どれを使えばいいのか思い出せないときに、いつでも相談に行くことができます。
"具体的な実装の詳細については、それほど重要ではありませんし、使う必要が出てきてから調べても遅くはありません。"
このルーティンでも、デザインパターンは難しいと感じますか?
私はヤシンです。顔が良くて楽しいプログラマーです。
個人ウェブサイト:https://yasinshaw.com





