抽象化:開発者の考え方
あらゆるソフトウェアシステム、ハードウェアアーキテクチャ、本質的にはすべての複雑な事象に根底にある最も重要な考え方は、抽象化です。
抽象化は、複雑な現実世界のシステムをより単純なコンポーネントに分解し、作成者と非作成者の両方が「このものは何か」を素早く理解するために役立ち、現実世界のシステムの複雑さを管理するのに役立ちます。抽象化は、ソフトウェアアプリケーションからハードウェアまで、そしてアニメーション映画などの「非技術」の産業にまで、現代の世界のほぼすべての側面で見つかります。しかし、それは特に開発者にとって重要であり、彼らはこのコンセプトに毎日取り組んで使っています。基本的に、抽象化はすべての開発者の第二本能であるべきです。
「抽象化」とは何ですか?
一般的に、「抽象化する」とは、「何かが誰かに対してどう見えるかを定義すること、それでいて関係のない情報を無視する」ことを大体意味します。
!!! ノート 抽象化は、「意味論」と呼ばれることもあります。
一部の人々は、「抽象化」という言葉を異なる方法で定義するかもしれません。 例えば、「複数の実体に共通する抽象的な自然」と定義することもできます。 ここでは、その定義を2つの部分に分けています。 「抽象的な性質」という部分を抽象化と定義しています; 「複数の実体に共通する」部分を後のセクションで紹介する「標準」と定義しています。
上記の定義によると、何かを抽象化する際に考慮するべきいくつかの重要な問いがあります。
- 抽象化する「もの」とは何ですか?
- その「誰か」とは何ですか?その「誰か」と「もの」はどのように相互作用しますか?
- その「誰か」の視点で見たとき、この「もの」は何ですか?
- どの情報が関連していますか?どの情報は関連していませんか?つまり、「誰か」が知る必要がある情報は何ですか?
これらの質問の答えは、抽象化の「対象オーディエンス」、すなわち、抽象化を使用し、抽象化と相互作用する人(またはシステム)に依存します。オーディエンスが変わると、「もの」は異なるように見え、関連する情報が無関係になったり、その逆になったりする可能性があります。
抽象化は他の人のためだけではありません。時には(実際にはほとんどの場合)、対象オーディエンスは、抽象化されるべきものを設計・実装している自分自身になります。
上記で定義を示しましたが、抽象化自体は非常に明確に定義することが非常に困難な「抽象的な」アイデアであり、広く受け入れられている定義はありません。したがって、抽象化が実際に何を意味するのかを示す例を使用します。
抽象化の例
朝忙しい時に車を見ると、最初に思い浮かぶのは何ですか?「この物体を運転できる」という意味ですか?それともシャーシ、エンジン、タイヤ、燃料タンクですか?
多くの人が前者の意味を持っていると思います。もちろん、後者の見方も重要ですが、その瞬間には関係のない情報です:忙しいので、重要なのは職場に早く行くために車を運転できることだけです。
信じるかどうかは別として、上記の例であなたは既に抽象化を作成しています。少し分解してみましょう:
- 抽象化の対象:車です。
- 抽象化の対象オーディエンス:あなたです。
- この「もの」(抽象化):どこにでも行けるように運転できるもの。
- 関連する情報:このものを運転できます。速いです。
- 関係のない情報:エンジン、燃料タンク、シャーシなどで構成されています。長さは4.6メートル、高さは1.6メートルで、最大出力は140馬力です。そのようなことです。
上記の説明は理解しやすいはずです。対象オーディエンスはあなたであり、知る必要があるのは車を運転できることだけです。それが抽象化です。
一方、車の工場で働く従業員にとっては、見方は異なります。従業員は車を製造します。車を運転する必要はありませんが、車の内部構造を知って車を組み立てる必要があります。この場合、以下のようになります。
- 抽象化の対象:車です。
- 抽象化の対象オーディエンス:工場の労働者です。
- この「もの」(抽象化):エンジン、燃料タンク、シャーシなどで構成されるもの。
- 関連する情報:車の内部構造。
- 関係のない情報:車を運転する方法。
ご覧のように、抽象化は対象オーディエンスに依存します。対象オーディエンスが変わると、抽象化の対象の定義が変わり、以前に関連する/関係のない情報が関係する/関係のない情報に変わることもあります。
抽象化はまた、対象オーディエンスの役割にも依存します。車を運転している間、車の抽象化は「運転できるもの」です。車を修理している間、抽象化にはエンジン、タイヤなども含まれ、それはあなたにとって関連する情報になります。
したがって、常に対象オーディエンスを識別し、その対象の抽象化の対象が何をするのかを理解し、どの情報が関連するか/関連しないかを理解し、対象をオーディエンスに対して抽象化することが重要です。
抽象化に関連する用語とフレーズ
開発者の世界では、抽象化に関連するいくつかの用語やフレーズに遭遇する可能性があります。 以下にいくつかの用語の意味を示します:
抽象化
シナリオによっては、「抽象化」には3つの異なる意味があります:
- 最初の意味は、このセクションで定義されているオブジェクトの「抽象的な定義」です。 この意味では、「何かが誰かにどのように見えるか」が重要ですが、それが単純か複雑かは「誰か」によって異なります。
- 2番目の意味は、「関係のない詳細を隠すことで作成されたオブジェクトの簡略化された定義」です。 この意味では、「抽象化」は詳細を隠した簡略化された説明であることを強調しています。
- 3番目の意味は、「潜在的に多くのオブジェクトに適用される抽象的な標準」です。 この意味では、「抽象化」が潜在的に多くのオブジェクトに適用されることを強調しています。
上位/下位の抽象化
高レベルの抽象化は、より抽象的な抽象化であり、低レベルの抽象化はより具体的な抽象化です。 言い換えると、高レベルの抽象化は通常、より単純ですが、実際のオブジェクトには遠いです。 一方、低レベルの抽象化は通常、より複雑ですが、抽象化の対象に近いです。
例えば、抽象化の対象が車である場合、高レベルの抽象化は「運転できるもの」であるかもしれません。 低レベルの抽象化は「エンジン、シャーシ、車輪などがあるもの」となるかもしれません (はい、これも抽象化です。すべての燃料駆動車にはエンジン、シャーシ、車輪があり、この定義はエンジン、シャーシなどの内部機能を隠しており、「抽象的で一般的」なイメージかもしれません)。
開発者の世界では、抽象化はどのように表れるのか?
車の例は、抽象化の概念を説明していますが、開発者の世界とは何の関係もないようです。では、実際のソフトウェアシステムやコードにおいて、抽象化がどのように表れるのかを見てみましょう。
以下は、KonnyakuGPTというAIパワードのアニメ字幕生成ツールのソースコードフラグメントです(コードの内容を理解する必要はありません):
def simple_split_subtitles(subtitles: Sequence[srt.Subtitle], max_duration: datetime.timedelta) -> List[srt.Subtitle]:
"""Splits subtitles that are too long.
The splitting scheme is simple; sentences are LIKELY to be broken into pieces.
Args:
subtitles (Sequence[srt.Subtitle]): Original subtitles.
max_duration (float, optional): The maximum duration of each output subtitle, in seconds. Defaults to 10.
"""
new_subtitles = []
for subtitle in subtitles:
remaining_text = subtitle.content
current_start = subtitle.start
splitted_subtitles = []
while len(remaining_text) > 0:
expected_text_length = math.floor(max_duration / (subtitle.end - current_start) * len(remaining_text))
actual_text_length = min(expected_text_length, len(remaining_text))
item_text = remaining_text[:actual_text_length]
item_duration = len(item_text) / len(remaining_text) * (subtitle.end - current_start)
splitted_subtitles.append(srt.Subtitle(
index=len(new_subtitles) + len(splitted_subtitles),
start=current_start,
end=current_start + item_duration,
content=item_text
))
remaining_text = remaining_text[actual_text_length:]
current_start += item_duration
new_subtitles += splitted_subtitles
return new_subtitles
この段落は、理解していることやその仕事のやり方については現時点では不要な人間が読めるテキストが最初にあることに気付いたかもしれません:
"""Splits subtitles that are too long.
The splitting scheme is simple; sentences are LIKELY to be broken into pieces.
Args:
subtitles (Sequence[srt.Subtitle]): Original subtitles.
max_duration (float, optional): The maximum duration of each output subtitle, in seconds. Defaults to 10.
"""
このようなテキストは「ドックストリング」と呼ばれ、その名前が示すように、関数のドキュメントを提供します。このドックストリングは、関数のユーザーに対する抽象化として機能し、ユーザーが知る必要のあること、つまり関数が何をするのかとそれを使用する方法だけを含んでいます。関数の残りの部分、つまりドックストリングの後にあるすべてのものは、ユーザーには関係のないものですが、それが関数が動作するための論理的なコードです。ユーザーは関数の使用方法だけを知る必要があり、関数の内部の動作には関心がありません。
このシナリオでは、抽象化は非常に重要です。なぜなら、抽象を使用する関数のユーザーが理解するために必要なものだけを素早く理解できるからです。ドックストリングがない場合、関数が何をするかを確認する唯一の方法は、コードを読んで理解することです。これは可能ですが、ドックストリングを読むよりも時間がかかり、さらに大きな問題は、ロジックコードが変更される場合、ユーザーは関数の使用方法を変更する必要があり、多くのコードの変更が発生します。しかし、抽象化があると、ロジックコードが変更されたとしても、抽象化で定義されたインターフェース(つまり、関数の機能と使用方法)を維持している限り、ユーザーは関数の使用方法を変更する必要はありません。
抽象化は、ソフトウェアシステムのユーザーだけでなく、システムを開発する人々にとっても重要です。ソフトウェアにたくさんのコードが含まれる場合(例えば、KonnyakuGPTには約2,000行のPythonコードがあります)、それぞれのコードが何を行っているかを覚えるのは難しくなります。ドックストリングのような抽象化がなければ、以前に書いたコードを理解するのも難しくなります。抽象化によって、ソフトウェアの理解、組織化、保守がはるかに容易になります。
おめでとうございます!あなたは、すべてのプログラミング言語とソフトウェア開発プロセスにとって基本的な概念である抽象化を理解しました。次に、コンプレックスさを管理する方法である階層構造について見ていきましょう。