Email Doanh NghiệpSSLFirewall Anti DDoSTối ưu tốc độ website

NỘI DUNG

Banner blog lễ 30.4 và 1.5

SOLID là gì? Tổng quan về nguyên lý SOLID

Cao Lê Viết Tiến

Đã kiểm duyệt nội dung

Ngày đăng:09/06/2025
Cập nhật cuối:13/06/2025
Lượt xem

Đánh giá

5/5 - (133 bình chọn)

SOLID là tập hợp 5 nguyên lý thiết kế hướng đối tượng giúp xây dựng phần mềm dễ bảo trì, mở rộng và ít lỗi. Việc áp dụng đúng SOLID giúp lập trình viên viết code rõ ràng, dễ hiểu và giảm thiểu phụ thuộc giữa các module. Trong bài viết này, mình sẽ cùng bạn tìm hiểu chi tiết từng nguyên lý trong SOLID, từ đó áp dụng hiệu quả vào thực tiễn lập trình.

Những điểm chính

  • Khái niệm: Hiểu được SOLID là gì, vai trò của nguyên lý này trong lập trình hướng đối tượng (OOP) và lý do nên áp dụng.
  • Tổng quan: Nắm bắt được cấu trúc của bộ nguyên tắc SOLID cùng mối liên hệ giữa các nguyên lý trong việc thiết kế phần mềm.
  • Lợi ích: Thấy rõ những lợi ích mà SOLID mang lại như tăng khả năng mở rộng, dễ bảo trì và nâng cao chất lượng mã nguồn.
  • Nguyên lý SOLID và cách áp dụng: Hiểu rõ từng nguyên lý trong bộ SOLID và cách triển khai thực tế để viết mã sạch, dễ hiểu và dễ mở rộng.
  • Mở rộng kiến thức: Biết thêm các khái niệm liên quan như OOP và Design Pattern để vận dụng SOLID hiệu quả hơn trong phát triển phần mềm.
  • Vietnix – Nhà cung cấp dịch vụ lưu trữ uy tín, chất lượng: Tìm hiểu đơn vị hỗ trợ hạ tầng mạnh mẽ, đáng tin cậy cho các dự án phần mềm chuyên nghiệp.
  • Câu hỏi thường gặp: Giải đáp những thắc mắc phổ biến liên quan đến nguyên lý SOLID và cách áp dụng trong thực tế.

SOLID là gì?

SOLID là viết tắt của 5 nguyên tắc thiết kế hướng đối tượng do Robert C. Martin và Michael Feathers đề xuất. Nhờ áp dụng SOLID, lập trình viên có thể viết ra những đoạn code dễ đọc, dễ hiểu và dễ bảo trì.

5 nguyên tắc trong SOLID bao gồm:

  • Single Responsibility Principle (SRP)  – Nguyên tắc trách nhiệm đơn lẻ.
  • Open/Closed Principle (OCP) – Nguyên tắc mở/đóng.
  • Liskov Substitution Principle (LSP) – Nguyên tắc thay thế Liskov.
  • Interface Segregation Principle (ISP) – Nguyên tắc phân tách giao diện.
  • Dependency Inversion Principle (DIP) –  Nguyên tắc đảo ngược phụ thuộc.
Solid là viết tắt của 5 nguyên tắc thiết kế hướng đối tượng
Solid là viết tắt của 5 nguyên tắc thiết kế hướng đối tượng

Việc áp dụng nguyên lý SOLID giúp hệ thống phần mềm trở nên linh hoạt, dễ mở rộng và dễ bảo trì hơn – điều này đặc biệt quan trọng khi triển khai các ứng dụng web hoặc dịch vụ online. Tuy nhiên, để khai thác tối đa lợi ích từ kiến trúc tốt, một nền tảng lưu trữ ổn định cũng đóng vai trò không thể thiếu. Đây là lúc các giải pháp VPS – đặc biệt là VPS Linux – phát huy thế mạnh. Tại Vietnix, dịch vụ VPS được xây dựng trên nền tảng SSD 100%, cho hiệu suất truy xuất vượt trội, đáp ứng tốt nhu cầu vận hành ứng dụng phức tạp. Với khả năng tùy chỉnh linh hoạt và bảo mật cao, VPS của Vietnix phù hợp cho cả nhà phát triển lẫn doanh nghiệp đang theo đuổi các chuẩn mực thiết kế phần mềm như SOLID.

Hạ tầng máy chủ an toàn tuyệt đối

Khám phá vps tốc độ cao, bảo mật tốt tại vietnix!

Vietnix mang đến giải pháp VPS chuyên nghiệp, giúp bạn vận hành hệ thống ổn định, bảo mật và dễ dàng mở rộng.

Chọn ngay VPS

Tổng quan về SOLID

Lập trình hướng đối tượng (Object Oriented Programming – OOP) là một trong những phương pháp lập trình phổ biến nhất hiện nay. Nhờ những đặc điểm nổi bật như tính trừu tượng, đóng gói, kế thừa và đa hình, OOP giúp lập trình viên giải quyết các vấn đề thực tế một cách hiệu quả:

  • Tính trừu tượng (Abstraction): Cho phép tạo ra các lớp mô phỏng các đối tượng thực tế trong thế giới thật.
  • Tính đóng gói (Encapsulation):  Bảo vệ dữ liệu bên trong lớp và chỉ cung cấp các phương thức truy cập an toàn.
  • Tính kế thừa (Inheritance): Tái sử dụng code hiệu quả bằng cách cho phép các lớp kế thừa tính năng từ các lớp cha.
  • Tính đa hình (Polymorphism): Cho phép thực hiện một hành động theo nhiều cách khác nhau tùy thuộc vào loại đối tượng cụ thể.
Tổng quan về SOLID
Tổng quan về SOLID

Tuy nhiên, việc kết hợp hiệu quả các tính chất này không phải điều dễ dàng. Nguyên tắc SOLID ra đời nhằm giải quyết vấn đề này, giúp các lập trình viên viết mã OOP một cách hiệu quả hơn.

Lợi ích của SOLID

Khi áp dụng SOLID vào viết code, lập trình viên sẽ nhận được nhiều lợi ích như:

  • Giảm thiểu sự phức tạp: SOLID giúp chia nhỏ phần mềm thành các thành phần độc lập, mỗi thành phần đảm nhiệm một chức năng riêng biệt. Nhờ vậy, code trở nên dễ đọc, dễ hiểu và dễ dàng sửa đổi hơn.
  • Dễ dàng bảo trì và mở rộng: Khi cần thay đổi, bạn chỉ cần tác động vào một phần nhỏ thay vì ảnh hưởng đến toàn bộ hệ thống. Nhờ vậy, việc bảo trì và mở rộng phần mềm trở nên đơn giản và hiệu quả hơn, đặc biệt là đối với các dự án lớn.
  • Tăng tính linh hoạt và khả năng tái sử dụng: Các thành phần được thiết kế linh hoạt, có thể dễ dàng áp dụng vào các dự án khác nhau, nhờ đó tiết kiệm thời gian và chi phí cho việc phát triển phần mềm.

Dù bạn đang muốn tìm hiểu SOLID trong Java hay SOLID trong C# thì đều cần nắm vững 5 nguyên lý chính sau:

1. Single responsibility principle

Nguyên tắc cốt lõi: Mỗi lớp chỉ nên đảm nhận một nhiệm vụ cụ thể. Single responsibility là nguyên tắc đầu tiên, ứng với chữ “S” trong bộ nguyên tắc SOLID, nhấn mạnh rằng mỗi lớp chỉ nên đảm nhận một trách nhiệm duy nhất. Việc gán quá nhiều nhiệm vụ cho một lớp sẽ khiến lớp này trở nên phức tạp, khó hiểu và khó bảo trì. Trong ngành IT, yêu cầu thay đổi và bổ sung chức năng là điều thường xuyên xảy ra nên việc sở hữu code rõ ràng, dễ hiểu là vô cùng quan trọng.

Nguyên tắc này nói rằng mỗi lớp chỉ nên đảm nhận một trách nhiệm duy nhất
Nguyên tắc này nói rằng mỗi lớp chỉ nên đảm nhận một trách nhiệm duy nhất

Bạn hãy tưởng tượng một công ty phần mềm có 3 vị trí công việc: : Lập trình viên (developer), kiểm thử phần mềm (tester) và nhân viên bán hàng (salesman). Mỗi nhân viên sẽ có một chức vụ và thực hiện công việc tương ứng. Vậy bạn có nên thiết kế lớp “Employee” với thuộc tính “position” và 3 phương thức developSoftware(), testSoftware() và saleSoftware() không?

Câu trả lời là KHÔNG.

Bạn hãy hình dung nếu có thêm vị trí quản lý nhân sự, bạn sẽ phải sửa đổi lớp “Employee” và thêm phương thức mới. Vậy nếu có thêm 10 vị trí khác thì sao? Khi đó, các đối tượng được tạo ra sẽ có rất nhiều phương thức dư thừa. Ví dụ, developer không cần sử dụng hàm testSoftware() và saleSoftware() và việc sử dụng sai phương thức có thể dẫn đến hậu quả nghiêm trọng.

Áp dụng nguyên tắc Single Responsibility: Hãy tạo một lớp trừu tượng “Employee” với phương thức working(). Sau đó, kế thừa từ lớp này để tạo ra 3 lớp cụ thể: Developer, Tester và Salesman. Mỗi lớp sẽ triển khai phương thức working() riêng theo chức năng của từng vị trí. Nhờ vậy, việc nhầm lẫn phương thức sẽ không còn xảy ra.

2. Open/Closed principle

Nguyên tắc cốt lõi: Không sửa đổi lớp có sẵn, thay vào đó hãy mở rộng bằng kế thừa. Open/Closed là nguyên tắc thứ hai trong SOLID, tương ứng với chữ “O” nhấn mạnh rằng khi cần bổ sung chức năng cho chương trình, ta nên tạo lớp mới kế thừa (hoặc sử dụng) lớp cũ thay vì chỉnh sửa trực tiếp lớp hiện tại. Điều này khiến chương trình có nhiều lớp hơn, nhưng bù lại ta không cần kiểm thử lại các lớp cũ mà chỉ tập trung vào các lớp mới.

Đây là nguyên tắc khi cần bố sung chức năng nên tạo một lớp mới để kế thừa
Đây là nguyên tắc khi cần bổ sung chức năng nên tạo một lớp mới để kế thừa

Tuy nhiên, việc mở rộng chức năng thường đi kèm với việc viết thêm code. Để thiết kế module dễ dàng mở rộng mà không cần sửa đổi code nhiều, ta cần tách biệt phần dễ thay đổi khỏi phần khó thay đổi, đảm bảo không ảnh hưởng đến những phần còn lại.

Giả sử, bạn có một lớp ConnectionManager dùng để quản lý kết nối đến cơ sở dữ liệu (CSDL). Ban đầu, lớp này chỉ hỗ trợ kết nối với SQL ServerMySQL.

class ConnectionManager 
{
  public function connect(Connection $connection) 
{
    if ($connection instanceof SqlServer) {
      // Kết nối với SQL Server
    } else if ($connection instanceof MySql) {
      // Kết nối với MySQL
    }
  }
}

Sau đó, yêu cầu được đặt ra là cần hỗ trợ thêm kết nối với Oracle và các CSDL khác. Để đáp ứng yêu cầu này, chúng ta có thể sửa đổi mã nguồn của lớp ConnectionManager bằng cách thêm các khối else-if cho các hệ quản trị CSDL mới. Tuy nhiên, cách này làm cho mã nguồn trở nên cồng kềnh và khó quản lý.

Áp dụng nguyên tắc Open/Closed – Áp dụng nguyên tắc OCP, bạn có thể thiết kế lại như sau:

  • Định nghĩa một lớp cơ sở Connection để mô tả các phương thức chung cho tất cả các lớp kết nối.
  • Áp dụng Abstract để tạo các lớp SqlServer, MySql, Oracle,… kế thừa từ lớp cơ sở Connection và triển khai phương thức doConnect cho từng lớp.
  • Lớp ConnectionManager chỉ cần sử dụng phương thức doConnect() của đối tượng Connection để kết nối đến cơ sở dữ liệu.

Thiết kế sau khi sửa đổi:

abstract class Connection 
{
    public abstract void doConnect();
}
class SqlServer extends Connection 
{
    public void doConnect() 
   {
          //connect with SqlServer
    }
}
class MySql extends Connection 
{
    public void doConnect() 
   {
        //connect with MySql
    }
}
class Oracle extends Connection 
{
  public function doConnection(Connection $connection)
 {
    //something
    //.................
    //connection
    $connection->doConnect();
  }
}
}

Với thiết kế này, lớp ConnectionManager không cần sửa đổi khi thêm các loại CSDL mới. Bạn chỉ cần tạo lớp mới kế thừa từ Connection và thực thi phương thức doConnect tương ứng cho loại CSDL đó.

3. Liskov substitution principle

Nguyên tắc cốt lõi: Đối tượng (instance) của lớp con có thể thay thế cho đối tượng của lớp cha mà không gây lỗi. Liskov substitution là nguyên tắc thứ 3 trong bộ nguyên tắc SOLID, tương ứng với chữ “L”. Nguyên tắc này quy định rằng các lớp con phải kế thừa và duy trì hành vi cơ bản của lớp cha. Nếu vi phạm nguyên tắc này, chương trình có thể gặp lỗi khi sử dụng các đối tượng của lớp con thay thế cho các đối tượng của lớp cha.

Nguyên tắc này quy định lớp con phải kế thừa duy trì hành vi của lớp cha
Nguyên tắc này quy định lớp con phải kế thừa duy trì hành vi của lớp cha

Tiếp nối ví dụ lớp Employee ở nguyên tắc 1, giả sử công ty đó tiến hành chấm công nhân viên chính thức vào mỗi buổi sáng. Lúc này, bạn sẽ bổ sung thêm phương thức  checkAttendance() cho lớp Employee. Tuy nhiên, công ty cũng thuê thêm nhân viên lao công làm vệ sinh văn phòng. Những nhân viên này không phải là nhân viên chính thức nên không được cấp ID cũng như  không được chấm công.

Lúc này bạn có thể tạo ra lớp CleanerStaff kế thừa từ Employee và thực thi hàm working() cho lớp này. Tuy nhiên, lớp CleanerStaff cũng sẽ kế thừa phương thức checkAttendance() để điểm danh, vi phạm quy định và gây lỗi chương trình. Do đó, thiết kế lớp CleanerStaff kế thừa từ Employee là không hợp lý.

Áp dụng nguyên tắc Liskov substitution – Có thể giải quyết vấn đề này bằng cách tách hàm checkAttendance() ra một giao diện riêng và chỉ dành cho các lớp Developer, Tester và Salesman. Lớp CleanerStaff sẽ không thực thi được giao diện trên nên sẽ không thể sử dụng hàm checkAttendance() để điểm danh. 

4. Interface segregation principle

Nguyên tắc cốt lõi: Thay vì sử dụng một giao diện (interface) lớn, hãy tách thành nhiều giao diện nhỏ hơn với các mục đích cụ thể. Interface segregation là nguyên tắc thứ 4 trong bộ nguyên tắc SOLID, tương ứng với chữ “I”. Bạn hãy tưởng tượng đang đối mặt với một interface khổng lồ có khoảng 100 methods. Lúc này, việc implements interface rất khó khăn bởi vì các lớp buộc phải thực thi tất cả các method trong interface. Điều này dẫn đến tình trạng dư thừa khi một lớp không cần sử dụng hết 100 methods đó.

Đây là nguyên tắc giúp bạn thiết kế hệ thống linh hoạt, dễ bảo trì và mở rộng hơn
Đây là nguyên tắc giúp bạn thiết kế hệ thống linh hoạt, dễ bảo trì và mở rộng hơn

Giải pháp chính là chia nhỏ interface lớn này thành các interface con, mỗi interface chỉ chứa methods liên quan chặt chẽ với nhau. Nhờ vậy, việc implements và quản lý trở nên dễ dàng, hiệu quả hơn. Đoạn code sau thể hiện giao diện Animal với các phương thức eat(), run(), và fly():

interface Animal {

    void eat();

    void run();

    void fly();

}

Tuy nhiên, việc sử dụng giao diện chung cho cả mèo (cat) và nhện (spider) là không hợp lý vì mèo không thể bay (fly) và nhện không thể chạy (run).

Áp dụng nguyên tắc Interface segregation – Để giải quyết vấn đề này, ta nên chia tách giao diện Animal thành 3 giao diện riêng biệt cho từng phương thức

interface Animal {
    void eat();
}
interface RunnableAnimal extends Animal {
    void run();
}
interface FlyableAnimal extends Animal {
    void fly();
}

5. Dependency inversion principle

Nguyên tắc cốt lõi:

  • Các module cấp cao không nên phụ thuộc vào các module cấp thấp. Cả hai nên phụ thuộc vào abstractions (sự trừu tượng).
  • Abstractions không nên phụ thuộc vào chi tiết (implementation) mà chi tiết nên phụ thuộc vào abstractions.

Dependency inversion có thể được hiểu như sau: Các thành phần trong một chương trình chỉ nên phụ thuộc vào các khái niệm trừu tượng (abstractions). Các khái niệm trừu tượng này không nên phụ thuộc vào những chi tiết cụ thể mà ngược lại, chính những chi tiết cụ thể nên phụ thuộc vào chúng.

Các khái niệm trừu tượng là những yếu tố ổn định, ít biến đổi, chúng bao gồm những đặc tính chung nhất của các yếu tố cụ thể. Dù các yếu tố cụ thể có thể rất khác nhau nhưng chúng vẫn tuân theo những nguyên tắc chung mà khái niệm trừu tượng đã định nghĩa. Sự phụ thuộc vào khái niệm trừu tượng giúp cho chương trình trở nên linh hoạt và thích ứng tốt hơn với các thay đổi liên tục.

Dependency inversion principle
Dependency inversion principle

Đối với ổ cứng máy tính, bạn có thể sử dụng ổ cứng thể rắn SSD mới nhất để tăng tốc độ truy cập dữ liệu, nhưng ổ đĩa quay HDD cũng hoàn toàn phù hợp. Nhà sản xuất mainboard không thể biết bạn sẽ chọn loại ổ nào, nhưng họ luôn đảm bảo mainboard tương thích với cả hai chuẩn giao tiếp SATA để bạn gắn vào bo mạch chủ dễ dàng. Trong trường hợp này, chuẩn giao tiếp SATA đóng vai trò là interface (giao diện), còn SSD và HDD là những implementation (trình triển khai) cụ thể.

Áp dụng nguyên tắc Dependency inversion – Tương tự, khi áp dụng nguyên lý này trong lập trình, bạn thường sử dụng interface thay vì kiểu kế thừa cụ thể ở các lớp trừu tượng cấp cao. Chẳng hạn, để kết nối với cơ sở dữ liệu, bạn thường thiết kế lớp trừu tượng DataAccess bao gồm các phương thức chung như save(), get(),… Sau đó, tùy theo loại DBMS nào được sử dụng (ví dụ như MySQL, MongoDB,…), bạn sẽ kế thừa và triển khai phương thức cụ thể. Nguyên lý này tận dụng tối đa tính đa hình của lập trình hướng đối tượng (OOP).

Vietnix – Nhà cung cấp dịch vụ lưu trữ chất lượng cao

Vietnix là đơn vị cung cấp dịch vụ lưu trữ chất lượng cao, nổi bật với hạ tầng sử dụng 100% ổ cứng SSD, giúp tối ưu tốc độ truy cập và đảm bảo độ ổn định cho hệ thống. Dịch vụ tại Vietnix hỗ trợ tùy biến cấu hình linh hoạt, phù hợp nhiều nhu cầu khác nhau như chạy website, ứng dụng, máy chủ email hoặc môi trường phát triển. Giao diện quản trị trực quan giúp người dùng dễ dàng theo dõi và điều chỉnh tài nguyên theo thời gian thực. Nếu bạn đang tìm kiếm một giải pháp VPS hoặc hosting hiệu suất cao với mức giá hợp lý, Vietnix là lựa chọn đáng cân nhắc.

Thông tin liên hệ:

  • Hotline: 18001093
  • Email: sales@vietnix.com.vn
  • Địa chỉ: 265 Hồng Lạc, Phường 10, Quận Tân Bình, Thành Phố Hồ Chí Minh
  • Website: https://vietnix.vn/

Câu hỏi thường gặp

Áp dụng nguyên lý SOLID trong team nhỏ có quá “nặng” không?

Không hẳn. Với team nhỏ, việc áp dụng SOLID có thể tạo cảm giác nặng nề nếu áp dụng máy móc hoặc quá phức tạp hóa cấu trúc code. Tuy nhiên, nếu hiểu đúng bản chất và áp dụng một cách linh hoạt, SOLID lại giúp team dễ đọc, dễ bảo trì và tránh phụ thuộc lẫn nhau trong mã nguồn—một vấn đề dễ xảy ra khi không có quy tắc rõ ràng.

Việc tuân thủ SOLID có ảnh hưởng đến hiệu suất runtime không?

Có, nhưng ảnh hưởng thường không đáng kể nếu áp dụng hợp lý. SOLID có thể làm tăng số lượng lớp, interface và dùng Dependency Injection, dẫn đến thêm một chút chi phí xử lý. Tuy nhiên, lợi ích về khả năng bảo trì, mở rộng và giảm lỗi thường vượt trội so với tác động nhỏ về hiệu suất. Tránh over engineering là chìa khóa để cân bằng giữa hiệu năng và kiến trúc tốt.

Lời kết

Trên đây là những thông tin mà mình muốn chia sẻ tới bạn về khái niệm SOLID là gì cũng như cách sử dụng từng nguyên tắc cụ thể trong bộ nguyên tắc này. Việc học hỏi và áp dụng các nguyên tắc SOLID có thể tốn nhiều thời gian, nhưng lợi ích mà chúng mang lại là không hề nhỏ. Nếu bạn là một nhà phát triển phần mềm, hãy dành thời gian để tìm hiểu về SOLID và bắt đầu áp dụng các nguyên tắc này vào các dự án ngay từ hôm nay.

THEO DÕI VÀ CẬP NHẬT CHỦ ĐỀ BẠN QUAN TÂM

Đăng ký ngay để nhận những thông tin mới nhất từ blog của chúng tôi. Đừng bỏ lỡ cơ hội truy cập kiến thức và tin tức hàng ngày

Đánh giá mức độ hữu ích của bài viết

icon 1 sao

Thất vọng

icon 2 sao

Chưa hữu ích

icon 3 sao

Bình thường

icon 4 sao

Hữu ích

icon 5 sao

Rất hữu ích

Kết nối với mình qua

Kết nối với mình qua

Tăng tốc độ website - Nâng tầm giá trị thương hiệu

Banner group
Tăng tốc tải trang

95 điểm

Nâng cao trải nghiệm người dùng

Tăng 8% tỷ lệ chuyển đổi

Thúc đẩy SEO, Google Ads hiệu quả

Tăng tốc ngay

SẢN PHẨM NỔI BẬT

Icon tab

MAXSPEED HOSTING

TĂNG TỐC WEBSITE TOÀN DIỆN

CÔNG NGHỆ ĐỘC QUYỀN

Vector

PHẦN CỨNG MẠNH MẼ

Vector

HỖ TRỢ 24/7

Vector
ĐĂNG KÝ NGAYGroup icon
khuyến mãi sinh nhật
Nhanh tay, số lượng có hạn!
17/05/2025 - 22/06/2025
Pattern

7 NGÀY DÙNG THỬ HOSTING

NẮM BẮT CƠ HỘI, THÀNH CÔNG DẪN LỐI

Cùng trải nghiệm dịch vụ hosting tốc độ cao được hơn 100,000 khách hàng sử dụng

icon popup single post

CẢM ƠN BẠN ĐÃ ĐÁNH GIÁ BÀI VIẾT

Vietnix sẽ luôn cố gắng cải thiện chất lượng dịch vụ mỗi ngày

ĐÓNG

Đánh giá mức độ hữu ích của bài viết

icon 1 sao

Thất vọng

icon 2 sao

Chưa hữu ích

icon 3 sao

Bình thường

icon 4 sao

Hữu ích

icon 5 sao

Rất hữu ích

Icon
ĐĂNG KÝ NHẬN TÀI LIỆU THÀNH CÔNG
Cảm ơn bạn đã đăng ký nhận tài liệu mới nhất từ Vietnix!
ĐÓNG

ĐĂNG KÝ DÙNG THỬ HOSTING

Asset

7 NGÀY MIỄN PHÍ

Asset 1

ĐĂNG KÝ DÙNG THỬ HOSTING

Asset

7 NGÀY MIỄN PHÍ

Asset 1
Icon
XÁC NHẬN ĐĂNG KÝ DÙNG THỬ THÀNH CÔNG
Cảm ơn bạn đã đăng ký thông tin thành công. Đội ngũ CSKH sẽ liên hệ trực tiếp để kích hoạt dịch vụ cho bạn nhanh nhất!
ĐÓNG