0Pricing
PHP Academy · Pelajaran

Kasus Penggunaan dan Layanan Aplikasi

Nyatakan tindakan bisnis sebagai kasus penggunaan yang bebas dari kerangka kerja.

Kasus Penggunaan dan Layanan Aplikasi adalah pelajaran PHP Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar PHP Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus PHP Academy mencakup 4 pelajaran total.

Apa Sebenarnya Kasus Penggunaan Itu

Sebuah kasus penggunaan (atau layanan aplikasi atau interaktor) secara tepat menangkap satu operasi khusus aplikasi: Daftarkan Pengguna, Buat Pesanan, Batalkan Langganan. Kasus ini mengoordinasikan entitas dan port untuk memenuhi satu maksud. Yang terpenting, kasus ini bebas dari kerangka kerja: tidak ada Request, tidak ada Response, tidak ada pembantu global — hanya PHP biasa yang dapat Anda panggil dari mana saja.

Objek Transfer Data Perintah dan Hasil

Sebuah kasus penggunaan menerima objek transfer data perintah yang tidak dapat diubah sebagai masukan dan mengembalikan objek transfer data hasil. Objek transfer data hanyalah pembawa data — tidak memiliki perilaku atau logika validasi selain pemeriksaan struktur. Properti readonly (PHP 8.1+) membuatnya tahan terhadap perubahan.

<?php
final class RegisterUserCommand
{
    public function __construct(
        public readonly string $email,
        public readonly string $plainPassword,
    ) {}
}

final class RegisterUserResult
{
    public function __construct(public readonly string $userId) {}
}

Isi Layanan Aplikasi

Layanan menerjemahkan perintah menjadi operasi domain. Layanan ini melakukan orkestrasi tingkat aplikasi — pemeriksaan keunikan, persistensi, dan pengembalian pengenal — sambil menyerahkan aturan kepada entitas.

<?php
final class RegisterUser
{
    public function __construct(
        private Users $users,
        private PasswordHasher $hasher,
    ) {}

    public function __invoke(RegisterUserCommand $c): RegisterUserResult {
        if ($this->users->existsByEmail($c->email)) {
            throw new EmailAlreadyRegistered($c->email);
        }
        $user = User::register(
            UserId::generate(),
            new Email($c->email),
            $this->hasher->hash($c->plainPassword),
        );
        $this->users->add($user);
        return new RegisterUserResult((string) $user->id());
    }
}

Simpan Logika di Entitas

Waspadalah terhadap model domain anemia: entitas yang hanya tersisa sebagai pengambil dan penyetel, sementara seluruh logika berada di dalam layanan. Invarian harus berada pada entitas. Kasus penggunaan seharusnya terbaca seperti skrip singkat berisi maksud, bukan dinding aturan bisnis.

<?php
final class User
{
    private function __construct(
        private UserId $id,
        private Email $email,
        private string $passwordHash,
        private bool $active = false,
    ) {}

    public static function register(UserId $id, Email $e, string $hash): self {
        return new self($id, $e, $hash); // invariants enforced here
    }
    public function activate(): void {
        if ($this->active) throw new AlreadyActive();
        $this->active = true;
    }
    public function id(): UserId { return $this->id; }
}

Batas Transaksi

Kasus penggunaan adalah batas transaksi yang alami: satu kasus penggunaan = satu unit kerja yang konsisten. Alih-alih memenuhi layanan dengan beginTransaction(), bungkus layanan tersebut dengan dekorator transaksional agar inti tetap tidak bergantung pada persistensi.

<?php
interface TransactionManager {
    public function transactional(callable $work): mixed;
}

final class TransactionalRegisterUser
{
    public function __construct(
        private RegisterUser $inner,
        private TransactionManager $tx,
    ) {}

    public function __invoke(RegisterUserCommand $c): RegisterUserResult {
        return $this->tx->transactional(fn() => ($this->inner)($c));
    }
}

Validasi: Tempatnya

Bagilah validasi menjadi dua tingkat:

  • Validasi masukan (format, bidang wajib) dilakukan di adaptor penggerak atau validator khusus sebelum kasus penggunaan dijalankan.
  • Validasi domain (invarian, aturan bisnis) berada di objek nilai dan entitas, lalu menimbulkan pengecualian domain.

Kasus penggunaan mengasumsikan masukan memiliki format yang benar dan menegakkan maknanya.

<?php
final class Email
{
    public function __construct(public readonly string $value) {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException("Invalid email: $value");
        }
    }
}

try { new Email('nope'); } catch (Throwable $e) { echo $e->getMessage(), PHP_EOL; }
echo (new Email('a@b.com'))->value, PHP_EOL;

Mengembalikan Keluaran Tanpa HTTP

Ada dua pola untuk mengembalikan data sambil tetap bebas dari kerangka kerja:

  • Mengembalikan objek transfer data hasil (sederhana, sinkron).
  • Port keluaran / penyaji — kasus penggunaan mendorong hasil ke batas keluaran yang disuntikkan, sehingga adaptor dapat menentukan pemformatannya (JSON, HTML, CLI). Dengan demikian, bahkan bentuk tanggapan tetap berada di luar inti.
<?php
interface RegisterUserOutput {
    public function present(RegisterUserResult $r): void;
}

final class RegisterUserWithPresenter {
    public function __construct(private Users $users, private PasswordHasher $h) {}
    public function __invoke(RegisterUserCommand $c, RegisterUserOutput $out): void {
        $user = User::register(UserId::generate(), new Email($c->email), $this->h->hash($c->plainPassword));
        $this->users->add($user);
        $out->present(new RegisterUserResult((string) $user->id()));
    }
}

Peristiwa Domain dari Kasus Penggunaan

Kasus penggunaan sering mencatat peristiwa domain yang dihasilkan entitas, lalu mengirimkannya setelah transaksi disahkan. Hal ini memisahkan efek samping (mengirim Email sambutan, memperbarui model baca) dari alur kerja inti.

<?php
trait RecordsEvents {
    private array $events = [];
    protected function record(object $e): void { $this->events[] = $e; }
    public function releaseEvents(): array {
        $e = $this->events; $this->events = []; return $e;
    }
}

final class UserRegistered {
    public function __construct(public readonly string $userId) {}
}

// Use case calls $user->releaseEvents() and hands them to a dispatcher
echo 'event recorded pattern', PHP_EOL;

Satu Kelas per Kasus Penggunaan

Lebih baik gunakan kelas satu tindakan (satu metode publik, sering kali __invoke) daripada layanan besar dengan sepuluh metode. Manfaatnya:

  • Tanggung jawab tunggal dan penamaan yang jelas (CancelSubscription, bukan SubscriptionService::cancel).
  • Konstruktor hanya menyuntikkan hal-hal yang dibutuhkan oleh operasi ini.
  • Mudah dibungkus dengan dekorator (transaksi, pencatatan log, otorisasi).

Perangkaian di Akar Komposisi

Kasus penggunaan tidak pernah membuat dependensinya sendiri; akar komposisi yang melakukannya. Berikut perangkaian manual yang dapat Anda tempatkan dalam definisi wadah DI.

<?php
$pdo      = new PDO('sqlite::memory:');
$users    = new PdoUsers($pdo);
$hasher   = new BcryptHasher();
$register = new RegisterUser($users, $hasher);

// Decorate with a transaction boundary
$register = new TransactionalRegisterUser($register, new PdoTransactionManager($pdo));

// Driving adapter calls it
$result = $register(new RegisterUserCommand('dev@coddykit.com', 's3cret!'));
echo $result->userId, PHP_EOL;

Hal-Hal Lintas Aspek melalui Dekorator

Pencatatan log, metrik, dan otorisasi adalah hal-hal lintas aspek — jauhkan semuanya dari isi kasus penggunaan. Bungkus layanan dengan dekorator yang menggunakan antarmuka yang sama, sehingga inti tetap berfokus pada alur kerja sementara hal-hal infrastruktur dirangkai di sekelilingnya.

<?php
interface RegisterUserHandler {
    public function __invoke(RegisterUserCommand $c): RegisterUserResult;
}

final class LoggingRegisterUser implements RegisterUserHandler {
    public function __construct(
        private RegisterUserHandler $inner,
        private LoggerInterface $log,
    ) {}
    public function __invoke(RegisterUserCommand $c): RegisterUserResult {
        $this->log->info('register.start', ['email' => $c->email]);
        $r = ($this->inner)($c);
        $this->log->info('register.ok', ['id' => $r->userId]);
        return $r;
    }
}

Pemeriksaan Singkat

Di mana aturan "alamat Email harus unik dan memiliki format yang benar" seharusnya berada?

Ringkasan

Kasus penggunaan yang bebas dari kerangka kerja memberi Anda lapisan aplikasi yang bersih:

  • Satu kelas satu tindakan untuk setiap operasi, menerima objek transfer data perintah dan mengembalikan objek transfer data hasil (atau mendorongnya ke port keluaran).
  • Entitas dan objek nilai memiliki invarian; layanan hanya melakukan orkestrasi — hindari model anemia.
  • Kasus penggunaan adalah batas transaksi, yang dibungkus oleh dekorator alih-alih menggunakan beginTransaction secara sebaris.
  • Pisahkan validasi masukan (adaptor/VO) dari validasi domain (entitas).
  • Peristiwa domain memisahkan efek samping; akar komposisi merangkai dependensi.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Kasus Penggunaan dan Layanan Aplikasi” gratis?

Ya — teks lengkap “Kasus Penggunaan dan Layanan Aplikasi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus PHP Academy, upgrade ke CoddyKit PRO. Kursus PHP Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Kasus Penggunaan dan Layanan Aplikasi”?

Nyatakan tindakan bisnis sebagai kasus penggunaan yang bebas dari kerangka kerja. Kamu berlatih PHP Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai PHP Academy?

Tidak diperlukan pengalaman sebelumnya. PHP Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Kasus Penggunaan dan Layanan Aplikasi” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran PHP Academy ini?

Ya. Setiap pelajaran PHP Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Dari Arsitektur Berlapis ke Arsitektur Bersih
  2. Port dan Adapter Dijelaskan
  3. Kasus Penggunaan dan Layanan Aplikasi
  4. Inversi Dependensi dalam Praktik
← Kembali ke PHP Academy