プログラミングとSEOと暇つぶし

駆け出しエンジニアdallPのブログです。元SEOコンサルタントです。プログラミング、SEO、アフィリエイト、お金などについて役に立つかもしれない情報をやりたいように書きます。

【日々の学び: プログラミング】同じ結果でもより良い書き方をする / 返り値にnullが入るケースを意識する

Node.jsエンジニアのdallPです。
肩書がエンジニアになってから5営業日が過ぎました。

分からないなりに初プッシュ・プルリクを出し、初マージまでこぎつけましたが、その間にもかなりのインプットがあったので、今後は自分のために不定期にまとめていきます。

今回はタイトル通り、プログラムの書き方と返り値について。
いずれもエンジニアとしてお仕事をされている方にとっては当たり前のことで、お目汚しスミマセン。

同じ結果でもより良い書き方をする

何が言いたいのかというと、実用的なプログラムを書く場合において、過程は結果と同じくらい重要視されるよ、ということです。

初めてのプルリクを出して諸先輩方にコードレビューをしていただいた際のフィードバックの殆どは、根本的にこの考え方を持ってコーディングしていれば避けられたものです。

具体例を下記で挙げています。

Array(配列)インスタンスメソッドの使い方について

ご存じの通り、Arrayオブジェクトには様々なメソッドが用意されています。
※非エンジニアの方向けに一応書くと、Arrayとは配列を扱うためのモデルのようなものです。詳しくはこちらなど参考にしてみてください。

指摘されてから初めてまともに下記ページを眺めてみたのですが、実にあらゆるケースを想定したメソッドがデフォルトで組み込まれているのですね。

developer.mozilla.org

例えば良く使われるメソッドでは下記のようなものがありますね。

push: 配列の最後に要素を追加する
forEach: 配列中のそれぞれの要素について、自分で定義した関数を逐次的に呼び出す

で、今回問題になったのは、「forEachよりどストライクなメソッドがあるのにforEachで頑張って書く」ことをしていた部分です。

やりたかったこととしては、「ある配列の中に特定の要素があるかどうかを判定する」ことです。
実は、JavaScriptのArrayインスタンスには、デフォルトで上記の処理を行ってくれる"includes()"というステキ関数が存在します。
しかしその存在を知らず、まともに使えるメソッドがforEachくらいしかなかったdallPは頑張ってそれを書いた、ということです。

ある配列の中に特定の要素があるかどうかを判定するだけであれば、forEachに限らず他の関数を利用することもできます。


JavaScriptのArrayのサンプルコード

上記を見ていただければお分かりだと思いますが、やりたいことは同じなのにも関わらず、コード量が全然違います。
書く側にとってメリットがあるのは明らかですが、読む側にとっても理解しやすい良いコードになりますね。
③より①の方が圧倒的に読みやすいです。

SQLで取得してきたデータを加工する処理について

SQLって正直面倒ですよね。
サクサク書ける人だとそうでもないのかもしれませんが、今回については必要ないデータまで取ってきて、いらない部分はプログラム側の実装で削ぎ落とす、ということをやってしまい、注意されました。

SQLでどうにかなる絞り込みは、できるだけSQL側でやる。
プログラム側での処理・加工は最低限で。

ちなみに上記の考え方でデータを取得してきたら、上記で話したArrayのコードは結局全て不要になりました笑

定数は定義された定数名で取得する

これも当たり前といえばそうなのですが、最初は定数の中身をそのままプログラムに記述してしまっていました。
これだと、もし仮にその数値が指し示すものが変わってしまった場合にコードの修正が面倒になるし、可読性も無くなるのでNG。

定数名で取得してきていれば、その定数名さえわかりやすい命名がされていれば可読性が上がります。
コード中での検索もしやすくなりますし。

結局「より良い書き方」をしてあると何が嬉しいのか

・知ってさえいればコーディングのスピードが上がる
・コードの可読性があがる、実装内容変更時にも理解しやすい
・無駄な処理を行わないので、実際にフロントで見たときの処理速度が上がる

など。他にもあるかもしれませんが、今回僕が感じたのはこの辺の部分です。

ただ、僕のように初心者がいきなり実務に入るケースだと、当然知らないメソッドや書き方も多くあるはずです。
なぜなら初学者レベルでは、具体的なユースケースすら分からないメソッドばかりだからです。

もはやこれについては実務の中で学んでいくしかないのかな、と思っています。

返り値にnullが入るケースを意識する

「より良い書き方」に比べるとだいぶ具体的なテーマですが、要は他人が書いた(= 言語に元々実装されてるものや、外部フレームワークなど全て)関数の返り値には気をつけようぜ、ということです。

今回は、SequelizeというNode.js用のORマッパーの関数の返り値に関して突っ込みが入りました。

Manual | Sequelize | The node.js ORM for PostgreSQL, MySQL, SQLite and MSSQL

Sequelizeでは、取得してきたデータは配列となっており、該当するカラムがそれぞれSequelizeオブジェクト?として要素に格納されています。
その返り値に対して、Sequelizeで元々定義されているgetメソッドを呼んでやると、中身が連想配列になります。

なので、特に何も考えずgetを使っていたところ、「返り値がnullだった場合はどうする?」という指摘を受けた、ということです。

実際調べてみた結果、もし生成されたQueryに該当するカラムがなかった場合は空配列が返ってくる仕様だったので、その可能性も加味したコードに修正しました。

僕はゲームを買っても取説を読まない人間なのですが、仕事としてプログラムを書く以上は、しっかり読むべきところは読んでおく必要があるなと実感しました。

その他

その他にも多数の学びがあったのですが、細かいことも多いので箇条書きっぽく。

JavaScriptの変数のscopeについて: varのscopeはヤバい(関数の中で定義した変数が外から参照できたりする)ので、letを意識的に使う。
Arrow関数について: できるだけfunctionではなく=>で書く (例えば function(name) {}; であれば、 name => {}; と書き換えられる)
OR演算子 (||) について: ORで繋いだ二つの条件について、仮に一つ目の条件が常にtrueとなる場合は二つ目が評価されることはない。つまり条件として書く意味がなくなる
引数について: 引数は使わないなら省略可能だが、順番は定義されている順にしか書けない。なので、仮にデフォルトで三つの引数を取ることができる関数について、二番目の引数だけ使いたい場合、三番目の引数は省略できるが一番目の引数は省略できない。
returnについて: JavaScriptでは(他の言語では知らない)、returnは関数の中にしか書けない。ついついif文の中に書いてしまい、Syntax Errorを喰らいました。

stackoverflow.com

gitの使い方について: 下記の便利なサイトを教えてもらった。branchやmergeなどの概念がわかりやすいのでこいつで勉強する。

k.swd.cc