--------------- <> -----------------
--- KHOA HỌC - CÔNG NGHỆ - GIÁO DỤC - VIỆC LÀM ---
--- Học để đi cùng bà con trên thế giới ---

Tìm kiếm trong Blog

Python (2x) - Thao tác với tập tin văn bản

Bài trước:
-----

23. Thao tác với tập tin văn bản

Ở các bài học trước, khi bạn chạy một chương trình và nhập dữ liệu (như họ tên, điểm số), dữ liệu đó chỉ tồn tại tạm thời trên bộ nhớ (RAM). Khi bạn tắt chương trình, mọi dữ liệu sẽ biến mất. Để lưu giữ dữ liệu lâu dài, chúng ta cần ghi chúng vào các tập tin (file) trên ổ cứng.

23.1 Các thao tác với tập tin

Thao tác với tập tin giống như việc bạn sử dụng một cuốn sổ tay để ghi chép. Để sử dụng, bạn cần thực hiện 3 bước cơ bản:

- [1] Mở sổ tay (open): Mở tập tin để sẵn sàng đọc hoặc ghi

- [2] Sử dụng sổ tay (read/write): Đọc thông tin từ sổ tay hoặc viết thông tin mới vào

- [3] Đóng sổ tay (close): Cất sổ tay đi để bảo đảm thông tin không bị mất

Chúng ta sẽ thực hành trên 2 kiểu tập tin văn bản là .txt và .csv.

23.2 Thao tác với tập tin .txt

Bạn hãy thực hiện các bước sau, để trải nghiệm việc thao tác với tập tin:

- Tạo một tập tin có tên chao_mung.txt. Viết dòng chữ “Chào mừng bạn đến với khóa học Python!” vào tập tin chao_mung.txt. Lưu ý: tập tin chao_mung.txt phải nằm cùng thư mục với tập tin mã nguồn TapTin.py

- Viết đoạn mã Python sau vào tập tin TapTin.py

[TapTin.py]

# Bước 1: Mở tập tin

f = open("chao_mung.txt", "r", encoding="utf-8")


# Bước 2: Đọc nội dung và in ra màn hình

noi_dung = f.read()

print(noi_dung)


# Bước 3: Đóng tập tin

f.close()

Ở đoạn mã trên, bạn đã:

- Sử dụng hàm open() để mở một tập tin có sẵn (chao_mung.txt

- Sử dụng tham số “r” (read) để đọc nội dung tập tin

- Sử dụng bảng mã encoding="utf-8" giúp máy tính đọc được các chữ có dấu tiếng Việt

- Sử dụng biến f để tham chiếu tới tập tin, và thực hiện các thao tác khác trên tập tin

- Sử dụng hàm read() để đọc toàn bộ nội dung tập tin

- Sử dụng hàm close() để đóng tập tin

Ghi nội dung vào tập tin

Để ghi dữ liệu, chúng ta có hai chế độ chính:

- "w" (Write): Xóa hết nội dung cũ và ghi mới hoàn toàn

- "a" (Append): Ghi thêm nội dung vào cuối tập tin cũ

Ví dụ minh họa:

[GhiTapTin.py]

# Ghi mới vào tập tin

f = open("nhat_ky.txt", "w", encoding="utf-8")

f.write("Hôm nay tôi bắt đầu học về tập tin trong Python.\n")

f.write("Lập trình thật thú vị!")

f.close()


Khi chạy đoạn mã trên, nếu chưa có sẵn tập tin nhat_ky.txt, Python sẽ tạo mới tập tin và ghi nội dung vào tập tin vừa tạo. Python sử dụng tham số “w” (write, viết) trong hàm open() để báo là mở tập tin để ghi nội dung; sử dụng hàm write() để ghi nội dung vào tập tin.


Ghi thêm nội dung vào cuối tập tin cũ


Kiểu ghi nội dung này rất hữu ích khi bạn muốn ghi nhật ký (log) hoặc ghi thêm dữ liệu mới mà không làm mất đi những gì đã có sẵn trong tập tin. Sử dụng tham số “a” khi mở tập tin (a là viết tắt của append - gắn vào cuối).


Ví dụ:


Giả sử bạn đã có một tập tin tên là nhat_ky.txt với nội dung cũ. Bây giờ chúng ta sẽ ghi thêm một dòng mới vào cuối tập tin đó.


[GhiVaoCuoi.py]


# Bước 1: Mở tập tin ở chế độ "a" (Append)

# encoding="utf-8" giúp ghi được tiếng Việt có dấu

file = open("nhat_ky.txt", "a", encoding="utf-8")


# Bước 2: Ghi thêm nội dung mới

# Sử dụng ký tự \n để dòng mới được xuống hàng, không bị dính liền với dòng cũ

file.write("\n10:00 AM - Đã hoàn thành bài tập Python về tập tin.")


# Bước 3: Đóng tập tin

file.close()


print("Đã ghi thêm nội dung thành công!")


Giải thích đoạn mã trên:


open("nhat_ky.txt", "a"):


- Nếu tập tin nhat_ky.txt đã tồn tại: Python sẽ đặt "con trỏ" ở cuối tập tin (tạm hiểu con trỏ là dấu nháy khi soạn thảo văn bản). Mọi nội dung bạn ghi sau đó sẽ nối tiếp vào đuôi


- Nếu tập tin nhat_ky.txt chưa tồn tại: Python sẽ tự động tạo một tập tin mới hoàn toàn


- \n: Đây là ký tự xuống dòng. Nếu bạn không thêm \n, nội dung mới sẽ nằm ngay sát sau ký tự cuối cùng của nội dung cũ


- Sự khác biệt của tham số "a" với "w": Nếu bạn dùng "w", toàn bộ nội dung cũ trong nhat_ky.txt sẽ bị xóa sạch trước khi ghi mới. Với "a", nội dung cũ được giữ nguyên.


Cách viết an toàn hơn (Khuyên dùng)


Trong thực tế, các lập trình viên kinh nghiệm thường dùng từ khóa with để tránh việc quên đóng tập tin (close()):


Ví dụ:


with open("nhat_ky.txt", "a", encoding="utf-8") as file:

    file.write("\n11:30 AM - Chuẩn bị nghỉ trưa.")

# Khi dùng 'with', file sẽ tự động đóng sau khi chạy hết khối lệnh bên trong.


Xóa tập tin

Trong lập trình, việc xóa các tập tin không còn sử dụng (như tập tin tạm, tập tin lịch sử cũ) là rất quan trọng để tiết kiệm không gian đĩa cứng. Để xóa tập tin trong Python, chúng ta cần dùng đến thư viện có sẵn tên là os (viết tắt của Operating System - Hệ điều hành).

Để xóa một tập tin, chúng ta sử dụng hàm os.remove().

Lưu ý: Khi bạn dùng lệnh xóa tập tin trong lập trình, tập tin sẽ bị xóa vĩnh viễn và không nằm trong "Thùng rác" (Recycle Bin) của máy tính. Vì vậy, bạn hãy cẩn thận.

Ví dụ:

Tạo sẵn một tập tin để xóa, ví dụ: FileTam.txt

import os  # Bước 1: Phải nạp thư viện os

# Bước 2: Gọi lệnh xóa

os.remove("FileTam.txt")

print("Đã xóa tập tin thành công!")

Cách xóa tập tin an toàn (Kiểm tra trước khi xóa)

Nếu bạn ra lệnh xóa một tập tin không tồn tại, chương trình sẽ bị "treo" và báo lỗi ngay lập tức. Một lập trình viên kinh nghiệm sẽ luôn kiểm tra xem tập tin đó có thực sự tồn tại hay không trước khi xóa.

Ví dụ:

import os


ten_file = "lich_su_cu.txt"


# Kiểm tra xem file có tồn tại trên ổ cứng không

if os.path.exists(ten_file):

    os.remove(ten_file)

    print(f"Đã xóa xong tập tin: {ten_file}")

else:

    print("Thông báo: Tập tin này không tồn tại nên không thể xóa.")

23.3 Thao tác với tập tin .csv

Tập tin CSV (Comma Separated Values) là loại tập tin mà các giá trị được ngăn cách bởi dấu phẩy. Nó trông giống như một bảng tính Excel đơn giản.

Ví dụ: ghi danh sách học sinh và điểm vào tập tin CSV:


import csv # Nạp thư viện hỗ trợ tập tin CSV


danh_sach = [

    ["Tên", "Điểm"],

    ["Tèo", 9],

    ["Bình", 10]

]


with open("diem_so.csv", "w", newline="", encoding="utf-8") as f:

    writer = csv.writer(f)

    writer.writerows(danh_sach)

# Dùng 'with' giúp tự động đóng tập tin, bạn không cần gọi f.close()

Giải thích đoạn mã trên:


- Đoạn mã trên sẽ tạo ra một bảng điểm và lưu nó vào một tập tin có thể mở được bằng Excel, nhờ vào đuôi của tập tin là .csv.

import csv

- Gọi thư viện của Python (csv), để dùng các hàm có sẵn khi làm việc với tập tin .csv

danh_sach = [

    ["Tên", "Điểm"],

    ["Tèo", 9],

    ["Bình", 10]

]

- Tạo danh sách lồng nhau (List of Lists). Mỗi danh sách con bên trong (như ["Tèo", 9]) đại diện cho một hàng trong bảng. Các phần tử trong danh sách con đại diện cho các cột (cột Tên và cột Điểm)

with open(...) as f:

- "diem_so.csv": Tên tập tin bạn muốn tạo ra

- "w" (Write): Chế độ ghi. Nếu tập tin đã có, nó sẽ xóa sạch để ghi mới. Nếu chưa có, nó sẽ tạo tập tin mới

- newline="": Một tham số để đảm bảo khi ghi tập tin trên các hệ điều hành khác nhau (Windows, Mac) sẽ không bị xuất hiện các dòng trống thừa

- encoding="utf-8": để làm việc với chữ có dấu tiếng Việt

- with...as f: Đây là cách viết thông minh. Nó mở tập tin ra và đặt tên tạm gọi là f. Khi chạy xong các lệnh thụt lề bên trong, Python sẽ tự động đóng tập tin lại cho bạn, giúp an toàn dữ liệu

writer = csv.writer(f)

- Tạo ra một "thợ viết" (đối tượng writer). Thợ viết này biết cách cầm "bút" f để ghi dữ liệu theo đúng định dạng CSV (ngăn cách nhau bằng dấu phẩy)

writer.writerows(danh_sach)

- Lệnh này yêu cầu "thợ viết" lấy toàn bộ các hàng trong danh_sach và chép vào tập tin. Kết quả là bạn sẽ có một bảng dữ liệu ngăn nắp

Sau khi chạy đoạn mã trên, vào thư mục chứa tập tin mã nguồn, bạn sẽ thấy một tập tin mới tên là diem_so.csv. Khi mở bằng Notepad, nó sẽ trông như thế này:

Tên,Điểm

Tèo,9

Bình,10

Nhưng khi mở bằng Excel hoặc Google Sheets, nó sẽ hiện ra thành một bảng tính với cột Tên và cột Điểm rõ ràng.

23.4 Bài tập và câu hỏi

Bài tập

Bài tập 23a: Viết chương trình máy tính thực hiện liên tục các phép tính: cộng, trừ, nhân, chia, và số mũ hai số. Sau khi tính xong, hãy ghi các phép tính đó vào tập tin lich_su.txt.

Ví dụ: Nếu nhập 5 + 3, tập tin sẽ ghi: 5 + 3 = 8


-----
Bài sau:

CNPM (5) - Thiết kế kiến trúc phần mềm

Bài trước: CNPM (4) - Lấy và phân tích yêu cầu
-----

Bài 5: Thiết kế kiến trúc phần mềm

5.1 Kiến trúc phần mềm là gì?

Kiến trúc phần mềm là bản thiết kế tổng thể của một hệ thống, giúp chúng ta hiểu rõ các bộ phận cấu thành, cách chúng kết nối và các quy tắc chi phối toàn bộ cấu trúc. Nó giống như bản vẽ kỹ thuật của một tòa nhà lớn, như: tòa nhà có bao nhiêu tầng, vật liệu chính là gì, hệ thống điện nước chạy như thế nào; mô tả các bộ phận (móng, cột, tường, mái), cách chúng được liên kết (hệ thống ống nước, dây điện) và mục tiêu chất lượng (chịu được động đất, tiết kiệm năng lượng).

Kiến trúc phần mềm trả lời câu hỏi: "Chúng ta nên xây dựng hệ thống này như thế nào?" thay vì "Hệ thống này làm được gì?" (câu hỏi của URS).

Kiến trúc phần mềm mô tả ba yếu tố chính của một hệ thống:

- Cấu trúc (structure): Hệ thống được chia thành các thành phần (components) hoặc mô-đun nhỏ hơn (ví dụ: mô-đun quản lý người dùng, mô-đun xử lý thanh toán)

- Tương tác (interaction): Các thành phần kết nối và trao đổi dữ liệu với nhau bằng cách nào (ví dụ: dùng API)

- Yếu tố chất lượng (quality attributes / NFR-Non-Functional Requirements): Đây là các yêu cầu phi chức năng mà kiến trúc phải có. Ví dụ: tốc độ, bảo mật, khả năng mở rộng, độ tin cậy

Vai trò quan trọng của Kiến trúc phần mềm:

- Tính ổn định: Đảm bảo hệ thống vững chắc, không bị sụp đổ khi lượng người dùng tăng lên

- Tính dễ hiểu: Giúp các lập trình viên “mới” hoặc các nhóm khác nhau dễ dàng nắm bắt được cách hệ thống hoạt động, từ đó đẩy nhanh quá trình phát triển, nâng cấp và sửa lỗi

- Tính mở rộng: Cho phép thêm tính năng hoặc tăng khả năng chịu tải một cách dễ dàng mà không cần phải phát triển lại toàn bộ hệ thống

5.2 Một số mô hình Kiến trúc phần mềm phổ biến

Có nhiều mô hình Kiến trúc phần mềm khác nhau, mỗi mô hình phù hợp với những yêu cầu và quy mô dự án cụ thể.

Bảng sau tóm tắt một số mô hình Kiến trúc phần mềm phổ biến:

Mô hình

Mô tả tóm tắt

Kiến trúc nguyên khối (monolithic)

Toàn bộ hệ thống được xây dựng như một đơn vị duy nhất, tất cả các chức năng đều nằm chung một khối mã và chia sẻ một cơ sở dữ liệu. (Giống như một căn nhà nhỏ, mọi thứ đều nằm chung một không gian)

Kiến trúc N-tầng (N-tiers)

Phân chia hệ thống thành các lớp (tầng) riêng biệt (thường là 3 tầng: Giao diện người dùng, Logic nghiệp vụ, Truy cập dữ liệu). Mỗi tầng chỉ giao tiếp với tầng cạnh nó. (Giống như một tòa nhà có các tầng chức năng rõ ràng)

Kiến trúc vi dịch vụ (Microservices)

(kiến trúc phân tán)

Hệ thống được chia thành nhiều dịch vụ nhỏ độc lập (microservices), mỗi dịch vụ chạy tiến trình riêng, có thể có cơ sở dữ liệu riêng, và giao tiếp với nhau qua mạng (thường là API). (Giống như một khu phức hợp với nhiều tòa nhà chuyên biệt, kết nối bằng hệ thống đường xá riêng)

Chúng ta cùng tìm hiểu sơ lược 3 mô hình kiến trúc phần mềm ở trên.

5.3 Kiến trúc nguyên khối

Kiến trúc nguyên khối là mô hình truyền thống, trong đó toàn bộ ứng dụng được xây dựng và triển khai dưới dạng một khối duy nhất. Tất cả các thành phần của ứng dụng như giao diện người dùng, logic nghiệp vụ và truy cập dữ liệu đều được tích hợp chặt chẽ trong cùng một ứng dụng.

Xem hình minh họa:

Trong đó:

- Giao diện người dùng (user interface)

- Logic nghiệp vụ (business layer)

- Truy cập dữ liệu (data interface)

Xem hình ảnh này để bạn dễ tưởng tượng hơn về kiến trúc monolithic:

Ưu điểm:

- Quá trình phát triển, triển khai đơn giản: Do tất cả nằm trong một khối duy nhất, việc phát triển, thử nghiệm và triển khai sẽ đơn giản hơn.

- Hiệu suất cao: Do không có giao tiếp liên bộ phận, ứng dụng thường có hiệu suất cao hơn.

Nhược điểm:

- Khó bảo trì và mở rộng: Khi ứng dụng phát triển lớn hơn, việc bảo trì và thêm tính năng mới trở nên phức tạp

- Khả năng chịu lỗi kém: Một lỗi nhỏ có thể làm gián đoạn toàn bộ hệ thống

Khi nào thì nên sử dụng mô hình nguyên khối:

- Dự án nhỏ, cần triển khai nhanh

- Đội ngũ phát triển ít thành viên

- Tài nguyên, máy móc ít

- Việc giao tiếp giữa các thành phần của ứng dụng cần hiệu suất cao

Ví dụ về các ứng dụng theo kiến trúc nguyên khối:

- Hầu hết các ứng dụng desktop truyền thống đều được thiết kế theo kiểu kiến trúc nguyên khối. Kiến trúc nguyên khối rất phù hợp với môi trường desktop vì toàn bộ ứng dụng chạy cục bộ trên một máy tính duy nhất.

- Hệ quản trị nội dung (CMS) cũ (wordpress), ứng dụng thương mại điện tử nhỏ

5.4 Kiến trúc N-tầng

Mô hình N-tầng (N-tiers) phân chia ứng dụng thành các tầng độc lập, chạy trên các máy chủ hoặc dịch vụ khác nhau. Sự phân tách này đạt được thông qua việc giới hạn sự giao tiếp: mỗi tầng chỉ được phép giao tiếp với tầng liền kề nó.

Mô hình N-tầng phổ biến nhất là Kiến trúc 3-tầng (3-tier architecture).

Kiến trúc 3-tầng

Kiến trúc 3-tầng là một mô hình kiến trúc phần mềm phổ biến. Nó được thiết kế để phân chia ứng dụng thành ba đơn vị logic và vật lý riêng biệt, giúp tăng tính linh hoạt, khả năng mở rộng, và bảo mật.

Kiến trúc 3-tầng được hình thành bằng cách tách ba chức năng chính của ứng dụng thành các tầng (tier) độc lập, thường chạy trên các máy chủ vật lý hoặc logic khác nhau. 

Ba tầng đó là: 

- Trình bày (presentation)

- Logic nghiệp vụ (business logic)

- Dữ liệu (data)

Xem hình minh họa:

Cụ thể hơn:

Tên lớp (tier)

Vai trò chính

Nhiệm vụ

Ví dụ công nghệ

Trình bày

(Presentation)

Giao diện người dùng

Xử lý việc hiển thị thông tin, nhận yêu cầu từ người dùng (nhập liệu, bấm chuột) và chuyển tiếp các yêu cầu xuống tầng Logic nghiệp vụ.

Frontend framework (React, Angular, Vue),

HTML/CSS, Ứng dụng di động

Logic nghiệp vụ

(Business logic/Application)

Logic cốt lõi

Chứa các quy tắc nghiệp vụ, logic xử lý dữ liệu và điều phối các tác vụ. Đây là “bộ não” của ứng dụng, nơi xử lý các yêu cầu từ tầng Trình bày trước khi tương tác với dữ liệu.

Backend framework (Spring Boot, .NET Core, Node.js/Express), REST APIs

Dữ liệu 

(Data)

Lưu trữ và quản lý dữ liệu

Chứa cơ sở dữ liệu (database management system - DBMS), lưu trữ, quản lý, truy xuất và đảm bảo tính toàn vẹn của dữ liệu

Cơ sở dữ liệu (SQL Server, PostgreSQL, MongoDB), Hệ thống lưu trữ tập tin

Ưu điểm:

- Khả năng tái sử dụng: Logic nghiệp vụ nằm ở tầng giữa, độc lập với tầng trình bày. Vì vậy, một logic nghiệp vụ có thể được sử dụng bởi nhiều giao diện khác nhau. Ví dụ: một API xử lý thanh toán có thể được gọi từ cả ứng dụng web và ứng dụng di động

- Khả năng mở rộng: Đây là ưu điểm lớn nhất so với kiến trúc nguyên khối. Bạn có thể mở rộng độc lập theo từng tầng. Ví dụ: thêm máy chủ cho tầng Logic nghiệp vụ khi có nhiều yêu cầu API hơn, mà không cần thêm máy chủ cho tầng Dữ liệu

-  Có tính bảo mật cao: Tầng Dữ liệu được cô lập, chỉ giao tiếp với tầng Logic nghiệp vụ, mà không giao tiếp với người dùng cuối. Điều này giúp bảo vệ cơ sở dữ liệu khỏi các truy cập trái phép từ bên ngoài

- Dễ phát triển và bảo trì: Vì mỗi tầng có trách nhiệm rõ ràng, các lập trình viên có thể tập trung vào một tầng cụ thể mà không làm ảnh hưởng đến các tầng khác. Đội Frontend có thể làm việc song song với đội Backend, chỉ cần tuân thủ giao diện API

Nhược điểm:

- Phức tạp: Việc thiết lập và quản lý kiến trúc phân tán nhiều tầng phức tạp hơn so với kiến trúc nguyên khối

- Độ trễ: Việc truyền dữ liệu qua nhiều tầng (qua mạng) có thể làm tăng độ trễ (latency) so với việc gọi hàm cục bộ

- Chi phí: Việc duy trì nhiều máy chủ/dịch vụ vật lý hoặc máy ảo cho mỗi tầng sẽ tốn kém hơn

Khi nào thì nên sử dụng kiến trúc 3-tầng:

- Khi ứng dụng của bạn phức tạp, dự kiến phát triển lớn trong tương lai, cần khả năng mở rộng cao và bảo mật dữ liệu được ưu tiên

5.5 Kiến trúc vi dịch vụ

Kiến trúc vi dịch vụ (microservices) là một phương pháp thiết kế phần mềm, trong đó một ứng dụng lớn được chia thành một tập hợp các dịch vụ nhỏ, độc lập. Nó là một kiến trúc phần mềm phân tán.

Một số đặc điểm:

- Tính độc lập: Mỗi dịch vụ (service) chạy trong tiến trình (process) riêng biệt của nó

- Chức năng chuyên biệt: Mỗi dịch vụ tập trung vào việc thực hiện một chức năng nghiệp vụ cụ thể (ví dụ: dịch vụ quản lý người dùng, dịch vụ xử lý thanh toán, dịch vụ kho hàng)

- Giao tiếp: Các dịch vụ giao tiếp với nhau qua mạng bằng các giao thức nhẹ, phổ biến nhất là RESTful API hoặc message broker (hàng đợi tin nhắn)

- Công nghệ đa dạng (polyglot): Các dịch vụ khác nhau có thể được xây dựng bằng các ngôn ngữ lập trình, framework và thậm chí là cơ sở dữ liệu riêng (independent database) phù hợp nhất với yêu cầu của dịch vụ đó

Mô hình này trái ngược hoàn toàn với kiến trúc nguyên khối (monolithic), nơi mọi thứ được đóng gói thành một đơn vị duy nhất.

Xem hình minh họa.

Ưu điểm:

- Khả năng mở rộng độc lập: Có thể mở rộng từng dịch vụ riêng biệt dựa trên nhu cầu tải thực tế, giúp tối ưu hóa tài nguyên (ví dụ: chỉ cần thêm server cho dịch vụ giỏ hàng mà không cần thêm server cho dịch vụ tài khoản)

- Linh hoạt công nghệ: Cho phép các nhóm sử dụng công nghệ (tech stack) tốt nhất cho từng dịch vụ cụ thể (polyglot programming)

- Dễ dàng bảo trì và phát triển: Mã nguồn của mỗi dịch vụ nhỏ và dễ hiểu hơn. Các nhóm phát triển có thể làm việc, triển khai và cập nhật dịch vụ của họ độc lập với các dịch vụ khác (decoupling)

- Khả năng chịu lỗi cao: Nếu một dịch vụ bị lỗi, các dịch vụ khác vẫn có thể tiếp tục hoạt động (fault isolation). Hệ thống không bị sập toàn bộ như trong monolithic

- Triển khai liên tục (CI/CD): Dễ dàng áp dụng DevOps và CI/CD vì chỉ cần triển khai lại các dịch vụ nhỏ đã thay đổi, không cần triển khai toàn bộ ứng dụng lớn

Nhược điểm:

- Phức tạp về vận hành: Việc quản lý, giám sát (monitoring) và gỡ lỗi (debugging) một hệ thống gồm hàng chục hoặc hàng trăm dịch vụ phân tán phức tạp hơn nhiều

- Độ trễ mạng (latency): Các dịch vụ giao tiếp qua mạng (API call) thay vì gọi hàm cục bộ, dẫn đến độ trễ cao hơn so với monolithic

- Quản lý dữ liệu phân tán: Xử lý giao dịch trải dài qua nhiều cơ sở dữ liệu (distributed transactions) rất phức tạp và cần các mẫu thiết kế như Saga

- Chi phí cơ sở hạ tầng: Cần nhiều tài nguyên hơn cho việc chạy nhiều tiến trình, nhiều cơ sở dữ liệu và các công cụ quản lý phức tạp (kubernetes, service mesh, API gateway)

- Kiểm thử tích hợp: Việc đảm bảo tất cả các dịch vụ phối hợp nhịp nhàng với nhau khó khăn hơn so với kiểm thử end-to-end trong monolithic

Khi nào thì nên sử dụng mô hình microservices:

Microservices không phải là giải pháp cho mọi vấn đề. Nó đặc biệt phù hợp khi dự án đạt đến một mức độ phức tạp và quy mô nhất định:

- Hệ thống phức tạp và quy mô lớn: Khi ứng dụng có nhiều chức năng nghiệp vụ riêng biệt và mã nguồn (codebase) trở nên quá cồng kềnh

- Yêu cầu khả năng mở rộng cao và độc lập: Khi một số chức năng (ví dụ: tìm kiếm, streaming) có nhu cầu tải (load) cao hơn nhiều so với các chức năng khác

- Tổ chức lớn với nhiều đội (team autonomy): Khi các nhóm khác nhau có thể sở hữu, phát triển và triển khai dịch vụ của riêng họ mà không bị phụ thuộc vào nhau

- Cần triển khai nhanh chóng và thường xuyên: Khi yêu cầu cập nhật, thêm tính năng mới liên tục và cần thời gian ngưng hệ thống (downtime) tối thiểu

- Có kinh nghiệm vận hành (DevOps maturity): Đội ngũ phát triển đã có kinh nghiệm với các công cụ như Docker, Kubernetes, CI/CD, và các hệ thống giám sát phân tán

5.6 Bài tập

Bài 5a. Dựa trên URS ứng dụng của bạn (nhóm), hãy phân tích và thiết kế theo kiến trúc 3-tầng. Bạn có thể tự phân tích, thiết kế hoặc nhờ sự hỗ trợ của chatbot.

Bài 5b. Dựa trên URS ứng dụng của bạn (nhóm), hãy phân tích và thiết kế theo kiến trúc vi dịch vụ. Bạn có thể tự phân tích, thiết kế hoặc nhờ sự hỗ trợ của chatbot.



-----
Bài sau: