過去数か月にわたって、私はいくつかの言語とフレームワークにわたるソフトウェアの設計と実践について多くのことを学びました。私にとって、最も魅力的で便利なデザインパターンは、オブジェクト指向のアプローチに従うものです。特に、再利用性、モジュール性、理解(理解されたコードの再利用)などを促進するアプローチに惹かれます。
私がよく使用する一般的なアプローチは、最小結合でプログラム機能を個別のコンポーネントにカプセル化するアプローチです。このデザインを視覚化すると、オブジェクトとサブオブジェクトの階層構造を想像することがよくあります。それぞれが独自のインターフェイスとそのメンバーのインターフェイスのみを認識しています。私が理解しているように、この最後の部分は、私が上で述べた求められている特性を達成するために不可欠です。
このことを念頭に置いて、私が過去2か月にわたって取り組んできたさまざまなプロジェクトで、設計の障害にぶつかっています。シンプルで直感的なインターフェイスを備えながら、アプリケーション内で目的の機能を実行できるように、オブジェクトをどのように正確に定義しますか?より具体的に(そしておそらくより簡単な言葉で)、オブジェクトに必要な機能を実装するにはどうすればよいですか?これも一般的なアプリケーションにはあまり具体的ではありませんか?
私がこの問題に直面しているケースについて説明します。
Java Server Faces(JSF)フレームワークを使用してWebアプリケーションを作成するため、私のデザインはページテンプレートを中心にしています。これには、必要なときにいつでも再利用できるXHTMLテンプレートを作成する必要があります。
Webサイト全体で使用するすべてのヘッダーマークアップを含むヘッダーテンプレートを作成したいと思います。次に例を示します。
<!-- header.xhtml -->
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html />
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://Java.Sun.com/jsf/facelets">
<body>
<div class="title">My Website</div>
</body>
</html>
ここで、さまざまなヘッダータイトルを提供するための柔軟性を追加したい場合は、次のように挿入タグを追加できます。
<body>
<div class="title">
<ui:insert name="insertTitle">My Website</ui:insert>
</div>
</body>
この説明では詳細は重要ではありませんが、挿入タグを使用すると、このテンプレートを使用するページで、デフォルトのMy Website
の代わりにカスタムタイトルを追加できます。
テンプレートに追加されたこの機能は適切であるように思われ、間違いなく一般的に使用される可能性があります。
ただし、ヘッダーにボタンを配置する必要があるWebサイトのページが1つある場合はどうなりますか?単一の使用法がある場合でも、この目的のために別の挿入タグを追加しますか?テンプレートの他のすべての使用法では、この機能は無視されるため、コードの無駄と見なされる可能性があります。
私のこの問題は、htmlテンプレートを使用する場合だけでなく、再利用可能なサブコンポーネントの設計を含むあらゆるアプローチで発生します。機能を選択するためのヒントや設計の洞察をいただければ幸いです。
OOPを使用しないように言ったことに反対票を投じるかもしれませんが、OOPを使用しないでください。
スペースを使い果たすことなく、その理由を説明しようと思います:)
特に、再利用性、モジュール性、理解(理解されたコードの再利用)などを促進するアプローチに惹かれます。
もちろんそうですね!それが、すべてのソフトウェアエンジニアが目指していることです。それは聖杯です。意図的に反モジュラーコードを作成しようとしている人は誰もいません。さらに、あなたが書いたすべてのコードをこれらの基準に適合させることができる言語はありません。魔法の弾丸の汎用プログラミング言語はありません。
私がよく使用する一般的なアプローチは、最小結合でプログラム機能を個別のコンポーネントにカプセル化するアプローチです。
それが目標であり、アプローチではありません。作成するコンポーネントをどのように決定しますか?それらとそれらの関係をどのようにモデル化しますか?インターフェースは何ですか?抽象化のレベルはどれくらいですか?これらは重要な決定です。
このデザインを視覚化すると、オブジェクトとサブオブジェクトの階層構造を想像することがよくあります。それぞれが独自のインターフェイスとそのメンバーのインターフェイスのみを認識しています。私が理解しているように、この最後の部分は、私が上で述べた求められている特性を達成するために不可欠です。
真実ではない。
第一に、階層は私たちの頭の中で想像するのは楽しいものですが、それほど単純なことはめったにありません。これはanyフィールドに当てはまります。生物の分類を調べてみたことがありますか?それは混乱です。残念ながら、意味的に意味のある正しいオントロジーを構築することは、人間にとってほぼ不可能な作業です。これは何度も何度も証明されています。
ソフトウェアの場合のように、オントロジーのメンバー自体が絶えず変化している場合、問題はさらに複雑になります。明日は、新しいコンポーネントを追加するか、既存のコンポーネントを更新する必要があるかもしれません。あなたの階層はまだ当てはまりますか?
次に、継承とsubytpingの2つのアイデアを1つの単語階層に合成します。継承は単にプログラムを書く方法です(つまり、キーストロークを保存します)。意味的な意味はありません。サブタイピングは、言語の一部のタイプ(クラス)間に存在する固有の関係です。 2つの概念は完全に分離可能です。サブクラスが自動的にスーパークラスのサブタイプにならない継承システムを作成することもできます。同様に、一部のタイプが他のタイプのサブタイプであると自動的に決定される言語を作成することもできます。これは構造的サブタイピングと呼ばれます。
階層はモジュラープログラミングに不可欠ではありません。モジュラープログラミングにとって重要なのは、まあ、modules-明確に定義されたインターフェースを持つコンポーネントです(インターフェース自体は何らかの形のタイプです)。モジュール間に階層は必要ありません。これは通常、小規模なプロジェクトに最適なアプローチです。プロジェクトが大きくなると、おそらく何らかの形で再利用する必要があります。これの正式な用語はポリモーフィズムです。サブタイピングは、ポリモーフィズムの一形態にすぎません。 パラメトリック多相は代替アプローチです(もちろん、2つを一緒に使用することもできます)。
継承のいくつかの欠点を適切に示している特定の例を見てみましょう。多くの人はHTMLテンプレートを真のプログラミングで書くことを考えませんが、私は定義について議論するつもりはありません。 Javaコードを書くこととは大きく異なりますが、どちらも継承の弱点を共有しています。
私は実際にこの特定のドメインで実践的な経験を持っています。私の会社では、ブロックベースの拡張を可能にする名前のないテンプレートシステムも使用しています。私は主にバックエンド開発者ですが、フロントエンド機能に取り組んでいるときに、あなたが言及した正確な問題に遭遇しました多数回。私たちのコードには、特定の1つのサブクラスでのみ使用される拡張ブロックが散らばっていて、コードを読んでいる人には意味がありません。私が思いついたクリーンな解決策は1つだけです。それは、継承を使用しないことです。
サイトが小さい場合は、正直なところ、再利用や抽象化は必要ありません。 HTMLを「生で」書くだけです。最終的には、複雑な継承階層と格闘するよりも多くの時間を節約できます。
サイトが大きい場合は、再利用可能なコンポーネントが私が好む代替ソリューションです。 Webページを、混合して一致させることができるブロックに分割できるようにする必要があります。 1つのテンプレートは別のテンプレートから継承しません。ページはすべて、ページ間で共有される場合と共有されない場合があるブロックのセットで構成されています。これは、私が覚えている限り、クロージャテンプレートが行うことです(私がそれらを使用してからしばらく経ちましたが、現在使用しているシステムよりも大幅にうまく機能しました)。
終了する前にもう1つ、できる限り読んでください。この質問に対する私の答えや他の人の答えを聖句と見なさないでください。学び、学び続けます。新しいプログラミング言語を発見し、他の人が書いたものを読み、言語設計に関する教科書を学びます。知っておくべきことは常にたくさんあり、言語のデザインは絶えず進化しています。
予期しないすべての状況をサポートするコンポーネントを設計することは不可能です。ボタンを追加するのはまさにそれです。次回は検索ボックスとボタンになる可能性があるので、わかりません。
最善のアプローチは、物事を複雑にすることなく最も単純なアプローチを使用することです。カスタマイズ可能なタイトルを追加するだけです(それが今必要なものであると想定しています)。
ただし、ボタンが必要になった場合は、変更できます(JSFがどのように機能するかはわかりませんが、...このようなことが可能であることを願っています)
<body>
<div class="title">
<insert component="ButtonComponent" default="TitleComponent"></insert>
</div>
</body>
そのため、コンポーネントをタイトルとして導入し、ページごとに変更することができます。ただし、現時点で必要ない場合は、必要ない可能性があるため、追加してコードを複雑にする必要はありません。