Lewati ke konten utama

BAB 36. CLEAN ARCHITECTURE

Konsep​

TemuBelajar mengimplementasikan Clean Architecture (Robert C. Martin) untuk memisahkan kepentingan bisnis dari detail teknis, sehingga sistem mudah diuji, diubah, dan diperluas.


Layer Diagram​

flowchart TD
subgraph OUTER ["🌐 Outer Layer"]
UI["📱 Presentation\n(Flutter Pages, Widgets, Controllers)"]
API["🔌 Infrastructure\n(Laravel Controller, API Resource)"]
end

subgraph MIDDLE ["⚙️ Application Layer"]
UC["📋 Use Cases\n(Business Logic)"]
end

subgraph INNER ["🎯 Domain Layer (Core)"]
ENT["🏛️ Entities\n(Pure Business Objects)"]
RI["📄 Repository Interfaces"]
end

subgraph DATA ["🗄️ Data Layer"]
REPO["Repository Implementation"]
DS["Data Source"]
DB[("MySQL")]
end

UI --> UC
API --> UC
UC --> ENT
UC --> RI
RI --> REPO
REPO --> DS
DS --> DB

style INNER fill:#1e1b4b,color:#a5b4fc
style MIDDLE fill:#4c1d95,color:#ddd6fe
style OUTER fill:#1f2937,color:#d1d5db
style DATA fill:#064e3b,color:#a7f3d0

Penjelasan Setiap Layer​

🎯 Domain Layer — Inti Sistem​

Layer paling dalam. Tidak bergantung pada apapun — tidak ada import Flutter, Laravel, atau database di sini.

Berisi:

KomponenDeskripsi
EntitiesObjek bisnis inti (Request, Booking, Meeting)
Repository InterfacesKontrak/abstraksi akses data
Value ObjectsTipe data bisnis (Rating, Score, Status)
Domain EventsEvent yang terjadi di domain (RequestCreated, etc.)

Contoh Entity (Flutter/Dart):

class RequestEntity {
final int id;
final String topic;
final String description;
final RequestStatus status;
final DateTime preferredTime;

const RequestEntity({
required this.id,
required this.topic,
required this.description,
required this.status,
required this.preferredTime,
});
}

⚙️ Application Layer — Use Cases​

Berisi logika bisnis aplikasi. Hanya bergantung pada Domain Layer.

Contoh Use Case (Flutter/Dart):

class CreateRequestUseCase {
final RequestRepository _repository;

CreateRequestUseCase(this._repository);

Future<Either<Failure, RequestEntity>> call(CreateRequestParams params) {
return _repository.createRequest(params);
}
}

Contoh Service (Laravel/PHP):

class RequestService
{
public function __construct(
private RequestRepositoryInterface $repository,
private MatchingEngine $matchingEngine
) {}

public function createRequest(CreateRequestDTO $dto): Request
{
$request = $this->repository->create($dto);
$this->matchingEngine->dispatch($request);
return $request;
}
}

🌐 Presentation / Infrastructure Layer​

Layer terluar. Bergantung pada semua layer di bawahnya.

Flutter:

  • Pages (UI)
  • Widgets (komponen UI)
  • Controllers/Notifiers (state management via Riverpod)

Laravel:

  • Controllers (HTTP handler)
  • API Resources (JSON transformer)
  • Form Requests (validasi)

Dependency Rule​

:::important Aturan Utama Ketergantungan kode hanya boleh mengarah ke dalam (dari luar ke dalam). Layer dalam tidak boleh mengetahui apapun tentang layer luar. :::

✅ Presentation → Domain
✅ Application → Domain
✅ Data → Domain (implements interface)
❌ Domain → Presentation (DILARANG)
❌ Domain → Data (DILARANG)

Implementasi di Flutter​

flowchart LR
Page --> Controller
Controller --> UseCase
UseCase --> RepositoryInterface
RepositoryInterface --> RepositoryImpl
RepositoryImpl --> RemoteDatasource
RemoteDatasource --> DioClient["Dio\nHTTP Client"]

style RepositoryInterface fill:#7c3aed,color:#fff

Implementasi di Laravel​

flowchart LR
Controller --> Service
Service --> RepositoryInterface
RepositoryInterface --> Repository
Repository --> Model["Eloquent\nModel"]
Model --> MySQL[("MySQL")]

style RepositoryInterface fill:#7c3aed,color:#fff

Keuntungan​

KeuntunganDampak
TestabilityDomain dan Use Case bisa diuji tanpa database
FlexibilityGanti database/framework tanpa ubah bisnis logic
MaintainabilityPerubahan terlokalisir per layer
Separation of ConcernsSetiap layer punya tanggung jawab yang jelas