0Pricing
PHP Academy · บทเรียน

หลักการ SOLID ในการใช้งานจริง

ประยุกต์ใช้หลักการ SOLID ทั้งห้าข้อกับคลาส PHP จริง

หลักการ SOLID ในการใช้งานจริง เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงใช้ SOLID

SOLID คือหลักการออกแบบห้าข้อที่ช่วยให้ PHP เชิงวัตถุ ยืดหยุ่น ทดสอบได้ และไม่เสื่อมสภาพง่าย หลักการเหล่านี้ไม่ใช่กฎที่ต้องทำตามอย่าง盲目 แต่เป็นแนวทางที่ช่วยลดการเชื่อมโยงระหว่างส่วนต่าง ๆ และทำให้ความรับผิดชอบชัดเจนขึ้น ในบทเรียนนี้ เราจะนำแต่ละหลักการไปใช้กับคลาส PHP ที่สามารถนำไปใช้งานจริงได้

  • Sความรับผิดชอบเดียว
  • Oเปิดเพื่อขยาย ปิดเพื่อแก้ไข
  • Lการแทนที่ของ Liskov
  • Iการแยกส่วนอินเทอร์เฟซ
  • Dการกลับทิศทางการพึ่งพา

ความรับผิดชอบเดียว

คลาสหนึ่งควรมี เหตุผลเดียวที่ต้องเปลี่ยนแปลง คลาสที่สร้างรายงาน จัดรูปแบบเป็น HTML และส่งอีเมลมีเหตุผลที่ต้องเปลี่ยนแปลงสามข้อ ให้แยกส่วนการจัดเก็บ การจัดรูปแบบ และการส่งต่อออกจากกัน

ด้านล่างนี้ Invoice มีหน้าที่เพียงจำลองข้อมูล ส่วนการแสดงผลและการบันทึกอยู่ที่อื่น

<?php
final class Invoice {
    public function __construct(
        public readonly string $number,
        public readonly int $cents
    ) {}
    public function total(): float { return $this->cents / 100; }
}

final class InvoiceRenderer {
    public function toText(Invoice $i): string {
        return sprintf('Invoice %s: $%.2f', $i->number, $i->total());
    }
}

$i = new Invoice('INV-1', 12500);
echo (new InvoiceRenderer())->toText($i), PHP_EOL;

SRP: การสังเกตสัญญาณผิดปกติ

การละเมิด SRP ที่พบได้ทั่วไปคือคลาสที่ชื่อมีคำว่า และ หรือ Manager ที่ทำทุกอย่าง ให้สังเกตเมธอดที่เปลี่ยนแปลงด้วยเหตุผลทางธุรกิจที่ไม่เกี่ยวข้องกัน หากการเปลี่ยนกฎภาษีและการเปลี่ยนรูปแบบ PDF ต่างก็แตะคลาสเดียวกัน แสดงว่าคลาสนั้นมีความรับผิดชอบมากเกินไป

หลักการเปิด-ปิด

องค์ประกอบของซอฟต์แวร์ควร เปิดเพื่อขยาย ปิดเพื่อแก้ไข การเพิ่มประเภทส่วนลดใหม่ไม่ควรบังคับให้แก้ไข switch ขนาดใหญ่ ให้ใช้พหุรูปแบบ โดยให้แต่ละกฎเป็นคลาสของตนเองที่ใช้อินเทอร์เฟซร่วมกัน

<?php
interface Discount { public function apply(float $total): float; }

final class PercentOff implements Discount {
    public function __construct(private float $pct) {}
    public function apply(float $t): float { return $t * (1 - $this->pct / 100); }
}
final class FlatOff implements Discount {
    public function __construct(private float $amount) {}
    public function apply(float $t): float { return max(0, $t - $this->amount); }
}

function checkout(float $total, Discount ...$discounts): float {
    foreach ($discounts as $d) { $total = $d->apply($total); }
    return $total;
}
echo checkout(100, new PercentOff(10), new FlatOff(5)), PHP_EOL; // 85

การแทนที่ของ Liskov

ประเภทย่อยต้องใช้งานได้ทุกที่ที่คาดว่าจะใช้ประเภทพื้นฐาน โดย ไม่ทำให้ผู้เรียกคาดเดาผิด ตัวอย่างที่มีชื่อเสียงคือ Square extends Rectangle ซึ่งละเมิด LSP เพราะการกำหนดความกว้างต้องไม่เปลี่ยนความสูงโดยไม่แจ้งให้ทราบ ควรจำลองทั้งสองเป็นประเภทแยกกันที่อยู่เบื้องหลังอินเทอร์เฟซ Shape ร่วมกัน

<?php
interface Shape { public function area(): float; }

final class Rectangle implements Shape {
    public function __construct(private float $w, private float $h) {}
    public function area(): float { return $this->w * $this->h; }
}
final class Square implements Shape {
    public function __construct(private float $side) {}
    public function area(): float { return $this->side ** 2; }
}

$shapes = [new Rectangle(2, 3), new Square(4)];
foreach ($shapes as $s) { echo $s->area(), PHP_EOL; }

LSP และสัญญา

LSP ยังมีข้อจำกัดต่อสัญญาของเมธอดด้วย ประเภทย่อยอาจ ลดความเข้มงวดของเงื่อนไขก่อนทำงาน และ เพิ่มความเข้มงวดของเงื่อนไขหลังทำงาน ได้ แต่ห้ามทำตรงกันข้าม การโยนประเภทข้อผิดพลาดใหม่ที่ประเภทพื้นฐานไม่เคยประกาศไว้ หรือการคืนค่า null ในกรณีที่ประเภทพื้นฐานรับประกันว่าจะคืนอ็อบเจ็กต์ ถือเป็นการละเมิดการแทนที่ ประเภทผลลัพธ์แบบร่วมแปรผันและประเภทพารามิเตอร์แบบแย้งแปรผันของ PHP บังคับใช้บางส่วนของหลักการนี้ในระดับประเภท

การแยกส่วนอินเทอร์เฟซ

ผู้ใช้บริการไม่ควรพึ่งพาเมธอดที่ตนไม่ได้ใช้ อินเทอร์เฟซ Worker ขนาดใหญ่ที่มี work() และ eat() จะบังคับให้ RobotWorker ต้องสร้างโครงร่างสำหรับ eat() ให้แยกเป็นอินเทอร์เฟซตามบทบาทที่เจาะจง เพื่อให้ผู้ที่นำไปใช้แต่ละรายรับรองเฉพาะสิ่งที่ตนทำจริง

<?php
interface Workable { public function work(): string; }
interface Feedable { public function eat(): string; }

final class Human implements Workable, Feedable {
    public function work(): string { return 'coding'; }
    public function eat(): string { return 'lunch'; }
}
final class Robot implements Workable {
    public function work(): string { return 'welding'; }
}

foreach ([new Human(), new Robot()] as $w) { echo $w->work(), PHP_EOL; }

การกลับทิศทางการพึ่งพา

นโยบายระดับสูงควรพึ่งพา สิ่งนามธรรม ไม่ใช่รายละเอียดที่เป็นรูปธรรม ให้ฉีดอินเทอร์เฟซแทนการระบุคลาสตายตัว วิธีนี้ทำให้คุณสลับตัวส่งอีเมลจริงเป็นตัวจำลองในการทดสอบ และใช้ผู้ให้บริการรายอื่นในระบบจริงได้โดยไม่ต้องแก้ไขผู้ใช้บริการ

<?php
interface Mailer { public function send(string $to, string $body): void; }

final class SmtpMailer implements Mailer {
    public function send(string $to, string $body): void {
        echo "SMTP -> $to: $body" . PHP_EOL;
    }
}

final class SignupService {
    public function __construct(private Mailer $mailer) {}
    public function register(string $email): void {
        $this->mailer->send($email, 'Welcome!');
    }
}

(new SignupService(new SmtpMailer()))->register('a@b.com');

DIP และตัวจัดการ

การ กลับทิศทาง การพึ่งพาคือหลักการ ส่วนการ ฉีด การพึ่งพาคือเทคนิคหนึ่งที่ใช้ปฏิบัติตามหลักการนั้น ตัวจัดการ DI (PSR-11) จะเชื่อม SmtpMailer ที่เป็นรูปธรรมเข้ากับสิ่งนามธรรม Mailer ที่จุดประกอบระบบ ผู้ใช้บริการไม่เคยเขียน new SmtpMailer() ดังนั้นทิศทางการพึ่งพาของซอร์สโค้ดจึงชี้ไปยังสิ่งนามธรรม ไม่ใช่รายละเอียด

<?php
// Composition root wiring (pseudo-container)
$bindings = [
    Mailer::class => fn() => new SmtpMailer(),
];
$resolve = fn(string $id) => $bindings[$id]();

$service = new SignupService($resolve(Mailer::class));
$service->register('user@example.com');

SOLID ร่วมกัน

หลักการเหล่านี้ช่วยเสริมกันและกัน ISP ทำให้อินเทอร์เฟซมีขนาดเล็ก เพื่อให้การฉีดตาม DIP ยังคงมุ่งเน้น OCP อาศัยพหุรูปแบบที่ LSP ช่วยให้ปลอดภัย SRP ทำให้คุณมีคลาสขนาดเล็กที่ทำให้ทุกอย่างนี้เป็นไปได้ มุ่งให้ ภายในมีความเป็นอันหนึ่งอันเดียวกัน และระหว่างส่วนต่าง ๆ เชื่อมโยงกันอย่างหลวม

  • อย่าสร้างสิ่งนามธรรมมากเกินไปสำหรับคลาสที่ใช้เพียงครั้งเดียว
  • แนะนำอินเทอร์เฟซเมื่อมีการนำไปใช้ครั้งที่สองหรือตัวจำลองสำหรับการทดสอบปรากฏขึ้น

การใช้วิจารณญาณเชิงปฏิบัติ

SOLID เป็นหนทาง ไม่ใช่จุดหมาย อินเทอร์เฟซที่สร้างขึ้นก่อนเวลาอันควรและมีการนำไปใช้เพียงแบบเดียวเพิ่มการอ้อมผ่านโดยไม่ให้ประโยชน์ (“การสร้างความทั่วไปโดยคาดเดา”) ให้ใช้หลักการเหล่านี้เมื่อการเปลี่ยนแปลงเกิดขึ้นจริงหรือเห็นได้ชัดว่ากำลังจะเกิดขึ้น การปรับโครงสร้างไปสู่ SOLID ทำได้ง่ายเมื่อมีการทดสอบแล้ว แต่การปรับโครงสร้างตามหลักการนี้อย่างไม่ไตร่ตรองตั้งแต่วันแรกเป็นการเสียเวลา

ตรวจสอบความเข้าใจ

ปัญหาการสืบทอด Square/Rectangle ละเมิดหลักการใด

ทบทวน

คุณได้นำหลักการ SOLID ทั้งห้าข้อมาใช้กับ PHP จริง:

  • SRP: แต่ละคลาสมีเหตุผลเดียวที่ต้องเปลี่ยนแปลง
  • OCP: ขยายผ่านคลาสที่ใช้พหุรูปแบบใหม่ แทนการแก้ไข switch
  • LSP: ประเภทย่อยปฏิบัติตามสัญญาของประเภทพื้นฐาน
  • ISP: ใช้อินเทอร์เฟซตามบทบาทขนาดเล็กแทนอินเทอร์เฟซขนาดใหญ่
  • DIP: พึ่งพาสิ่งนามธรรม และฉีดรายละเอียดที่จุดประกอบระบบ

ใช้หลักการเหล่านี้เป็นแนวทางในการปรับโครงสร้าง ไม่ใช่ทำตามพิธีการ

คำถามที่พบบ่อย

บทเรียน “หลักการ SOLID ในการใช้งานจริง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “หลักการ SOLID ในการใช้งานจริง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “หลักการ SOLID ในการใช้งานจริง”

ประยุกต์ใช้หลักการ SOLID ทั้งห้าข้อกับคลาส PHP จริง คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “หลักการ SOLID ในการใช้งานจริง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม

ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. หลักการ SOLID ในการใช้งานจริง
  2. รูปแบบการสร้าง: Factory, Builder, Singleton
  3. รูปแบบโครงสร้าง: Adapter, Decorator, Facade
  4. รูปแบบพฤติกรรม: Strategy, Observer, Command
← กลับไปที่ PHP Academy