👃

「不吉なにおい」考 - 「不吉なにおい」の構造について

12 min read

本記事は、 DDD-Community-Jp Advent Calendar 2020 の22日目です。


はじめに

概要

この記事は、以下の記事の内容を受けて、私達が時折直観的に感じ取る「不吉なにおい」について、その認識としての性質および構造の考察を試みたものとなります。

ドメイン駆動設計に関するコミュニティであるDDD-Commumity-JpのDiscordサーバー内で現在(2020/12/19時点)も実施されているイベント(通称「モデリング会」)での体験を基に、これらの記事は記述されています。これら記事内では、モデリングの最中でも「コードの不吉なにおい」に類似した体験があること、その体験は「コードの不吉なにおい」同様にある程度分類可能かもしれないことが、それぞれ示されています。

本記事は、こうした「コードの不吉なにおい」に類似した認識がモデリングの最中でも、すなわちプログラムコード以外を対象とした活動においても見いだされた点に注目し、「不吉なにおい」というメタファを通じて私達が抱いている認識がどのような構造と性質を持っているのかについて、考察を試みたものです。

注意事項

本記事は、「不吉なにおい」というメタファで表現される認識についての考察を試みるものです。何が「不吉なにおい」として認識されるかの解明、すなわちコードやモデル表現等に対して、いつ、どのように手を入れるべきかという基準の明確な定義を試みるものではありません。

表記について

本記事では「臭い」「匂い」「におい」といった表記方法について、引用箇所を除いて、ひらがな表記の「におい」で統一します。

「不吉なにおい」

ここでは、「不吉なにおい」という同一のメタファを用いながらコードとモデル表現というそれぞれ異なる対象へとそのメタファを適用した、2つの表現を比較します。

「コードの不吉な臭い」

掲題の「不吉なにおい」は、プログラミングあるいはソフトウェア開発の文脈で使われてきた「コードの不吉な臭い(Bad Smells in Code)」という言葉が由来となります(以降では、表記の統一と簡単のため、「におい」表記で統一します)。これはもともとKent Beckによる造語であり、Martin Fowlerの著書「リファクタリング」の第三章で公に使用されたものです[1]
「コードの不吉なにおい」は、リファクタリングに取り組む「きっかけ」を表す比喩として与えられた言葉であり、具体的な基準や状態を指すものではありません。『リファクタリング』(Fowler 2019)では、こうした「コードの不吉なにおい」の種類、すなわちリファクタリングを開始する「きっかけ」となる兆候を分類し、名前をつけ、有効な対処方法を与えることで、リファクタリングをいつ始め、いつ終了するかにいて、いくつかの判断材料を提示しています[2]

「コードの不吉なにおい」は、あるコードを対象としたリファクタリングへ進む「きっかけ」を示します。「コードの不吉なにおい」を認識した人間は、その認識をきっかけにリファクタリングへ、すなわち「におい」を認識した対象であるコードへと「外部から見た時の振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させ」るよう駆り立てられるのです[3]

「モデルの不吉なにおい」

冒頭の記事では、「コードの不吉なにおい」で使われた「臭い」というメタファをコードだけでなくソフトウェア適用対象の各種モデルを表現する図・テキスト(以下、「モデル表現」)に対しても適用しており、「コードの不吉なにおい」に倣って「モデルの不吉なにおい」と呼称しています。

その中で最も大きな影響を与えていたように感じたのは『皆の理解がずれてしまった』という点です。
そう、実装を進める中で知らず知らずのうちにお互いの話す言葉や単語の前提がずれ始めていたのです。
(中略)
コミュニケーションの不一致を契機 として、いわゆる『コードのにおい』と同じように『モデルのにおい』を感じ取っているのです。[4]

上で取り上げた記事では、それになぞらえて「モデルに対する皆の理解がずれてしまう」「モデルに対しての違和感が発生する」の状態をモデルの不吉なにおいと表現しています。
(中略)
ここでは「モデルの不吉なにおい」というのを、「モデリングか実装の手を止め、モデル自体に立ち返って見直す必要性を感じさせる場面」としておきます。 [5]

記事を見ると、「コードの不吉なにおい」と同じく「不吉なにおい」というメタファで表現される何らかの現象が、コードではなくモデル表現を対象として直観されている様子が伺えます。そしてまた、そうした「不吉なにおい」を認識することを「きっかけ」として、「モデリングか実装の手を止め、モデル自体に立ち返って見直」そうという動き、すなわち、モデル表現という対象への「修正」「見直し」といった働きかけが促されている様が綴られています。

この「修正」「見直し」は、「モデルに対する皆の理解がずれてしま」った状態、あるいは「モデルに対しての違和感が発生」した状態を解消するために行われる傾向があります。モデル表現内部にあらわれている言葉を改め、言葉や図の間の繋がりを改め、曖昧な部分と明確な部分の切り分けを改めます。
こうした「修正」「見直し」は、最終的には、そのモデル表現を通じて語ろうとしている対象への認識を、より厳密かつ整合した形でしようとする方向へと向かっているように見えます。

「不吉なにおい」の基礎的構造と性質

「コードの不吉なにおい」にせよ「モデルの不吉なにおい」にせよ、「不吉なにおい」を私達が認識する時、それぞれ対象を異にしつつも共通しているのは以下の二点です。

  • その「不吉なにおい」をひとつの「きっかけ」として、ある特定の方向へと「駆り立てられる」こと
  • その「駆り立て」は、専ら、「不吉なにおい」を認識した対象を「より"正しい"(と予感する)形」へ変容させるという方向へ向かうこと

「コードの不吉なにおい」では、リファクタリングを開始する「きっかけ」の比喩として、「不吉なにおい」が記述されています。この「不吉なにおい」という認識を「きっかけ」として、私達はリファクタリングという活動へと駆り立てられます。その「駆り立て」は、対象のコードを「理解や修正が簡単になるように修正されなければならない」という方向へと向けられます。この「駆り立て」においては、対象のコードがより「理解や修正が簡単になる」ことが、「より”正しい”形」として予感されています。

他方、「モデルの不吉なにおい」は「モデルに対する皆の理解がずれてしまう」「モデルに対しての違和感が発生する」「モデリングか実装の手を止め、モデル自体に立ち返って見直す必要性を感じさせる場面」として記述されています。そうした「不吉なにおい」という認識を得た時、人は「モデリングか実装の手を止め、モデル自体に立ち返って見直」し、そのモデル表現がより厳密かつ整合した認識を語るよう、そのような表現形式を持つよう改める方向へと「駆り立て」られます。この場面においてはそのような様相が、すなわち「モデル表現がより厳密かつ整合した認識を語る」ことが、モデル表現の「より”正しい”」形として予感されていると考えられます。

「コードの不吉なにおい」と「モデルの不吉なにおい」は、それぞれ対象が異なります。対象が異なる故に、こうした「不吉なにおい」を認識した後の具体的なふるまいの内容も異なるでしょう。「不吉なにおい」という認識が発生する具体的箇所や、具体的内容も、それぞれ一致しない場面が多いと推測することになるでしょう。

一方で、以下の点については、両者は一致していると考えられるのではないでしょうか。

  • 何かしらの対象を取る
    • 一方はコードであり、一方はモデル表現である
  • 対象について、その対象を「より”正しい”形」へ変化させようという働きかけへ、認識者を駆り立てる
    • 一方の認識は個々のコードやコード構造において、一方の認識はモデル表現の図・テキスト・関連線などにおいて、それぞれ「より”正しい”形」が予感されている
  • 「対象にはより”正しい”形がある」という予感を伴う
    • この予感は多くの場合に直観的であり、論理的な推論や情報に基づく解釈をしばしば省略する

ここであげた構造および性質は、コードのみ、あるいはモデル表現を対象とした場合にのみ成立する要素ではないように見えます。むしろこの構造・性質こそ、ここで言う「不吉なにおい」という認識の基礎的構造にして基礎的性質であると言えるでしょう。
このように考えるなら、「不吉なにおい」が基礎として持つこうした構造と性質をコードやモデル表現といった具体的対象へ適用した一例として、「コードの不吉なにおい」「モデルの不吉なにおい」を捉えることができそうです。

この基礎的構造および性質をまとめて、「コードの不吉な臭い」「モデルの不吉なにおい」の一般化としての「不吉なにおい」を定義してみます。

  • 「不吉なにおい」は、それを認識する何らかの対象を取る
  • 「不吉なにおい」は、それを認識した人に、「対象にはより”正しい”形がある」という予感を抱かせる
  • 「不吉なにおい」は、上記の予感を「きっかけ」として、その対象を「より”正しい”形」に近づける働きかけへと駆り立てる

この定義を受け入れるなら、私達はより一般的な概念としての「不吉なにおい」を手に入れたと言えます。

「不吉なにおい」の構造

「コードの不吉なにおい」と「モデルの不吉なにおい」という、同一のメタファを用いながら異なる対象へとそのメタファを適用した2つの表現についてその特徴をそれぞれまとめ、さらに比較を行いました。結果、メタファを適用した対象こそ違えど全体構造としては然程類似性を失っていないことを見出し、最終的には「不吉なにおい」というより一般的な表現を得るに至りました。

ここからは、さらにこの「不吉なにおい」という認識形態について、より正確に言えば、この認識形態はどのような構造を持ち、その認識形態はどのような前提を要求しているのか、その分析と記述を試みます。

「不吉なにおい」を構成する予感

「コードの不吉なにおい」にせよ「モデルの不吉なにおい」にせよ、「不吉なにおい」を私達が認識する時、そこには「より”正しい”形がある」という対象への予感があります。この予感を、より細かく観察してみましょう。

まず「より”正しい”形」という予感は、そこに「より”正しい”」という語が含まれていることから、決して無方向なものでは無いことがわかります。今あるままでなく、より”悪い”(と予感される)方向ではなく、あくまでそれは「より”正しい”形」へと指向付けられた予感です。また、「より”正しい”形」という表現からは、有る種の「規範的」な予感と、そうした(「より”正しい”」という性質を伴う)形の実在に対する予感が含まれていることが見て取れます。

上記のことから、「より”正しい”形」という予感には、制約・規範・実在など、さらにいくつかの種類の確信が複合することによって構成されていると考えられそうです。そうした構成要素としての確信の内訳として、以下のような分類と記述を考えてみます。

1. 「その対象には、より”正しい”形が現にある」という予感

他者から見ても同様の感想を抱くかはわかりませんが、少なくとも観測者にとっては、その対象には(何らかの観点から)「より”正しい”形」があると予感されています。この予感が無い、それこそ「より”正しい”形は、もはやこれ以上無い」予感を抱いているならば、私達はただ対象および自身のあるがままに(特に事前に手を加える事無く)対処と接することを試みるでしょう。

2. 「より”正しい”形との乖離は、対象自身によってもたらされている」という予感

その対象が「より”正しい”形」から離れている(そのように予感される)原因が、その対象を認識している自身の能力や知識ではなく、その対象自身の状態や有り様に由来していることも、同時に予感されています。このような予感が抱かれているからこそ、自身をではなく、対象を「より”正しい”形」へ近づけようという働きかけを試みるのです。逆に、自身の能力や知識に困難さの多くが由来すると確信したなら、次の行動は自身を「より”正しい”形」へと近づけることをを目的としたもの(学習、調査による知識の獲得など)となるでしょう。

3. 「その対象は、人間の手によってより”正しい”形へ近づけることができる」という予感

2.で予感された、対象自身に起因する「より”正しい”形」からの乖離に対して、その対象を現に「より”正しい”形」へと近づけようと働きかける時、そこでは「より”正しい”形」への接近が人間の働きかけによって現実に可能であるということが予期されています。人間が老衰・病気・事故など何らかの要因で死んでしまった時、例えば「生きている」という状態こそが人間にとって「より”正しい”形」であるということがいかに強く(それこそ確信とも言える程度に)予感されていたとしても、その死んでしまった人物を現に「生きている(という、より”正しい”形)」へと近づけようとすることはないでしょう。人間の手によって、現にその対象を「より”正しい”形」へと近づけることが可能であることと同時に予感されているからこそ、「不吉なにおい」という予感は、対象を「より”正しい”形」に近づける働きかけへと人間を駆り立てるのです。

4. 「対象は、より”正しい”形へと近づくべきだ」という確信

1.〜3.の確信が抱かれたとして、最終的に、「より”正しい”形」へとその対象は進むべきであるということが予感されていなければ、対象「より”正しい”形」へと現に近づけようという「駆り立て」は発生しません。対象の観察が苦痛であったり、将来的な経済活動に支障を来す危険が予期されたり、ただ美しくないという感覚であったり、何かしらの形で「この対象はより”正しい”形になるべきだ」という予感が伴って、はじめて「不吉なにおい」を「きっかけ」として対象が「より”正しい”形」へと近づくように働きかけようとするのです[6]

4つの予感

本記事では、こうして見いだされた構成要素としての予感を、それぞれ以下のように呼ぶこととします。

  1. 実在への予感(対象には「より”正しい”形」が、現にあるという予感)
  2. 原因への予感(現実の対象と「より”正しい”形」との乖離は、現実の対象によってもたらされているという予感)
  3. 接近可能への予感(その対象は、人間の働きかけによって「より”正しい”形」へと接近可能であるという予感)
  4. 義務への予感(対象は、現実に今ある状態から「より”正しい”形」へと歩を進めるべきであるという予感)

「重複したコード」を例に

前節で、「不吉なにおい」という予感を構成する要素としての、4つの予感を記述しました。
この節では、こうして見いだされた4つの予感が実際にどのような様相で現れてくるか、あるいは見出しうるのか、具体的な「不吉なにおい」の例を基に検討してみます。

「リファクタリング」(Fowler 2019)では、「コードの不吉なにおい」の具体的な種類の一つとして、「重複したコード」を挙げています。「リファクタリング」では、以下のように説明されています。

同じ構造のコードが2か所以上にある場合、1か所にまとめることができると、より良いプログラムになります。コードに重複があると、コピーされた箇所に出くわすたびに、似ているけれども違う部分はないか、 注意深く読み込まなければならなくなります。重複したコードを修正することになった際には、重複部分を漏れなく見つけ、すべてに同様の修正を施していく必要があります。[7]

この「不吉なにおい」を題材に、先に上げた4つの予感が「不吉なにおい」に含まれていること、「不吉なにおい」を構成する予感として現に見いだせることを、以下で確認します。

「実在への予感」

この説明からは、「注意深く読み込まなければならなくな」るという理解についての困難さ、および「すべてに同様の修正を施していく必要があ」るという事態が予感されています。一方で、「1箇所にまとめることができると、より良いプログラム」になることができるとも記述されています。この記述からは、先述したような事態が不在あるいは減衰した、「より”正しい”形」が有るだろうと予感されています。

「原因への予感」

また、上記の「実在への予感」は、自身の知識や理解の能力ではなく、対象となるコードに由来することが同時に予感されています。自身の知識やプログラミング技術に問題が有るために「注意深く読み込まなければならなくな」ったり、「すべてに同様の修正を施していく必要」が生じているのではなく、その原因は、対象のコード内部に重複が存在しているが故であるという予感、すなわち「原因への予感」がここにあります。

「接近可能への予感」

『リファクタリング』(Fowler 2019)では、先述の「重複したコード」の説明の後、「関数の抽出」「ステートメントスライド」「メソッドの引き上げ」などを挙げ、それらの方法によって問題の解決、あるいは解決しやすい状態にできると説明しています。
この説明からは、「重複したコード」という「不吉なにおい」を通じて予感された「より”正しい”形」へと、すなわち、「コードの重複が存在せず、注意深く読む必要も複数箇所を修正する必要も無い」という「(「重複したコード」を「不吉なにおい」と見る文脈において)より”正しい”形」への「接近可能の予感」を見出すことができます。

「義務への予感」

『リファクタリング』では、「重複したコード」を「不吉なにおい」として、さらにその説明の中で以下のように記述しています。

  • 「重複したコード」によって生じる現象へのネガティブな説明
  • 「重複したコード」を取り除くための方法の提示
  • 「重複したコード」を取り除くための方法へのポジティブな説明

これらから、「重複したコード」という「不吉なにおい」は取り除かれる「べき」ものであり、そこには「義務への予感」が存在していると考えられます。

その他の例について

今回は『リファクタリング』から「重複したコード」を、すなわち「コードの不吉なにおい」の具体例を題材として、4つの予感がそこに現に含まれていること、実際に「不吉なにおい」の具体例が4つの予感によって構成されていることを確認しました。

他の「コードの不吉なにおい」および「モデルの不吉なにおい」の具体例についても当てはまるかの検証は、ここでは省略します。また、筆者自身全ての例について検証ができているわけではありません。しかし、ほとんど全ての具体例について、この構造が共通に見いだせるのではないかと筆者は考えています。

まとめ

本記事は、「コードの不吉なにおい」と「モデルの不吉なにおい」が、いずれも「不吉なにおい」というメタファを用いて何らかの認識を表現しようとしている点への注目から出発しました。

第一に、両者がこのメタファを用いて表現しようとした内容を整理し、その共通点をまとめました。その結果、両者をより一般化した表現としての「不吉なにおい」という言葉を定義しました。

続いて、「不吉なにおい」という認識の構造について、より詳細に分析することを試みました。その結果、「不吉なにおい」は以下の4つの予感によって構成されていることを確認できました。

  1. 実在への予感
  2. 原因への予感
  3. 接近可能への予感
  4. 義務への予感

また、現に『リファクタリング』で挙げられている「コードの不吉なにおい」を題材として、実際にこれらの予感がそこに含まれていることを確認しました。

応用

現実のプログラミングやモデリング、あるいは設計など、様々な活動の中で「不吉なにおい」あるいはそれに類する認識を抱くことがあるでしょう。それは時に「コードの不吉なにおい」、時に「違和感」、時に「気持ち悪い」という言葉で表現されるものかもしれません。

そうした直観は時に、論理的推論や情報の積み重ねからは到達できないような、飛躍を伴った課題解決方法、あるいは問題の発見へ至ることがあります。一方で、それは多くの場合に論理的推論や情報の分析を経由していないがために、他者への共有や、妥当性の検証が困難です。「不吉なにおい」が、実際には思い込みや錯覚である可能性も有ります。

ここで見いだされた4つの予感は、他者へ共有するための言語化や、妥当性の検証を助ける道具として活用できるのではないかと考えています。

例えばあるコードから「不吉なにおい」を感じた時であれば、以下のような問を立てることができそうです。

  • 「実在の予感」に基づいて「この対象について私が予感している、より”正しい”形はどのようなものか?」と問う
  • 「原因への予感」に基づいて「より”正しい”形からの乖離は、本当に対象に由来しているのか? 自身の知識不足や技術不足が、対象が”正しくない”ように見せているのではないか?」と問う
  • 「接近可能への予感」に基づいて「より”正しい”形への接近は可能なのか? このプロダクトの性質上、実質的には接近不能だったりしないか? 接近可能なら、(より”正しい”形へと)どのように接近していくことができるか?」と問う
  • 「義務への予感」に基づいて「これはより”正しく”なるべきものなのか? 実際には現状で十分に”正しい”場合があり、私がそれを知らないだけなのではないか?」と問う

これらの問を通じて、「不吉なにおい」の種類・性質・背景の言語化、および「不吉なにおい」という認識の妥当性を検証することができそうです。この他にも、多様な問いを立てることができるでしょう。

このように、「不吉なにおい」を構成するそれぞれの予感について、「本当にこの予感は妥当なのか?」という問を立てることで、現実に直面する様々な「不吉なにおい」をより精緻に捉え、より的確な問題解決方法を見つける機会を増やせるのではないでしょうか。

課題:「不吉なにおい」のメカニズム

本記事で記述を試みたのは、実際に認識した「不吉なにおい」の構造にとどまります。なぜこのような認識が発生するのか、「不吉なにおい」というメタファで表現される種類の認識が、どのようなプロセスを通じてこのような構造を伴って私達の認識として立ち上って来るのかは、ここでは問われていません。

本記事に続くさらなる問として、「不吉なにおい」という認識が生まれてくるそのメカニズムを問うことができたなら、そしてそのメカニズムを解明し定義付けることができたなら。
その時には、コードやモデル表現を記述するにあたって、どのような時に立ち止まり「修正」へと向かうべきなのか、その基準を見出すことができるのかもしれません。

参考資料

脚注
  1. https://wiki.c2.com/?CodeSmell ↩︎

  2. Martin Fowler(2019)『リファクタリング 既存のコードを安全に改善する 第2版』p.73 ↩︎

  3. Martin Fowler(2019)『リファクタリング 既存のコードを安全に改善する 第2版』p.45 ↩︎

  4. @t2-kob https://qiita.com/t2-kob/items/3d1ec6a780107036d6b2#-実装とモデルの不吉なにおい 「コードの不吉なにおい」について、記事本文中では一部省略されて「コードのにおい」と記述されている。 ↩︎

  5. @jnuank_ https://jnuank.hatenablog.com/entry/2020/12/14/094851#はじめに ↩︎

  6. ここの「より”正しい”形へと近づくべきだ」という予感についての議論では、予算・人員・時間といった外部条件からくる「このままで良い」「このままが良い」といった判断は取り扱っていません。ここで問題としているのは、そうした具体的情報・制約・思考に基づく判断ではなく、対象を通じて直観的に得た予感です。 ↩︎

  7. Martin Fowler(2019)『リファクタリング 既存のコードを安全に改善する 第2版』p.74 ↩︎