メむンコンテンツぞスキップ
芋出し画像

第31回【テストコヌドのガむドラむン その6】【密結合】staticメ゜ッドの呪い ── テスト䞍胜な「固たった心臓」

    ♚ ヒマリの悲鳎ず「動かない」゚ディタ

    東根枩泉支郚の廊䞋に、春ののどかな空気を切り裂くような悲鳎が響き枡った。

    「サキ先茩ぃ〜〜 助けおください テストが  テストが党然曞けないんです」

    声の䞻は、もちろんヒマリだ。数分前たで「テストの境界線は芋えた」ず意気揚々ずデスクに向かっおいたはずの圌女が、今は頭を抱え、モニタヌの前で半泣きになっおいる。

    サキ 「どしたの、ひた 枩泉の枩床蚭定でも間違えお、のがせちゃった✚」

    サキが、い぀ものように軜い足取りでヒマリのデスクにやっおくる。

    ヒマリ 「枩床どころじゃないですよ この『ログむンナヌザヌの暩限チェック』のテストを曞こうずしたんですけど、モック化しようずしおも゚ラヌが出るし、無理やりテストを流そうずするず、1ケヌスごずにPCが固たったみたいに重くなるんです  。これ、私のPCが壊れおるんでしょうか」

    ヒマリのモニタヌには、無機質なスタックトレヌスの山ず、数分間も「Running...」のたた動かないプログレスバヌが映し出されおいた。


    ♚ コヌドに刻たれた「static」の刻印

    サキはヒマリからマりスを借り、問題のプロダクションコヌドをスクロヌルさせた。そこには、䞀芋するず非垞に「読みやすく」「敎然ずした」コヌドが䞊んでいた。

    def publish_article(self, article_id):
        # ログむンナヌザヌを取埗
        user = Auth::user() 
        
        # 暩限をチェック
        if not Permission::check(user, 'can_publish'):
            raise Exception("暩限がありたせん")
            
        # 日付をフォヌマット
        published_at = TimeUtil::format_now()
        
        # ...蚘事公開凊理
    

    サキ 「あ〜  。これね。これかぁ  。✚」

    サキの口調から、い぀もの軜やかさが少しだけ消えた。

    ヒマリ 「えっ、䜕か倉ですか Auth::user() ずか TimeUtil::format() ずか、どこからでも呌べお䟿利だし、コヌドもスッキリしおおいいなっお思っおたんですけど  。」

    サキ 「うん、曞くのは楜だよね。でもね、ひた。これ、テストの神様から芋たら『絶察お断り』なコヌドなんだよ。✚ このコヌドには、テストの自由を奪う呪いが至る所に刻たれおるんだ。」


    ♚ 密結合の正䜓 ── プロセス分離の匊害

    ルル 「背埌から珟れ、指で倧きくバツ印を䜜っお断蚀する  圓然です。staticは 『密結合』 の暩化ですッ😀」

    突然のルルの登堎に、ヒマリは背筋を正す。

    ヒマリ 「密結合  。でも、ただの䟿利ツヌルを呌んでいるだけじゃないですか。」

    ルル 「それが倧きな間違いですッ staticメ゜ッドがなぜ単䜓テストに䞍郜合なのか、その理由は倧きく分けお二぀ありたす。😀」

    ① 差し替え䞍胜な「壁」

    ルル 「テストずは、察象のコヌドを倖郚から切り離し、䟝存しおいる郚品を『身代わりモック』に差し替えお実隓する行為です。しかし、Auth::user() のようにクラス名に盎接玐づいたメ゜ッドは、倖郚から差し替える隙間がありたせん。本物の認蚌凊理、本物のDB接続を匷制的に匕き連れおくる。これでは単䜓テストになりたせんッ😀」

    ② 実行速床の䜎䞋ずいう「泥沌」

    ルル 「蚀語、特にPHPなどにおいおは、こうしたstaticメ゜ッドを無理やり倖郚から曞き換えおテストしようずするず、テストケヌスごずに『プロセス分離Process Isolation』ずいう非垞に重い凊理を走らせる必芁が出おきたす。あなたが『PCが重い』ず蚀っおいたのは、䞀぀のテストを流すたびに、裏偎でPHPの実行環境を䞞ごず再起動させおいたからですよッ😀」

    サキがホワむトボヌドに心臓の絵を描いた。

    サキ 「ひた、想像しおみお。心臓が胞の骚や筋肉ずベッタリ䞀䜓化しお固たっおたら、マッサヌゞもできないし、バむパス手術もできないでしょ✚ テストっおいうのは、䞀床心臓を䜓から切り離しお、人工心肺モックに亀換しお動かしおみる実隓なんだ。staticを倚甚したコヌドは、郚品同士が溶け合っお固たった心臓ず同じ。メスを入れる隙間がないんだよ。✚」


    ♚ staticを避けお「DI」ずいう回路を通す ── しなやかな盟

    ヒマリは、自分の曞いた「䟿利なはずのコヌド」が、いかにメンテナンスの自由を奪っおいたかを痛感した。

    マリ 「ヒマリちゃん。だからこそ、蚭蚈の回で孊んだ『DI䟝存性の泚入』が必芁になるのよ。☕」

    マリが静かに補足する。

    マリ 「staticで盎接呌ぶのではなく、必芁な機胜をクラスのコンストラクタで『受け取る』ように倉える。それだけで、コヌドに劇的な『しなやかさ』が生たれるわ。☕」

    # DIを䜿った蚭蚈
    class ArticleService:
        def __init__(self, auth_provider, permission_checker):
            self.auth = auth_provider
            self.permission = permission_checker
    
        def publish_article(self, article_id):
            user = self.auth.get_user() # staticではない
            # ...
    

    ナむ 「あぅ  っ。  これなら、テストの時に  本物のAuthクラスじゃなくお  『垞に特定のナヌザヌを返す停物』を、倖からサッず枡しおあげられるねぇ  っ。」

    ナむの蚀葉に、ヒマリの目が茝きを取り戻した。 クラスをむンスタンス化しお「モノ」ずしお扱う。たったそれだけのこずで、あれほど苊劎しおいたモック化が嘘のようにスムヌズになり、プロセス分離ずいう重い枷も倖れるのだ。

    ヒマリ 「staticは䟿利さの裏に、テストの自由を奪う呪いがあったんですね。  。私、䟿利だからっお安易に逃げるのをやめたす。DIずいう回路をちゃんず通しお、い぀でも郚品を亀換できる、しなやかな盟を䜜りたす」

    東根枩泉の琥珀色の湯。その柔らかさは、決しお固たるこずのない「しなやかさ」の象城のようだった。 ヒマリの打鍵音は再び軜快になり、今床は「Running...」のプログレスバヌが、瞬く間にGreenぞず駆け抜けおいった。


    📜 ボスの秘蔵蚭蚈の矎孊ず珟堎のリアル

    staticメ゜ッドは、確かに䟿利です。 むンスタンス化の手間もいらず、どこからでも手軜に呌び出せる。しかし、その「手軜さ」こそが、倧芏暡なプロゞェクトにおいおは臎呜的な足かせずなりたす。

    これたでの蚭蚈の連茉でも觊れおきたしたが、私たちはDIDependency Injectionを基本に据えるべきです。 なぜなら、staticメ゜ッドを内郚で呌び出した瞬間、そのメ゜ッドは呌び出し先ず「密結合」しおしたうからです。倖郚から切り離しおテストしようずしおも、staticメ゜ッドずいう壁が立ちはだかり、䟝存関係の泥沌に匕きずり蟌たれるこずになりたす。

    技術的な偎面から芋れば、回避策がないわけではありたせん。 Pythonであればテスト実行時にメ゜ッド自䜓を差し替えるこずができたすし、PHPでもラむブラリを駆䜿しおstaticメ゜ッドを匷匕に䞊曞きOverrideするこずは可胜です。

    しかし、ここには倧きな代償が䌎いたす。 特にPHPでは本来メモリ䞊にロヌドされるべき「正しい定矩」をテストのために歪めおしたうため、他のテストケヌスに深刻な副䜜甚を及がすリスクが生じたす。その副䜜甚を避けるために「実行プロセスを分ける」ずいう遞択をせざるを埗なくなり、結果ずしおテストの実行時間が膚れ䞊がっおいく  。これが、前回お話しした「遅すぎるテスト」を生む元凶の䞀぀なのです。

    䞀方で、Laravelの「Facade」のように、staticなむンタヌフェヌスを持ちながらもテスト時には Fake メ゜ッドぞ容易に切り替えられる仕組みを備えたものもありたす。これはPythonの差し替えに近い利䟿性を提䟛しおくれたす。

    ですが、これらはあくたで「救枈措眮」に過ぎたせん。 本質的には、staticメ゜ッドに䟝存する蚭蚈そのものが密結合を招いおいる事実に倉わりはないのです。

    DIを軞に蚭蚈を行い、䟝存関係を倖から泚入する。 この「疎結合」を保぀ための芏埋こそが、クリヌンアヌキテクチャぞず続く王道であり、倉化に匷く、か぀爆速で怜蚌可胜な「盟」を䜜り䞊げるための唯䞀の解ではないでしょうか。

    ぀づく

    #゚ンゞニア #プログラミング #テストコヌド #ナニットテスト #蚭蚈 #DI #䟝存性の泚入 #staticメ゜ッド #密結合 #疎結合 #゜フトりェア開発 #リファクタリング #クリヌンコヌド #PHP #Python #技術的負債 #東根枩泉秘密結瀟 #テスト容易性

    あなたぞのおすすめ