Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

module-pattern

コードの整理とカプセル化のためのモジュールパターンを解説します。JavaScriptをパブリックとプライベートの境界を明確に持つ、再利用可能でメンテナブルな構造に整理したい場面で活用してください。

description の原文を見る

Teaches the module pattern for code organization and encapsulation. Use when structuring JavaScript into reusable, maintainable pieces with clear public and private boundaries.

SKILL.md 本文

Module パターン

目次

アプリケーションとコードベースが成長するにつれて、コードの保守性と分離を保つことがますます重要になります。module パターンを使用することで、コードをより小さく再利用可能な部品に分割できます。

コードを小さく再利用可能な部品に分割できるだけでなく、module を使用することで、ファイル内の特定の値を プライベート に保つことができます。module内の宣言はデフォルトでそのmoduleにスコープ(カプセル化)されます。特定の値を明示的にエクスポートしない場合、その値はそのmoduleの外では利用できません。このため、値がグローバルスコープで利用できないため、コードベースの他の部分で宣言された値との名前衝突のリスクが軽減されます。

いつ使うか

  • コードを保守可能でカプセル化されたユニットに整理する必要があるときに使用してください
  • module をプライベートに保ち、グローバルスコープの汚染を避けたい場合に役立ちます
  • tree-shaking を有効にしてバンドルサイズを削減するのに使用します

いつ使わないか

  • ES2015のネイティブ modules で静的な import/export が利用可能な場合 — より良いツーリングと tree-shaking のために静的インポートを使用してください
  • IIFEベースの module パターンが、既にバンドラを使用しているコードベースでカプセル化の目的で使用されている場合
  • module のオーバーヘッドが不要な複雑さを追加する些細なスクリプトの場合

使用方法

  • module の定義には ES2015 の import/export 構文を使用してください
  • 複数の値には名前付きエクスポート、module の主な値にはデフォルトエクスポートを使用してください
  • エクスポートされていない値をプライベートに保ち、名前衝突のリスクを減らしてください
  • 初期バンドルサイズを削減するために、オンデマンド module ローディングに動的な import() を使用してください

詳細

ES2015 Modules

ES2015では、ネイティブなJavaScript modules が導入されました。module は JavaScript コードを含むファイルで、通常のスクリプトと比べていくつかの動作の違いがあります。

math.js と呼ばれる module の例を見てみましょう。これは数学的な関数を含んでいます。

export function add(x, y) {
  return x + y;
}

export function multiply(x) {
  return x * 2;
}

export function subtract(x, y) {
  return x - y;
}

export function square(x) {
  return x * x;
}

math.js ファイルに簡単な数学的ロジックが含まれています。ユーザーが渡した値の加算、乗算、減算、二乗を計算できる関数があります。

他のファイルから math.js の関数を利用可能にするためには、まずそれらを エクスポート する必要があります。module からコードをエクスポートするために、export キーワードを使用できます。関数をエクスポートする方法の1つは、名前付きエクスポート を使用することです。公開したい部分の前に export キーワードを追加するだけです。

別のファイルで import キーワードを使用して値をインポートできます。JavaScriptにどのmoduleからこれらの関数をインポートするかを知らせるために、from 値とmoduleへの相対パスを追加する必要があります。

import { add, multiply, subtract, square } from "./math.js";

module を使用することの素晴らしい利点は、export キーワードを使用して明示的にエクスポートされた値にのみアクセスできることです。export キーワードを使用して明示的にエクスポートされなかった値は、その module 内でのみ利用可能です。

math.js ファイル内でのみ参照可能にする privateValue という値を作成しましょう。

const privateValue = "This is a value private to the module!";

export function add(x, y) {
  return x + y;
}

export function multiply(x) {
  return x * 2;
}

export function subtract(x, y) {
  return x - y;
}

export function square(x) {
  return x * x;
}

privateValue の前に export キーワードを追加していないことに注意してください。privateValue 変数をエクスポートしなかったため、math.js module の外でこの値にアクセスすることはできません!

値を module プライベートに保つことで、グローバルスコープを誤って汚染するリスクが軽減されます。同じ名前の module を使用している開発者が作成した値を誤って上書きしてしまう心配はありません。プライベート値と同じ名前を使用している可能性があります。これにより、名前衝突を防ぎます。

インポートの名前が局所値と衝突することがあります。この場合、as キーワードを使用してインポートされた値の名前を 変更 できます。

import {
  add as addValues,
  multiply as multiplyValues,
  subtract,
  square,
} from "./math.js";

function add(...args) {
  return args.reduce((acc, cur) => cur + acc);
}

function multiply(...args) {
  return args.reduce((acc, cur) => cur * acc);
}

/* From math.js module */
addValues(7, 8);
multiplyValues(8, 9);
subtract(10, 3);
square(3);

/* From index.js file */
add(8, 9, 2, 10);
multiply(8, 9, 2, 10);

名前付きエクスポートに加えて、デフォルトエクスポート を使用することもできます。1つの module につき、デフォルトエクスポートは 1つだけ です。

export default function add(x, y) {
  return x + y;
}

export function multiply(x) {
  return x * 2;
}

export function subtract(x, y) {
  return x - y;
}

export function square(x) {
  return x * x;
}

名前付きエクスポートとデフォルトエクスポートの違いは、moduleから値がエクスポートされる方法で、効果的に値をインポートする必要がある方法が変わります。

以前は、名前付きエクスポート用の括弧を使用する必要がありました。import { module } from 'module' です。 デフォルトエクスポートの場合、括弧 なしで 値をインポートできます。import module from 'module' です。

import add, { multiply, subtract, square } from "./math.js";

add(7, 8);
multiply(8, 9);
subtract(10, 3);
square(3);

JavaScriptはこの値が常にデフォルトでエクスポートされた値であることを知っているため、インポートされたデフォルト値に、エクスポートした名前とは異なる名前を付けることができます。

アスタリスク * を使用して moduleのすべてのエクスポートをインポートすることもできます。つまり、すべての名前付きエクスポート デフォルトエクスポートをインポートし、moduleをインポートしたい名前を指定します。

import * as math from "./math.js";

math.default(7, 8);
math.multiply(8, 9);
math.subtract(10, 3);
math.square(3);

この場合、moduleの すべての エクスポートをインポートしています。これを行う場合は注意してください。不要な値をインポートしてしまう可能性があります。

* を使用するとエクスポートされたすべての値のみをインポートします。moduleプライベートな値は、明示的にエクスポートしない限り、moduleをインポートするファイルでは利用できません。

React

Reactでアプリケーションを構築する場合、多くのコンポーネントを扱う必要があります。すべてのコンポーネントを1つのファイルに書く代わりに、コンポーネントを独自のファイルに分離できます。実質的に、各コンポーネント用の module を作成します。

コンポーネントを別のファイルに分割できます:

  • TodoList.jsList コンポーネント用
  • Button.js — カスタマイズされた Button コンポーネント用
  • Input.js — カスタマイズされた Input コンポーネント用

アプリケーション全体で、UIライブラリからインポートされたデフォルトの ButtonInput コンポーネントを使用したくありません。代わりに、カスタムスタイルを追加して、各ファイルの styles オブジェクトで定義されたカスタム版のコンポーネントを使用したいです。UIライブラリからデフォルトの ButtonInput コンポーネントをインポートして、カスタムスタイルを追加し、毎回それを繰り返す代わりに、デフォルトの ButtonInput コンポーネントを1回インポートしてスタイルを追加し、カスタムコンポーネントをエクスポートできます。

Button.jsInput.js の両方に style という名前のオブジェクトを持つことができる方法に注意してください。この値は module スコープ なので、名前衝突のリスクなく変数名を再利用できます。

動的インポート

ファイルの最上部にすべての modules をインポートする場合、ファイルの残りの部分が読み込まれる前にすべての modules が読み込まれます。場合によっては、特定の条件に基づいて module をインポートする必要があるだけです。動的インポート を使用して、moduleをオンデマンドでインポートできます。

import("module").then((module) => {
  module.default();
  module.namedExport();
});

// または async/await で
(async () => {
  const module = await import("module");
  module.default();
  module.namedExport();
})();

動的に modules をインポートすることで、ページロード時間を削減できます。ユーザーが 本当に必要とする コードのみを、ユーザーが それが必要なとき に読み込み、解析、コンパイルするだけです。

moduleをオンデマンドでインポートできることに加えて、import() 関数は式を受け取ることができます。テンプレートリテラルを渡して、特定の値に基づいて動的に modules を読み込むことができます。

const res = await import(`../assets/dog${num}.png`);

このように、ハードコードされた module パスに依存していません。ユーザー入力、外部ソースから受け取ったデータ、関数の結果など、様々な方法に基づいて modules をインポートする柔軟性が追加されます。

module パターンを使用することで、公開されるべきではないコードの部分をカプセル化できます。これは誤った名前衝突とグローバルスコープ汚染を防ぎ、複数の依存関係と名前空間で作業する際のリスクを軽減します。すべてのJavaScript ランタイムで ES2015 modules を使用できるようにするために、Babel のようなトランスパイラが必要です。

参考資料

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
patternsdev
リポジトリ
patternsdev/skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/patternsdev/skills / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: patternsdev · patternsdev/skills · ライセンス: MIT