Skip to content

コードの書き方

技術記事におけるコードの書き方と、読者が理解しやすいコードの提示方法を詳しく解説します。

技術記事におけるコードの書き方は、読者が理解しやすく、実践しやすいコードを提示することです。

コードの書き方
├─ 実際に動作するコードを提供
├─ コメントで説明を追加
├─ 段階的に説明
├─ エラーと解決方法を説明
└─ コードの背景を説明

なぜコードの書き方が重要なのか

Section titled “なぜコードの書き方が重要なのか”

コードの書き方が悪い記事の問題

Section titled “コードの書き方が悪い記事の問題”

問題のあるコード:

- 実際に動作しないコード
- コメントがない
- 説明が不十分
- エラーと解決方法がない

影響:

  • 読者が理解できない
  • 読者が実践できない
  • 記事の評価が低い
  • 実践に役立たない

良いコードの書き方のメリット

Section titled “良いコードの書き方のメリット”

改善されたコード:

- 実際に動作するコード
- コメントで説明を追加
- 段階的に説明
- エラーと解決方法を説明

メリット:

  • 読者が理解できる
  • 読者が実践できる
  • 記事の評価が高い
  • 実践に役立つ

1. 実際に動作するコードを提供する

Section titled “1. 実際に動作するコードを提供する”

1.1 実際に動作するコードの重要性

Section titled “1.1 実際に動作するコードの重要性”

実際に動作するコードの重要性

Section titled “実際に動作するコードの重要性”

実際に動作するコードを提供することで、読者が実践できる記事になります。

実際に動作するコードの例:

## 実際に動作するコードの例
### ✅ 良い例
「## ReactのuseStateフックの実装例
以下のコードは、実際に動作する完全な例です:
```typescript
// App.tsx
import { useState } from 'react';
function Counter() {
// useStateの初期値を0に設定
const [count, setCount] = useState(0);
// インクリメント関数
const increment = () => {
setCount(count + 1);
};
// デクリメント関数
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
);
}
export default Counter;

このコードをそのままコピーして使用できます。」

「## ReactのuseStateフックの実装例

const [count, setCount] = useState(0);

(問題点: 完全なコードではない、動作しない、説明がない)」

### 1.2 コードの検証方法
#### コードの検証方法
コードを提供する前に、必ず動作確認を行います。
**コードの検証方法:**
1. **実際に実行する**: コードを実際に実行し、動作確認する
2. **エラーを確認する**: エラーがないか確認する
3. **動作環境を明記する**: 動作環境(Node.jsのバージョンなど)を明記する
**コードの検証例:**
```markdown
## コードの検証例
「## 動作環境
- Node.js: 18.0.0以上
- React: 18.0.0以上
- TypeScript: 5.0.0以上
## 実装例
以下のコードは、上記の環境で動作確認済みです:
```typescript
// 動作確認済みのコード
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
```」

コメントを追加することで、読者がコードを理解しやすくなります。

コメントの例:

## コメントの例
### ✅ 良い例
「## ReactのuseStateフックの実装例
```typescript
import { useState } from 'react';
function Counter() {
// useStateの初期値を0に設定
// count: 現在のカウント値
// setCount: カウント値を更新する関数
const [count, setCount] = useState(0);
// インクリメント関数
// countの値を1増やす
const increment = () => {
setCount(count + 1);
};
// デクリメント関数
// countの値を1減らす
const decrement = () => {
setCount(count - 1);
};
return (
<div>
{/* 現在のカウント値を表示 */}
<h1>カウント: {count}</h1>
{/* インクリメントボタン */}
<button onClick={increment}>+1</button>
{/* デクリメントボタン */}
<button onClick={decrement}>-1</button>
</div>
);
}

説明:

  • useState(0): 初期値を0に設定
  • count: 現在のカウント値
  • setCount: カウント値を更新する関数
  • increment: カウント値を1増やす関数
  • decrement: カウント値を1減らす関数」

「## ReactのuseStateフックの実装例

const [count, setCount] = useState(0);

(問題点: コメントがない、説明がない)」

### 2.2 コメントの書き方のコツ
#### コメントの書き方のコツ
**コツ:**
1. **重要な部分にコメントを追加**: 複雑な部分や重要な部分にコメントを追加する
2. **なぜそうするかを説明**: 何をするかだけでなく、なぜそうするかを説明する
3. **簡潔に**: コメントは簡潔に、必要最小限にする
**コメントの書き方の例:**
```markdown
## コメントの書き方の例
### ✅ 良い例
「```typescript
// パフォーマンス最適化のため、メモ化を使用
const memoizedValue = useMemo(() => {
// 重い計算処理
return expensiveCalculation(data);
}, [data]); // dataが変更されたときのみ再計算
// イベントハンドラーのメモ化
// 子コンポーネントの不要な再レンダリングを防ぐ
const handleClick = useCallback(() => {
onClick(id);
}, [id, onClick]);
```」
### ❌ 悪い例
「```typescript
// メモ化
const memoizedValue = useMemo(() => {
return expensiveCalculation(data);
}, [data]);
// コールバック
const handleClick = useCallback(() => {
onClick(id);
}, [id, onClick]);

(問題点: なぜメモ化するのか、なぜコールバックを使うのかが不明確)」

## 3. 段階的に説明する
### 3.1 段階的な説明の重要性
#### 段階的な説明の重要性
段階的に説明することで、読者が理解しやすくなります。
**段階的な説明の例:**
```markdown
## 段階的な説明の例
### ✅ 良い例
「## Next.jsでSSRとSSGを実装する手順
### ステップ1: 基本的なSSRの実装
まず、基本的なSSRの実装から始めます:
```typescript
// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
// サーバーで毎回データを取得(SSR)
const product = await fetch(`https://api.example.com/products/${params.id}`, {
cache: 'no-store', // キャッシュしない(SSR)
}).then(res => res.json());
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
</div>
);
}

説明:

  • cache: 'no-store': キャッシュしないことで、SSRを実現
  • サーバーで毎回データを取得するため、最新のデータを表示できる

次に、SSGの実装を追加します:

app/blog/[slug]/page.tsx
export async function generateStaticParams() {
// ビルド時にすべてのブログ投稿のパスを生成(SSG)
const posts = await fetch('https://api.example.com/posts').then(res => res.json());
return posts.map(post => ({ slug: post.slug }));
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
// ビルド時にデータを取得(SSG)
const post = await fetch(`https://api.example.com/posts/${params.slug}`).then(res => res.json());
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}

説明:

  • generateStaticParams: ビルド時にすべてのパスを生成
  • ビルド時にデータを取得するため、高速に表示できる

ステップ3: 使い分けの判断基準

Section titled “ステップ3: 使い分けの判断基準”

最後に、SSRとSSGの使い分けの判断基準を説明します:

  • 更新頻度が高い(1時間以内): SSR
  • 更新頻度が低い(1日以上): SSG
  • ユーザー固有のコンテンツ: SSR
  • 全ユーザー共通のコンテンツ: SSG」

「## Next.jsでSSRとSSGを実装する方法

// SSRの実装
// SSGの実装

(問題点: 段階的な説明がない、一度にすべてを説明している)」

## 4. エラーと解決方法を説明する
### 4.1 エラーと解決方法の重要性
#### エラーと解決方法の重要性
エラーと解決方法を説明することで、読者が実践しやすくなります。
**エラーと解決方法の例:**
```markdown
## エラーと解決方法の例
### ✅ 良い例
「## よくあるエラーと解決方法
### エラー1: `generateStaticParams`が定義されていない
**エラーメッセージ:**

Error: generateStaticParams is required for dynamic routes using SSG

**原因:**
SSGを使用する場合、`generateStaticParams`関数を定義する必要があります。
**解決方法:**
`generateStaticParams`関数を追加します:
```typescript
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then(res => res.json());
return posts.map(post => ({ slug: post.slug }));
}

エラー2: 動的なコンテンツが表示されない

Section titled “エラー2: 動的なコンテンツが表示されない”

エラーメッセージ:

Error: Cannot read property 'name' of undefined

原因: SSGを使用している場合、ビルド時にデータが存在しない可能性があります。

解決方法: SSRに変更するか、ISR(Incremental Static Regeneration)を使用します:

// ISRを使用する場合
export const revalidate = 60; // 60秒ごとに再生成
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.slug}`, {
next: { revalidate: 60 }, // 60秒ごとに再生成
}).then(res => res.json());
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
```
### ❌ 悪い例
「## 実装例
```typescript
// コード例

(問題点: エラーと解決方法がない、読者が困ったときに助けがない)」

## 5. コードの背景を説明する
### 5.1 コードの背景の重要性
#### コードの背景の重要性
コードの背景を説明することで、読者がなぜその実装をするのかを理解できます。
**コードの背景の例:**
```markdown
## コードの背景の例
### ✅ 良い例
「## パフォーマンス最適化の実装例
### 背景
Reactアプリケーションで、大量のデータを表示する際、パフォーマンスの問題が発生することがあります。
**問題:**
- 1000件のデータを一度にレンダリングすると、初回表示が遅い
- スクロール時にフレームレートが低下する
**解決方法:**
仮想スクロールを使用して、表示されている部分のみをレンダリングします。
### 実装例
```typescript
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
// 仮想スクロールの設定
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50, // 各アイテムの高さ(推定)
overscan: 5, // 表示範囲外の要素も少しレンダリング
});
return (
<div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
width: '100%',
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map(virtualItem => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
{items[virtualItem.index].name}
</div>
))}
</div>
</div>
);
}

説明:

  • 仮想スクロールにより、表示されている部分のみをレンダリング
  • パフォーマンスが大幅に向上し、1000件のデータでもスムーズにスクロールできる」

「## パフォーマンス最適化の実装例

// コード例

(問題点: 背景の説明がない、なぜその実装をするのかが不明確)」

## 6. まとめ
コードの書き方は、読者が理解しやすく、実践しやすい記事を書くための重要な要素です。
**重要なポイント:**
- **実際に動作するコードを提供**: 動作確認済みのコードを提供する
- **コメントで説明を追加**: 重要な部分にコメントを追加し、なぜそうするかを説明する
- **段階的に説明**: 複雑な場合は、段階的に説明する
- **エラーと解決方法を説明**: よくあるエラーと解決方法を説明する
- **コードの背景を説明**: なぜその実装をするのかを説明する
これらのポイントを守ることで、読者にとって価値のある技術記事を書くことができます。