大きな関数を分割することはコードの可読性と再利用性を向上させる

Close-Up Photography of Sleeping Tabby Cat

大きな関数を小さな関数に分割することは、コードの可読性と再利用性を向上させるための効果的な方法です。特に、異なる責任を持つロジックを分けることが重要です。

ChatGPT

住所変換機のコード整理の続きだ。

今回は「validateAndUpdateInput」という次の関数だ。

JavaScript
        // 入力を検証し、エラーがなければ住所を更新
        function validateAndUpdateInput(inputElementId, value) {
            let isValid = validateDetailAdressInput(inputElementId, value);
            if (isValid) {
                // 根据 inputElementId 更新相应的全局变量
                if (inputElementId === 'block_lot') {
                    currentBlockLot = value;
                } else if (inputElementId === 'building') {
                    currentBuilding = value;
                } else if (inputElementId === 'room') {
                    currentRoom = value;
                }
                updateJapaneseAddressDisplay(); // 更新显示的地址
            }
        }

既存コードを概覧

この関数も複数の機能を持っているので、可能な限り分解し、シンプルにしたい。

まず、3行目では前回記事で整理した「validateDetailAdressInput」関数を呼び出して、引数、つまりフォーム要素のIDと値の検証している。引数はフォーム要素のIDと値だ。

検証をパスした場合、6行目以降でグローバル変数にフォーム要素の値を代入する

そして13行目ではこちらの記事で整理した「updateJapaneseAddressDisplay」関数で日本語の住所を更新している

こう見てくると、「validateDetailAdressInput」と「updateJapaneseAddressDisplay」はこの関数内に入っているのが目障りになってくる。いわゆる「単一責任の原則」から逸脱するからだ。

ただ、いきなりその2つを外してしまうとコードが走らなくなるので、「validateAndUpdateInput」がどこで呼び出されているかをチェックし、然るべき対策をしなければならない。

検索してみたら、イベントハンドラー内でしか使われていないことがわかった。▼

JavaScript
            document.getElementById('postal_code').onblur = function() {     
              validatePostalCodeAndUpdateAddress(); 
            };
            
            document.getElementById('block_lot').onblur = function() { 
              validateAndUpdateInput('block_lot', this.value); 
            };
            
            document.getElementById('building').onblur = function() { 
              validateAndUpdateInput('building', this.value); 
            };

            document.getElementById('room').onblur = function() { 
              validateAndUpdateInput('room', this.value); 
            };
            
            document.getElementById('convert-button').onclick = function() { 
              convertToEnglish(); 
            };

既存の関数を2つに分解する

イベントでは1つしか関数を設定できないことはないが、複雑にしたくないので、1つにしておく。「validateDetailAdressInput」と「updateJapaneseAddressDisplay」と、今回修正した関数を呼び出す関数とし、あとでこれを作る。

JavaScript
        // 入力を検証し、エラーがなければ住所を更新
        function setGlobalVariable(inputElementId, value) {
            // 根据 inputElementId 更新相应的全局变量
            if (inputElementId === 'block_lot') {
                currentBlockLot = value;
            } else if (inputElementId === 'building') {
                currentBuilding = value;
            } else if (inputElementId === 'room') {
                currentRoom = value;
            }
        }

ひとまず、上記のように、この関数をグローバル変数のみをセットする関数に修正し、名前変更した

続いて下記通り、新しい関数「validateAndUpdateJapaneseAddressDisplay」を作り、元の「validateAndUpdateInput」と同じ機能を実現する

JavaScript
        function validateAndUpdateJapaneseAddressDisplay(inputElementId, value) {
            if (validateDetailAdressInput(inputElementId, value)) {
                setGlobalVariable(inputElementId, value);
                updateJapaneseAddressDisplay();
            }
        }

テストしたところ問題がない。これで大方完了するが、JSDocコメントと、中国語のコメントを日本語に翻訳するのと、適宜コメントを追加するのをChatGPTに依頼する。

JSDocコメントを追加

setGlobalVariableのJSdocコメントをChatGPTに提案してもらう
setGlobalVariableのJSdocコメントをChatGPTが提案してくれる

続いて「validateAndUpdateJapaneseAddressDisplay」だ。

validateAndUpdateJapaneseAddressDisplayのJSdocコメントをChatGPTに提案してもらう
validateAndUpdateJapaneseAddressDisplayのJSdocコメントをChatGPTが提案してくれる

今回の教訓

今回も教訓をChatGPTから引き出す。

ChatGPTに記事から得られる教訓を引き出す
ChatGPTが記事から得られる教訓を回答する

教訓は7つまであるが、今回は2番目の「関数の分解」がいちばんやってきたことに合うのでこれにする

今回は以上だ。