<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cong Quy Nguyen</title>
    <description>The latest articles on DEV Community by Cong Quy Nguyen (@congquynguyen296).</description>
    <link>https://dev.to/congquynguyen296</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2628741%2Fb354ae92-301f-4e64-9680-2dfdd493acea.jpg</url>
      <title>DEV Community: Cong Quy Nguyen</title>
      <link>https://dev.to/congquynguyen296</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/congquynguyen296"/>
    <language>en</language>
    <item>
      <title>Sequence diagram - Drawing process</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sat, 22 Feb 2025 09:50:55 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/sequence-diagram-drawing-process-1aj4</link>
      <guid>https://dev.to/congquynguyen296/sequence-diagram-drawing-process-1aj4</guid>
      <description>&lt;h1&gt;
  
  
  Tìm Hiểu Quy Trình Vẽ Sequence Diagram
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Sequence Diagram&lt;/strong&gt; (Biểu đồ tuần tự) là một công cụ mạnh mẽ trong UML để mô hình hóa quá trình tương tác giữa các đối tượng (objects) trong hệ thống theo trình tự thời gian. Nó giúp hiểu rõ luồng thực thi, sự trao đổi thông điệp (messages), và trách nhiệm của từng thành phần. Quy trình vẽ Sequence Diagram đòi hỏi sự chính xác về logic và thứ tự, đặc biệt hữu ích trong giai đoạn thiết kế và kiểm thử hệ thống.&lt;/p&gt;

&lt;p&gt;Trong bài viết này, chúng ta sẽ khám phá chi tiết từng bước xây dựng &lt;strong&gt;Sequence Diagram&lt;/strong&gt;, từ việc xác định các thành phần cơ bản đến áp dụng các kỹ thuật nâng cao để mô tả luồng phức tạp.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Các Bước Cơ Bản Trong Quy Trình Vẽ Sequence Diagram
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Xác Định Các Đối Tượng Tham Gia (Participants)
&lt;/h3&gt;

&lt;p&gt;Bước đầu tiên là xác định các &lt;strong&gt;đối tượng&lt;/strong&gt; (objects) hoặc &lt;strong&gt;thành phần hệ thống&lt;/strong&gt; tham gia vào quá trình tương tác. Mỗi đối tượng đại diện cho một thực thể trong hệ thống, chẳng hạn như lớp (class), actor, hoặc hệ thống con.&lt;/p&gt;

&lt;h4&gt;
  
  
  Các bước thực hiện:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Liệt kê tất cả các đối tượng&lt;/strong&gt; liên quan đến use case cụ thể.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sắp xếp đối tượng theo vai trò&lt;/strong&gt;: Đặt actor (người dùng hoặc hệ thống bên ngoài) ở phía trái, các đối tượng nghiệp vụ ở giữa và phải.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ví dụ minh họa:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Actor&lt;/strong&gt;: Khách hàng.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Đối tượng&lt;/strong&gt;: &lt;code&gt;LoginPage&lt;/code&gt;, &lt;code&gt;AuthenticatioController&lt;/code&gt;, &lt;code&gt;AuthenticationService&lt;/code&gt;, &lt;code&gt;AuthenticationRepository&lt;/code&gt;, &lt;code&gt;Database&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ký hiệu:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Đối tượng được biểu diễn bằng &lt;strong&gt;hình chữ nhật&lt;/strong&gt; với tên đối tượng và lớp (ví dụ: &lt;code&gt;user: Customer&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifeline&lt;/strong&gt; (đường đời): Đường đứt nét dọc dưới mỗi đối tượng, thể hiện vòng đời của đối tượng trong quá trình tương tác.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  1.2 Xác Định Thông Điệp (Messages) và Thứ Tự Thực Thi
&lt;/h3&gt;

&lt;p&gt;Thông điệp là các hành động hoặc lời gọi phương thức giữa các đối tượng. Thứ tự của chúng được sắp xếp từ trên xuống dưới theo dòng thời gian.&lt;/p&gt;

&lt;h4&gt;
  
  
  Các loại thông điệp phổ biến:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Synchronous Message&lt;/strong&gt; (Thông điệp đồng bộ): 

&lt;ul&gt;
&lt;li&gt;Được biểu diễn bằng &lt;strong&gt;mũi tên liền nét&lt;/strong&gt; kèm đầu mũi tên đặc.&lt;/li&gt;
&lt;li&gt;Ví dụ: Gọi phương thức &lt;code&gt;login()&lt;/code&gt; từ &lt;code&gt;LoginPage&lt;/code&gt; đến &lt;code&gt;AuthenticationController&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Message&lt;/strong&gt; (Thông điệp bất đồng bộ):

&lt;ul&gt;
&lt;li&gt;Biểu diễn bằng &lt;strong&gt;mũi tên liền nét&lt;/strong&gt; với đầu mũi tên rỗng.&lt;/li&gt;
&lt;li&gt;Ví dụ: Gửi sự kiện &lt;code&gt;onPaymentComplete&lt;/code&gt; từ hệ thống thanh toán đến &lt;code&gt;OrderService&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return Message&lt;/strong&gt; (Phản hồi):

&lt;ul&gt;
&lt;li&gt;Biểu diễn bằng &lt;strong&gt;mũi tên đứt nét&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Ví dụ: &lt;code&gt;AuthenticationService&lt;/code&gt; trả về kết quả &lt;code&gt;success: boolean&lt;/code&gt; cho &lt;code&gt;AuthenticationController&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Các bước thực hiện:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Liệt kê các thông điệp theo trình tự logic từ khi bắt đầu đến khi kết thúc quy trình.&lt;/li&gt;
&lt;li&gt;Đảm bảo mỗi thông điệp được gán đúng đối tượng gửi và nhận.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ví dụ minh họa:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Khách hàng&lt;/code&gt; → &lt;code&gt;LoginPage&lt;/code&gt;: Nhập thông tin đăng nhập.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoginPage&lt;/code&gt; → &lt;code&gt;AuthenticationController&lt;/code&gt;: Kiểm tra và điều hướng thông tin đến &lt;code&gt;AuthenticationService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AuthenticationService&lt;/code&gt; → &lt;code&gt;AuthenticationRepository&lt;/code&gt;: Thực hiện logic nghiệp vụ của chức năng &lt;strong&gt;login&lt;/strong&gt;, sau đó tiến hành lưu các thông tin cần thiết thông qua việc gọi &lt;code&gt;AuthenticationRepository&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AuthenticationRepository&lt;/code&gt; → &lt;code&gt;Database&lt;/code&gt;: Truy vấn dữ liệu và lưu thông tin cần thiết.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  1.3 Thêm Activation Bars (Thanh Kích Hoạt)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Activation Bar&lt;/strong&gt; (thanh kích hoạt) thể hiện khoảng thời gian một đối tượng đang xử lý một tác vụ. Nó giúp làm rõ thời điểm phương thức được thực thi.&lt;/p&gt;

&lt;h4&gt;
  
  
  Các bước thực hiện:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Vẽ &lt;strong&gt;hình chữ nhật hẹp&lt;/strong&gt; dọc theo lifeline của đối tượng khi nó đang xử lý thông điệp.&lt;/li&gt;
&lt;li&gt;Kéo dài thanh kích hoạt cho đến khi phương thức hoàn tất.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ví dụ:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Khi &lt;code&gt;AuthenticationService&lt;/code&gt; xử lý &lt;code&gt;authenticate()&lt;/code&gt;, một activation bar xuất hiện trên lifeline của nó.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Xử Lý Các Tình Huống Phức Tạp Với Combined Fragments
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Combined Fragments&lt;/strong&gt; là các khối logic giúp mô tả các luồng điều kiện, vòng lặp, hoặc luồng song song. Chúng được biểu diễn bằng hình chữ nhật với nhãn và điều kiện.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Fragment Điều Kiện (Alt/Opt)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alt (Alternative)&lt;/strong&gt;: Dùng để mô tả các trường hợp "if-else".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;alt [Điều kiện 1]&lt;/code&gt; =&amp;gt; Thông điệp 1&lt;/p&gt;

&lt;p&gt;&lt;code&gt;else [Điều kiện 2]&lt;/code&gt; =&amp;gt; Thông điệp 2&lt;/p&gt;

&lt;p&gt;&lt;code&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opt (Optional)&lt;/strong&gt;: Mô tả trường hợp "if" không có else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;opt [Điều kiện]&lt;/code&gt; =&amp;gt; Thông điệp&lt;/p&gt;

&lt;p&gt;&lt;code&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Ví dụ:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alt&lt;/strong&gt;: Nếu xác thực thành công, hiển thị trang chủ; ngược lại, hiển thị thông báo lỗi.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2.2 Fragment Lặp (Loop)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Loop&lt;/strong&gt; thể hiện một nhóm thông điệp được lặp lại nhiều lần dựa trên điều kiện.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;loop [5 lần]&lt;/code&gt; =&amp;gt; Thông điệp&lt;/p&gt;

&lt;p&gt;&lt;code&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Ví dụ:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Lặp lại việc gửi OTP tối đa 3 lần nếu không nhận được phản hồi.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Kiểm Tra và Tối Ưu Sequence Diagram
&lt;/h2&gt;

&lt;p&gt;Sau khi hoàn thành, cần kiểm tra kỹ lưỡng để đảm bảo tính chính xác:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kiểm tra tính logic&lt;/strong&gt;: Thứ tự thông điệp phải đúng với nghiệp vụ thực tế.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kiểm tra phạm vi&lt;/strong&gt;: Tránh thêm quá nhiều đối tượng làm biểu đồ phức tạp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tối ưu hóa&lt;/strong&gt;: Nhóm các thông điệp liên quan vào combined fragments.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tóm Tắt Quy Trình Vẽ Sequence Diagram
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Các bước thực hiện:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bước 1:&lt;/strong&gt; Xác định chức năng cần thiết kế. Bạn dựa vào Use Case Diagram để xác định xem chức năng nào cần thiết kế.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bước 2:&lt;/strong&gt; Xác định các bước thực hiện theo nghiệp vụ.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bước 3:&lt;/strong&gt; Đối chiếu với Class Diagram để xác định lớp trong hệ thống tham gia vào nghiệp vụ.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bước 4:&lt;/strong&gt; Vẽ Sequence Diagarm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bước 5:&lt;/strong&gt; Cập nhật lại bản vẽ Class Diagram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sequence Diagram không chỉ giúp thiết kế hệ thống mà còn là công cụ đắc lực trong việc debug và giao tiếp giữa các bên liên quan. Bằng cách tuân thủ quy trình này, bạn có thể tạo ra các biểu đồ mô tả rõ ràng và hiệu quả luồng nghiệp vụ của hệ thống.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>community</category>
      <category>software</category>
    </item>
    <item>
      <title>Agile project managerment</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sat, 22 Feb 2025 09:48:31 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/agile-project-managerment-moi</link>
      <guid>https://dev.to/congquynguyen296/agile-project-managerment-moi</guid>
      <description>&lt;h1&gt;
  
  
  Phương pháp Scrum trong phát triển phần mềm: Lý thuyết và ứng dụng thực tế
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Giới thiệu về Scrum và sự cần thiết trong quản lý dự án phần mềm
&lt;/h2&gt;

&lt;p&gt;Trong bất kỳ doanh nghiệp phần mềm nào, các nhà quản lý luôn cần theo dõi tiến độ và đánh giá khả năng hoàn thành dự án đúng thời hạn với ngân sách đề ra. Để đáp ứng yêu cầu này, các phương pháp phát triển phần mềm theo kế hoạch (Plan-driven approaches) đã ra đời. Tuy nhiên, khi Agile xuất hiện, nó đã đưa ra một cách tiếp cận linh hoạt hơn, trong đó Scrum nổi lên như một phương pháp phổ biến nhất để tổ chức và quản lý các dự án phát triển phần mềm.&lt;/p&gt;

&lt;p&gt;Scrum không chỉ giúp tổ chức công việc trong các nhóm phát triển mà còn giúp tăng cường khả năng thích ứng với thay đổi và đảm bảo tính minh bạch trong dự án. Nhờ vậy, Scrum đã trở thành một phương pháp quản lý quan trọng trong các công ty phần mềm, đặc biệt là trong những môi trường có yêu cầu thay đổi liên tục.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Tổng quan về phương pháp Scrum
&lt;/h2&gt;

&lt;p&gt;Scrum là một phương pháp phát triển phần mềm theo mô hình Agile, tập trung vào việc tổ chức công việc theo các chu kỳ phát triển ngắn gọi là Sprint (thường kéo dài từ 2 đến 4 tuần). Các thành viên trong nhóm Scrum làm việc cùng nhau để hoàn thành một phần chức năng của sản phẩm sau mỗi Sprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Các thành phần chính trong Scrum
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thuật ngữ&lt;/th&gt;
&lt;th&gt;Định nghĩa&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nhóm phát triển (Development Team)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Một nhóm tự tổ chức, gồm tối đa 7 thành viên, chịu trách nhiệm phát triển phần mềm và các tài liệu liên quan.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sản phẩm có thể giao hàng (Potentially Shippable Product Increment)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Một phần mềm hoàn chỉnh được tạo ra sau mỗi Sprint, có thể được triển khai ngay mà không cần chỉnh sửa.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Danh sách công việc tồn đọng (Product Backlog)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Danh sách các yêu cầu, tính năng hoặc nhiệm vụ mà nhóm Scrum cần thực hiện.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Chủ sở hữu sản phẩm (Product Owner)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Người chịu trách nhiệm xác định các tính năng, sắp xếp thứ tự ưu tiên và đảm bảo rằng sản phẩm đáp ứng nhu cầu kinh doanh.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ScrumMaster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Người hướng dẫn và đảm bảo Scrum được thực hiện đúng cách, đồng thời bảo vệ nhóm khỏi sự can thiệp từ bên ngoài.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sprint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Một chu kỳ phát triển phần mềm kéo dài từ 2 đến 4 tuần.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tốc độ phát triển (Velocity)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Số lượng công việc mà nhóm có thể hoàn thành trong một Sprint, giúp ước tính tiến độ của dự án.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Quy trình làm việc trong Scrum
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1. Lập kế hoạch Sprint
&lt;/h3&gt;

&lt;p&gt;Mỗi Sprint bắt đầu bằng một cuộc họp lập kế hoạch Sprint (Sprint Planning). Trong cuộc họp này:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Owner ưu tiên các mục trong Product Backlog.&lt;/li&gt;
&lt;li&gt;Nhóm phát triển lựa chọn các mục có thể hoàn thành trong Sprint.&lt;/li&gt;
&lt;li&gt;Sprint Backlog được tạo ra, chứa danh sách công việc của Sprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Một công ty phát triển ứng dụng thương mại điện tử muốn thêm tính năng "Thanh toán qua ví điện tử". Trong cuộc họp lập kế hoạch Sprint, Product Owner sẽ xác định các hạng mục công việc như:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tích hợp API của nhà cung cấp dịch vụ ví điện tử.&lt;/li&gt;
&lt;li&gt;Thiết kế giao diện người dùng cho trang thanh toán.&lt;/li&gt;
&lt;li&gt;Viết unit test để kiểm tra chức năng.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.2. Thực hiện Sprint
&lt;/h3&gt;

&lt;p&gt;Trong thời gian Sprint diễn ra, nhóm phát triển làm việc để hoàn thành các nhiệm vụ đã cam kết. Mỗi ngày, nhóm tổ chức cuộc họp Scrum ngắn (Daily Scrum) để cập nhật tiến độ.&lt;/p&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Nếu trong Sprint, nhóm phát triển gặp lỗi khi tích hợp API ví điện tử, họ sẽ báo cáo trong Daily Scrum và điều chỉnh công việc để giải quyết vấn đề kịp thời.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3. Kết thúc Sprint
&lt;/h3&gt;

&lt;p&gt;Khi Sprint kết thúc, có hai cuộc họp quan trọng:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sprint Review:&lt;/strong&gt; Trình bày sản phẩm đã hoàn thành.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint Retrospective:&lt;/strong&gt; Đánh giá lại cách làm việc và đề xuất cải tiến cho Sprint tiếp theo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Nếu sau Sprint, nhóm nhận thấy việc giao tiếp giữa các thành viên chưa hiệu quả, họ có thể đề xuất sử dụng công cụ như Slack hoặc Trello để cải thiện quy trình làm việc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dưới đây là ảnh minh họa vòng đời của một chu kỳ Scrum:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/%25C4%2591%25C6%25B0%25E1%25BB%259Dng_d%25E1%25BA%25ABn_%25C4%2591%25E1%25BA%25BFn_h%25C3%25ACnh_%25E1%25BA%25A3nh" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/%25C4%2591%25C6%25B0%25E1%25BB%259Dng_d%25E1%25BA%25ABn_%25C4%2591%25E1%25BA%25BFn_h%25C3%25ACnh_%25E1%25BA%25A3nh" alt=" The Scrum sprint cycle" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Lợi ích của Scrum và ứng dụng thực tế
&lt;/h2&gt;

&lt;p&gt;Scrum mang lại nhiều lợi ích cho doanh nghiệp và nhóm phát triển, bao gồm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tăng cường khả năng thích ứng:&lt;/strong&gt; Khi yêu cầu thay đổi, nhóm có thể điều chỉnh kế hoạch mà không làm ảnh hưởng đến toàn bộ dự án.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cải thiện giao tiếp và minh bạch:&lt;/strong&gt; Mọi thành viên đều biết rõ tiến độ công việc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tăng năng suất:&lt;/strong&gt; Nhóm tập trung vào các nhiệm vụ ưu tiên, giúp nâng cao hiệu suất làm việc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Khách hàng có thể thấy kết quả sớm:&lt;/strong&gt; Do sản phẩm được phát triển theo từng phần nhỏ, khách hàng có thể kiểm tra và phản hồi ngay.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Công ty phát triển phần mềm quản lý bệnh viện đã sử dụng Scrum để phát triển từng module (quản lý bệnh nhân, quản lý thuốc, thanh toán). Nhờ Scrum, họ có thể đưa vào sử dụng từng module một cách nhanh chóng thay vì chờ hoàn thành toàn bộ hệ thống.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Những thách thức khi áp dụng Scrum
&lt;/h2&gt;

&lt;p&gt;Mặc dù Scrum mang lại nhiều lợi ích, nó cũng có những thách thức:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Khó khăn khi áp dụng trong các nhóm lớn:&lt;/strong&gt; Khi có nhiều nhóm làm việc cùng nhau, cần có sự điều phối tốt để tránh xung đột.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phụ thuộc vào Product Owner:&lt;/strong&gt; Nếu Product Owner không quản lý Product Backlog hiệu quả, dự án có thể bị chậm tiến độ.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yêu cầu sự thay đổi văn hóa làm việc:&lt;/strong&gt; Scrum đòi hỏi nhóm làm việc chủ động và tự tổ chức, điều này có thể gây khó khăn trong môi trường truyền thống.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Một công ty phần mềm tại Việt Nam áp dụng Scrum nhưng gặp khó khăn vì nhân viên đã quen với mô hình quản lý truyền thống. Để khắc phục, công ty đã tổ chức các buổi đào tạo về Scrum và dần dần thay đổi cách làm việc.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Scrum trong môi trường phát triển phần mềm phân tán
&lt;/h2&gt;

&lt;p&gt;Ngày nay, nhiều công ty có nhóm phát triển làm việc từ nhiều quốc gia khác nhau. Để áp dụng Scrum hiệu quả trong môi trường này, có thể sử dụng:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Công cụ quản lý dự án như Jira, Trello để theo dõi tiến độ.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Họp Scrum qua video call (Zoom, Google Meet).&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chia múi giờ làm việc hợp lý để đảm bảo giao tiếp hiệu quả.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ:&lt;br&gt;
Một công ty phần mềm tại Mỹ có nhóm phát triển tại Việt Nam và Ấn Độ. Họ sử dụng Jira để quản lý công việc và tổ chức họp Scrum vào buổi tối (theo giờ Việt Nam) để cả ba nhóm có thể tham gia.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Kết luận
&lt;/h2&gt;

&lt;p&gt;Scrum là một phương pháp linh hoạt giúp nâng cao hiệu suất làm việc trong phát triển phần mềm. Khi được áp dụng đúng cách, nó giúp tổ chức công việc hiệu quả, tăng tính minh bạch và đảm bảo sản phẩm đáp ứng yêu cầu của khách hàng. Tuy nhiên, việc triển khai Scrum cũng đi kèm với những thách thức, đòi hỏi sự thích nghi từ cả đội ngũ quản lý lẫn nhân viên.&lt;/p&gt;

&lt;p&gt;Việc hiểu rõ và ứng dụng Scrum một cách linh hoạt sẽ giúp các công ty phần mềm tối ưu hóa quy trình làm việc và đạt được thành công bền vững. Do đó đây sẽ là nền tảng quan trọng để các nhóm phát triển phần mềm nâng cao hiệu suất, giảm thiểu lãng phí thời gian và tài nguyên, đồng thời tăng khả năng thích ứng với những thay đổi nhanh chóng của thị trường.&lt;/p&gt;

&lt;p&gt;Ngoài lĩnh vực phần mềm, Scrum cũng được áp dụng rộng rãi trong các ngành khác như quản lý dự án, sản xuất, giáo dục và thậm chí cả y tế. Việc hiểu sâu về phương pháp này không chỉ giúp nhóm làm việc hiệu quả hơn mà còn góp phần xây dựng văn hóa làm việc linh hoạt, tập trung vào kết quả và cải tiến liên tục.&lt;/p&gt;

&lt;p&gt;Với sự phát triển không ngừng của công nghệ và nhu cầu đổi mới sáng tạo, Scrum sẽ tiếp tục là một trong những phương pháp quản lý dự án quan trọng nhất, giúp các tổ chức cạnh tranh và phát triển bền vững trong thời đại số. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>software</category>
      <category>agile</category>
    </item>
    <item>
      <title>Quyết định kiến trúc phần mềm</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Wed, 08 Jan 2025 16:00:41 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/architectural-design-decisions-quyet-dinh-kien-truc-phan-mem-5ad4</link>
      <guid>https://dev.to/congquynguyen296/architectural-design-decisions-quyet-dinh-kien-truc-phan-mem-5ad4</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Xin chào mọi người!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hôm nay, chúng ta sẽ cùng nhau khám phá một chủ đề rất thú vị trong thiết kế phần mềm: &lt;strong&gt;Architectural Design Decisions&lt;/strong&gt;. Đây là những quyết định cực kỳ quan trọng, ảnh hưởng đến cách một hệ thống phần mềm được xây dựng, vận hành và mở rộng. Hãy cùng mình tìm hiểu và làm rõ tại sao các quyết định này lại quan trọng nhé!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Architectural Design Decisions là gì?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Khi xây dựng phần mềm, nhóm phát triển thường phải đối mặt với rất nhiều câu hỏi, chẳng hạn như:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sử dụng công nghệ nào?
&lt;/li&gt;
&lt;li&gt;Làm thế nào để xử lý hiệu quả khi có hàng triệu người dùng?
&lt;/li&gt;
&lt;li&gt;Làm sao để hệ thống dễ bảo trì, dễ nâng cấp trong tương lai?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Những câu hỏi này chính là nền tảng của &lt;strong&gt;Architectural Design Decisions&lt;/strong&gt; – các quyết định kiến trúc, giúp định hình hệ thống phần mềm từ những bước đầu tiên.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Tại sao cần phải đưa ra quyết định kiến trúc?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Nếu ví một hệ thống phần mềm như một ngôi nhà, thì các quyết định kiến trúc chính là việc chọn nền móng, thiết kế cột trụ, và xác định cách xây dựng. Một quyết định sai lầm có thể dẫn đến việc phải "đập đi xây lại", tốn kém cả về thời gian lẫn chi phí.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Một số lý do cụ thể:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Đảm bảo đáp ứng yêu cầu của dự án:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hệ thống phải đáp ứng được cả yêu cầu chức năng (functional) và phi chức năng (non-functional).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tối ưu tài nguyên:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Các quyết định kiến trúc cần cân đối giữa chi phí, hiệu năng và khả năng mở rộng.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Giảm thiểu rủi ro:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Một hệ thống được thiết kế tốt sẽ ít bị gián đoạn khi gặp sự cố.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Các yếu tố cần cân nhắc khi đưa ra quyết định kiến trúc&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Yêu cầu của hệ thống (System Requirements):&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Hiểu rõ mục tiêu và yêu cầu của dự án là bước đầu tiên. Ví dụ:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hệ thống cần xử lý bao nhiêu yêu cầu mỗi giây?
&lt;/li&gt;
&lt;li&gt;Dữ liệu có cần bảo mật cao không?
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Ràng buộc về tài nguyên (Constraints):&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ngân sách:&lt;/strong&gt; Có bao nhiêu tiền để đầu tư?
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thời gian:&lt;/strong&gt; Deadline có sát không?
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Đội ngũ:&lt;/strong&gt; Team có đủ kỹ năng và kinh nghiệm để thực hiện không?
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Xu hướng công nghệ (Technology Trends):&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Chọn công nghệ phổ biến và được hỗ trợ lâu dài sẽ giúp giảm rủi ro.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Những quyết định kiến trúc thường gặp&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monolithic vs Microservices:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c3qjhge8rvwykg7ehoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c3qjhge8rvwykg7ehoh.png" alt=" " width="800" height="469"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Monolithic Architecture&lt;/em&gt; là một kiểu kiến trúc mà mọi chức năng của hệ thống được gom lại trong một ứng dụng duy nhất. Kiến trúc này dễ triển khai và có tính đơn giản cao, vì tất cả các thành phần của hệ thống đều nằm trong cùng một mã nguồn và cấu hình. Tuy nhiên, khi hệ thống phát triển lớn mạnh, việc mở rộng và bảo trì trở nên khó khăn, vì mọi thay đổi đều có thể ảnh hưởng đến toàn bộ ứng dụng, khiến việc duy trì và nâng cấp trở nên phức tạp.&lt;/p&gt;

&lt;p&gt;Ngược lại, &lt;em&gt;Microservices Architecture&lt;/em&gt; chia hệ thống thành nhiều dịch vụ nhỏ, mỗi dịch vụ đảm nhận một nhiệm vụ cụ thể và có thể phát triển độc lập. Kiến trúc này dễ mở rộng và bảo trì, vì mỗi dịch vụ có thể được thay đổi, mở rộng mà không ảnh hưởng đến các dịch vụ khác. Tuy nhiên, việc triển khai Microservices đòi hỏi kỹ năng cao và tài nguyên tốt hơn, vì cần quản lý nhiều dịch vụ và đảm bảo chúng hoạt động phối hợp một cách hiệu quả.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQL hay NoSQL?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6596q7vvocnzs6ydi84.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6596q7vvocnzs6ydi84.jpg" alt=" " width="728" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL:&lt;/strong&gt; Dành cho dữ liệu có cấu trúc rõ ràng và quan hệ chặt chẽ (VD: MySQL, PostgreSQL).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NoSQL:&lt;/strong&gt; Dành cho dữ liệu phi cấu trúc hoặc khi cần tốc độ xử lý cao (VD: MongoDB, Redis, Neo4j).
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Tổng kết&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Các quyết định kiến trúc đóng vai trò quan trọng trong việc đảm bảo hệ thống phần mềm vận hành hiệu quả, linh hoạt và bền vững. Mỗi quyết định đều phải dựa trên sự cân nhắc kỹ lưỡng về yêu cầu dự án, tài nguyên, và xu hướng công nghệ.  &lt;/p&gt;

&lt;p&gt;Hy vọng qua bài viết này, các bạn đã hiểu rõ hơn về tầm quan trọng của &lt;strong&gt;Architectural Design Decisions&lt;/strong&gt;. Nếu có thắc mắc hay ý kiến, đừng ngần ngại để lại bình luận nhé!  &lt;/p&gt;

&lt;p&gt;Cảm ơn các bạn đã theo dõi bài viết, chúc các bạn học tập thật tốt! 😊&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>learning</category>
      <category>software</category>
    </item>
    <item>
      <title>Interface và Abstract class</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sun, 05 Jan 2025 11:17:01 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/interface-va-abstract-class-164f</link>
      <guid>https://dev.to/congquynguyen296/interface-va-abstract-class-164f</guid>
      <description>&lt;p&gt;Xin chào mọi người! Hôm nay, ở bài học hôm nay, chúng ta sẽ nói về một chủ đề rất thú vị trong lập trình hướng đối tượng. Đó là sự khác biệt giữa &lt;strong&gt;Interface&lt;/strong&gt; và &lt;strong&gt;Abstract Class&lt;/strong&gt;. Khi nào chúng ta nên dùng Interface? Khi nào thì Abstract Class mới là lựa chọn phù hợp? Và cùng tìm hiểu một vài ví dụ nhỏ minh họa của chúng! Hãy cùng mình tìm hiểu nhé!&lt;/p&gt;

&lt;p&gt;Đây là hai khái niệm khá "trừu tượng", nhưng nếu hiểu rõ thì bạn sẽ dễ dàng áp dụng vào thiết kế phần mềm. Giờ thì bắt đầu thôi!&lt;/p&gt;

&lt;p&gt;Do bài học này chủ yếu là ôn lại để củng cố kiến thức cho các bạn trước khi bước vào UML, nên mình sẽ cố gắng trình bày một cách cô đọng nhất những kiến thức chính của phần này để giúp các bạn có thể dễ nhớ và áp dụng.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Định nghĩa
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Interface
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Interface&lt;/strong&gt; trong Java giống như một "hợp đồng" mà các lớp phải thực hiện. Nó chỉ chứa các phương thức trừu tượng (abstract methods) và hằng số (constants). Khi triển khai "hợp đồng" này thì các đối tượng triển khai bắt buộc phải triển khai các method đã được quy định. Từ Java 8 trở đi, Interface đã "nâng cấp" khi có thêm phương thức mặc định (default methods) và phương thức tĩnh (static methods). Thật tiện lợi phải không nào?&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstract Class
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Abstract Class&lt;/strong&gt; thì hơi khác một chút. Nó giống như một "bản thiết kế" nhưng có thể cung cấp cả các chi tiết cụ thể (phương thức thông thường) và các phần trừu tượng (phương thức abstract). "Bản thiết kế" này quy định điểm chung về thuộc tính hay method của các đối tượng kế thừa nó, điểm đặc biệt là bạn không thể khởi tạo trực tiếp một Abstract Class.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Sự khác biệt chính
&lt;/h2&gt;

&lt;p&gt;Chúng ta cùng so sánh để thấy rõ hơn nhé:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Đặc điểm&lt;/th&gt;
&lt;th&gt;Interface&lt;/th&gt;
&lt;th&gt;Abstract Class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Từ khóa sử dụng&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;interface&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;abstract class&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kế thừa&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Một lớp có thể triển khai nhiều interface&lt;/td&gt;
&lt;td&gt;Một lớp chỉ có thể kế thừa một abstract class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phương thức&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chỉ chứa phương thức trừu tượng (trước Java 8)&lt;/td&gt;
&lt;td&gt;Có cả phương thức trừu tượng và thông thường&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Constructor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Không có&lt;/td&gt;
&lt;td&gt;Có&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Biến&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chỉ chứa hằng số (public static final)&lt;/td&gt;
&lt;td&gt;Có thể chứa biến với mọi mức độ truy cập&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tốc độ thực thi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nhanh hơn (được tối ưu hóa hơn)&lt;/td&gt;
&lt;td&gt;Chậm hơn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Thích hợp cho&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Các hành vi chung giữa các lớp không liên quan&lt;/td&gt;
&lt;td&gt;Các lớp có mối quan hệ kế thừa&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Đơn giản vậy thôi, nhưng tuỳ vào trường hợp, bạn sẽ chọn cái nào hợp lý nhất nhé!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Khi nào nên sử dụng?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Interface
&lt;/h3&gt;

&lt;p&gt;Bạn nên dùng Interface khi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Muốn định nghĩa một tập hợp hành vi mà nhiều lớp (không liên quan) có thể thực hiện. Ví dụ: Bay, bơi, chạy.&lt;/li&gt;
&lt;li&gt;Cần hỗ trợ &lt;strong&gt;đa kế thừa&lt;/strong&gt;, vì Java không cho phép đa kế thừa với Abstract Class.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Abstract Class
&lt;/h3&gt;

&lt;p&gt;Abstract Class thì phù hợp nếu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bạn muốn chia sẻ code giữa các lớp "cùng họ hàng" (liên quan trực tiếp).&lt;/li&gt;
&lt;li&gt;Cần định nghĩa các thuộc tính hoặc phương thức có thể tái sử dụng trong lớp con. Ví dụ: Các loài động vật đều "ăn" và "ngủ".&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Ví dụ minh họa
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Interface
&lt;/h3&gt;

&lt;p&gt;Hãy tưởng tượng bạn đang xây dựng một chương trình về các loài động vật:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dog eats bones"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dog sleeps in a kennel"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Như bạn thấy, &lt;strong&gt;Dog&lt;/strong&gt; chỉ cần thực hiện những hành vi được định nghĩa trong Interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstract Class
&lt;/h3&gt;

&lt;p&gt;Nếu các loài động vật có vài điểm chung nhưng mỗi loài lại "ăn" theo cách riêng thì sao?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This animal sleeps"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dog eats bones"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ở đây, &lt;strong&gt;Dog&lt;/strong&gt; không cần tự định nghĩa hành vi "ngủ" vì nó đã có sẵn từ Abstract Class rồi!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Tổng kết
&lt;/h2&gt;

&lt;p&gt;Vậy là chúng ta đã hiểu thêm về sự khác biệt giữa Interface và Abstract Class rồi. Tóm lại:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nếu bạn cần "đa kế thừa" hoặc các lớp không liên quan cùng thực hiện một hành vi, hãy chọn &lt;strong&gt;Interface&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Nếu bạn muốn chia sẻ code và các lớp có mối quan hệ "họ hàng", hãy chọn &lt;strong&gt;Abstract Class&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cảm ơn các bạn đã theo dõi! Có câu hỏi nào không? Đừng ngại để lại bình luận nhé! 😊&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>learning</category>
      <category>java</category>
    </item>
    <item>
      <title>DRY Principles</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sun, 05 Jan 2025 11:16:30 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/dry-principles-38l8</link>
      <guid>https://dev.to/congquynguyen296/dry-principles-38l8</guid>
      <description>&lt;h1&gt;
  
  
  DRY Principle - "Don't Repeat Yourself"
&lt;/h1&gt;




&lt;h2&gt;
  
  
  🤔 Vậy DRY là gì nhỉ?
&lt;/h2&gt;

&lt;p&gt;"DRY" là viết tắt của &lt;strong&gt;"Don't Repeat Yourself"&lt;/strong&gt;, một nguyên tắc vàng trong lập trình (và cả trong cuộc sống nữa đó!). Ý tưởng rất đơn giản: &lt;strong&gt;"Đừng lặp lại chính mình."&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Hãy tưởng tượng bạn viết một công thức nấu ăn mà phải copy-paste từng bước mỗi khi làm một món ăn khác. Lỡ bạn muốn thêm muối, bạn sẽ phải cập nhật từng bản copy. Ngán chưa? Đó chính là "lặp lại" trong lập trình!&lt;/p&gt;




&lt;h2&gt;
  
  
  DRY dưới góc nhìn lập trình
&lt;/h2&gt;

&lt;p&gt;Nguyên tắc DRY yêu cầu bạn &lt;strong&gt;cô lập logic&lt;/strong&gt; hoặc đoạn mã thường lặp lại vào một vị trí duy nhất. Khi cần thay đổi, bạn chỉ việc sửa một nơi mà không cần tìm từng dòng để sửa.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Ví dụ:
&lt;/h3&gt;

&lt;p&gt;Bạn đang viết một ứng dụng quản lý thú cưng:&lt;/p&gt;

&lt;h4&gt;
  
  
  Trước khi áp dụng DRY:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;feedDog&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Feeding the dog"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;feedCat&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Feeding the cat"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;feedParrot&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Feeding the parrot"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cứ thêm thú cưng là bạn phải viết thêm một phương thức mới. Thật phiền phức đúng không nào? 🙈&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;feedAnimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Feeding the "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bây giờ, bạn chỉ cần gọi &lt;code&gt;feedAnimal("dog")&lt;/code&gt;, &lt;code&gt;feedAnimal("cat")&lt;/code&gt; mà không lo lặp lại đoạn code y chang nhau! Tiết kiệm thời gian, giảm đau đầu. 🥳&lt;/p&gt;




&lt;h2&gt;
  
  
  DRY trong thực tế
&lt;/h2&gt;

&lt;p&gt;DRY không chỉ giúp bạn viết code "ngầu" hơn mà còn cải thiện khả năng bảo trì và mở rộng ứng dụng.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Một ví dụ thực tế:
&lt;/h3&gt;

&lt;p&gt;Giả sử bạn xây dựng một website và phải sử dụng cùng một đoạn HTML cho phần footer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Contact us at: congquynguyen@gmail.com&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trước DRY&lt;/strong&gt;:&lt;br&gt;
Bạn copy-paste đoạn HTML này vào mọi trang. Lỡ email thay đổi? Hoặc đó là một đoạn code dài ơi là dài ? Bạn phải chỉnh sửa từng trang. Quá tốn công!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sau DRY&lt;/strong&gt;:&lt;br&gt;
Sử dụng một tệp template hoặc component tái sử dụng:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"footer.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/include&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bây giờ chỉ cần sửa một tệp duy nhất khi có thay đổi. Đơn giản hơn nhiều, đúng không?&lt;/p&gt;




&lt;h2&gt;
  
  
  Lợi ích khi áp dụng DRY
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Dễ bảo trì hơn:&lt;/em&gt; Sửa một chỗ thay vì "sửa toàn cầu".&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Code gọn gàng:&lt;/em&gt; Giảm "sự lộn xộn" và tăng độ đọc hiểu.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Ít lỗi hơn:&lt;/em&gt; Mỗi thay đổi đều được áp dụng nhất quán.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Thách thức khi thực hiện DRY
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Over-DRY:&lt;/em&gt; Đừng cố DRY mọi thứ! Đôi khi, chia nhỏ quá mức sẽ làm code phức tạp và khó hiểu hơn.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Lựa chọn sai ngữ cảnh:&lt;/em&gt; DRY chỉ hiệu quả khi áp dụng đúng lúc, đúng chỗ. Nếu không, nó sẽ trở thành một "cơn ác mộng bảo trì."&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tóm lại
&lt;/h2&gt;

&lt;p&gt;Nguyên tắc DRY là một trong những "bí kíp" giúp bạn trở thành lập trình viên chuyên nghiệp. Tuy nhiên, hãy nhớ rằng cân bằng là chìa khóa. Không phải lúc nào DRY cũng là giải pháp tốt nhất, nhưng khi áp dụng đúng, nó sẽ giúp bạn tiết kiệm cả thời gian và năng lượng! 💪&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>discuss</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>SOLID Principles</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sun, 05 Jan 2025 11:16:06 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/solid-principles-3m01</link>
      <guid>https://dev.to/congquynguyen296/solid-principles-3m01</guid>
      <description>&lt;h1&gt;
  
  
  SOLID: Bí mật để code "đỉnh" hơn mỗi ngày!
&lt;/h1&gt;

&lt;p&gt;Chào bạn,&lt;br&gt;&lt;br&gt;
Hôm nay, hãy tưởng tượng chúng ta ngồi lại, pha tách cà phê và nói chuyện về thứ gì đó vừa ngầu vừa hữu ích cho công việc viết code hằng ngày nhé. Chủ đề chính là: &lt;strong&gt;SOLID&lt;/strong&gt;, một tập hợp nguyên tắc giúp chúng ta viết code sạch hơn, dễ bảo trì hơn và, nói thẳng ra, "ngầu" hơn khi làm việc nhóm.  &lt;/p&gt;

&lt;p&gt;Nếu bạn từng nghĩ:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Sao code của mình dễ bị lỗi vậy?"
&lt;/li&gt;
&lt;li&gt;"Code này sửa một tí là lan ra cả dự án, phải làm sao đây?"
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thì đây, &lt;strong&gt;SOLID chính là người bạn đồng hành tuyệt vời&lt;/strong&gt;! 😎  &lt;/p&gt;
&lt;h2&gt;
  
  
  Vậy SOLID là gì?
&lt;/h2&gt;

&lt;p&gt;SOLID gồm 5 nguyên tắc "vàng" trong thiết kế phần mềm, đặt nền móng cho code dễ hiểu, dễ mở rộng và dễ bảo trì. Chúng ta cùng đi qua từng nguyên tắc nhé!  &lt;/p&gt;


&lt;h3&gt;
  
  
  1. &lt;strong&gt;S&lt;/strong&gt;ingle Responsibility Principle (SRP)
&lt;/h3&gt;
&lt;h4&gt;
  
  
  "Một lớp chỉ nên có một lý do để thay đổi."
&lt;/h4&gt;

&lt;p&gt;Hãy nghĩ về nó như việc mỗi người chỉ nên làm một việc cụ thể trong nhóm. Nếu bạn làm cả code backend lẫn thiết kế giao diện, bạn sẽ nhanh chóng mệt mỏi và mắc lỗi.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ví dụ xấu&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Thêm người dùng&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Gửi email chào mừng&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ở đây, &lt;code&gt;UserManager&lt;/code&gt; vừa quản lý người dùng, vừa lo việc gửi email. Không ổn chút nào!  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cải thiện&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Tách riêng trách nhiệm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Thêm người dùng&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Gửi email chào mừng&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. &lt;strong&gt;O&lt;/strong&gt;pen/Closed Principle (OCP)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  "Mở rộng được nhưng không sửa đổi."
&lt;/h4&gt;

&lt;p&gt;Bạn thích thêm tính năng mà không phải đụng vào code cũ chứ? Đây là nguyên tắc dành cho bạn. Code cũ không sửa thì ít lỗi, đúng không? 😉  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ví dụ xấu&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Discount&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NEW_YEAR"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BLACK_FRIDAY"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ở đây, nếu bạn muốn thêm một dịp giảm giá nào đó thì sao, ví dụ như giảm giá cho cô Thơ chẳng hạn? Hiển nhiên là bạn phải động vào class Discount và chỉnh sửa mã nguồn của nó rồi, nhưng điều này thật sự thì không được hay cho lắm, hãy đọc tiếp để biết được cách giải quyết sao cho thật "ngầu" nhé =))&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cải thiện&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Sử dụng kế thừa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Discount&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewYearDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Discount&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlackFridayDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Discount&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bạn có thể sử dụng một interface để đưa ra các ràng buộc mà các class thực thi phải làm theo (có thể tham khảo lại bài trước). Lúc này thì bạn chỉ cần tạo mới một đối tượng thôi chứ không cần phải can thiệp vào mã nguồn cũ. Trên thực tế, các vấn đề sẽ không đơn giản như thế này đâu nhé!&lt;/p&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;L&lt;/strong&gt;iskov Substitution Principle (LSP)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  "Lớp con phải có thể thay thế lớp cha mà không làm hỏng chương trình."
&lt;/h4&gt;

&lt;p&gt;Nguyên tắc này nghe thì hơi "trừu tượng", nhưng ý tưởng rất đơn giản: nếu bạn thay lớp cha bằng lớp con, mọi thứ vẫn phải chạy tốt.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hãy cùng xem một ví dụ nổi tiếng từ cuốn Head First Design Patterns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Duck&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;quack&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quack!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Swimming!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RubberDuck&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Duck&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;quack&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Squeak!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rubber duck can't swim!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DuckTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Duck&lt;/span&gt; &lt;span class="n"&gt;duck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RubberDuck&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Thay thế lớp cha bằng lớp con&lt;/span&gt;
        &lt;span class="n"&gt;duck&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Lỗi xảy ra do RubberDuck không thể bơi&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ở đây, &lt;code&gt;RubberDuck&lt;/code&gt; (ở đây là vịt đồ chơi nhea) kế thừa &lt;code&gt;Duck&lt;/code&gt; nhưng lại phá vỡ hành vi dự kiến của lớp cha vì nó không thực hiện được phương thức &lt;code&gt;swim&lt;/code&gt;. Điều này gây ra lỗi khi sử dụng.&lt;/p&gt;

&lt;p&gt;Để cải thiện điều này, dưới góc độ cá nhân của mình thì mình đánh giá là vì kế thừa, sử dụng interface để đảm bảo rằng chỉ những lớp thực sự có khả năng bơi mới triển khai hành vi này sẽ khả thi và hợp lý hơn (các bạn có thể chia sẻ cách khác nhé).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Đây là ví dụ minh họa để giải quyết vấn đề của mình&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SwimBehavior&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;QuackBehavior&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;quack&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Duck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SwimBehavior&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;QuackBehavior&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Swimming!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;quack&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quack!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RubberDuck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;QuackBehavior&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;quack&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Squeak!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. &lt;strong&gt;I&lt;/strong&gt;nterface Segregation Principle (ISP)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  "Không nên bắt ai đó dùng những thứ họ không cần."
&lt;/h4&gt;

&lt;p&gt;Nếu bạn tạo ra một interface quá lớn, các lớp triển khai sẽ phải "gánh" những thứ không liên quan.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ví dụ xấu&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Robot&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Làm việc&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// ??? Robot đâu có ăn!&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cải thiện&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Tách interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Eater&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trên đây là cách giải quyết dựa trên tư tưởng của &lt;strong&gt;ISP&lt;/strong&gt;, tuy nhiên bạn cũng đừng nên lạm dụng quá nhé, bởi vì như bạn thấy đấy, cách giải quyết này có một nhược điểm đó chính là sản sinh ra nhiều interface nên nếu không khéo léo thì dễ gây ra sự thừa thải trong mã nguồn. Vậy nên hãy cẩn thận khi sử dụng nhé!&lt;/p&gt;




&lt;h3&gt;
  
  
  5. &lt;strong&gt;D&lt;/strong&gt;ependency Inversion Principle (DIP)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  "Code nên phụ thuộc vào abstraction, không phụ thuộc vào implementation."
&lt;/h4&gt;

&lt;p&gt;Nghe hơi phức tạp, nhưng bạn chỉ cần nhớ: thay vì code phụ thuộc vào chi tiết cụ thể, hãy để nó dựa vào cái tổng quát.  &lt;/p&gt;

&lt;p&gt;Bây giờ mình sẽ trình bày một ví dụ để các bạn dễ hình dung. Do phần này khá là khó nên các bạn chú ý tập trung nhé!&lt;/p&gt;

&lt;p&gt;Mình sẽ lấy ví dụ về việc thiết kế một service xử lý &lt;strong&gt;thanh toán&lt;/strong&gt;. Hiện tại, ví dụ chúng ta có 1 phương thức thanh toán là &lt;code&gt;PayPalPayment&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Payment of $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" processed via PayPal."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt; &lt;span class="n"&gt;payPalPayment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payPalPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;payPalPayment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Main&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tại đây sẽ xuất hiện một vấn đề, &lt;code&gt;PaymentProcessor&lt;/code&gt; phụ thuộc trực tiếp vào lớp &lt;code&gt;PayPalPayment&lt;/code&gt;. Nếu cần tích hợp thêm phương thức thanh toán mới (ví dụ: &lt;em&gt;Stripe&lt;/em&gt;, &lt;em&gt;Bank Transfer&lt;/em&gt;), bạn sẽ phải sửa đổi code trong &lt;code&gt;PaymentProcessor&lt;/code&gt;, vi phạm &lt;strong&gt;OCP&lt;/strong&gt; và tăng rủi ro lỗi.&lt;/p&gt;

&lt;p&gt;Lúc này, để tuân thủ theo &lt;strong&gt;DIP&lt;/strong&gt;, chúng ta cần tạo ra một abstraction (interface &lt;code&gt;PaymentService&lt;/code&gt;) để đại diện cho hành vi thanh toán.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Abstraction&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// PayPal&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Payment of $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" processed via PayPal."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Stripe&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripePayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Payment of $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" processed via Stripe."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="n"&gt;paymentService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Dependency Injection qua constructor&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="n"&gt;paymentService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paymentService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;paymentService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Main&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Inject PayPalPayment&lt;/span&gt;
        &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="n"&gt;payPalProcessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;payPalProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Inject StripePayment&lt;/span&gt;
        &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="n"&gt;stripeProcessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StripePayment&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;stripeProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;200.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Khi triển khai như thế này thì &lt;code&gt;PaymentProcessor&lt;/code&gt; chỉ biết &lt;code&gt;PaymentService&lt;/code&gt; và không cần quan tâm tới chi tiết của &lt;code&gt;PayPalPayment&lt;/code&gt; hay &lt;code&gt;StripePayment&lt;/code&gt;, do đó khi muốn thêm một phương thức thanh toán mới (ví dụ: &lt;code&gt;BankTransferPayment&lt;/code&gt;), chỉ cần tạo lớp mới triển khai &lt;code&gt;PaymentService&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lời kết
&lt;/h2&gt;

&lt;p&gt;Bạn thấy đó, nguyên tắc SOLID không hề "đáng sợ" như tên gọi. Nó giống như những bài học nhỏ, giúp bạn trở thành một lập trình viên thông minh hơn mỗi ngày. Để áp dụng được tốt SOLID trong quá trình code của mình, không phải ngày một ngày hai mà được nhé, nó sẽ dần tích hợp vào khả năng của bạn trong quá trình phát triển.&lt;/p&gt;

&lt;p&gt;Vậy, bạn đã sẵn sàng áp dụng SOLID vào code của mình chưa? Cùng thử ngay và xem sự khác biệt nhé! 🚀&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Include vs Extend</title>
      <dc:creator>Cong Quy Nguyen</dc:creator>
      <pubDate>Sun, 05 Jan 2025 11:15:29 +0000</pubDate>
      <link>https://dev.to/congquynguyen296/include-vs-extend-239m</link>
      <guid>https://dev.to/congquynguyen296/include-vs-extend-239m</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Include vs Extend – Vấn đề Use Case!&lt;/strong&gt;
&lt;/h1&gt;




&lt;h2&gt;
  
  
  💡 &lt;strong&gt;Chào mừng bạn đến với thế giới của Use Case =))&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hôm nay, chúng ta sẽ khám phá hai mối quan hệ nổi tiếng nhất trong mô hình Use Case: &lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt; và &lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;. Hãy tưởng tượng đây là hai người bạn trong thế giới lập trình, mỗi người đều có sức cách hành xử riêng và mục tiêu đặc biệt.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;1. &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt; – Người bạn "luôn luôn bên nhau"&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt; là kiểu bạn đồng hành trung thành. Họ &lt;strong&gt;luôn xuất hiện&lt;/strong&gt; mỗi khi bạn cần hoàn thành công việc. Đây là người mà bạn gọi khi muốn tái sử dụng những việc làm lặp đi lặp lại.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ví dụ siêu đơn giản:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Hãy tưởng tượng bạn đang quản lý một trang web bán sách.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Khi khách hàng &lt;strong&gt;đăng ký tài khoản&lt;/strong&gt;, bạn &lt;strong&gt;luôn luôn&lt;/strong&gt; cần thực hiện bước &lt;strong&gt;xác nhận email&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Tương tự, khi &lt;strong&gt;xác nhận&lt;/strong&gt; một đơn hàng, bạn cũng &lt;strong&gt;luôn luôn&lt;/strong&gt; cần &lt;strong&gt;thực hiện phương thức xác nhận&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Tính cách của &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cần thiết:&lt;/strong&gt; Không có họ, công việc sẽ không thể hoàn thành.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cứu tinh của sự lặp lại:&lt;/strong&gt; Nếu một hành động xuất hiện ở nhiều nơi? Gọi ngay cho &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;!
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ký hiệu:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Mũi tên đứt nét, có nhãn &lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;, trỏ từ Use Case chính đến Use Case được bao gồm.  &lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Tóm lại:&lt;/strong&gt; &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt; là kiểu bạn không thể thiếu, luôn đi cùng bạn trên hành trình.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. &lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt; – Người bạn "chỉ đến khi cần"&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt; lại là kiểu bạn đặc biệt, chỉ xuất hiện khi bạn thực sự cần. Họ là người mang đến &lt;strong&gt;sự tùy chọn&lt;/strong&gt; trong các tình huống cụ thể.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ví dụ siêu thực tế:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Quay lại trang web bán sách:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Khi khách hàng thực hiện &lt;strong&gt;xem đơn hàng&lt;/strong&gt;, họ &lt;strong&gt;có thể&lt;/strong&gt; yêu cầu thêm tính năng &lt;strong&gt;hủy đơn hàng&lt;/strong&gt; hoặc &lt;strong&gt;hoàn trả đơn hàng&lt;/strong&gt; nếu muốn.
&lt;/li&gt;
&lt;li&gt;Hoặc trong quá trình &lt;strong&gt;đăng nhập&lt;/strong&gt;, nếu khách hàng quên mất mật khẩu, tính năng &lt;strong&gt;quên mật khẩu&lt;/strong&gt; &lt;strong&gt;có thể&lt;/strong&gt; được áp dụng để giảm lấy lại mật khẩu cho khách hàng.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Tính cách của &lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tùy chọn:&lt;/strong&gt; Không phải lúc nào cũng cần đến họ.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linh hoạt:&lt;/strong&gt; Chỉ xuất hiện khi điều kiện đặc biệt xảy ra.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ký hiệu:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Mũi tên đứt nét, có nhãn &lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;, trỏ từ Use Case mở rộng đến Use Case chính.  &lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Tóm lại:&lt;/strong&gt; &lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt; là người bạn thêm "gia vị" cho cuộc sống của bạn khi cần thiết.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt; vs &lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt; – Ai là ai?&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Tiêu chí&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Khi nào dùng?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Khi một Use Case &lt;strong&gt;luôn cần&lt;/strong&gt; Use Case khác.&lt;/td&gt;
&lt;td&gt;Khi một Use Case &lt;strong&gt;có thể mở rộng&lt;/strong&gt; hành vi của Use Case chính.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hành vi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Bắt buộc&lt;/strong&gt;: Luôn được thực hiện.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Tùy chọn&lt;/strong&gt;: Chỉ thực hiện khi điều kiện xảy ra.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mục đích&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tái sử dụng, giảm lặp lại.&lt;/td&gt;
&lt;td&gt;Thêm chức năng đặc biệt, linh hoạt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ví dụ&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gửi mail khi đăng ký tài khoản.&lt;/td&gt;
&lt;td&gt;Quên mật khẩu khi đăng nhập.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  💡 &lt;strong&gt;Kết luận&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt; giúp bạn tổ chức công việc hợp lý và không lặp lại chính mình.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt; mang đến sự linh hoạt và những trải nghiệm thú vị, cá nhân hóa hơn.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dù là &lt;code&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/code&gt; hay &lt;code&gt;&amp;lt;&amp;lt;extend&amp;gt;&amp;gt;&lt;/code&gt;, cả hai đều là những người đồng hành đáng tin cậy, những trợ thủ đắt lực trên trên hành trình thiết kế Use Case của bạn! 🚀&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
