JavaScriptとGo言語でToDoリストアプリを作ろう!~バックエンド開発~

こんにちは。KOUKIです。

前回は、JavaScripでTodoリストアプリケーション(UI)を作成しました。

今回は、サーバーサイド側の処理を実装します。

前回

サーバーサイド処理

サーバーサイドの処理 1. Todoの保存
2. Todoの取得
3. Todoのステータス更新
4. Todoの削除

ワークスペース

ワークスペースを準備しましょう。

FiberでWebサーバー構築

Fiberを使って、Webサーバーを立てましょう。

インストール

Webサーバーの立ち上げ

公式サイトからWebサーバーのサンプルをコピーして貼り付けます。

次のコマンドで、Webサーバーを立ち上げてください。

ブラウザから「localhost」にアクセスします。

ホットリロードの導入

Mac(Linux)ユーザー向けの内容になりますが、ホットリロードを導入しましょう。

Go言語はコンパイル型の言語なので、コードの変更を反映させるために、毎回「go run main.go」を実行する必要があります。それだと開発が大変なので、ホットリロードで自動的にビルドするようにします。

Go言語では「reflex」というツールで簡単に導入できますが、Windowsだと動かないかもしれません

実行コマンドが少し複雑なので、Makefileに書いておきましょう。

これで、ソースコードを保存するとその変更を検知して、ホットリロードが走るようになります。

クリーンアーキテクチャで実装

仕事でAPIを作成するときに、クリーンアーキテクチャを意識して実装しています。

以下の図が有名ですよね。

クリーンアーキテクチャは結構複雑なので、詳細な説明については他のサイトに任せます。

ここで意識したことは、「円の外側から内側にデータが流れるように意識して実装する」ことです。例えば、Use CasesからEntitiesへのアクセスは許可しますが、EntitiesからUse Casesへのアクセスは禁止します。

これにより、密結合が低いアプリケーションを実装することができるようです。

ドメイン

ドメインは、Entities(黄色レイヤ)にあたるところです。ここには、ビジネスロジックを表現するオブジェクトやインターフェースを定義します。

Todoは、その名の通りタスクを表現したオブジェクトです。
TodoUsecaseは、ユースケースから呼びだすインターフェースです。
TodoRepositoryは、データベース(sync.Map)にアクセスするためのインターフェースです。

インターフェースをここで実装している理由は、依存性逆転の原則にあるのですが、後ほど説明します。

レポジトリ

レポジトリは、インターフェースアダプター(緑色レイヤ)にあたるところです。ここには、DBへアクセスするためのロジックを記述します。

MySQLやPostgreSQLを使っても良かったのですが、今回は、sync.Mapを使うことにします。

sync.Mapは正確にはDBじゃないのですが、その代用ができます。具体的な使い方は、以下の記事を参考にしてください。

DB操作メソッド

todo_map.goには、DB操作用のメソッドを実装します。

NewSyncMapTodoRepository関数の戻り値にTodoRepositoryインターフェースを返すところがポイントです。

これは、Domainに実装したインターフェースです。

DB操作メソッドのほとんどでnilを返しているため、何のためにerrorを戻り値にしているのか不思議だと思います。これは、以前紹介した「DB切り替え」の仕組みを導入しているためです。

インターフェースを使ってDBヘのアクセスメソッドを抽象化すると、将来、他のDBに切り替えたくなった時に容易に切り替えできる仕組みを作れます。TodoRepositoryインターフェースを満たせば、利用する側ではDBの種類を意識する必要がなくなるからです。

sync.Mapのメソッドはエラーを返さないものがほとんどですが、他のDB(MySQLやPostgreSQL)ではデータ操作失敗時にエラーを返すので、errorを返すインターフェースを定義しました。

テスト

sync.Mapは戻り値をinterface型で返すなどちょっとした癖があるので、簡単なテストコードを実装します。

テストを実行します。

OKですね。

コメントにも記載しましたが、「DB切り替え処理」を意識したコードのメリットがここに出てますね。DBを切り替えても呼び出し元のRepositoryを変更すればテストコードの修正も最小限で済みそうです。エラーテストは追加しないといけないですが。

デリバリー

デリバリーは、インターフェースアダプター(緑色レイヤ)にあたるところです。ここでは、ハンドラーを定義し、リクエストを捌きます。

また、各メソッドごとにファイルを分けて実装します。※ファイルを分けておいた方がメンテがしやすい、コンフリクトがしにくいなどのメリットがある

似たような処理なのでリファクタリングできるかもしれませんが、これでOKです。

ユースケース

ユースケースは、UseCases(赤色レイヤ)にあたるところです。ここには、ビジネスロジックを実装します。

個々の役割に紐づく、DB操作メソッドの呼び出しを行いました。

本来であれば、上位レイヤーであるDeliivery(DB操作メソッド)にUseCaseからアクセスしたくありません。それを回避するため、domainにインターフェースを実装し、そのインターフェース経由でdeliveryのメソッドにアクセスしています。

これを依存性逆転の原則と呼ぶそうです。

Interfaceの利便性はこんなところにも発揮されるようですね。

フレームワーク&ドライバー

最後に、フレームワーク&ドライバー(青色レイヤ)を実装します。ここには、Web FrameworkやDB Driverの定義などを実装します。

本アプリでは、Fiberのエンジン設定、レポジトリやユースケースのインスタンス化などがそれに該当します。このレイヤーは最外枠のレイヤーであるため、ここからデータの流れが始まります。

動作確認

Talend API Testerで動作確認をしてみましょう。

今回、4つのエントリポイントを用意しました。

  1. GET: http://localhost/todos
  2. POST: http://localhost/todo/delete
  3. POST: http://localhost/todo/statusupdate
  4. POST:http://localhost/todo/store

Store

storeは、Todoの追加ができます。 以下のリクエストデータを送信すればOKです。

Todos

次に、todosを試します。これで、格納されたデータを全て取得します。

StatusUpdate

次に、statusupdateを試します。これでcompletedステータスをfalse->trueに変更します。

todosでデータを取得してみましょう。

completedが、trueになりました。

Delete

最後に、deleteを確認します。

この状態で、todosを実行するとnullが返却されます。

OKですね。

次回

次回は、 UIと今回実装したバックエンドを繋げてみましょう。

関連記事

こちらの記事も人気です!

JavaScriptまとめ

おすすめ書籍


コメントを残す