開発初心者が3ヶ月で社内向けにシステムを1人でプレリリースまでやってみた【開発】

# はじめに
社会人1年目のインフラエンジニアです。

今回は配属して約3ヶ月ほどでWEBシステムを作り(開発期間：約3ヶ月)プレリリースまですることになって苦労した話を書こうと思います。開発に関しては全くの素人なので、もっとこうすればいいんじゃない的なアドバイスいただけるとありがたいです。

# 筆者スペック
* AWSメインに扱うクラウド部門に所属
* 大学院ではデータサイエンスを学習(python)
* 趣味でweb開発(python,golang,javascript,html)
* インフラ系もすこし(AWS,GCP,Docker)

どれも熟練度的には高くなく、広く浅く触ってみたレベル

# 開発が始まるまでの経緯
業務で分析基盤を扱っている。
この分析基盤に入っているデータの詳細(テーブルやカラムの登録名称や何を表しているかの説明。以下、メタと呼ぶ)の管理が大変という話になった。

□ イケてないポイント
* スキーマやテーブルごとのメタデータをファイル管理
* 検索のしにくさ
* 管理場所が散らかっている
* 管理場所へのアクセスが特殊で手間がかかる

このようなメタ管理は参照するユーザーにとって面倒であろうから技術で解決したいということになった。

こんな感じで他の業務と平行しながら上記のイケてないポイントを改善できるシステム開発を1人で取り組む流れとなった。

# 始まった開発生活
## 要件を超簡単に定義してみた
上記のイケていないポイントを改善するための要件はなんだろうと考えてみて、簡単に以下のような結論に至った。

#### 考慮すべきポイント
ここでのポイントとして、利用者の技術力に関わらず使いやすいシステムを念頭においた。

### 定義したシステム要件
* メタ関連のファイルを一元的に管理する
* キーワードなどの検索ができると良い
* 誰でも使えるインターフェースが欲しい → GUIでの操作が可能にする
* レスポンスが速い

#### 勉強になったポイント
このように現状に対して課題を洗い出すことで、何を軸として解決すればよいのかが明確になると感じた。こういった要件定義は初めてだったが、超簡単でもしっかり書き出してずれがないことを認識することは重要だと思った。

## 要件を実現するための超簡単な設計
設計とかどのレベルまでやるもんだなんだろうと漠然と思いながら、技術選択とシステムのアーキテクチャを考えてみた。イメージとしてはGUIで操作できる検索システムのような作ればいけるかなって感じだった。

#### 考慮すべきポイント
ここでのポイントは、開発要件からイメージしたスケジュールでこなすためにはどうするべきかという点だった。短期間で開発を行うため、学習コストが高い新しい技術を用いるのは断念した。8割くらいは自身のスキルセットからできるだけ技術を採用し、残りの2割を+αで新しく学ぶ技術を採用するような形で自身の勉強になるように考えた。

### フロントエンド
* HTML
* Javascript
* CSS

本当はVueやReactなんかを勉強して採用してみたかったが、今回は開発速度を優先してベーシックな技術選択をした。(と言っても、筆者はフロント部分はあまりやったことがなくベーシックなものでも苦労したw)

### サーバーサイド
* Python(Django：REST flameworkパッケージ)
* Nginx
* uWSGI

サーバーサイドは書きなれてるPythonを採用。ただ、フレームワークは今までFlaskしか使ったことがなかったため、今回はDjangoに挑戦してみた。そのなかでも、爆速でAPI開発ができそうだったREST Flameworkを使ってみた。

Djangoでビューワー部分とバックエンド部分をまかなってしまうという選択肢もあったが、最近の開発ではモジュール同士を密にしすぎないという風潮(DevOps)を聞いたことがあったことからビューワー部分とバックエンド部分を切り離し、DjangoのREST Flameworkを使うことでAPIに特化させることにした。

後は、Django+uWSGI+Nginxはよくあるパターンだったためミドルウェアもこのような選択をした。Djangoが初めてだっため、NginxのようなWebサーバーとDjangoの連携も勉強になった。

### データベース
* PostgreSQL

以上、条件の中で上記の技術選択をしてみた。
振り返ってみると、この技術選択は正解だった。DjangoのREST FrameworkのHTTPメソッドの使い分けによるDB操作やNginx,uWSGI,Djangoの連携はかなり苦労した。

## ごりごり開発
### 開発環境
開発を始める前に開発環境を整えた。Production,Staging,開発の3つを用意した。

AWSを使える環境を用意して、開発はインターネット接続ありでセキュリティグループなどはProductionに似せた環境にした。

### 開発手順
#### サーバーサイド開発
DBの構成を考えてダミーデータを作ったら、DjangoでのAPI開発に取りかかった。

REST Frameworkでの開発は初期の学習コストをそこそこあったが、覚えてからはかなりのスピードで開発・拡張ができた。Djangoのマイグレーション機能や管理画面もあって、GETでのデータ取得操作の実装は短期間で終えることができた。

#### フロントエンド開発
フロント部分であるUIの作成は、テンプレートをベースとして手探りでHTML,CSS,Javascriptを独自に変更した。

ここから約2週間でミドルウェアの設定や閉鎖網環境を持ち込むためのAMI作成,Stagin・Production環境の作成を行った。

## 閉鎖網環境へのデプロイ
Production・Staging環境は上記にも書いた通り特殊な環境のため、開発環境で作ったAMIを環境に持ち込み、そのイメージを元にEC2を立てた。

ここまで約2ヶ月。ここからユーザーへの公開に向けて、検索システム用のデータベースへの本データの投入・テストを行った。

#### 勉強になったポイント
特殊な環境へのデプロイにAMIやコンテナによる持ち込みは相性が良いのがわかった。導入用のファイルを持ち込んで手動でやるのではなく、あらかじめ作りあげた物をAMIとして持ち込むことでスーピーディで再現性の高い展開が可能であることがわかった。

## 初めてのテストフェーズ
学生のころにも自分用のWEBアプリ的なものはつくっていたが、テストなんてものは微塵も行わなかった。そのため、今回行ったテストが公開に向けて必要・十分だったかはわからないが初めてのテストに取り組んだ。

### 挙動確認テスト
Staging環境にデプロイしたシステムを第3者に使ってもらい、網羅的なテスト項目を作成してもらった。

こういった項目作成はどの段階で行うのがベスクトプラクティスなんだろうか。。

#### 勉強になったポイント
ここで勉強になったのが、自分が考えている仕様と第3者が認識する仕様に大きな乖離があることだった。(当たり前かもしれないが自分としては初めての気づきだったw)

自分で使うときは、もちろん仕様を自分で決めているからシステムの挙動に対して「こーいう物だ！」と思っているため違和感を感じなかった。しかし、第3者、つまり本当のユーザーに近い人が触ってみると「ふつーこーいう挙動するよな」のような違和感が多くあったようだ。

### システム負荷テスト
分析基盤のデイリーアクティブユーザー数をもとに時間毎のユーザー数を割り出し、最大同時アクセス数でテストをおこなった。

このアクセス数でAPIからのレスポンスは全て返ってきているか、実際にUIを操作してみて挙動に遅れがないかなどの確認を行った。

## 本番環境へのデプロイからのリリース
テストが完了したあと、Production環境へデプロイ。挙動に問題ないことを確認してリリースした。
ここまでで約2ヶ月半。かなりしんどかった(笑)

## リリース対象を順次拡大・システム改善
今回は「システムがユーザーのニーズに合っているか」というの確認するため、プレリリースを行いフィードバックをもらうという流れだった。

そのため、公開対象は以下のような流れで拡大した。

* 公開第1段階：分析基盤利用者の中で一番身近な分析チーム
* 公開第2段階：分析基盤利用者の中の同じ部署の複数の分析チーム
* 公開第3段階：分析基盤利用者の中の２割ほどにあたる特定の分析チーム

このような段階を踏む間にフィードバックをもらいシステムの機能改善に取り組んだ。

#### 勉強になったポイント
システムができたからといっていきなり「みなさん使ってください！」ではなくて、まずは身近な人たちにつかってもらってフィードバックをすぐもらう。次にもう少し範囲を拡大させて、使ってもらってフィードバックをもらうといった段階を踏むことは開発者に優しいサイクルだと感じた。

自分は最初システムに自信がなかったが、このサイクルを得てユーザーがどう感じるのかが直接わかるしシステム的な不備も多くの人にさらす前にわかってブラッシュアップできる　という点がすごくやりやすかった。

## おわりに
今回取り組んだ開発工程をだらだらと書いてみました。
この記事を見直してみると、1人アジャイル開発的なことをやっていたのかと思いました。(あまり意識せず、無我夢中でやっていましたがw)

要件定義・設計→開発→デプロイ→テスト→リリースというサイクルを公開の段階ごとに回せていたのかなと。しかし、要件定義は甘いだろうし、テストももっと本格的にやるべきであったりと、本来のソフトウェア開発からは似ても似つかないような工程になってしまいました。

ただ、今回のシステム開発を一通りを経験できたことは大きかったと思ってます。今まで漠然と全体像を追っていたソフトウェア開発が、経験した各フェーズをそれぞれを深掘りすることでより効率の良くできて、質の良いシステム作りに繋げられると感じてます。

もし、この記事をここまで読んでくださってアドバイスしてもいいなと思った方はぜひコメントお願いします。