嗅いだことありますか?不吉な臭い(仕様スメル・制約スメル・設計スメル・コードスメル)


はじめに

コードの不吉な臭い(Code smell)という言葉があります。
仕様や設計にも不吉な臭いはある気がします。
仕様スメル・制約スメル・設計スメル・コードスメルを独自に整理していきます。臭いを検知するための道具・方法も検討していきます。

皆様の嗅いだことのある不吉な臭いも教えていただけますと幸いです。

先行研究

参考文献[1]「新装版 リファクタリング―既存のコードを安全に改善する―」に示されている『コードの不吉な臭い』

  • 重複したコード(Duplicated Code)
  • 長すぎるメソッド(Long Method)
  • 巨大なクラス(Large Class)
  • 長すぎるパラメータリスト(Long Parameter List)
  • 変更の偏り(Divergent Change)
  • 変更の分散(Shotgun Surgery)
  • 特性の横恋慕(Feature Envy)
  • データの群れ(Data Clumps)
  • 基本データ型への執着(Primitive Obsession)
  • スイッチ文(Switch Statement)
  • パラレル継承(Parallel Inheritance Hierarchies)
  • 怠け者クラス(Lazy Class)
  • 疑わしき一般化(Speculative Generality)
  • 一時的属性(Temporary Field)
  • メッセージの連鎖(Message Chains)
  • 仲介人(Middle Man)
  • 不適切な関係(Inappropriate Intimacy)
  • クラスのインタフェース不一致(Alternative Class with Different Interfaces)
  • 未熟なクラスライブラリ(Incomplete Library Class)
  • データクラス(Data Class)
  • 相続拒否(Refused Bequest)
  • コメント(Comments)

参考文献[2]「組込みソフトウェアのアーキテクチャ設計の可視化」に示されている『ソフトウェア疲労』

  • 一筆書き
  • クローン
  • 神様データ
  • 中央集権
  • スパゲッティ
  • 老舗温泉旅館
  • 一枚岩

参考文献[3]「派生開発における 母体に由来するバグとその対応」に示されている『母体に由来するバグ』

  • 新規設計の段階でタスクの負荷分散が図られていない
  • いくつかのタスクが同じ優先度に設計されている
  • 機能中心のタスク設計が行われている
  • タスク間のグローバルデータが多用されている
  • メインモジュールの周期処理のなかでフラグの判定によってイベントの発生を認識する構造になっている
  • データ構造の選択を間違えた
    • 機能の使われ方を考えずに単純な配列構造だけで作られた
    • データの受信処理でキューの制御を持ち込むべきところを、リングバッファで対応していた
  • モジュールの凝集度や複雑度が悪い
    • 一つのモジュールの中に複数の機能が組み込まれていて、この中の1つだけを利用できない
    • 母体のモジュールが既に論理的凝集になっていて論理的凝集の選択肢を増やして対応
  • 巨大な状態遷移の処理関数
    • 「SWITCH文」の2段構成と、そのなかで「IF文」が使われるため、複雑度は800を越すことも少なくない
    • それぞれの「CASE」の処理をコピー&ペーストで作られると、マトリクスが正しく選択されることの検証に、すべての組み合わせのテストケースが必要になる

参考文献[4]「「派生開発」を成功させるプロセス改善の技術と極意」に示されている『地雷』

  • ドラえもんのポケット

参考文献[5]「Re-collection of embedded software QA in the last decade」に示されている『ソフトウェアトラップ』

  • 二卵性双生児
  • 例外
  • 浦島太郎
  • 山登り船頭
  • 逆向きの予備動作
  • 永遠とゼロ
  • 「備考」

参考文献[6]「モデルの不吉なにおい」に示されている『モデルの不吉さを感じる瞬間』

  • モデルに出てくる言葉と実装されているコードの言葉が違う
  • 名前に対する違和感
  • つながりを見出すことができない
  • ふきだしの多さ
  • ほぼ一緒の関連を持つ別の概念
  • どこから来たかわからない概念
  • 実装を始めたときのぎこちなさ
  • ずっとモデリングをしている

独自定義を検討中の不吉な臭い

仕様スメル・制約スメル・設計スメル・コードスメルと分けて定義します。
先行研究で挙げられている臭いは省きます。

以下のような問題が良く起きていると思います。こういった問題の臭いに気づきたいと考えています。

  • 「似て非なるもの」に対する取り違え
  • 「製品内・製品群内で複数種類があるもの」に対する思い込み
  • 「広い範囲・複数個所を見ないと理解できないこと」に対する考慮漏れ
  • 「使い慣れていないこと」に対する使用誤り
  • 「非機能要求に対して特別に対応していること」に対する認識漏れ

仕様スメル

仕様スメルは仕様書から検知できる臭いとする。

不吉な臭い 引き起こす問題
複数の種類がある概念 英語(米国英語,英国英語,豪州英語)
改行(CR+LF,LF,CR)
仕様の誤解釈
複数の構成要素からなる概念 ○○情報 仕様の誤解釈
対象によって具体的な行為が変わる概念 記憶(対象データや対象製品によって記憶場所が変わる)
開始(対象機能によって開始タイミングが変わる)
中止(対象機能によって中止時に実施する処理が変わる)
仕様の誤解釈
(あいまいな)修飾語 “使用可能な”モード以外には遷移しない.
“不要となる”処理を実行しないように変更する.
初期化が“必要な”データを更新する.
※要注意品詞:形容詞、副詞、形容動詞、副詞可能
仕様の誤解釈
同義語 合計額 / 合計金額 / 投入金額 検索での関連仕様の抽出漏れ

制約スメル

制約スメルは制約の変化から検知できる臭いとする。

不吉な臭い 引き起こす問題
実行不可能から実行可能に変化 考慮漏れ
キャンセル不可能からキャンセル可能に変化 考慮漏れ
非同期処理不可能から非同期処理可能に変化 考慮漏れ
データの歯抜けの可能性なしから歯抜け可能性ありに変化 考慮漏れ
データの並び順が変化 考慮漏れ
データサイズの制約が変化 考慮漏れ

設計スメル

設計スメルは設計書から検知できる臭いとする。

不吉な臭い 引き起こす問題
設計図がシーケンス図のみ 考慮漏れ
状態はあるが状態遷移表なし 考慮漏れ
特殊な状態あり※ 考慮漏れ
データの生存期間の定義なし 考慮漏れ
複数のレイヤで同様の状態を保持 考慮漏れ

※仕様変更に伴い後から追加された状態(初期はシステムに不要であった状態)を、特殊な状態と位置付ける。
※特定のシステムだけに存在している状態(ソースコードの一部が共通である他の多くのシステムには存在しない状態)を、特性な状態と位置付ける。

コードスメル

コードスメルはソースコードから検知できる臭いとする。

不吉な臭い 引き起こす問題
型と変数名の不整合 取り違え
同一名称の変数が複数あり 取り違え
似ている名前・似ている用途の変数あり 取り違え
同様のデータを格納するバッファが複数あり 考慮漏れ
複数機能で共有しているデータあり 考慮漏れ
ビットデータ/ビットフィールド 誤り

不吉な臭いに関する気づき

その1 : 一般的な表現だけでは使い物にならないかも

独自のスメルを自分達で定義し、スメルを検出するシステムを構築し、開発中に継続的にチェックを行い、仕様・設計・コード等の見直しのきっかけとすることを検討しています。
このときに、スメルが一般的な表現で示されているだけだと、当てはまりすぎて(疑陽性が出すぎて)使い物にならない可能性がある。

その2 : 成果物の関連に着目するのは有効かも

今回、仕様スメル・制約スメル・設計スメル・コードスメルと分けて定義してしまいました。
参考文献・参考記事を読んでいて、一つの成果物から不吉な臭いを嗅ぐのではなく、複数の成果物の関係から不吉な臭いを嗅ぐようなことも有効かもしれないと感じました。

  • 参考文献[11]「テキスト処理でできるレビュー支援」

    仕様書と設計書の単語の差分から抜けを見つける

  • 参考記事「RDRA と EventStroming(デザインレベル) の組み合わせの可能性」

    コードに感じたにおいが切っ掛けとなってモデルのにおいに気が付き、モデルを修正することができるようになります

  • 参考記事「@kazuo_reve「嗅いだことありますか?不吉な臭い(仕様スメル・制約スメル・設計スメル・コードスメル)」の「設計」に反応。」

    仕様=制約=設計=コード

その3 : ヒューマンエラーについても整理したほうがいいかも

不吉な臭いをもつ成果物が仕掛ける罠にはまって、人はヒューマンエラーを起こすという関係があると考える。
以下の文の中で表現されている”取り違え”、”思い込み”、”考慮漏れ”、”使用誤り”、”認識漏れ”などをヒューマンエラーと位置付ける。

  • 「似て非なるもの」に対する取り違え
  • 「製品内・製品群内で複数種類があるもの」に対する思い込み
  • 「広い範囲・複数個所を見ないと理解できないこと」に対する考慮漏れ
  • 「使い慣れていないこと」に対する使用誤り
  • 「非機能要求に対して特別に対応していること」に対する認識漏れ

不吉な臭いをもつ成果物とヒューマンエラーの関係を整理をしておいたほうがよいのかもしれない。
不吉な臭いをもつ成果物は、制約があり修正できないことが多い。そのため、不吉な臭いをもつ成果物の罠にはまって起きるヒューマンエラーを防止・検出する方法を考えたほうがよいかもしれない。

ヒューマンエラーの分類

株式会社アイリンクは、以下のサイト・書籍で、ヒューマンエラーの分類を示している。

参考文献・参考記事

参考文献

[1] Martin Fowler,「新装版 リファクタリング―既存のコードを安全に改善する―」,オーム社,2014
https://bookmeter.com/books/8154535

[2] 山田大介,「組込みソフトウェアのアーキテクチャ設計の可視化」,Embedded Technology 2015,2015
https://www.ipa.go.jp/files/000049841.pdf

[3] 清水吉男,「派生開発における 母体に由来するバグとその対応」,JaSST'09 Tokyo,2009
http://www.jasst.jp/archives/jasst09e/pdf/A2.pdf

[4] 清水吉男,「「派生開発」を成功させるプロセス改善の技術と極意」,技術評論社,2007
https://bookmeter.com/books/422459

[5] 西康晴,「Re-collection of embedded software QA in the last decade」,JaSST'20 Tokai,2020
https://www.slideshare.net/YasuharuNishi/recollection-of-embedded-system-qa-in-the-last-decade

[6] jnuank,「モデルの不吉なにおい」,はてなブログ,2020
https://jnuank.hatenablog.com/entry/2020/12/14/094851

[7] 柏原一雄,岡本晃,鈴木裕一郎,田村光義,東久保理江子,保栖真輝,細川宣啓,永田敦,「ソフトウェア欠陥予測アルゴリズム~欠陥混入メカニズムのモデリング手法を利用した欠陥予測方法の提案~」,ソフトウェア品質シンポジウム2015,2015
https://www.juse.jp/sqip/symposium/archive/2015/day1/files/ronbun_B2-2.pdf
https://www.juse.jp/sqip/symposium/archive/2015/day1/files/happyou_B2-2.pdf

[8] 柏原一雄,新留光治,藤田亮太,周廣有,小林展英,竹下千晶,林香織,「欠陥混入メカニズムの知識を活用したDRBFMの提案」,ソフトウェア品質シンポジウム2018,2018
https://www.juse.jp/sqip/symposium/archive/2018/day1/files/B2-1_ronbun.pdf
https://www.juse.jp/sqip/symposium/archive/2018/day1/files/B2-1_happyou.pdf

[9] 柏原一雄,長井亘,不破慎之介,林香織,石川冬樹,栗田太郎,「要求仕様の誤解釈を検出するDomain Word Modelingの提案」,ソフトウェア・シンポジウム2020,2020
https://www.sea.jp/ss2020/download/SS2020-2.pdf

[10] 柏原一雄,新留光治,李路雲,鈴木淳,松原潤弥,不破慎之介,「要求仕様に対する形態素ベースドレビューの提案」,ソフトウェア・シンポジウム2021,2021
https://www.sea.jp/ss2021/download/22-SS2021.pdf

[11] 森崎修司,「テキスト処理でできるレビュー支援」,オルタナティブ・ブログ,2020
https://blogs.itmedia.co.jp/morisaki/2020/08/post_1040.html

参考記事(Qiita)

Wikipedia

アンチパターン

おわりに

不吉な臭いは、人から教えてもらった抽象的な概念を利用して嗅ぐことは難しいと思います。
不吉な臭いは、自分の経験をもとに自分で概念を定義し、それを利用して嗅ぐほうがよい気がします。