hacomono TECH BLOG

フィットネスクラブ・スクールなど施設・店舗のための会員管理・予約・決済システム「hacomono」 開発チームの技術ブログ

なるべく楽して JS のライブラリを作ってみる (part 1: 設計)

フロントエンドテックリードのみゅーとん(@_mew_ton)です。どうも。

今まで、ライブラリを作りたい要件だけはずっと溜まっていって、どうも時間がなく手がつけられていませんでした。

が、個々最近AIが話題ですね。ChatGPT に文書を書かせたりするのがかなり流行ってますし、非常に面白いです。

また、同じタイミングで弊社では GitHub Copilot を使えるようになりました。

これはいい機会なので、なるべく楽して npm に公開したいライブラリを作ってみました。

ライブラリは要件が確定しており、この要件をもとに、ライブラリの名前・メソッド名・ライブラリのREADMEを作ってもらうところまでを行いました。

この記事は、その直後にChatGPT に以下のお願いをして本文を書いてもらったものです。

「ChatGPT を使って、JSのライブラリをひたすら楽して作ってみる」というブログを作ろうとしています。 今日は JS のライブラリの要件から、ライブラリ名と、不足しているメソッド名と、READMEの作成までを実際にしてもらいましたが、ここまでの内容をブログ記事として私の代わりにまとめていただけませんか?

証拠:

多少加筆を含みますが、以下は全てChatGPT による出力になります。


ChatGPT を使って、JSのライブラリをひたすら楽して作ってみる

JavaScript のライブラリ開発は面白いですが、名前や機能を考えたり、ドキュメントを作成したりと、手間がかかることもあります。そこで、OpenAI の ChatGPT を使って、これらの作業を効率化してみましょう!この記事では、私がChatGPT に何をお願いして、ChatGPT がどういう出力をし、結果ライブラリがどういう設計に決定したかをご紹介します。

ライブラリの要件定義

まず、以下の要件を満たす JavaScript ライブラリを作成しようとしています。

  • lodash のタイプガード関数に互換性がある
  • TypeScript ファーストの実装で、型推論が正常に動作する
  • ESModule 向けの実装 (TreeShaking をしてバンドルサイズを減らせることを考慮する)
  • 7種のタイプガード関数を提供する
    1. isString .. lodash 互換のタイプガード関数
    2. assertString .. TypeScript の Type Assertion を提供する. タイプチェックで駄目なら例外を投げる
    3. (名称未定義) .. 第1引数の値についてタイプチェックを行い、OKならその値をそのまま変えす。駄目なら例外を投げる
    4. (名称未定義) .. 第1引数の値についてタイプチェックを行い、OKならその値を返す。駄目なら第2引数の値を返す
    5. b, c, d について、判定式を反転したもの
  • 依存するライブラリがないこと
  • TypeScript のタイプガードユーティリティであること

ライブラリ名の決定

私は ChatGPT に、先程の要件に加えて以下の命名条件を伝え、ライブラリ名を考えてもらいました。

  • util, lib などの汎用的な単語や略語を使用しない
  • 長くしすぎない。2単語を上限とする
  • わかりやすいとなお良い
  • npm に公開されているライブラリとは重複しないこと
  • kebab-case とする
  • npm にライブラリが公開されているプロダクトの単語を含まないこと(もしくは紛らわしい名前でないこと)

ChatGPT は以下の案を出してくれました。

  1. type-guardian:型の保護者という意味で、型の安全性を担保する役割を表現していますが、他の候補と比べてやや一般的な名前であると感じました。
  2. type-keeper:型を保持・保護するという意味で、型の安全性を担保する役割を示していますが、他の候補と比べてやや抽象的な名前であると判断しました。
  3. type-safeguard:型の安全を守る、保証するという意味で、型の安全性を強調しています。しかし、保護・監視の意味によりすぎているため、他の案を検討しました。
  4. type-assure:保証や確信を意味するため、型の安全性を担保する役割を表現しています。

最終的に、type-assurer という名前に決定しました。これは、型の安全性を保証・確実にするという意味で、ライブラリの目的に適していると判断しました。

不足しているメソッド名の決定

ライブラリの設計にあたり、名称未定義のメソッドが2つありました。まず、上記のcで示している関数について、xxxxString の形式でいくつかの案をChatGPTに提案してもらいました。以下が提案された案です。

  1. ensureString:型が正しければそのまま値を返し、そうでなければエラーを投げる関数
  2. assertString:型が正しければそのまま値を返し、そうでなければエラーを投げる関数
  3. validateString:型が正しければそのまま値を返し、そうでなければエラーを投げる関数

この中から、ensureString が適切であると判断しました。

次に、dで示す関数について提案を求めました。以下が提案された案です。

  1. defaultString:型が正しければそのまま値を返し、そうでなければデフォルト値を返す関数
  2. fallbackString:型が正しければそのまま値を返し、そうでなければデフォルト値を返す関数
  3. withStringFallback:型が正しければそのまま値を返し、そうでなければデフォルト値を返す関数

この中から、fallbackString が適切であると判断しました。

さて、これらの選択により、ライブラリの設計が完成しました。

完成したライブラリの設計から README を作ってもらう

ライブラリの設計が完成したので、続いてChatGPTにREADMEを作成してもらいました。以下が、ChatGPTによって生成されたREADMEのドラフトです。

# type-assurer

`type-assurer` is a TypeScript-first type checking library, providing compatibility with lodash's type guard functions while ensuring type safety. Designed with ESModules in mind, it allows for tree-shaking to minimize bundle sizes.

## Features

- Compatible with lodash type guard functions
- TypeScript-first implementation with accurate type inference
- ESModule ready for tree-shaking and bundle size optimization
- No external dependencies
- A collection of 7 type guard functions:
  a. isString - Similar to lodash's type guard functions
  b. assertString - Provides TypeScript's type assertion feature
  c. ensureString - Evaluates the argument's type and returns the value if the type guard passes, otherwise throws an exception
  d. fallbackString - Evaluates the first argument's type and returns the value if the type guard passes, otherwise returns the second argument's value
  - The reversed versions of the above b, c, and d
  - Generator provided for custom type guards for non-primitive types

## Installation

 ```bash
 npm install type-assurer
 ```

## Usage

 ```typescript
 import {
  isString,
  assertString,
  ensureString,
  fallbackString,
  assertNotString,
  ensureNotString,
  fallbackNotString
} from "type-assurer";

// Example usage
const value = someFunctionThatMightReturnNonString();

// Using isString
if (isString(value)) {
  // value is a string
}

// Using assertString
assertString(value); // Throws an exception if value is not a string

// Using ensureString
try {
  const stringValue = ensureString(value); // Throws an exception if value is not a string
  doSomethingWith(stringValue);
} catch (error) {
  console.error("Value is not a string:", error);
}

// Using fallbackString
const valueWithDefault = fallbackString(value, "default value"); // Returns "default value" if value is not a string
doSomethingWith(valueWithDefault);

// Using assertNotString
assertNotString(value); // Throws an exception if value is a string

// Using ensureNotString
try {
  const nonStringValue = ensureNotString(value); // Throws an exception if value is a string
  doSomethingWith(nonStringValue);
} catch (error) {
  console.error("Value is a string:", error);
}

// Using fallbackNotString
const valueWithAlternative = fallbackNotString(value, "alternative value"); // Returns "alternative value" if value is a string
doSomethingWith(valueWithAlternative);
 ```

## Contributing

Contributions are welcome! Please submit a pull request or open an issue to discuss any proposed changes or feature requests.

## License

MIT

このREADMEには、ライブラリの概要、主な機能、インストール方法、使い方、ライセンスが含まれており、開発者がライブラリを簡単に利用できるようになっています。

まとめ

この記事では、私がChatGPTを使ってJavaScriptのライブラリを効率的に設計する方法を紹介しました。ChatGPTは、ライブラリ名や関数名の提案など、開発の手間を軽減するのに役立ちました。さらに、READMEの作成も手助けしてくれました。

ChatGPTを使って開発を効率化し、より多くの時間を他の重要なタスクに割くことができます。もちろん、ChatGPTが提案した名前や機能は参考程度に考え、最終的には自分の判断で選択することが大切です。今後もChatGPTを活用して、開発プロセスをより効率的に進めていきましょう。


本当のまとめ

さすがに問題解決まで爆速とまではいきませんでしたが、かなりスムーズに設計まで完了しました。READMEもほとんど完璧かなと思います。

ブログ記事も実は9割原文そのままです。説明不足や、文脈がおかしいところ、細かい命名が変わっている点などはありましたが、ほとんど文章や体裁を治す必要がありませんでした。

うまく使って、仕事をどんどん楽にしていきたいですね。