Cline × クリーンアーキテクチャ:ユースケース駆動と境界の切り出し
AI アシスタントを活用した開発が当たり前になってきた今、コードの品質を保ちながら効率的に開発を進めることが重要です。特に Cline のような AI コーディングツールを使う際、クリーンアーキテクチャの原則に従うことで、保守性と拡張性の高いコードベースを構築できるでしょう。
本記事では、Cline を使った開発においてクリーンアーキテクチャを実践する方法、特にユースケース駆動開発と境界の切り出しに焦点を当てて解説します。AI が生成するコードを構造化し、長期的に保守しやすいアプリケーションを作る実践的な手法をご紹介しますね。
背景
Cline とクリーンアーキテクチャの関係性
Cline は VSCode の拡張機能として動作する AI コーディングアシスタントで、Claude API を活用してコード生成や編集を行います。開発者の指示に基づいて、ファイルの作成、編集、削除を自動的に実行できる強力なツールですね。
しかし、AI が生成するコードは時として構造が曖昧になりがちです。そこで、クリーンアーキテクチャの原則を導入することで、以下のメリットが得られるでしょう。
以下の図は、Cline がクリーンアーキテクチャの各層にどのように関与するかを示しています。
mermaidflowchart TB
dev["開発者"] -->|指示| cline["Cline AI"]
cline -->|生成| entities["エンティティ層<br/>ビジネスルール"]
cline -->|生成| usecases["ユースケース層<br/>アプリケーションロジック"]
cline -->|生成| adapters["アダプター層<br/>インターフェース"]
cline -->|生成| frameworks["フレームワーク層<br/>外部ツール・DB"]
entities -.->|依存| usecases
usecases -.->|依存| adapters
adapters -.->|依存| frameworks
style cline fill:#e1f5ff
style entities fill:#fff4e6
style usecases fill:#e8f5e9
style adapters fill:#f3e5f5
style frameworks fill:#fce4ec
図で理解できる要点:
- Cline は各層のコードを生成しますが、依存関係は内側から外側への一方向のみです
- 開発者は Cline に指示を出し、各層の責務に応じたコード生成を促します
- エンティティ層が最も内側で、外部の変更に影響されにくい構造になっています
クリーンアーキテクチャでは、ビジネスロジックを中心に据え、外部の技術的詳細から分離します。この分離により、AI が生成したコードであっても、明確な責務と境界を持つモジュールとして整理できますね。
ユースケース駆動開発の重要性
ユースケース駆動開発は、システムが「何をするか」を中心に設計を進める手法です。これは AI アシスタントに指示を出す際、非常に相性が良いアプローチと言えるでしょう。
Cline に対して「ユーザー登録機能を作って」と曖昧に指示するのではなく、「ユーザー登録ユースケースを実装して。メールアドレスの重複チェックと、パスワードのハッシュ化を含めて」と具体的に指示することで、より構造化されたコードを生成できます。
課題
AI 生成コードの一般的な問題点
Cline のような AI ツールを使うと、コード生成は速くなりますが、以下のような課題に直面することが多いですね。
- 層の混在: ビジネスロジックとデータアクセスロジックが同じファイルに混在する
- 密結合: データベースや外部 API への直接的な依存が多発する
- テスト困難: モックやスタブを使ったテストが難しい構造になる
- 境界の曖昧さ: どこまでがユースケースで、どこからがインフラ層かが不明瞭になる
以下の図は、構造化されていないコードの問題点を示しています。
mermaidflowchart TD
controller["Controller"] -->|直接呼び出し| db[("Database")]
controller -->|直接呼び出し| api["External API"]
controller -->|ビジネスロジック<br/>を含む| validation["バリデーション"]
style controller fill:#ffebee
style db fill:#ffebee
style api fill:#ffebee
style validation fill:#ffebee
この図が示す問題点:
- Controller が複数の責務を持ち、変更の影響範囲が広い
- データベースや外部 API への直接依存により、テストが困難
- ビジネスルールの再利用ができない構造になっています
境界が曖昧なコードの影響
境界が曖昧なコードは、以下のような具体的な問題を引き起こします。
| # | 問題 | 具体例 | 影響 |
|---|---|---|---|
| 1 | テスト困難 | データベース接続が必須 | ユニットテストが書けない |
| 2 | 変更コスト増 | DB 変更時に複数ファイル修正 | 開発速度の低下 |
| 3 | 再利用性低下 | ロジックが特定の実装に依存 | コードの重複が発生 |
| 4 | AI の理解困難 | 責務が不明瞭 | Cline が適切な修正を提案できない |
特に 4 番目の問題は見落とされがちですが、重要なポイントです。Cline に「このユーザー登録機能を修正して」と指示しても、コードの境界が曖昧だと、どこをどう修正すべきか AI が判断しづらくなるでしょう。
解決策
ユースケースファーストの設計アプローチ
クリーンアーキテクチャでは、ユースケースを中心に設計を始めます。Cline を使う際も、この原則を守ることで、構造化されたコードを生成できますね。
以下の手順で、ユースケース駆動の開発を進めましょう。
ステップ 1:ユースケースの定義
まず、実現したい機能をユースケースとして言語化します。例えば「ユーザー登録」というユースケースであれば、以下のように定義できます。
typescript// src/domain/usecases/RegisterUserUseCase.ts
/**
* ユーザー登録ユースケース
* - メールアドレスの重複をチェック
* - パスワードをハッシュ化
* - ユーザーを永続化
*/
export interface RegisterUserUseCase {
execute(
input: RegisterUserInput
): Promise<RegisterUserOutput>;
}
このインターフェースは、ユースケースの入出力を明確に定義しています。Cline にこのインターフェースを示すことで、実装すべき内容が明確になりますね。
ステップ 2:入出力型の定義
次に、ユースケースの入出力型を定義します。これにより、データの境界が明確になります。
typescript// src/domain/usecases/RegisterUserUseCase.ts
export interface RegisterUserInput {
email: string;
password: string;
username: string;
}
export interface RegisterUserOutput {
userId: string;
email: string;
username: string;
createdAt: Date;
}
入出力型を分けることで、ユースケースが何を受け取り、何を返すのかが一目瞭然です。Cline にも、この型情報を基に適切なコードを生成するよう指示できるでしょう。
境界の明確な切り出し方
クリーンアーキテクチャの核心は、適切な境界を設けることです。以下の図は、推奨される層の構造を示しています。
mermaidflowchart LR
subgraph domain["ドメイン層(内側)"]
entities["エンティティ"]
usecases["ユースケース<br/>インターフェース"]
end
subgraph application["アプリケーション層"]
impl["ユースケース<br/>実装"]
end
subgraph infrastructure["インフラ層(外側)"]
repo["リポジトリ<br/>実装"]
db[("Database")]
end
impl -->|依存| usecases
impl -->|使用| repo
repo -->|アクセス| db
style domain fill:#e8f5e9
style application fill:#fff3e0
style infrastructure fill:#f3e5f5
境界を切り出す際の原則:
- ドメイン層は外部に依存しない純粋なビジネスロジック
- アプリケーション層はユースケースの実装を含むが、技術的詳細は含まない
- インフラ層は具体的な実装(DB、API など)を担当します
依存性逆転の原則の適用
境界を切り出す際、最も重要なのが依存性逆転の原則(DIP)です。これは、具体的な実装ではなく、抽象(インターフェース)に依存させる原則ですね。
まず、リポジトリのインターフェースをドメイン層で定義します。
typescript// src/domain/repositories/UserRepository.ts
import { User } from '../entities/User';
/**
* ユーザーリポジトリインターフェース
* ドメイン層で定義し、インフラ層で実装する
*/
export interface UserRepository {
findByEmail(email: string): Promise<User | null>;
save(user: User): Promise<User>;
findById(id: string): Promise<User | null>;
}
このインターフェースをユースケースで使用することで、具体的なデータベース実装から分離できます。
次に、ユースケースの実装で、このインターフェースに依存します。
typescript// src/application/usecases/RegisterUserUseCaseImpl.ts
import {
RegisterUserUseCase,
RegisterUserInput,
RegisterUserOutput,
} from '../../domain/usecases/RegisterUserUseCase';
import { UserRepository } from '../../domain/repositories/UserRepository';
import { User } from '../../domain/entities/User';
export class RegisterUserUseCaseImpl
implements RegisterUserUseCase
{
constructor(private userRepository: UserRepository) {}
// ユースケースの実装は次のセクションで説明
}
コンストラクタで UserRepository インターフェースを受け取ることで、具体的な実装への依存を排除しています。Cline にこのパターンを指示する際も、「依存性注入を使って」と明示すると良いですね。
Cline への効果的な指示の出し方
Cline にクリーンアーキテクチャを守らせるには、指示の出し方が重要です。以下のような指示が効果的でしょう。
悪い指示例:
ユーザー登録機能を作って
良い指示例:
diffRegisterUserUseCase インターフェースを実装する RegisterUserUseCaseImpl クラスを作成してください。
- UserRepository インターフェースに依存させること
- パスワードハッシュ化には bcrypt を使用
- メールアドレスの重複チェックを実装
- src/application/usecases/ に配置
このように具体的に指示することで、Cline は適切な場所に適切なコードを生成できます。
具体例
エンティティの定義
クリーンアーキテクチャでは、まずエンティティ(ビジネスルール)を定義します。これは最も内側の層で、外部の変更に影響されません。
typescript// src/domain/entities/User.ts
/**
* ユーザーエンティティ
* ビジネスルールを含む純粋なドメインオブジェクト
*/
export class User {
constructor(
public readonly id: string,
public readonly email: string,
public readonly passwordHash: string,
public readonly username: string,
public readonly createdAt: Date
) {}
エンティティにビジネスルールを含める場合は、メソッドとして実装します。
typescript /**
* メールアドレスのバリデーション
* ビジネスルールとしてエンティティに含める
*/
static isValidEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
エンティティの残りの部分を実装します。
typescript /**
* パスワードの強度チェック
* 最低8文字、英数字を含む
*/
static isStrongPassword(password: string): boolean {
if (password.length < 8) return false;
const hasLetter = /[a-zA-Z]/.test(password);
const hasNumber = /[0-9]/.test(password);
return hasLetter && hasNumber;
}
}
これらのバリデーションルールは、データベースや UI フレームワークに依存しない純粋なビジネスロジックです。Cline にエンティティを作成させる際は、「ビジネスルールのみを含めて」と指示すると良いでしょう。
ユースケースの実装
次に、ユースケースを実装します。ここでは、エンティティとリポジトリインターフェースを使用しますが、具体的な実装には依存しません。
typescript// src/application/usecases/RegisterUserUseCaseImpl.ts
import {
RegisterUserUseCase,
RegisterUserInput,
RegisterUserOutput,
} from '../../domain/usecases/RegisterUserUseCase';
import { UserRepository } from '../../domain/repositories/UserRepository';
import { User } from '../../domain/entities/User';
import * as bcrypt from 'bcrypt';
必要な依存関係をインポートします。ここで注目すべきは、すべてインターフェースに依存している点ですね。
次に、ユースケースクラスの基本構造を定義します。
typescriptexport class RegisterUserUseCaseImpl implements RegisterUserUseCase {
private readonly SALT_ROUNDS = 10;
constructor(private userRepository: UserRepository) {}
コンストラクタで UserRepository を受け取り、プライベートフィールドに格納しています。これが依存性注入の基本パターンです。
ユースケースのメイン処理を実装します。
typescript async execute(input: RegisterUserInput): Promise<RegisterUserOutput> {
// 1. 入力バリデーション
if (!User.isValidEmail(input.email)) {
throw new Error('Invalid email format');
}
if (!User.isStrongPassword(input.password)) {
throw new Error('Password must be at least 8 characters with letters and numbers');
}
エンティティに定義したバリデーションルールを使用して、入力をチェックします。
メールアドレスの重複チェックとユーザー作成処理を実装します。
typescript// 2. メールアドレスの重複チェック
const existingUser = await this.userRepository.findByEmail(
input.email
);
if (existingUser) {
throw new Error('Email already registered');
}
// 3. パスワードのハッシュ化
const passwordHash = await bcrypt.hash(
input.password,
this.SALT_ROUNDS
);
リポジトリインターフェースを通じてデータアクセスを行い、具体的な実装からは分離されています。
最後に、ユーザーを保存して結果を返します。
typescript // 4. ユーザーエンティティの作成と保存
const user = new User(
this.generateId(),
input.email,
passwordHash,
input.username,
new Date()
);
const savedUser = await this.userRepository.save(user);
// 5. 出力への変換
return {
userId: savedUser.id,
email: savedUser.email,
username: savedUser.username,
createdAt: savedUser.createdAt
};
}
private generateId(): string {
return `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}
この実装により、ビジネスロジックが明確に分離され、テスト可能な構造になりました。
リポジトリの実装(インフラ層)
最後に、インフラ層でリポジトリの具体的な実装を行います。ここでは例として TypeORM を使用しますが、他の ORM でも同様です。
typescript// src/infrastructure/repositories/TypeORMUserRepository.ts
import { Repository } from 'typeorm';
import { UserRepository } from '../../domain/repositories/UserRepository';
import { User } from '../../domain/entities/User';
import { UserEntity } from '../entities/UserEntity';
TypeORM の Repository と、ドメイン層のインターフェースをインポートします。
リポジトリクラスの基本構造を定義します。
typescript/**
* TypeORM を使用した UserRepository の実装
* インフラ層に配置し、技術的詳細を担当
*/
export class TypeORMUserRepository implements UserRepository {
constructor(private ormRepository: Repository<UserEntity>) {}
TypeORM の Repository を受け取り、内部で使用します。
findByEmail メソッドを実装します。
typescript async findByEmail(email: string): Promise<User | null> {
const userEntity = await this.ormRepository.findOne({
where: { email }
});
if (!userEntity) return null;
return this.toDomain(userEntity);
}
データベースから取得したエンティティを、ドメインのエンティティに変換しています。
save メソッドと変換メソッドを実装します。
typescript async save(user: User): Promise<User> {
const userEntity = this.toEntity(user);
const saved = await this.ormRepository.save(userEntity);
return this.toDomain(saved);
}
async findById(id: string): Promise<User | null> {
const userEntity = await this.ormRepository.findOne({
where: { id }
});
if (!userEntity) return null;
return this.toDomain(userEntity);
}
各メソッドで、データベース層とドメイン層の境界を明確に保っています。
エンティティ変換メソッドを実装します。
typescript /**
* DB エンティティからドメインエンティティへ変換
*/
private toDomain(entity: UserEntity): User {
return new User(
entity.id,
entity.email,
entity.passwordHash,
entity.username,
entity.createdAt
);
}
/**
* ドメインエンティティから DB エンティティへ変換
*/
private toEntity(user: User): UserEntity {
const entity = new UserEntity();
entity.id = user.id;
entity.email = user.email;
entity.passwordHash = user.passwordHash;
entity.username = user.username;
entity.createdAt = user.createdAt;
return entity;
}
}
この変換により、ドメイン層は TypeORM の存在を知らず、完全に分離されています。
依存性の注入と組み立て
すべての部品が揃ったら、依存性注入を使って組み立てます。以下は、Express を使った例ですね。
typescript// src/infrastructure/http/routes/userRoutes.ts
import { Router } from 'express';
import { getRepository } from 'typeorm';
import { UserEntity } from '../../entities/UserEntity';
import { TypeORMUserRepository } from '../../repositories/TypeORMUserRepository';
import { RegisterUserUseCaseImpl } from '../../../application/usecases/RegisterUserUseCaseImpl';
必要な依存関係をすべてインポートします。
ルーターの設定と依存性の組み立てを行います。
typescriptconst router = Router();
/**
* ユーザー登録エンドポイント
* POST /api/users/register
*/
router.post('/register', async (req, res) => {
try {
// 1. リポジトリの作成
const ormRepository = getRepository(UserEntity);
const userRepository = new TypeORMUserRepository(ormRepository);
TypeORM のリポジトリを取得し、それをラップした実装を作成します。
ユースケースを実行して、結果を返します。
typescript// 2. ユースケースの作成と実行
const useCase = new RegisterUserUseCaseImpl(userRepository);
const result = await useCase.execute({
email: req.body.email,
password: req.body.password,
username: req.body.username,
});
// 3. レスポンスの返却
res.status(201).json({
success: true,
data: result,
});
ユースケースに依存性を注入し、実行します。
エラーハンドリングを実装します。
typescript } catch (error) {
console.error('Registration error:', error);
res.status(400).json({
success: false,
message: error.message || 'Registration failed'
});
}
});
export default router;
この構造により、各層が明確に分離され、テストや変更が容易になります。
完成したアーキテクチャの全体像
以下の図は、実装した各コンポーネントの関係性を示しています。
mermaidflowchart TB
subgraph presentation["プレゼンテーション層"]
route["Express Route"]
end
subgraph application["アプリケーション層"]
usecase["RegisterUserUseCaseImpl"]
end
subgraph domain["ドメイン層"]
interface["RegisterUserUseCase<br/>Interface"]
repoInterface["UserRepository<br/>Interface"]
entity["User Entity"]
end
subgraph infrastructure["インフラ層"]
repo["TypeORMUserRepository"]
db[("PostgreSQL")]
end
route -->|使用| usecase
usecase -->|実装| interface
usecase -->|依存| repoInterface
usecase -->|使用| entity
repo -->|実装| repoInterface
repo -->|アクセス| db
style domain fill:#e8f5e9
style application fill:#fff3e0
style infrastructure fill:#f3e5f5
style presentation fill:#e3f2fd
この図から読み取れるポイント:
- 依存関係が常に内側(ドメイン層)に向かっている
- ドメイン層は他の層に依存せず、最も安定している
- インフラ層の変更(例:TypeORM から Prisma への移行)は、ドメイン層に影響しません
- プレゼンテーション層(Express Route)の変更も、ビジネスロジックに影響しない構造です
Cline でのテスト駆動開発
クリーンアーキテクチャの利点は、テストが容易になることです。Cline にテストコードを生成させる際も、境界が明確なので効率的ですね。
typescript// src/application/usecases/__tests__/RegisterUserUseCaseImpl.test.ts
import { RegisterUserUseCaseImpl } from '../RegisterUserUseCaseImpl';
import { UserRepository } from '../../../domain/repositories/UserRepository';
import { User } from '../../../domain/entities/User';
/**
* ユースケースのユニットテスト
* モックリポジトリを使用して、インフラ層から独立してテスト
*/
describe('RegisterUserUseCaseImpl', () => {
let useCase: RegisterUserUseCaseImpl;
let mockRepository: jest.Mocked<UserRepository>;
モックを使用することで、データベースなしでテストできます。
テストケースのセットアップを行います。
typescriptbeforeEach(() => {
// モックリポジトリの作成
mockRepository = {
findByEmail: jest.fn(),
save: jest.fn(),
findById: jest.fn(),
};
useCase = new RegisterUserUseCaseImpl(mockRepository);
});
各テストの前に、新しいモックとユースケースインスタンスを作成します。
成功ケースのテストを実装します。
typescript it('should register a new user successfully', async () => {
// Arrange
mockRepository.findByEmail.mockResolvedValue(null);
mockRepository.save.mockResolvedValue(
new User('user_123', 'test@example.com', 'hashed', 'testuser', new Date())
);
// Act
const result = await useCase.execute({
email: 'test@example.com',
password: 'Password123',
username: 'testuser'
});
AAA パターン(Arrange-Act-Assert)でテストを構造化しています。
テストのアサーション部分を実装します。
typescript // Assert
expect(result.userId).toBe('user_123');
expect(result.email).toBe('test@example.com');
expect(mockRepository.findByEmail).toHaveBeenCalledWith('test@example.com');
expect(mockRepository.save).toHaveBeenCalled();
});
期待される結果と、モックの呼び出しを検証しています。
エラーケースのテストを実装します。
typescriptit('should throw error when email already exists', async () => {
// Arrange
mockRepository.findByEmail.mockResolvedValue(
new User(
'existing',
'test@example.com',
'hashed',
'existing',
new Date()
)
);
// Act & Assert
await expect(
useCase.execute({
email: 'test@example.com',
password: 'Password123',
username: 'testuser',
})
).rejects.toThrow('Email already registered');
});
境界が明確なため、様々なシナリオを簡単にテストできますね。
バリデーションエラーのテストを追加します。
typescript it('should throw error for invalid email format', async () => {
await expect(useCase.execute({
email: 'invalid-email',
password: 'Password123',
username: 'testuser'
})).rejects.toThrow('Invalid email format');
});
it('should throw error for weak password', async () => {
await expect(useCase.execute({
email: 'test@example.com',
password: 'weak',
username: 'testuser'
})).rejects.toThrow('Password must be at least 8 characters');
});
});
Cline に「このユースケースのテストを書いて」と指示すれば、このような包括的なテストコードを生成できます。
まとめ
Cline とクリーンアーキテクチャを組み合わせることで、AI の生産性とコードの品質を両立できます。本記事で紹介したユースケース駆動と境界の切り出しは、長期的に保守可能なシステムを構築する基盤となるでしょう。
重要なポイントの振り返り:
| # | ポイント | 効果 | Cline への指示 |
|---|---|---|---|
| 1 | ユースケースファースト | ビジネスロジックの明確化 | 「〇〇ユースケースを実装して」 |
| 2 | 依存性逆転の原則 | テスト容易性の向上 | 「インターフェースに依存させて」 |
| 3 | 層の明確な分離 | 変更影響の局所化 | 「ドメイン層に配置して」 |
| 4 | 具体的な指示 | AI の理解精度向上 | 詳細な要件と配置場所を指定 |
AI アシスタントは強力なツールですが、構造化されたアーキテクチャがあってこそ、その真価を発揮します。クリーンアーキテクチャの原則に従うことで、Cline が生成するコードを整理し、長期的に価値のある資産として育てていけるでしょう。
まずは小さなユースケースから始めて、徐々に境界を明確にしていくアプローチをおすすめします。Cline に適切な指示を出し、生成されたコードをレビューしながら、理想的なアーキテクチャへと近づけていってくださいね。
クリーンアーキテクチャは最初は複雑に感じるかもしれませんが、一度構造が確立されれば、新機能の追加やリファクタリングが驚くほどスムーズになります。AI と協力しながら、保守性の高いコードベースを構築していきましょう。
関連リンク
- Cline 公式サイト - Cline の最新情報とドキュメント
- Clean Architecture(Robert C. Martin) - クリーンアーキテクチャの原典解説
- TypeORM 公式ドキュメント - TypeORM の詳細な使用方法
- 依存性逆転の原則(DIP) - SOLID 原則の詳細解説
- Jest 公式ドキュメント - JavaScript/TypeScript のテストフレームワーク
- The Clean Code Blog - Robert C. Martin による設計原則の記事
articleCline × クリーンアーキテクチャ:ユースケース駆動と境界の切り出し
articleCline コマンド/アクション早見表:よく使う操作 50 連発
articleCline × Monorepo(Yarn Workspaces)導入:パス解決とルート権限の最適解
articleGitHub Copilot Workspace と Cursor/Cline の比較検証:仕様駆動の自動化能力はどこまで?
articleCline × Claude/GPT/Gemini モデル比較:長文理解とコード品質の相性
articleCline が差分を誤適用する時:改行コード・Prettier・改フォーマット問題の解決
articlemacOS(Apple Silicon)で Docker を高速化:qemu/仮想化設定・Rosetta 併用術
articleCline × クリーンアーキテクチャ:ユースケース駆動と境界の切り出し
articleDevin 用リポジトリ準備チェックリスト:ブランチ戦略・CI 前提・テスト整備
articleClaude Code プロンプト設計チートシート:役割・入力・出力フォーマット定番集
articleConvex と Next.js Server Actions “直書き”比較:保守性・安全性・速度をコードで実測
articleBun でリアルタイムダッシュボード:メトリクス集計と可視化を高速化
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来