プログラミング初心者の俺がGeoDjangoで業務効率化地図アプリを作りきった話[開発後記編]

# はじめに
本記事はDjangoフレームワークを使ったウェブアプリPublic Mappingをプログラミング初心者の私が開発した、開発記録のうち「開発後記編」です。
開発に至った経緯、開発のモチベーションやアプリの詳細なコンセプトなどは「[経緯編：プログラミング初心者の俺がGeoDjangoで業務効率化地図アプリを作りきった話](https://qiita.com/hiro-ishi/items/24cd71129cad3d64edd5)」をご参照ください。
※アプリは現在停止中（2021年5月1日現在）
[公開リポジトリはこちら](https://github.com/hiro-ishi/publicmapdeploy)

# 目次
1.アプリの構成
2.開発プロセスとプロジェクト管理方法
3.完成したアプリ
4.技術的課題と解決方法
5.まとめ

# アプリの構成
アプリの大まかの構成は以下のようになっています。
![app_structure_withtitle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304391/4ac36c5b-76ef-e7a1-5de3-ee40a7f0ce07.png)
### フレームワークの選択
もともと、位置情報を扱うアプリを作る、地理空間情報(GI:Geographical Information)解析をweb上で行うための基礎を学びたい、と考えていましたので、Geo Djangoがあり、豊富な解析に関するプラグインがあるPythonを採用しているフレームワーク、Djangoを選択しました。デスクトップGIS(Geographical Information System)ソフトのArcGISとQGISでPythonをいじった経験があったのもpythonを選択した理由の一つです。
### 地図表示にLeaflet + OSMを採用
地図表示に関しては無料かつオープンソースであるLeafletとOpenStreetMapを採用しました。商用利用をしても料金が発生しないので、お金のない組織、お金を払いたくない組織でも運用できるようにという意図があります。
また、行政相手に仕事をする上では必要になることの多い国土地理院の地理院地図も表示できるようにしてあります。<br/>
フロントエンドについてはVue.js等のフレームワークを使うことも考えましたが・フロントエンドのフレームワークについて全く知識がなく・開発期間が短い、ことを考慮し、シンプルな構成のアプリとするために、使用しませんでした。

# 開発プロセスとプロジェクト管理方法
プログラミング経験ほぼ無し、開発経験無し、短い開発期間、ということもあり、ゲーム開発者の友人[Yuu氏](https://qiita.com/john95206)にスーパーバイズをお願いすることにしました。
コンセプト決定、設計、開発、デプロイ、進捗管理とそれらにまつわる課題解決はあくまで自分で行い、
開発プロセスのディレクション、進捗管理ツールの提供、進捗管理のサポート（発破をかける）等、技術面よりはプロジェクト管理面をYuu氏に支援してもらった形になりました。
hiro-ishiの個人開発に、一般的なアプリ開発プロセスというフレームワークを与えてくれたのがYuu氏です。

## 開発期間と開発開始時のスキル的な前提
- 開発期間：2019年11月17日〜2020年2月29日
海外大学院に留学中ということもあり、まとまった時間を確保できる２学期終了後11月16日から、新学期が始まる直前の2月29日を開発期間としました。課題、実習、身内の不幸等もあり実働では２ヶ月半くらいの期間だったかと思います。

- 開始時のスキル
HTML, CSS, JavaScript: 2019年5-6月ドットインストール・プロゲートで一通り履修
Python:大学、院の授業でScientific Visualisationのために使用した経験あり
Django他webアプリフレームワーク:未経験

## 開発プロセス
以下のようなアプリ開発の枠組みを踏襲しました。α版・β版の２段階で第三者によるデバッグ・コードレビューを実施することで、致命的な欠陥の検出、開発モチベーションの維持を図りました。<br/>
- 企画書の作成、締め切りの設定（〜11/28）
- 要件提議書、仕様書の作成（〜11/30）
- タスクの細分化、優先順位付け、見積もり時間の算出、スケジュール管理表への落とし込み（〜12/7）
- 開発
- α版完成（バックエンド実装完了）（2/8）デバッグ・修正対応
- β版完成（フロントエンド実装完了）（2/22）デバッグ・コードレビュー・修正対応
- マスターアップ・プロジェクトのクローズ（2/29）

### 企画書・仕様書
開発開始当初の企画書は以下の通り。
[SlideShare.net "Public Mapping企画書"](https://www.slideshare.net/hiroakii1/public-mapping)

・日常的に解決したいと思っている問題
・このアプリで解決できる課題
・どうやって使ってもらうか
・どうやってそれを実現するのか<br/>

を整理し、ページを何種類作るのか、どういうデザインにするのか、までできる限り具体化しました。
企画書作成時点で「なんとなく必要だと思って」入れていた設定画面など無駄な機能・テンプレートは、工数削減のために可能な限り排除し、シンプルに課題解決に効く機能だけを残すように努めました。
この企画書をもとに要件定義書、仕様書を（ざっくり）作り、タスク・スケジュールに落とし込んで行きました。

>「開発の軸になるから毎日企画書を見るくらいの気持ちでいろ」

というYuu氏の発言を、あれもやりたいこれもやりたいと軸がぶれるたびに思い出すことになります。

### タスクの細分化、優先順位付け、見積もり時間の算出、スケジュール管理表への落とし込み

スケジュール管理表は、タスクごとの実施状況・見積もり時間・消費した時間・残り時間がわかるようにしたものをGoogle Sheetsで作成し、毎日記録・管理し、スーパーバイザーの監視下に置きました。（ちゃんと更新しないと怒られる仕組みの構築）

![Screen Shot 2020-03-05 at 6.19.56 pm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304391/95000025-a3f3-edcd-0f79-1d191b8bab34.png)
タスクは以下の４×３＝１２分類で管理し、のタグ付けをして優先度の高いものから手をつけて行った。

|分類|項目|
|----|---|
|時間軸：4分類|調査・フロントエンド実装・バックエンド実装・デバッグ対応|
|優先順位:3分類|Must（α版までに絶対実装）, Should（β版までになるべく実装）, Will（余裕があれば実装or先送り）|

「この機能を実装するのに何が必要かわからない」状況から出発したため、新たな作業が必要だと分かった時点でスケジュール管理表を更新していきました。締め切りとの相談でMust->ShouldもしくはShould->Willへ格下げした機能もありました。

### 開発：タスク管理・進捗管理
個人開発ではあるがスーパーバイザーと私とでの共同プロジェクト開発、という形をとったので、作業優先度・期限については厳格に守るよう心がけました。
Mustが終わっていないのに、煮詰まって気分転換に特に優先度の低いShouldに手をつけ1日を消費し、ウキウキしながら「こんなの出来たよ〜〜」と報告したら「プロジェクト開発ってのはそういうもんじゃない、規律を守れ」とすごく怒られました。

### Git によるバージョン管理
開発開始時からGitでバージョン管理をしました。
α版デバッグに際してGithub上にリポジトリを作成し、レビュアー、デバッガと共有、issueにバグ報告をしてもらい、以降のタスク管理はスケジュール管理表とGithubで行いました。

### デプロイ・デバッグ・コードレビュー
デプロイ先は簡易さ、今後スケールする予定がないことを踏まえてPythonanywhereを採用ました。
プログラマーの友人3人にデバッグを依頼し、そのうちDjango開発経験のある一人にコードレビューをしてもらいました。
コードレビューもしてくれるという話を聞いてKENTAオンラインサロンに参加したりもしましたが、Slackワークスペースで情報を共有しながら密なデバッグ・コードレビュー・フィードバック対応ができたので、友人の伝手を頼ってよかったと思います。

# 完成したアプリ
デモサイトは現在停止中（2021年5月1日現在）(http://hiroshi55.pythonanywhere.com/map_mainview_nonauth/)
![help_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304391/6ced09af-3726-d6c3-c0f3-8b6708eab910.png)

現地調査をチームでする人たち、営業をチームでする人たちが現地状況を気軽に記録できるようなシステムを目指しました。技術的に実装できなかった機能を運用でカバーできるような余地を持たせ、現場フレンドリーなアプリを目指しました。

- ログイン認証でセキュリティ対応（admin管理者によるユーザー名・パスワードの付与）
- 記録情報はシンプルにタイトル、番号、メモの３項目。
- 1〜999番で任意に番号を振れるので、グループ毎に使用する番号帯を決めて情報をクラスタリング
- 地図上のマーカーに番号が表示されているため、スクリンーンショットを共有したり・印刷して誰かに渡したりした際に、番号で指示を出せる。
- ログインユーザーなら誰でもデータを修正できるので、フレキシブルに情報の更新が行える（編集ルールをチームで共有して運用）
 
![app_overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304391/21cce237-9492-b766-7064-0cea760e8e9d.png)

# 技術的課題と解決方法
小規模人数での利用を想定したアプリ、パイロット版的な性質を考慮して力技で機能を実装している部分もあります。

## バックエンド
- CRUDの実装は、勉強のためにクラスベース汎用ビューは使わなかった。
- 位置情報（緯度経度）のデータベースへの登録は位置情報を扱えるpostgresqlを使用し、Formでの登録はGeoDjangoのPointFieldを使用。
- セキュリティ対策はDjango adminのAuthorization機能を利用してログイン機能を実装。Views.pyの必要なviewに`@login_required`を付与することで非ログイン者の閲覧制限を実装。
- ユーザー管理についてはDjango admin機能を使ってadminユーザーが手作業で管理。
- 現状で、一つのデータベースにログインユーザー全員がアクセスしている状態になっているため、不特定多数のユーザーがアクセスするには適さないデータ構造となってしまっている。Django customizeuser によるグループの付与など、フィルター機能の実装が望まれるが解決できなかったため、現時点では運用でカバーすることとした。

## フロントエンド
- メインビューの地図表示は、シリアライザで生成したJSONファイルのURLをjQueryの`$getJSON`で受け取り、データを抽出し、地図上にマーカーを置いた。
- マップ上で指定した場所へのジャンプは、jQueryの`$getJSON`内で緯度経度を取得し、Leafletの`panTo`を用いてジャンプさせた。
- パソコン・スマホ両方へのレスポンシブ対応はBootstrapを使い、データ一覧テーブルと地図をそれぞれ別のコラムに格納することで実装。
- 新規追加・編集画面のマップウィジットはGeo DjangoのOSM map widjetを利用。
- Djangoの`{% extends 'base.html' %}`によるbase.htmlの継承、`{% load static %}`によるJSファイルの引用が、指定した地点の緯度経度情報を格納した変数のテンプレート間でやりとりを阻害し、最後まで解決できなかった。

## その他
- 煮詰まる→ネット検索で解決方法を探る→あきらめて公式ドキュメントに立ち返る→それでも解決できずに質問を投げる　という一連の課題解決プロセスをいかに早く回し、生産効率を挙げていくかがこれからの課題。
- 質問できる場所を複数用意するための日頃からのコミュニケーション・努力・人間関係構築が最後の追い込み時期に効いてくるなと感じた。
- 年度末の繁忙期ということもあり、デバッガの確保に難儀した。人への依頼は早め早めに。
- Gitによるバージョン管理はチームとのコミュニケーションのためにも学習必須事項

# まとめ
期限内に必要な機能を実装したアプリを完成・公開させた、という点で一つ目のポートフォリオとしては十分だと思いたいのですが、正直なところ、約３ヶ月もの時間と多くの労力を投下してもこれか！！という気持ちもあります。
経験不足・知識不足・技術不足というディスアドバンテージを補うには、シンプルな機能でもしっかりとユーザーのニーズにフィットする、しっかりと練られたコンセプトを構築できる能力も磨く必要があると痛感しました。
自分の開発工程を、デバッグも含めたアプリ開発の一般的なプロセスをに当てはめたことは、成果物であるアプリの完成度を上げるだけでなく、開発過程に関して多くの気付きと学びを得るということにも大きな効果があったと思います。