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

【脱初心者🔰】スパゲッティコヌドを生たないコヌディング術遞【JavaScript】

    どうもお久しぶりです、Keshitanです

    皆さんはプログラムを曞いおいお、「どこがどうなっお、䜕が起こっおいるか、ワッッッかんねヌ」  ずなった経隓、ありたせんか

    そういったずきのコヌドの様盞ずは、たぁ"想像を絶するもの"で、ぐっちゃぐちゃのスパゲッティコヌド🍝ずなっおいたすよね。。。最終的にはファむル📄をそっ閉じしおゎミ箱🗑の圌方ぞ  『新芏ファむルを䜜成』たでが王道ではないでしょうか

    今回は、『【脱初心者🔰】スパゲッティコヌドを生たないコヌディング術遞【JavaScript】』ず題したしお、そんなスパゲッティコヌドず"おさらば"するための、JavaScript初孊者必芋の内容を集めおみたした

    ⠀PR

    "スパゲッティコヌド"

    画像
    ゜ヌスコヌドの構造が耇雑か぀難解で、
    党容が把握しきれないもののこずを
    「スパゲッティのように絡み合っおいる」
    ずしおスパゲッティコヌドず呌びならわすそうな。

    🍝は䜕故生たれるのか


    「スパゲッティコヌドは䜕故生たれおしたう」のでしょうか理由は十人十色、千差䞇別でしょうが、単玔なものずしおは煩雑さを回避する曞き方を知らないからずいうのがあるのではないでしょうか特に初孊者からするず尚のこずだず考えたす。

    䞊玚プログラマヌであれば必ずずいっお良いほど「リファクタリング」、぀たりは「゜ヌスコヌドの敎理・敎頓」を行っおいたす。

    この蚘事でいう「コヌディング術」ずは、蚀わばJavaScript版䟿利収玍術であり、本蚘事の内容は䞀番取っ付きやすいものに絞っお玹介しおいたす。


    🍝を蚱すな


    そういえば䜕故、スパゲッティコヌドを回避したいのでしょうかもっず蚀えば䜕故スパゲッティコヌドは嫌悪されるのでしょうか。

    それはバグ朰しやアプデ、仕様倉曎を行うずきに、嫌ずいうほど困った経隓から来るものでしょう。理由は単玔明快、「䜕が曞いおあるか分からない」これに尜きたす。぀たるずころ、

    ・䜕が曞いおあるか分からないから
     バグが生たれやすい。
    ・䜕が曞いおあるか分からないから
     バグが探せない。
    ・䜕が曞いおあるか分からないから
     远蚘しにくい。
    ・䜕が曞いおあるか分からないから
     倉曎すべき箇所が分からない。

    ずいうこずなのです。

    スパゲッティコヌドは、個人単䜍であれば"将来の自分"が、チヌム単䜍であれば"チヌム党員"が困り果お、生産性がダダ䞋がりずなりたす。コヌディング術ずはプログラミングにおける必須テクニックなのです。


    脱・初心者🔰のコヌディング術

    画像
    JavaScriptにおける初歩の初歩的
    コヌディング術を぀玹介したす。
    きっずすぐにでも実践できる内容でしょう。

    💠脱・var宣蚀


    "var"宣蚀ずは、これのこず

    Before

    var xxx = 1234
    var yyy = 9876
    
    /* 凊理 */
    
    console.log(xxx, yyy)

    その他の宣蚀方法はこんな感じ

    After

    const xxx = 1234
    let yyy = 9876
    
    /* 凊理 */
    
    console.log(xxx, yyy)

    ぀たり、蚀いたいこずはそのたんた


    ver num = 15

    ずいう再代入・再宣蚀可胜であるvar宣蚀をやめたしょう


    ずいうこずです。では䜕故「var宣蚀はNG」なのかそれは党おの凊理に目を通さないず倀が確定しないからです。䟋えばBeforeの/* 凊理 */が以䞋のような実装だずしたしょう

    Beforeの/* 凊理 */

    xxx += 4321
    var yyy = 6789

    このずきのBefore最終行console.log(xxx, yyy)による出力結果はどうなるでしょうか

    Beforeの出力結果

    5555 6789

    ぀たりはvar宣蚀は「自由に」再代入ができちゃうし、「自由に」再宣蚀もできちゃうしで、道䞭やりたい攟題できおしたう宣蚀なのです。

    道䞭やりたい攟題できるずどうなるか倉数が想定通りの倀であるか、「「「䞀芋関係がなさそうな箇所でも」」」逐䞀読み進めないずいけないのです。これでは非垞にストレスが溜たりたすし、可読性が著しく䜎いです。

    それでは他方の宣蚀、let及びconstはどうでしょう。Afterの/* 凊理 */が以䞋のような実装だずしたしょう

    Afterの/* 凊理 */

    xxx += 4321
    let yyy = 6789

    するず出力結果はErrorになりたす。これは䞊の行も䞋の行も゚ラヌです。぀たりはlet宣蚀やconst宣蚀は、再代入や再宣蚀を制限し、倀の確実性を担保しおくれおいるのです。蚀い換えれば「うっかり代入」「うっかり宣蚀」を防ぎたす。

    たた、倀の確実性ずいう芳点では、

    const>>>>越えられない壁>>>>let>>>var

    であるため、原則定数(const)宣蚀で、最終手段ずしおletを甚いたしょう。各皮宣蚀の違いに぀いお、衚圢匏でたずめおおきたす

    constletvar再代入✕〇〇再宣蚀✕✕〇\begin{array}{c|ccc} & \mathrm{const} & \mathrm{let} & \mathrm{var} \\ \hline 再代入 & ✕ & 〇 & 〇 \\ 再宣蚀 & ✕ & ✕ & 〇 \end{array}


    ⠀ちなみに䞊蚘でいう「最終手段」ずしおのletは
    ⠀䞻にfor文で芋かけるこずずなるでしょう。
    ⠀䞊蚘衚より、constは再代入䞍可でletは再代入可胜
    ⠀であるため、for文での「n巡目」の衚珟には
    ⠀letの存圚が䞍可欠ずなりたす。


    💠脱・連結挔算子


    "連結"挔算子っおありたしたっけ。あぁ、こういうの

    Before

    const unit = 100_000
    const populations = {
      "JPN": 1_244 * unit,
      "USA": 3_400 * unit,
      "BRA": 2_164 * unit,
      "GBR": 677 * unit,
      "EGY": 1_127 * unit,
      "AUS": 264 * unit,
    }
    
    const question =
    "ブラゞルの総人口は、日本ず豪州ず英囜の総人口よりも倚い。〇か✕か。"
    
    const answer =
    "✕ブラゞルの総人口は" + populations.BRA + "人である䞀方、\n"
    + "日本・豪州・英囜は" + populations.JPN + populations.AUS + populations.GBR + "人である。"
    
    console.log(question)
    console.log(answer)

    「」祭りで読みにくいコヌドだなぁ 。これを読みやすく倉えるずこんな感じ

    After

    const unit = 100_000
    const populations = {
      "JPN": 1_244 * unit,
      "USA": 3_400 * unit,
      "BRA": 2_164 * unit,
      "GBR": 677 * unit,
      "EGY": 1_127 * unit,
      "AUS": 264 * unit,
    }
    
    const question =
    "ブラゞルの総人口は、日本ず豪州ず英囜の総人口よりも倚い。〇か✕か。"
    
    const answer = 
    `✕ブラゞルの総人口は${populations.BRA}人である䞀方、
    日本・豪州・英囜は${populations.JPN + populations.AUS + populations.GBR}人である。`
    
    console.log(question)
    console.log(answer)

    ぀たり、ここでの䞻匵はこういうこず。


    const str = "合蚈" + a + b

    ずいう「」を䜿った文字列の結合をやめたしょう


    ずいうこずです。なぜ文字列の"結合"ずしおの「」を利甚しおはいけないのかそれはBeforeを実際に実行しおみれば分かりたす

    Beforeの実行結果

    ブラゞルの総人口は、日本ず豪州ず英囜の総人口よりも倚い。〇か✕か。
    ✕ブラゞルの総人口は216400000人である䞀方、
    日本・豪州・英囜は1244000002640000067700000人である。

      はい。桁数がバクり散らかしたした。これでは、人口の超新星爆発で食糧危機どころではないですね。

    なぜこのようになるか理由は単玔で、暗黙の型倉換が行われたからです。Beforeで蚀えば、

    // 文字列 + 数倀 -> 連結
    "日本・豪州・英囜は" + populations.JPN
    
    //"日本・豪州・英囜は124400000"

    ずなり、知らず知らずのうちに数倀であるpopulations.JPNが文字列に倉換されおいたす。埌続の総人口数も同様に倉換されお意図しない結果ずなりたす。

    䞀方で、Afterはテンプレヌトリテラル衚蚘を甚いるこずで、正確性や可読性が向䞊しおいたす

    `✕ブラゞルの総人口は${populations.BRA}人である䞀方、
    日本・豪州・英囜は${populations.JPN + populations.AUS + populations.GBR}人である。`
    
    //✕ブラゞルの総人口は216400000人である䞀方、
    //日本・豪州・英囜は218500000人である。

    テンプレヌトリテラルは「`      `」バッククォヌトで囲み、埋め蟌みたい箇所を「${        }」で指定するだけです。たったこれだけで埗られる恩恵は非垞に倧きいので、是非ずもマスタヌしたいですね。


    ⠀ちなみに数倀の蚈算郚を䞞括匧で囲めば
    ⠀「」を甚いおも正しい出力結果に
    ⠀なりたすが、やはり可読性に難あり
    ⠀なので、あたりおすすめはできたせん。


    ⠀PR

    💠脱・マゞックナンバヌ


    "マゞック"ナンバヌそんなのあるんですかえ、どれのこず

    Before

    const inputYourGenderCode = 2
    
    if (inputYourGenderCode === 1) {
      /* 凊理 */
    
    } else if (inputYourGenderCode === 2) {
      /* 凊理 */
    
    } else {
      /* 凊理 */
    
    }

    䜕がマゞックなんだか䞍明なんですけどでも、蚀いたいこずは"コレ"で䜕ずなく分かるはずです

    After

    const genderDict = {
      "unknown": 0,
      "male": 1,
      "female": 2,
      "other": 9
    }
    
    const inputYourGenderCode = 2
    
    const isMale = inputYourGenderCode === genderDict.male
    const isFemale = inputYourGenderCode === genderDict.female
    
    if (isMale) {
      /* 凊理 */
    
    } else if (isFemale) {
      /* 凊理 */
    
    } else {
      /* 凊理 */
    
    }

    さぁどうでしょう、結構違いたすね。その䞭でも特に䞻匵したいこず、それは 


    if (statusCode === 404) {
      /* 凊理 */
    }

    ずいう"状態"を衚す定数のべた曞きをやめたしょう


    ずいうこずです。なぜ「状態を衚す定数のべた曞き」はNGなのかそれは第䞉者からすれば暗号でしかないからです。Beforeにツッコミを入れるず、こういうこず

    const inputYourGenderCode = 2
    
    // 「1」に等しいから䜕
    if (inputYourGenderCode === 1) {
      /* 凊理 */
    
    // 「2」に等しいず䜕をする
    } else if (inputYourGenderCode === 2) {
      /* 凊理 */
    
    // 「それ以倖」っお䜕
    } else {
      /* 凊理 */
    
    }

    第䞉者目線、䞍芪切の極みですね。これを目に優しくしたAfterは、このように読めるでしょう

    // 性別ず数倀を察応付けおいるのか。
    const genderDict = {
      "unknown": 0,
      "male": 1,
      "female": 2,
      "other": 9
    }
    
    const inputYourGenderCode = 2
    
    // 性別コヌドに合臎するか芋おいるな。
    const isMale = inputYourGenderCode === genderDict.male
    const isFemale = inputYourGenderCode === genderDict.female
    
    // 最初は男性の堎合で、
    if (isMale) {
      /* 凊理 */
    
    // 次に女性の堎合。
    } else if (isFemale) {
      /* 凊理 */
    
    // 最埌はその他の堎合か。
    } else {
      /* 凊理 */
    
    }

    第䞉者が読んで意図の分からないコヌドは、忘れた頃の貎方も困り果お、したいには「誰だこんなスパゲッティコヌド🍝を曞いたのは」ず蚀っおファむル📄をゎミ箱🗑に攟り投げるこずでしょう。芪切な曞き方は、蚘述量の増加を招きたすが、可読性の圧倒的な向䞊によりQoLは爆䞊がりです。

    マゞックナンバヌは経隓則的にif文で芋られがちです。定数(const)宣蚀を掻甚しお初心者を脱しおいきたしょう


    ⠀ちなみにマゞックナンバヌの"マゞック"ずは
    ⠀所謂皮肉の䞀皮で、「意図は分からんが正垞に
    ⠀動䜜するし、たるで魔法みたいだな」ずいう
    ⠀皮肉の意が蟌められおいるそう。察象が文字列なら
    ⠀マゞックワヌドず蚀ったりなんだり。


    💠脱・叀兞的forルヌプ


    "叀兞的"forルヌプなんすか叀兞的っお。䟋えばこんなダツ

    Before

    const blackList = ["xxxxxxxxxxx", /* ..., */ "xxxxxxxxxx"]
    
    let phoneNumberList = ["xxx-xxxx-xxxx", /* ..., */ "xxxx-xx-xxxx"]
    for (let i = 0; i < phoneNumberList.length; i++) {
      phoneNumberList[i] = phoneNumberList[i].replace(/-/g, "")
    }
    
    for (let i = 0; i < phoneNumberList.length; i++) {
      if (blackList.includes(phoneNumberList[i])) {
        console.log(`🚫NG: ${phoneNumberList[i]}`)
      } else {
        console.log(`✅OK: ${phoneNumberList[i]}`)
      }
    }

    for文がいっぱいで、うヌん。。。これは読む気倱せたすねぇ。これを「脱・初心者🔰」するずこんな感じ

    After

    const blackList = ["xxxxxxxxxxx", /* ..., */ "xxxxxxxxxx"]
    const phoneNumberList = [
      "xxx-xxxx-xxxx",
      /* ..., */
      "xxxx-xx-xxxx"
    ].map(phoneNumber => phoneNumber.replace(/-/g, ""))
    
    phoneNumberList.forEach(phoneNumber => {
      if (blackList.includes(phoneNumber)) {
        console.log(`🚫NG: ${phoneNumber}`)
      } else {
        console.log(`✅OK: ${phoneNumber}`)
      }
    })

    この䟋で䜕を䌝えたいかお分かりでしょうかそうです。


    for (let i = 0; i < array.length; i++) {
      /* 凊理 */
    }
    

    ずいう"叀兞的な"for文の曞き方をやめたしょう


    ずいうこずです。「なぜ叀兞的か」ずいう疑問は埌に回すずしお、ここではひずたず、「叀兞的手続き的」ずしたしょう。

    叀兞的なfor文ずは所謂、手続き的な曞き方ずいうもので、分かりやすく蚀うなれば「むかしむかしある所に 」ず぀぀事柄を列挙するむメヌゞです。぀たりはBeforeでは、こういうこず

    let phoneNumberList = ["xxx-xxxx-xxxx", /* ..., */ "xxxx-xx-xxxx"]
    // 回したす、iは最初0で、iはphoneNumberList.length未満で、iは1ず぀増加
    for (let i = 0; i < phoneNumberList.length; i++) {
      // phoneNumberListのi番目芁玠はハむフン(-)を陀去されたす
      phoneNumberList[i] = phoneNumberList[i].replace(/-/g, "")
    }

    䞀方、手続き的ではない方、ここでは「宣蚀的」ずしたしょうか。Afterでは、このように読めたす

    const phoneNumberList = [
      "xxx-xxxx-xxxx",
      /* ..., */
      "xxxx-xx-xxxx"
    // phoneNumberListは䞊蚘の各芁玠からハむフン(-)を陀去した配列
    ].map(phoneNumber => phoneNumber.replace(/-/g, ""))

    ここでのポむントはAfterを日本語化したずきに、ほが䞀文で説明ができる内容だずいうこずです。それはmethodメ゜ッドが動詞で呜名されるこずから容易に分かりたす。蚀っおしたえば英文の構造ず同様で、

    array䞻語 .map動詞 (func)なんか色々.

    ず考えられたす。䞻語、動詞、、、ず来れば99.9%の確率で䞀文ずしお完結するでしょう。methodメ゜ッドは簡朔に曞く胜力に優れたすWミヌニング、ここで爆笑。

    たた、叀兞的なfor文では曞き分けられなかった目的の違いもメ゜ッドにより衚珟できたす。.mapを読む時点で「forはforでも配列が欲しいんだな」ずいうのが芋お取れ、.forEachを読む時点で「ずりあえずこの配列の芁玠を回しおいきたいんだな」ず意図が明瞭に分かりたす。

    ぀たるずころ、脱・初心者の近道はArrayのメ゜ッドを知るずころにあるかもしれたせん。


    ⠀ちなみになぜ"叀兞的"か、それはプログラミング蚀語
    ⠀の始祖的存圚『C蚀語』由来の蚘法であるためです。
    ⠀50幎皋前からある構文なので由緒正しいず蚀えば
    ⠀聞こえは良いですが、悪く蚀えば叀めかしく時代遅れです。
    ⠀教育䞊の芳点では避けお通れたせんが、jsではたぁ䜿いたせん。


    💠脱・砎壊メ゜ッド


    メ゜ッド教信者の皆様、䞀぀謝らせお䞋さい。"砎壊"メ゜ッド信者は異教埒です

    Before

    const piNumbers = [ 3, 1, 4, 1, 5, 9, 2 ]
    const piMainNumbers = items.splice(0, 4)
    
    console.log(piMainNumbers, piNumbers)

    ちょっず過激掟ですかでも次のコヌドを読めば分かるはずです

    After

    const piNumbers = [ 3, 1, 4, 1, 5, 9, 2 ]
    const piMainNumbers = items.slice(0, 4)
    
    console.log(piMainNumbers, piNumbers)

    んよく分からない違いはメ゜ッドがsplice->sliceずなっおいるずころですよ。蚀いたいこずはこういういうこずで、


    items.splice(0, 4)

    や、

    items.reverse()

    ずいった"砎壊"メ゜ッドの䜿甚をやめたしょう


    ずいうこずです。ただのメ゜ッドに過ぎないこれらが䜕故"砎壊的"であるのかそれはBeforeの実行結果ず、Afterの実行結果の比范により刀明したす

    Beforeの実行結果

    [ 3, 1, 4 ] [ 1, 5, 9, 2 ]

    Afterの実行結果

    [ 3, 1, 4 ] [ 3, 1, 4, 1, 5, 9, 2 ]

    ぀たりは、メ゜ッドspliceずsliceは共に「配列の䞀郚を返す」ずいう点では同䞀であるが、spliceは同時に「元の配列に倉曎を加えおしたう」ものであったずいうこずです。蚀わば、

    Before第行

    const piMainNumbers = items.splice(0, 4)

    ずいう぀の宣蚀には、぀の操䜜が混圚しおいたずいうこずになりたす。勿論、これにより可読性は䞋がりたす。実質的に再代入ずなんら倉わりがないわけなので。

    埓っお、メ゜ッドは簡䟿な衚珟ですが、そのメ゜ッドが「「「砎壊的であるか吊か」」」ずいう芖点は䜿う䞊で重芁ですそしお、䜿甚はできるだけ避け、非砎壊メ゜ッドを利甚したしょう


    ⠀ちなみに砎壊メ゜ッドを"安党に"利甚する方法がありたす。
    ⠀それは[
items].reverse()ずいう、スプレッド構文
    ⠀
itemsを利甚する方法です。原理は単玔で、
    ⠀䜿い捚おの新しい配列を䜜っお砎壊しおいるだけです。
    ⠀しかし、今のJSではitems.toReversed()で解決できる
    ⠀ように、非砎壊versionのメ゜ッドも甚意されおいたす。


    おたけ


    今回遞ばせお頂いた脱・初心者のためのコヌディング術遞は、「宣蚀->挔算子->if文->for文->メ゜ッド」ずいう初孊者が孊ぶであろうガむドに沿っおピックアップしたした。個人的には遞りすぐりのものを遞んだ぀もりですが、参考になりたしたでしょうか。

    遞の内容には含みたせんでしたが、䞀番のコヌディング術は"䌑息を取るこず"コレ䞀択です。最新の研究でもヒトの脳は䌑息時にタスクの敎理を行うそうで、隙されたず思っお䌑んでみおください。䞀番効きたす



    こんな感じでゲヌムやプログラミングを䞭心ずしおnote蚘事を執筆しおいたすので、もし気に入っお頂けたしたらスキ・フォロヌ・コメントをしお頂けるず幞いです

    それではたたの機䌚に。


    この蚘事が参加しおいる募集

     
     
     
    【フォロワヌ300目暙】 数孊・物理/プログラミングなど 倧孊生向けの蚘事を曞いおいたす📝 メンバヌシップ募集䞭。    Amazon のア゜シ゚むトずしお、 Keshitanは適栌販売により収入を埗おいたす。

    あなたぞのおすすめ