これはクラウドワークス Advent Calendar 2023 シリーズ2 / 21日目の記事です。
はじめに
こんにちは。ビズアシでエンジニアをしている@cw-yamadaです。
アドベントカレンダーに参加するのもこれで三回目です。感慨深い・・・
前回はPO代理をしていたので、プロダクトオーナーに関する記事を執筆しましたが、今年の7月にまたエンジニアに戻ったので、今回はエンジニアっぽい記事を書こうと思います。
ズバリ!エンジニアに必要な論理的な感覚。
気になる方は是非最後まで見ていってください!
これ見て、どう思う?
突然ですが、これを見てあなたはどう思いますか?
私はこれを見せられた時に大体以下のことを考えたと思います。
- 料理と素材が混ざってる
- 献立とは考えられない
- 雑多に好きな食べ物を並べた?
- 右に余白があるから、左を参考に献立やら買うものをまとめるのかな?
これは前職のエンジニア採用で一時行われてたテストです。※左側の記載内容はうろ覚えなので適当です。
正解は「情報の粒度が揃ってなくて気持ち悪い」だそうです。
この気持ち悪いという感覚は、エンジニアにとって大事なモノだと私は考えています。
よくロジカルシンキングや論理的思考力という単語は聞くと思います。物事を筋道立てて考える力ですね。
「エンジニア 論理的思考力」と検索すると、かなりの件数がヒットしますし、書籍なんかもあります。
でも、考え方のフレームワークの話が多いような気がします。
ちょっと違うんだよなあ。
コードを見た瞬間に何がとは分からずとも、「なんか気持ち悪い!」と思ってしまう、その感覚。
より根っこの部分にありそうな、本質的な「論理的な感覚」って何なんでしょう?
今回は「具体と抽象」という概念から、その内容を見ていきたいと思います。
具体と抽象
情報というのはひとつのベクトルとして、抽象的か具体的かという軸があります。
そうは言われてもなんのこっちゃ分からんと思うので、具体例を見ていきましょう。
例えば、イヌ。これをより具体的、抽象的に表すと、以下のようになります。
指し示す内容が広がっていくのが抽象的な概念、より狭く限定的になるのが具体的な情報です。
イヌの例だと直線的ですが、実際には、ピラミッドやツリー構造を取ります。
この階層構造がとても重要なポイントになります。
他にも、具体と抽象における重要な定義、法則、事柄をいくつかピックアップしてみました。
後の章で述べる内容と照らし合わせてみてください。
- 具体と抽象は相対的な概念、対比によってどちらがより抽象的か / 具体的かが決まる
- 抽象化とは、ごく少数の言葉や図形で森羅万象を説明すること
- つまり、抽象概念を具体的に説明すると、冗長になる
- 下位にある概念は上位にある概念を引き継ぐ(逆はない)
- 抽象は概念、具体は実態
エンジニアと具体と抽象
では、この具体と抽象、エンジニアとどう関わってくるのでしょうか?
今回、「エンジニア 具体と抽象」で検索してみたのですが、思いの外熱量の高い記事が多い印象を受けました。
仕事でのコミュニケーションにおける抽象化能力、抽象度のズレみたいな話もあるのですが、今回取り上げたいのは、プログラムやシステム、あらゆるエンジニアリング的思想の多くが具体と抽象で捉えられるのではないか、ということです。
では、早速具体例を見ていきましょう。
オブジェクト指向
オブジェクト指向は、まさに具体と抽象そのものです。今回参照した書籍には以下のような記載がありました。
これはソフトウェアの開発方法論でいうオブジェクト指向にも用いられています。オプジェクト指向でいう「インスタンスとクラス」という関係がまさに本書でいう「具体と抽象」の関係に当たり、また「上位の抽象レベルであるクラスの属性を、抽象レベルが下位のサブクラスも受け継ぐ」という関係を 「インヘリタンス (継承)」という言葉で表現し、 ソフトウェアの対象物 (オブジェクト) を記述するのにこのような具体と抽象の関係をフルに活用しています。
参照: 「具体⇄抽象」トレーニング 細谷 功 第二章 具体と抽象とは何か?
インスタンスクラスは設計や概念であって、それそのものを取り扱うことはできないので、インスタンス化することで物理的に扱うことができる、と理解しています。
これはまさに「抽象は概念、具体は実体」の構造そのものですね。
カプセル化
カプセル化は大きく捉えると抽象化です。
例えば、カレーを作る処理を書くとして、大体皆さんこう書くのではないでしょうか?
def make_curry():
prepare()
wash()
cut()
stir_fry()
stew()
make_curry()
カレーを作るたびにprepare()からstew()を律儀に呼び出すことはしませんよね。
また、レシピが変わって隠し味を入れることにした場合、make_curry()に処理が追加されますが、そのことは呼び出し側には影響しません。
これは、「抽象は簡潔、具体は冗長」「下位概念は上位概念を引き継ぐが逆はない」といった特徴に該当しそうですね。
もっと基礎の話
オブジェクト指向とかカプセル化とか、ちょっとカッコつけて取り上げてみたのですが、もっともっと基本的なところで「具体と抽象」を使ってます。
本当にあらゆるところに「具体と抽象」が潜んでいますし、エンジニアは意識せずに扱っています。
(この「意識せず」という部分が、冒頭で述べた「なんか気持ち悪い」につながってきます。)
リポジトリ
プログラム、ソースコードそのものが「具体と抽象」で管理されてます。
さっき見たイヌの例まんまですね。
わざわざ図式にはしませんが、システムはリポジトリ同様、具体と抽象のツリー構造ですし、開発フローは抽象からの具体化の一連の流れです。
もはや「具体と抽象」でしか、仕事してないのでは...?
まとめ
エンジニアの仕事に具体と抽象が密接に関わっていることが伝えられたと思います。
冒頭で、「情報の粒度が揃ってなくて気持ち悪い」と記載しましたが、この「情報の粒度が揃っていない」とは、抽象概念が異なる具体物がごちゃまぜになっているとか、抽象的なものと具体的なものとが並列に扱われている、と言い換えられます。
具体と抽象を理解すると、「論理的に気持ち悪い」とか逆に「論理的に気持ちいい」という感覚が研ぎ澄まされていきます。
じっくり考えずとも瞬間的に理解できるということは、普段の業務に役立つのはもちろんですが、デザインパターンやアーキテクチャ、設計思想等を学ぶときにも有利です。
是非、皆さんも具体と抽象を意識してみてください!