型があるのが良いのか🤔
この話題は度々、議題に上がり、多くの人が討論をしています。
個人的な近年の傾向としては、golang
やTypeScrpit
の流行、Python
やRuby
が型アノテーションが導入されるなど、型のある言語(静的型付け言語)への需要が高まっているように思います。それ以前はRuby
やPython
のような型のない言語(動的型付け言語)がトレンドだったと認識しています。
(検索ボリュームだけでは比較は難しそうです👀)
僕個人としては型がある方が嬉しいです。型があれば、想定外のエラー発生を減らすことが出来ますし、どのようなデータが処理されてくるのかをすぐに理解することが出来ます。またコードに不備や誤りがあればビルド、コンパイル時に気付くことが出来ます。
とはいえ、型のある言語を採用するかどうかはプロダクトやチームの意向、メンバーの経験など様々な要員によって決まるので、必ずしも型があれば良いというものでもないでしょう。
そんな中、「やっぱり一度は型のある言語をやった方が良いな」という出来事が起きたのでした。
新メンバーがやってきた🏃♂️
ある日、我々の開発チームに新たなメンバーがやってきました。
業務経験はありませんが、個人で熱心にプログラミングに取り組んできたとのことで採用が決まりました。
彼の経験のあるメイン言語がTypeScript
で「JavaScript
ではなく何でTypeScript
にしたの?」と聞いてみたところ、「元々、ブログを作りたかった。参考にした情報がTypeScript
でブログを開発をしていたから」だったそうで、特に型の有無を意識して選択したという意図はありませんでした。
彼のコードをレビューすることに👓
彼にやってもらった初めてのタスクはFiteStore
に記録されているドキュメントからパスを指定してIDの一覧を配列で取得してくるという内容です。注意点として「取得するパスが存在しない場合に例外エラーが発生する」とだけ伝えました。
一通りの処理が書けたという報告を受けたので、一度、自分がコードレビューをすることにしました。業務未経験の彼はコードレビューを受けるのも初めてとのことで、とても緊張していました。
以下が彼が仕上げてきたコードを再現したものです(※再現したコードなので実際には動作しません)。
const getIds = async (dbClient, path) => { try { return await dbClint.collection(path).get().map(data => data.id); } catch (e) { console.error(e); return []; } }
「ん?何か変わったところある?」と思われるかもしれませんが... はい。あります。
僕が驚いたのは業務未経験の彼が「例外が発生しない場合と発生した場合で関数が返す値の型を揃えていた」ということです。
例外が発生しない時はreturn await dbClint.collection(path).get().map(data => data.id);
より文字列を含む配列[]String
が返され、例外が発生した場合には、空の配列が返ります。
自分の観測上、業務未経験、型のある言語を経験したことのない開発者は例外発生時に空配列ではなく、null
を返すか、明示的に何も返さない(JavaScript
の場合はundefined
)という記述が多いです。
catch (e) { console.error(e); return null; }
catch (e) { console.error(e); }
過去の記事でも触れていますが、動的型付けの場合であっても、関数が返す型は揃えるべきだと自分は考えています。
JavaScript
ではnull
を返してしまうと、呼び出し元でTypeError: Cannot read property '***' of null
が発生してしまう可能性がありますし、配列が返ってくることを期待していてmap
関数を記述していたりすると、例外発生時にmap
を呼び出すことでさらに例外が発生してしまいます。
上記2つの問題は例外発生時に空配列を返せば回避可能なのです。
なんで空配列を返そうと思ったか聞いてみた✒️
「TypeScript
だったら[]String
という値を返す関数を定義するので、素のJavaScript
でも無意識に同じように考えて書いてたかも」
...
とのことでした。素晴らしいですね。
この出来事をきかっけに、やはり一度は型のある言語を経験した方が良い、コードのクオリティは上がるのだと確信しました。