保守性や堅牢性を高める！モダンフロントエンド開発に必要な周辺技術をまとめてみました

## はじめに

前日もくもく会で一緒になったエンジニア初学者の方を見て、ポートフォリオとしてフロントエンド開発はちゃんとできてはいるものの、実務において必要な保守性や堅牢性の高いコードについての意識がどうしても不足しているなという印象を受けました。

もちろん初学者の方にそのようなことを求めるのは酷な話なので知らないからダメ、ということを言うつもりは毛頭ありません。
が、職業としてエンジニアを目指すためにフロントエンド開発をやっている場合、保守性や堅牢性を意識すると企業からの評価が段違いなのではないかと思うのです。

そこで今回の記事では単にフロントエンドが開発できるというスキルだけではなく、実務における保守性や堅牢性を意識したフロントエンドを開発するために有効になるであろう技術について説明してみたいと思います。

## 対象者

- プログラミング初学者の方で、モダンなJavaScriptフレームワークを使ってフロントエンド開発を行っている方
- これからモダンなJavaScriptによるフロントエンド技術をプロダクトに導入しようとしている企業のエンジニア
- ReactやVueを導入はしたが、コードの管理やバグが頻出したりして悩んでいる方

## 紹介する技術・ライブラリの一覧
保守性や管理性を向上させるために有効なものとして、ざっと下記が挙げられます。

- eslint, prettierによるコード解析およびコードフォーマット
- TypeScriptによる静的片付け
- ReactHooks.useReducer, Vuexによる状態の一元管理
- Storybookによるコンポーネントのカタログ管理
- Atomic Design等のコンポーネント分割ポリシー
- Jestによるメソッドの単体テスト
- Testing Library(or Enzyme)によるコンポーネントの振る舞いテスト
- CypressによるE2E(End to End)テスト
- CIパイプライン上でのlintおよび単体テストの実行による自動検査、テストの実行
ではそれぞれの技術の概要と、導入したときのメリットについてみていきます。


## ESLint, prettier

### lintとは？何が嬉しい？
> lint とは、主にC言語のソースコードに対し、コンパイラよりも詳細かつ厳密なチェックを行うプログラムである。
静的解析ツールとも呼ばれる。
> lint - Wikipedia

実行するのに問題はないが、不具合の原因になるようなコードだったり、不要な記述についてチェックし、あらかじめ開発者に警告ないしエラーとして通知することでそれの解消をしてくれるツールがLintです。

ESLintにおいては静的解析を行う際に確認するルールを自由に設定することができ、例えば下記のようなことができます。

- no-console: consoleを使っていないこと
- no-empty: 空のブロックを使っていないこと
- no-func-assign: functionを再定義していないこと
- no-unreachable: 到達可能なコードが記述されていないこと
- no-eval: evalを使わないこと

等々ですね。
さらにプラグインを利用すればReactやJSXの記述を確認したり、様々なことが可能です。


### Prettierとは？何が嬉しい？

Prettierはコードフォーマッターのためのライブラリで、様々な言語のフォーマットが可能です。

ESLintがコードの問題を解消するのに対し、prettierではコードの整形を主眼としてしています。

業務におけるプログラミングではチーム開発が基本で、他人のコードを読んだり変更したりすることが多い。

そのため開発者ごとにコードの記述が異なると、コードの可読性が下がって効率が下がってしまいます。

Prettierを導入することで、チーム開発において重要なコードのフォーマットを維持し、自動化もさせることができます。

### Further Reading - 参考
- [ESLint公式サイト](https://eslint.org/)
- [TSLint公式サイト](https://palantir.github.io/tslint/)
- [Prettier公式サイト](https://prettier.io/)
- [Prettier - Github](https://github.com/prettier/prettier)
- [Prettier 入門 ～ESLintとの違いを理解して併用する～](https://qiita.com/soarflat/items/06377f3b96964964a65d)

## TypeScript

### TypeScriptとは？何が嬉しい？

TypeScriptはMicrosoftが主体となって開発している、JavaScriptのスーパーセット言語です。

その名の通り、JavaScriptに型を与えた言語で、動的型付けのJavaScriptに対して厳密な静的型付けを与えます。

動的型付け言語は変数の型が動的に変わり、その特性上スピード感のある開発が可能ですが、その代わりに意図しない型に変換されて不具合が発生したりすることもあり、安全性という意味では静的型付け言語に劣ります。

今のところフロントエンド開発においてJavaScriptは不動の地位を占めていますが、裏を返すと動的型付けのJavaScriptしか選べなかったということでもありました。

TypeScriptはそのようなフロントエンドに対して、静的型付け機能を与え、型の不整合による不具合の発生を予防することを可能にします。

また、TypeScriptは実行前にJavaScriptに変換されます。
そのためOptional Chainingなどの機能をブラウザサポートを考えることなく利用することができ、新しい機能をフル活用することも可能です。

### Further Reading 
- [TypeScript公式サイト](https://www.typescriptlang.org/)
- [TypeScript - GitHub](https://github.com/microsoft/TypeScript)
- [TypeScriptの型入門](https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a)

## Redux, Vuex, ReactHooks.useReducer等によるステート管理

### ステート管理とは？何が嬉しい？

ReactとVueにはpropsとstateという値があり、stateはその名の通りコンポーネントの状態を表しています。

このstateを使うポリシーを定めていないと、stateの管理ができず不具合の温床になることがあります。

例えばあるコンポーネントの値を使って別のコンポーネントの動作が決定され、そしてそのコンポーネントの動作によってまた別のコンポーネントの動作が...というようなことが起こり、動作のロジックが複雑になり、デバッグが困難になります。

この問題を解決するためにstateを一元管理(Single source of truth)し、state管理をシンプルにするという手法が取られることがあります。

そしてそれを実現するためのツールが、ReduxやVuex(Vue)、useReducer(React)です。

例えばReduxというライブラリでは3つの原則を掲げていて、

- Single source of truth(単一の正しい情報源)
- State is read-only(Stateは読み込みのみ)
- Changes are made with pure functions(変更は純粋関数を利用して行われる)

というものになっており、この原則によって安全な状態管理が実現されます。

ステート管理を一元的に行うことで現在のアプリケーションの状態を明確にし、複雑な状態を持たせず管理しやすくなり、stateによる不具合を抑制しやすくなります。

### Further Reading
- [Redux公式サイト](https://redux.js.org/)
- [Three Principles - Redux](https://redux.js.org/introduction/three-principles/)
- [Redux入門【ダイジェスト版】10分で理解するReduxの基礎](https://qiita.com/kitagawamac/items/49a1f03445b19cf407b7)

## Storybookによるコンポーネントのカタログ管理

### Storybookとは？何が嬉しい？
> Storybook is an open source tool for developing UI components in isolation for React,
> Storybookは独立した状態でReact, Vue, そしてAngularのUIコンポーネントを開発するためのオープンソースツールです。

> [Storybook 公式サイト](https://storybook.js.org/) より
上記の公式サイトの紹介にあるように、Storybookはフロントエンドフレームワークにおけるコンポーネント開発のためのツールで、コンポーネント単位での開発と管理を可能にします。

これの何が嬉しいかというと、一つのコンポーネントの修正のために、ページ全体を開いて操作をする必要がなくなる、ということです。

例えばテーブル中に存在するソート順を変更するボタンを押した際に、各行がそれぞれ指定した列で並んでいるか、というのを確認したい時に、今までのやり方ではトップページを表示して、テーブルのあるページに移動して、ボタンを押して...ということを毎回やる必要がありました。

しかしStorybookを使えば、そのテーブルコンポーネントだけを表示させることができ、さらに指定したpropsをあらかじめ与えた状態にすることも可能です。

そのため、特定の状態のコンポーネントをあらかじめ用意して、それを一目で見ることも可能というわけです。

これによってコンポーネントの確認、修正のために不要な操作をする必要がなく、モダンフロントエンドにおけるコンポーネントの管理が格段に楽になります。

下記に記載しているStorybook Demoをみると、Storybookがどのようなものか一目で分かるかと思います。


### Further Reading 
- [Storybook公式サイト](https://storybook.js.org/)
- [Storybook Demo(React Dates)](https://airbnb.io/react-dates/)

## Atomic Design等のコンポーネント管理ポリシー

### Atomic Designとは？何が嬉しい？
> Atomic design is methodology for creating design systems. There are five distinct levels in atomic design:
> Atomic Designはデザインシステムのための方法論である。
Atomic Designにおいては5つの別個のレベルが存在する。

> [Atomic Design](https://bradfrost.com/blog/post/atomic-web-design/) - Brad Frost
Atomic Designはデザインにおける部品を化学的な概念に当てはめたもので、部品構成の単位を明瞭にしたものです。

元々はデザインガイドとして作られたが、それをフロント開発に応用しているプロダクトが増えています。

Atomic Designの何がいいかというと、コンポーネントの大きさによってコンポーネントを分類することで、管理しやすくするという点です。

Prettierの説明においてはコードの記述が開発者によってバラバラになるのを防ぐメリットがある、ということを説明しましたが、Atomic Designを使えば、開発者ごとにばらけがちなコンポーネントの大きさを統一し、再利用しやすくすることができるというわけです。

### Further Reading
- [Atomic Design原著](https://bradfrost.com/blog/post/atomic-web-design/)
- [Atomic Designを分かったつもりになる](https://design.dena.com/design/atomic-design-%E3%82%92%E5%88%86%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A4%E3%82%82%E3%82%8A%E3%81%AB%E3%81%AA%E3%82%8B/)
- [React Atomic Design](https://github.com/danilowoz/react-atomic-design)

## Jestによるメソッドの単体テスト

### Jestとは？何が嬉しい？
JestはJavaScriptにおける、ユニットテストのためのツールです。

ユニットとは「単位」の意味で、ユニットテストでは小さい部品のテストを実現することができます。

基本的にはJavaScriptやTypeScriptの関数、メソッドの中で記述したロジックがテスト対象となり、関数に与えた引数やAPIリクエストの返り値ごとに、それらが期待した通りの動作になっているかを確認します。

ユニットテストを導入することで、文字通り小さい単位のテストを実施することができるため、それらをつなぎ合わせて全体のアプリケーションを動作させた時の動作が保証しやすくなります。

先ほどStorybookの項目ではページ全体ではなくコンポーネント単位での確認が可能と言いましたが、Jestではそれのメソッドバージョンと言い換えるといいかもしれません。

古典的にはページを表示して、画面を動かした時に実行されるメソッドが正しく動いているかを手動で確認する必要があったりしますが、ユニットテスト済みのメソッドのロジックに関してはテストする必要はないと言っていいでしょう。


### Further Reading
- [Jest公式サイト](https://jestjs.io/)
- [Jest - GitHub](https://github.com/facebook/jest)
- [Facebook製のJavaScriptテストツール「Jest」の逆引き使用例](https://qiita.com/chimame/items/e97883fd46b67529d59f)

## Testing Library(or Enzyme)によるコンポーネントの振る舞いテスト

### Testing Library, Enzymeとは？何が嬉しい？
こちらもJestの話と似ていますが、こちらは関数やメソッドではなく、画面に表示するコンポーネントをテスト対象としています。

Storybookではコンポーネントの表示がどうなるかを確認することができましたが、あくまで開発者が自分の目で確認する必要がありました。

Testing LibraryやEnzymeを利用することで開発者の目視ではなく、コード上でコンポーネントがどのように動作するかを保証させることが可能になります。

そのため後述するCIパイプラインにおける自動テストなどに組み込みやすく、コードを開発してPRを出した時にテストを実行し、常に動作が問題ないことを保証することが可能になったりします。


### Further Reading
- [Testing Library公式サイト](https://testing-library.com/)
- [Testing Library - GitHub](https://github.com/testing-library)
- [フロントエンドでTDDを実践する（react-testing-libraryを使った実践編）](https://qiita.com/taneba/items/b21f5fee17eb593b30c8)

## CypressやSeleniumによるE2E(End to End)テスト

### Cypress, Seleniumとは？何が嬉しい？
Cypress, SeleniumはE2E(End to End)テストのためのライブラリで、E2Eテストはアプリケーション全体の動作をテストするものです。

JestやTesting Libraryはユニットやコンポーネントという小さな単位でのテストでしたが、E2Eテストではアプリケーションが全体として期待通りの動作をしてくれるのか、ということをテストします。

ユニットという単位では動作しているものの、それらをつなげた時に期待する動作をやっているかを保証してくれる機構はJestとTesting Libraryだけでは実現できません。

各種操作を画面上で行った時などのシナリオ全体での動作を保証させることが可能になるというわけです。


### Further Reading
- [cypress公式サイト](https://www.cypress.io/)
- [cypress - GitHub](https://github.com/cypress-io/cypress)
- [Cypressを使ったインテグレーションテストの導入](https://qiita.com/sinpaout/items/4313ed75e603508696b1)

## CIパイプライン上でのlintおよび単体テストの実行による自動検査、テストの実行

### CIパイプラインとは？何が嬉しい？
CIとはDevOpsにおける考え方で、継続的インテグレーション(Continuous Integration)の略語です。

言葉としては難しいですが、やっていることとしては要するに新しく書いたコードをマージした時にアプリケーションが正しく動作することを確認する仕組み、と考えれば良いでしょう。

GitHubなどでCIの仕組みを導入すると、PRを出したときに自動テストを実行させ、テストが失敗したときはPRをマージできない状態にしたり、slackにテストが失敗したことを通知させたりします。

ここまでで紹介したlint, jest, testing libraryなどをCIで実行できるようにすれば、PRを出した時にコード解析とテストが自動で実行され、コードの品質やメソッド・コンポーネントの動作が常にテストされた状態のリポジトリを維持することが可能になります。

CIのためのツールとしてはCircleCIやJenkins, AWSではCodeシリーズなどがあります。


### Further Reading
- [CircleCI](https://circleci.com/)
- [CI/CDのエキスパートが解説：CI/CDとは何か？ なぜ今、必要とされるのか？](https://codezine.jp/article/detail/11083)

## 最後に

以上、各種関連言語、ライブラリ等について紹介させていただきました。

これらを利用することで職業エンジニアを目指している方であれば、実用的な技術を使ったポートフォリオを構築して企業からの評価を高めることができるでしょうし、実務で利用すれば保守性が高くかつ堅牢なアプリケーションを継続的に開発することが可能になります。

もちろん導入自体にもコストがかかりますし、これら全てを導入する必要はありませんが、時間とリソースが許す限り導入を検討し、そして導入するのがいいでしょう。

(時間的余裕があれば、実際にここで並べた技術を用いてフロントエンドアプリケーションを開発するハンズオン記事を書きたいと思いますが、それはまた次回...)

ここ間違ってない？これも使った方がいんじゃね？というものがあれば教えてください！

それでは、ありがとうございました！