一ヶ月ぶりです。こんにちは。whatacotton です。ここ一ヶ月くらい記事を書きたいと思いつつ、課題などに押しつぶされていて更新できていませんでした。今回は今のカリスワークスプロジェクトの進捗とこれからの展望について書きます。
カリスワークスについての報告は 3 ヶ月ぶりになります。
#
はじめに
カリスワークスとは私が開発しているプラットフォーム型 EC サイトです。このプロジェクトは現在も進行していて、リファクタリングのフェーズに入っています。
リファクタリングに際して、nameless_itf さんに協力していただいております。
新しくリポジトリをたて、ある程度処理をもとのコードから持ってきてはいますが、ほとんどは再定義したものを使っています。
#
新プロジェクトの目的
リファクタリングにおけるテーマは以下のとおりです。
保守性のあるコードにするために
- インターフェースを用いた安全なコーディング
- DI(Dependency Injection)の導入
堅牢なシステムにするために
将来 OSS になることを期待して
#
保守性のあるコードにするために
#
インターフェースを用いた安全なコーディング
関数群を実装する上でインターフェースを定義して、それを埋めるような設計をしています。
これを行うことによって、このプロジェクトが大きくなっていった際にもメンバーが簡単に参加できるようになっています。3 年後の自分に向けてでもあります。
request.ts
1
2
3
4
5
6
7
|
type query = { [key: string]: string };
interface IRequests {
Get(path: string, params?: query): Promise<Response>;
Post(path: string, body: any): Promise<Response>;
Patch(path: string, body: any): Promise<Response>;
Delete(path: string, params?: query): Promise<Response>;
}
|
fetch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
class FetchRequests implements IRequests {
private url: URL = new URL(
process.env.NEXT_PUBLIC_SERVER_ADDRESS
? process.env.NEXT_PUBLIC_SERVER_ADDRESS
: "localhost"
);
async Get(path: string, params?: query): Promise<Response> {
const url: URL = this.url;
url.pathname = path;
if (params) {
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, value);
});
}
const response: Response = await fetch(url.toString(), {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
});
return response;
}
async Post(path: string, body: any): Promise<Response> {
const url: URL = this.url;
url.pathname = path;
const response: Response = await fetch(url.toString(), {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
return response;
}
//patch,deleteの実装が続きます
}
|
#
DI(Dependency Injection)の導入
DI と呼ばれる依存性の注入を実装することでテストのためのモックサーバーを作成したり、接続する DB の向き先を変えることを実現したいと考えています。
実際にこのコードでは fetch リクエストの関数の DI を行っています。
item.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import { ItemPreview, ItemDetail, IItemRequests } from "./models/item";
import { IRequests } from "./models/request";
class ItemRequests implements IItemRequests {
Requests: IRequests;
constructor(Requests: IRequests) {
this.Requests = Requests;
}
async Get(): Promise<ItemPreview[] | null> {
const response: Response = await this.Requests.Get("/api/item");
const data: ItemPreview[] = await response.json();
return data;
}
//...
}
export { ItemRequests };
|
この実装では、コンストラクタに入れる関数群を差し替えることで簡単に内部実装を変えることができます。インターフェースの章で紹介したFetchRequests
を入れることで fetch を使用することもできますし、テスト用に同じような内部実装したものを使用してインスタンスを生成することもできます。
次の例は実際に呼び出すときの例です。
lib.ts
1
2
3
4
5
6
|
import { ItemRequests } from "../item";
import { IItemRequests } from "../models/item";
export const ItemRequestImpl: IItemRequests = new ItemRequests(
new FetchRequests()
);
|
item.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
"use client";
import { ItemRequestImpl } from "@/app/api/lib/firebase";
import { ItemDetail } from "@/app/api/models/item";
import { useParams } from "next/navigation";
import { useEffect, useState } from "react";
const ItemPage = () => {
const params = useParams<{ slug: string }>();
const [Item, setItem] = useState<ItemDetail | undefined>(undefined);
useEffect(() => {
(async () => {
const item = await ItemRequestImpl.GetDetail(params.slug);
setItem(item);
})();
}, []);
console.log(params);
return (
<>
<h2>商品詳細ページ</h2>itemId:{params.slug}
</>
);
};
export default ItemPage;
|
lib.ts
でFetchRequests
としているところを別のクラスに置き換えることでitem.tsx
に変更を加えることなくテストを実装することもできます。
#
堅牢なシステムにするために
#
DB 設計の見直し
DB の設計の見直しも行っています。
旧設計は一枚目で、二枚目が新しい設計です。
テーブルを 2 つに分け、片方をログメインで設計しています。テーブルを分けたことによって上部の DB はオンプレミスのサーバーにおいて、下部をクラウドサービスを利用して保存するなど、拡張性を重視しています。
#
テストの実装
まだ具体的な実装はまだ行っていませんが、インターフェースや DI を利用して作成しやすい環境はできているのではないかと思います。
これから実装を行っていきます。
#
将来 OSS になることを期待して
このプロジェクトは将来的に OSS として開発したい意志があります。
#
OpenAPI でのドキュメント作成
まだ完成形ではないのでメンバーはそこまで多くないですが、デプロイ後にいろいろな人に自分のコードを読んでもらいたいと思っています。
そのために OpenAPI で API 仕様を定義しています。
#
現在の進捗
2024 年 2 月 17 日の現在の進捗としては
- DB の再設計
- フロントエンド・バックエンドの API のやり取りのインターフェースの実装
- firebase Authentication との連携
- stripe の決済を埋め込みコンポーネントで行えるようにする実装
- stripe との連携
この 5 つが終わった感じです。
これからのタスクとしては
- DB とのやり取りの実装
- フロントエンドの作成
- 出品者用の画面の作成
など
があります。やること盛りだくさんですが、これからも頑張っていきます!!!