APIサーバを設計する際、各層の責務を明確に分離することで、保守性や拡張性を向上させることができる。ここでは、APIサーバの代表的な設計パターンを例に、各層の役割とその連携の流れを解説する。
コントローラやハンドラーは、クライアントからのHttpリクエストを受け取り、適切なレスポンスを返す役割を担う。これらは通常、リクエストのルーティングやバリデーションを行い、次の層(サービス層)に処理を委譲する。
ポイント:
csharppublic class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userService.GetUserById(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
}
サービス層は、アプリケーション固有のビジネスロジックやアプリケーションロジックを集約する役割を持つ。データの加工やビジネスルールの実行など、コントローラから受け取ったリクエストに対して、必要な処理を実行する。
サービス層は、外部とのインターフェースとして機能するが、具体的なデータ操作や外部接続のロジックはリポジトリに委譲する。
csharppublic class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<User> GetUserById(int id)
{
var user = await _userRepository.FindById(id);
if (user == null)
{
throw new NotFoundException("User not found");
}
// ビジネスロジックを実行(必要に応じて)
return user;
}
}
リポジトリ層は、データベースや外部APIなどのデータソースに対するアクセスを抽象化する役割を担う。これにより、データの永続化や取得のロジックがサービス層に露出しないようにする。
リポジトリは、外部接続に特化しており、複雑なビジネスロジックを持たない。サービス層やコントローラ層からの要求に対して、必要なデータ操作を行い、結果を返す。
csharppublic class UserRepository : IUserRepository
{
private readonly AppDbContext _context;
public UserRepository(AppDbContext context)
{
_context = context;
}
public async Task<User> FindById(int id)
{
return await _context.Users.FindAsync(id);
}
}
APIサーバの各層の呼び出し順序は以下の通り:
呼び出しの流れは以下のようになる:
csharppublic class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
enum
は、定義ファイルにまとめておくことでコードの可読性や保守性を向上させる。csharppublic static class Constants
{
public const string AdminRole = "Admin";
}
csharppublic enum UserStatus
{
Active,
Inactive,
Suspended
}
APIサーバの責務を分離することで、各層が担う役割が明確になり、保守性や拡張性が大幅に向上する。コントローラはリクエスト処理に集中し、サービス層はビジネスロジックを扱い、リポジトリ層はデータアクセスを抽象化する。この分離により、コードがよりモジュール化され、変更や拡張が容易になる。また、共通処理や定数の適切な管理も忘れずに行うことで、コードベース全体の品質を向上させることができる。