Common defect checklist | Báo cáo môn Công nghệ phần mềm | Đại học Bách Khoa, Đại học Đà Nẵng

Báo cáo tài liệu về Common defect checklist môn Công nghệ phần mềm | Đại học Bách Khoa, Đại học Đà Nẵng giúp sinh viên tham khảo, ôn luyện và phục vụ nhu cầu học tập của mình cụ thể là có định hướng, ôn tập, nắm vững kiến thức môn học và làm bài tốt trong những bài kiểm tra, bài tiểu luận, bài tập kết thúc học phần, từ đó học tập tốt và có kết quả cao cũng như có thể vận dụng tốt những kiến thức mình đã học

4. Common defect checklist
4.1. Exception
Lỗi Exception trong lập trình là một tình huống bất thường xảy ra trong quá trình thực thi
chương trình. Khi một Exception xảy ra, chương trình hiện tại sẽ dừng lại và tìm kiếm một xử lý
(handler) cho Exception đó. Nếu không có xử lý phù hợp, chương trình sẽ kết thúc và thông báo
lỗi cho người dùng.
Exceptions được sử dụng để xử lý các tình huống đặc biệt, như lỗi logic, lỗi chia cho 0, truy cập
mảng vượt quá chỉ số, hoặc lỗi không xử lý dữ liệu đầu vào không hợp lệ. Khi một Exception xảy
ra, nó sẽ tạo ra một đối tượng Exception chứa thông tin về lỗi và ném ra (throw) cho phần code
gọi đến.
Trong ngôn ngữ lập trình, để xử lý Exceptions, chúng ta sử dụng các khối try-catch. Khối try bao
bọc các dòng code có thể gây ra Exception. Nếu một Exception xảy ra trong khối try, nó sẽ được
ném ra (throw) và các khối catch liên quan sẽ được kiểm tra để tìm xem có xử lý Exception đó
hay không. Nếu một khối catch phù hợp được tìm thấy, nó sẽ được thực thi để xử lý Exception.
Ví dụ, trong Java, một đoạn code xử lý Exception có thể trông như sau:
try {
// Các dòng code có thể gây ra Exception
} catch (ExceptionType1 e1) {
// Xử lý ExceptionType1
} catch (ExceptionType2 e2) {
// Xử lý ExceptionType2
} finally {
// Mã được thực thi sau khi try-catch kết thúc (tùy chọn)
}
Trong ví dụ trên, các khối catch sẽ kiểm tra xem Exception có phù hợp với loại nào và xử lý
tương ứng. Nếu không có khối catch phù hợp, Exception sẽ được ném ra tiếp theo để kiểm tra
tại các phạm vi gọi đến khác.
Xử lý Exceptions giúp chương trình có khả năng xử lý các tình huống bất thường và tránh việc
chương trình bị dừng do lỗi.
4.2. Syntax Error
Lỗi Syntax Error là một loại lỗi trong lập trình xảy ra khi mã nguồn không tuân thủ cú pháp của
ngôn ngữ lập trình. Điều này có nghĩa là bạn đã viết một cấu trúc, một từ khóa hoặc một phần
tử không đúng cách trong mã nguồn của bạn.
Ví dụ, trong ngôn ngữ Java, nếu bạn quên dấu chấm phẩy (;) ở cuối mỗi dòng lệnh, hoặc không
đóng các dấu ngoặc ({}) đúng cách, bạn sẽ gặp lỗi Syntax Error. Dưới đây là một số ví dụ về lỗi
Syntax Error:
Quên dấu chấm phẩy (;) ở cuối dòng lệnh:
int a = 5
Không đóng dấu ngoặc nhọn ({}):
for (int i = 0; i < 10; i++
{
// Code xử lý
}
Sử dụng từ khóa không đúng cách:
int int = 10;
Sử dụng cú pháp không hợp lệ:
if (x > 5) then {
// Code xử lý
}
Khi gặp lỗi Syntax Error, trình biên dịch hoặc môi trường phát triển tích hợp (IDE) sẽ thông báo
lỗi cụ thể và chỉ ra vị trí mà lỗi xảy ra trong mã nguồn. Để khắc phục lỗi này, bạn cần xem xét lại
cú pháp và sửa chữa mã nguồn để tuân thủ cú pháp của ngôn ngữ lập trình đang sử dụng.
4.3. Runtime Error
Lỗi Runtime Error (Lỗi Thời gian chạy) là một loại lỗi trong lập trình xảy ra khi chương trình đang
thực thi và gặp phải một vấn đề không mong muốn. Lỗi này không phải là lỗi cú pháp và không
được phát hiện trong quá trình biên dịch, mà chỉ xảy ra khi chương trình đang chạy.
Dưới đây là một số ví dụ về lỗi Runtime Error:
Lỗi Chia cho 0 (Divide By Zero Error): Khi chúng ta chia một số cho 0, lỗi này sẽ xảy ra. Ví
dụ:
x = 10 / 0
Lỗi Truy cập Mảng Vượt quá chỉ số (Array Index Out of Bounds Error): Khi chúng ta truy
cập vào một phần tử trong mảng bằng một chỉ số không hợp lệ, lỗi này sẽ xảy ra. Ví dụ:
int[] array = {1, 2, 3};
int element = array[5]; // Lỗi vượt quá chỉ số mảng
Lỗi Null Pointer (Null Pointer Exception): Khi chúng ta cố gắng truy cập vào một đối
tượng null hoặc không được khởi tạo, lỗi này xảy ra. Ví dụ:
String str = null;
int length = str.length(); // Lỗi null pointer
Lỗi Stack Overflow: Khi chúng ta gọi đệ quy một cách vô hạn hoặc có quá nhiều lời gọi
hàm chồng chất, lỗi này sẽ xảy ra. Ví dụ:
def recursive_function():
recursive_function()
recursive_function() # Lỗi stack overflow
Lỗi Type Error: Khi chúng ta thực hiện một phép toán không hợp lệ hoặc không tương
thích với kiểu dữ liệu, lỗi này sẽ xảy ra. Ví dụ:
var result = "Hello" + 5; // Lỗi type error
Khi một lỗi Runtime Error xảy ra, chương trình sẽ dừng lại và thông báo lỗi. Để khắc phục lỗi
này, chúng ta cần xem xét và sửa chữa mã nguồn, kiểm tra các giá trị đầu vào, xử lý các trường
hợp đặc biệt và đảm bảo rằng chương trình không gặp phải các tình huống không mong muốn
trong quá trình thực thi.
4.4. Memory Management Error
Lỗi Quản lý bộ nhớ (Memory Management Error) là một loại lỗi trong lập trình xảy ra khi quá
trình quản lý bộ nhớ không được thực hiện đúng cách. Các lỗi quản lý bộ nhớ có thể gây ra các
vấn đề như rò rỉ bộ nhớ (memory leak), truy cập vào bộ nhớ không hợp lệ, hoặc gây ra hiện
tượng "double free" (giải phóng bộ nhớ hai lần).
Dưới đây là một số lỗi quản lý bộ nhớ phổ biến:
Rò rỉ bộ nhớ (Memory Leak): Lỗi này xảy ra khi một phần của bộ nhớ được cấp phát
không được giải phóng sau khi không còn cần thiết. Điều này dẫn đến việc tiêu tốn
nguồn tài nguyên và có thể gây ra sự suy giảm hiệu suất hoặc hết bộ nhớ.
Truy cập vào bộ nhớ không hợp lệ (Invalid Memory Access): Lỗi này xảy ra khi chúng ta
cố gắng truy cập vào một vùng bộ nhớ không được cấp phát hoặc đã được giải phóng.
Kết quả có thể là crash chương trình hoặc dữ liệu không chính xác.
Double Free: Lỗi này xảy ra khi chúng ta giải phóng một vùng bộ nhớ hai lần. Điều này có
thể dẫn đến sự xáo trộn trong việc quản lý bộ nhớ và gây ra lỗi không xác định hoặc
crash chương trình.
Derefencing Null Pointer: Lỗi này xảy ra khi chúng ta cố gắng truy cập vào một con trỏ
null. Khi một con trỏ không được khởi tạo hoặc được gán giá trị null, việc truy cập vào
nó sẽ gây ra lỗi.
Buffer Overflow: Lỗi này xảy ra khi chúng ta ghi dữ liệu ngoài giới hạn vùng nhớ được
cấp phát. Điều này có thể dẫn đến việc ghi đè dữ liệu quan trọng hoặc ghi đè lên bộ nhớ
khác.
Để tránh lỗi quản lý bộ nhớ, cần tuân thủ các quy tắc và phương pháp quản lý bộ nhớ
đúng cách. Điều này bao gồm cấp phát và giải phóng bộ nhớ theo đúng thứ tự, sử dụng
các hàm và công cụ quản lý bộ nhớ một cách chính xác, và kiểm tra và xử lý các lỗi liên
quan đến bộ nhớ một cách cẩn thận.
Để tránh lỗi quản lý bộ nhớ, cần tuân thủ các quy tắc và phương pháp quản lý bộ nhớ đúng
cách. Điều này bao gồm cấp phát và giải phóng bộ nhớ theo đúng thứ tự, sử dụng các hàm
và công cụ quản lý bộ nhớ một cách chính xác, và kiểm tra và xử lý các lỗi liên quan đến bộ
nhớ một cách cẩn thận.
4.5. Logic Error
Lỗi Logic (Logic Error) là một loại lỗi trong lập trình xảy ra khi chương trình không hoạt động
chính xác vì có sai sót trong logic của mã. Lỗi này không phải là lỗi cú pháp hoặc lỗi thời gian
chạy, mà là do cách mà chương trình đã được thiết kế và triển khai.
Dưới đây là một số ví dụ về lỗi Logic Error:
Sai điều kiện trong câu lệnh rẽ nhánh (Conditional Statement): Lỗi này xảy ra khi
chúng ta không đặt các điều kiện đúng trong câu lệnh rẽ nhánh if, else if hoặc switch.
Điều này có thể dẫn đến việc thực thi sai mã hoặc bỏ qua các trường hợp quan
trọng.
Lỗi Toán tử (Operator Error): Lỗi này xảy ra khi chúng ta sử dụng toán tử không đúng
hoặc không áp dụng đúng logic. Điều này có thể dẫn đến kết quả không chính xác
hoặc không mong muốn.
Lỗi Vòng lặp (Loop Error): Lỗi này xảy ra khi vòng lặp không được kiểm soát hoặc
điều kiện thoát khỏi vòng lặp không đúng. Điều này có thể dẫn đến lặp vô hạn hoặc
không đủ lặp.
Lỗi Hàm (Function Error): Lỗi này xảy ra khi chúng ta triển khai hàm không đúng hoặc
không trả về kết quả chính xác. Điều này có thể dẫn đến việc lỗi tính toán hoặc kết
quả không chính xác.
Lỗi Xử lý Dữ liệu (Data Handling Error): Lỗi này xảy ra khi chúng ta không xử lý dữ liệu
đúng cách, bao gồm việc gán giá trị sai cho biến, không kiểm tra giá trị đầu vào hoặc
không xử lý các trường hợp đặc biệt.
Để khắc phục lỗi Logic Error, chúng ta cần xem xét và sửa chữa logic của mã. Điều này bao
gồm kiểm tra và xác định các lỗi logic, sử dụng các điều kiện và toán tử đúng, kiểm tra và
sửa đổi vòng lặp, kiểm tra kết quả hàm, và đảm bảo xử lý đúng dữ liệu. Gỡ rối (debugging)
và kiểm thử (testing) cũng là phần quan trọng trong việc tìm và sửa lỗi logic.
4.6. File Handling Error
Lỗi xử lý tệp tin (File Handling Error) là một loại lỗi trong lập trình xảy ra khi chương trình
gặp vấn đề trong việc đọc, ghi hoặc xử lý tệp tin. Các lỗi xử lý tệp tin có thể gây ra việc mất
dữ liệu, không thể truy cập tệp tin hoặc không thực hiện được các thao tác mong muốn trên
tệp tin.
Dưới đây là một số ví dụ về lỗi xử lý tệp tin:
Lỗi không tìm thấy tệp tin (File Not Found Error): Lỗi này xảy ra khi chương trình
không thể tìm thấy tệp tin được yêu cầu. Có thể do đường dẫn không chính xác, tên
tệp tin sai hoặc tệp tin không tồn tại.
Lỗi không thể mở tệp tin (File Open Error): Lỗi này xảy ra khi chương trình không thể
mở tệp tin để đọc hoặc ghi. Nguyên nhân có thể là tệp tin bị khóa bởi một quy trình
khác, quyền truy cập bị từ chối hoặc tệp tin bị hỏng.
Lỗi ghi tệp tin (File Write Error): Lỗi này xảy ra khi chương trình không thể ghi dữ liệu
vào tệp tin. Có thể do tệp tin bị khóa chỉ cho phép đọc, không đủ quyền ghi hoặc
không đủ không gian trên ổ đĩa.
Lỗi đọc tệp tin (File Read Error): Lỗi này xảy ra khi chương trình không thể đọc dữ
liệu từ tệp tin. Có thể do tệp tin bị hỏng, không đủ quyền truy cập hoặc định dạng dữ
liệu không đúng.
Lỗi đóng tệp tin (File Close Error): Lỗi này xảy ra khi chương trình không thể đóng tệp
tin sau khi hoàn thành thao tác. Điều này có thể dẫn đến rò rỉ tài nguyên hoặc không
thể truy cập tệp tin sau này.
Để khắc phục lỗi xử lý tệp tin, chúng ta cần kiểm tra và xử lý các điều kiện đặc biệt như tệp
tin không tồn tại, quyền truy cập bị từ chối hoặc tệp tin bị hỏng. Sử dụng các phương pháp
xử lý ngoại lệ (exception handling) cũng là cách hiệu quả để xử lý lỗi xử lý tệp tin. Đảm bảo
rằng các tệp tin được đóng đúng cách sau khi hoàn thành các thao tác cũng là một yếu tố
quan trọng để tránh lỗi xử lý tệp tin.
4.7. Error Handling Errors
Lỗi xử lý lỗi (Error Handling Errors) là một loại lỗi xảy ra khi việc xử lý lỗi trong chương trình
không được thực hiện đúng cách hoặc bị bỏ qua. Điều này có thể gây ra các vấn đề như
không hiển thị thông báo lỗi, không phục hồi được từ lỗi hoặc không xử lý các trường hợp
ngoại lệ một cách đúng đắn.
Dưới đây là một số ví dụ về Error Handling Errors:
Bỏ qua lỗi: Đây là trường hợp khi lỗi xảy ra nhưng chương trình không kiểm tra hoặc
không xử lý lỗi một cách đúng đắn. Thay vì hiển thị thông báo lỗi hoặc thực hiện các
biện pháp phục hồi, chương trình tiếp tục thực thi mà không có hành động phù hợp.
Điều này có thể gây ra các lỗi tiềm ẩn và gây khó khăn trong việc tìm ra nguyên nhân
gốc rễ của vấn đề.
Xử lý lỗi không đúng: Đây là trường hợp khi chương trình xử lý lỗi một cách không
đúng đắn. Ví dụ, chương trình có thể hiển thị thông báo lỗi không rõ ràng, không
cung cấp thông tin chi tiết về lỗi, hoặc thực hiện các biện pháp phục hồi không chính
xác. Điều này có thể làm cho việc gỡ lỗi và sửa lỗi trở nên khó khăn hơn.
Không phục hồi được từ lỗi: Đây là trường hợp khi chương trình không thể phục hồi
từ lỗi và tiếp tục thực thi một cách bất thường. Thay vì thực hiện các biện pháp phục
hồi hoặc thoát khỏi chương trình một cách an toàn, chương trình có thể gây ra các
lỗi tiếp theo hoặc dẫn đến trạng thái không ổn định.
Khắc phục Error Handling Errors:
Sử dụng cấu trúc điều kiện để kiểm tra và xử lý lỗi một cách đúng đắn.
Hiển thị thông báo lỗi rõ ràng và cung cấp thông tin chi tiết về lỗi.
Ghi lại các lỗi trong tệp nhật ký (log file) để dễ dàng gỡ lỗi và xác định nguyên nhân
gốc rễ.
Xử lý các trường hợp ngoại lệ bằng cách sử dụng cơ chế xử lý ngoại lệ như try-catch.
Đảm bảo rằng mã chương trình được kiểm tra và xử lý lỗi trong các kịch bản kiểm
thử đa dạng.
Sử dụng các thư viện hoặc framework hỗ trợ xử lý lỗi một cách hiệu quả, chẳng hạn
như thư viện log, thư viện xử lý ngoại lệ, hoặc framework kiểm thử tự động.
Bằng cách tuân thủ các quy tắc và quy ước lập trình tốt, nhà phát triển có thể giảm thiểu số
lượng lỗi xử lý lỗi và tăng tính ổn định và đáng tin cậy của chương trình.
4.8. String Handling Errors
Lỗi xử lý chuỗi (String Handling Errors) là các lỗi xảy ra trong quá trình xử lý chuỗi trong
chương trình. Đây là một vấn đề phổ biến trong lập trình và có thể dẫn đến các hậu quả như
lỗi logic, kết quả không chính xác hoặc sự cố chương trình.
Dưới đây là một số lỗi phổ biến liên quan đến xử lý chuỗi:
Lỗi truy cập ngoài giới hạn mảng: Đây là trường hợp khi chúng ta cố gắng truy cập
vào một vị trí không hợp lệ trong chuỗi, ví dụ như truy cập vào một chỉ số âm hoặc
vượt quá kích thước của chuỗi. Điều này có thể dẫn đến lỗi chương trình hoặc kết
quả không chính xác.
Lỗi cấp phát bộ nhớ không đủ: Khi làm việc với chuỗi động (dynamic string), chúng ta
có thể gặp phải lỗi khi cấp phát bộ nhớ không đủ cho chuỗi. Điều này xảy ra khi
chúng ta không kiểm tra được kích thước của chuỗi hoặc không xử lý các trường hợp
cấp phát bộ nhớ không thành công.
Lỗi xử lý ký tự đặc biệt: Trong xử lý chuỗi, có thể xảy ra lỗi khi không xử lý đúng các
ký tự đặc biệt như dấu nháy kép, ký tự backslash (), hoặc ký tự đặc biệt trong mã
Unicode. Điều này có thể gây ra sai sót trong các xử lý như ghi hoặc đọc chuỗi từ tệp
tin.
Lỗi mã hóa và giải mã: Khi làm việc với các chuỗi có mã hóa hoặc giải mã đặc biệt
như UTF-8, UTF-16, hoặc Base64, có thể xảy ra lỗi khi không xử lý chính xác quá trình
mã hóa hoặc giải mã. Điều này có thể dẫn đến kết quả không chính xác hoặc lỗi trong
việc xử lý dữ liệu.
Lỗi định dạng chuỗi: Khi chúng ta thực hiện các thao tác định dạng chuỗi như ghép
nối (concatenation), định dạng (formatting) hoặc phân tách (splitting), có thể xảy ra
lỗi nếu không xử lý đúng các quy tắc và định dạng của chuỗi. Ví dụ, việc sử dụng sai
ký tự định dạng hoặc thứ tự các đối số trong định dạng chuỗi có thể dẫn đến lỗi kết
quả.
Để khắc phục các lỗi xử lý chuỗi, hãy áp dụng những phương pháp và quy ước lập trình tốt
sau:
Kiểm tra và xử lý kích thước và giới hạn mảng khi làm việc với chuỗi.
Đảm bảo cấp phát đủ bộ nhớ cho chuỗi động và xử lý các trường hợp cấp phát bộ
nhớ không thành công.
Xử lý chính xác các ký tự đặc biệt và mã hóa/giải mã chuỗi khi cần thiết.
Tuân thủ các quy tắc và định dạng chuỗi khi thực hiện các thao tác như ghép nối,
định dạng hoặc phân tách chuỗi.
4.9.
4.10.
5. Thu hoạch kết thúc môn học
5.1. How to work in Software Project ?
5.1.1 Software Project Activities
Quản lý dự án:
Planning: Lập kế hoạch dự án, xác định các bước tiến hành và lịch trình.
Tracking: Theo dõi tiến độ dự án, đảm bảo thực hiện đúng kế hoạch.
Closure: Hoàn thành dự án, đánh giá kết quả và rút kinh nghiệm.
Kỹ thuật:
Requirements Analyzing: Phân tích yêu cầu của dự án phần mềm.
Designing: Thiết kế các thành phần và cấu trúc của phần mềm.
Coding: Lập trình, viết mã nguồn cho phần mềm.
Testing: Kiểm thử phần mềm để đảm bảo chất lượng và tính năng hoạt động đúng.
Configuration Management: Quản lý các phiên bản và thay đổi trong quá trình phát triển
phần mềm.
Deployment (Installation): Triển khai và cài đặt phần mềm trên môi trường thực tế.
Maintenance: Bảo trì, sửa chữa và nâng cấp phần mềm sau khi triển khai.
Customer Support: Hỗ trợ khách hàng sử dụnggiải quyết vấn đề liên quan đến phần
mềm.
5.1.2. Software Project Lifecycle
Dự án phát triển phần mềm:
Khởi đầu (Inception): Xác định nhu cầu mục tiêu của dự án, đánh giá tính khả thi
xác định phạm vi.
Định nghĩa (Definition): Thu thập yêu cầu, phân tích, thiết kế khối và xác định cấu trúc tổ
chức.
Giải pháp (Solution): Xây dựng, kiểm tra và kiểm soát quy trình phát triển phần mềm.
Xây dựng (Construction): Lập trình, kiểm thử và tích hợp các thành phần phần mềm.
Chuyển giao (Transition): Triển khai, huấn luyện, hỗ trợ chuyển giao phần mềm cho
khách hàng.
Kết thúc (Closure): Đánh giá dự án, rút kinh nghiệm hoàn thành các công việc cuối
cùng.
Dự án bảo trì phần mềm:
Phân tích (Analysis): Phân tích yêu cầu bảo trì, xác định vấn đề và thiết kế giải pháp.
Thiết kế (Design): Thiết kế các thay đổi, xác định phạm vi và tạo kế hoạch bảo trì.
Triển khai (Implementation): Thực hiện các thay đổi, kiểm thử tích hợp vào phần
mềm hiện có.
Kiểm tra (Testing): Kiểm tra phần mềm sau các thay đổi để đảm bảo tính năng chất
lượng.
Phân phối (Delivery): Triển khai, chuyển giao cung cấp phiên bản phần mềm đã bảo
trì.
Kết thúc (Closure): Đánh giá quá trình bảo trì, rút kinh nghiệm hoàn thành các công
việc cuối cùng.
5.1.3. Project Roles & Responsibilities
Tổ chức dự án:
Project Manager: Quản toàn bộ dự án, lập kế hoạch, theo dõi tiến độ và đảm bảo đạt
được mục tiêu dự án.
Technical/Team Leader: Đứng đầu nhóm kỹ thuật, phân công nhiệm vụ, giám sát công
việc và hỗ trợ thành viên nhóm.
Business Analyst (BA): Phân tích yêu cầu của khách hàng, xác định nhu cầu thiết kế
giải pháp phần mềm.
Developer: Lập trình, viết mã nguồn và xây dựng các thành phần của phần mềm.
Tester: Kiểm thử phần mềm, tìm lỗi và đảm bảo chất lượng sản phẩm.
Quality Assurance (QA): Đảm bảo tính chính xác đáng tin cậy của phần mềm, thực
hiện kiểm tra và kiểm soát chất lượng.
Các vai trò khác trong dự án:
Technical Architect: Thiết kế kiến trúc phần mềm và hướng dẫn việc triển khai.
Database Administrator (DBA): Quản lý cơ sở dữ liệu, đảm bảo hiệu suất và bảo mật.
User Interface (UI)/User Experience (UX) Designer: Thiết kế giao diện người dùng hấp
dẫn và tương tác tốt.
System Administrator: Quản lý môi trường phát triển và triển khai phần mềm.
Technical Writer: Tạo tài liệu hướng dẫn sử dụng và tài liệu kỹ thuật.
Customer/Client: Người đại diện cho khách hàng, cung cấp yêu cầu và phản hồi.
5.1.4. Tasks to be done in each stage
Giai đoạn khởi đầu (Inception):
Xác định nhiệm vụ và mục tiêu của dự án.
Phân tích tính khả thi và xác định phạm vi dự án.
Lập kế hoạch tổng quan cho dự án.
Xác định các rủi ro ban đầu và tiến hành đánh giá rủi ro.
Xác định các bên liên quan và thiết lập mối quan hệ với khách hàng.
Giai đoạn định nghĩa (Definition):
Thu thập yêu cầu của khách hàng và đưa ra đặc tả yêu cầu.
Phân tích yêu cầu, xác định chức năng và phi chức năng.
Thiết kế kiến trúc tổng quan cho phần mềm.
Xác định các thành phần chính và xác định các phụ thuộc giữa các thành phần.
Xác định phạm vi dự án chi tiết và lập kế hoạch chi tiết cho giai đoạn tiếp theo.
Giai đoạn giải pháp (Solution):
Xây dựng các thành phần phần mềm.
Kiểm thử và tích hợp các thành phần.
Đánh giá và giám sát hiệu suất của phần mềm.
Thực hiện kiểm tra chất lượng phần mềm.
Đảm bảo tuân thủ quy trình và quy định phát triển phần mềm.
Giai đoạn xây dựng (Construction):
Lập trình và viết mã nguồn cho các thành phần phần mềm.
Kiểm thử và sửa lỗi trong quá trình xây dựng.
Tích hợp các thành phần và kiểm tra tính tương thích.
Xây dựng và kiểm tra giao diện người dùng.
Đảm bảo mã nguồn và tài liệu được quản lý và bảo mật.
Giai đoạn chuyển giao (Transition):
Triển khai phần mềm trong môi trường thực tế.
Huấn luyện người dùng và cung cấp hỗ trợ.
Đảm bảo tính ổn định và hiệu suất của phần mềm.
Tiếp nhận phản hồi từ người dùng và xử lý các vấn đề phát sinh.
Hoàn thiện tài liệu và báo cáo dự án.
Giai đoạn kết thúc (Closure):
Đánh giá kết quả của dự án và so sánh với mục tiêu đề ra.
Rút kinh nghiệm từ dự án và tạo báo cáo tổng kết.
Đảm bảo việc hoàn thành các công việc cuối cùng và giao nộp tài liệu.
Lập kế hoạch cho việc bảo trì và hỗ trợ sau triển khai.
Tổ chức buổi họp cuối cùng với khách hàng để đánh giá sự hài lòng và thu thập phản hồi.
5.1.5. Communication in Projects
1. Kế hoạch giao tiếp: Đây là quá trình lập kế hoạch cho các hoạt động giao tiếp trong dự
án. Kế hoạch này bao gồm xác định các bên liên quan, phương tiện giao tiếp, lịch trình
và phạm vi giao tiếp.
2. Các phương tiện giao tiếp: Các dự án sử dụng nhiều phương tiện giao tiếp khác nhau,
bao gồm cuộc họp trực tiếp, email, cuộc gọi điện thoại, tin nhắn, công cụ giao tiếp trực
tuyến như Slack hay Microsoft Teams, và các công cụ quản lý dự án như Jira hay Trello.
3. Truyền thông nội bộ: Giao tiếp trong dự án bao gồm cả truyền thông nội bộ trong nhóm
dự án. Điều này bao gồm việc chia sẻ thông tin, ý kiến và thông báo giữa các thành viên
trong nhóm để đảm bảo hiểu rõ mục tiêu, nhiệm vụ và tiến độ dự án.
4. Giao tiếp với khách hàng: Giao tiếp với khách hàng là một phần quan trọng để hiểu và
đáp ứng yêu cầu của họ. Điều này có thể bao gồm cuộc họp, báo cáo tiến độ, thảo luận
với khách hàng để xác định yêu cầu mới hoặc thay đổi, và cung cấp các bản cập nhật về
dự án.
5. Giao tiếp hiệu quả: Giao tiếp hiệu quả là khả năng truyền đạt thông tin một cách rõ ràng
và đảm bảo sự hiểu biết đúng đắn. Điều này bao gồm việc lựa chọn phương tiện giao
tiếp phù hợp, sử dụng ngôn ngữ rõ ràng và tránh nhầm lẫn, lắng nghe và hiểu quan điểm
của người khác và kiểm tra lại sự hiểu biết.
6. Giao tiếp trong văn bản: Việc lưu trữ thông tin dự án trong văn bản là rất quan trọng.
Đảm bảo rằng tài liệu, báo cáo, biên bản cuộc họp và email được ghi lại một cách rõ ràng
và có thể tra cứu sau này.
7. Giao tiếp không chính thức: Ngoài giao tiếp chính thức, giao tiếp không chính thức như
trò chuyện bên lề, giao tiếp qua các kênh xã hội nội bộ và các hoạt động giao tiếp không
chính thức khác có thể giúp tạo ra môi trường làm việc thoải mái và tăng cường sự gắn
kết trong nhóm dự án.
5.2. Software Requirement Concepts
5.2.1. Requirement Concepts
1. Định nghĩa yêu cầu: Yêu cầu được định nghĩa là một tuyên bố về dịch vụ mà hệ thống
phải thực hiện hoặc ràng buộc mà hệ thống phải đáp ứng.
2. Lý do chúng ta cần yêu cầu: Đề mục này giải thích vì sao chúng ta cần yêu cầu phần
mềm. Yêu cầu giúp xác định và giới hạn phạm vi dự án phần mềm, là cơ sở để đưa ra
hợp đồng và tạo ra các kế hoạch phát triển.
3. Mục đích của yêu cầu: Yêu cầu thường phục vụ như là cơ sở cho việc đấu thầu hợp
đồng, do đó phải được mô tả ở mức cao để mở ra nhiều cách hiểu. Ngoài ra, yêu cầu
cũng phải được chi tiết hóa để trở thành cơ sở cho hợp đồng chính thức.
4. Những gì không phải là yêu cầu: Đề mục này nêu rõ những điều không phải là yêu cầu.
Điều này bao gồm các chi tiết thiết kế hoặc triển khai (ngoại trừ ràng buộc đã biết),
thông tin về kế hoạch dự án và thông tin về kiểm thử.
5. Phân loại yêu cầu: Đề mục này giới thiệu về phân loại yêu cầu. Yêu cầu có thể được phân
loại là chức năng và phi chức năng. Yêu cầu chức năng mô tả các dịch vụ mà hệ thống
phải thực hiện, trong khi yêu cầu phi chức năng mô tả các ràng buộc mà hệ thống phải
tuân thủ.
5.2.3. Requirement Modeling
1. Mục đích: Mục đích chính của mô hình hóa yêu cầu là ghi lại, phân tích và biểu diễn yêu cầu
phần mềm một cách cấu trúc và có tổ chức. Nó giúp các bên liên quan có cái nhìn rõ ràng về
những gì hệ thống cần phải thực hiện.
2. Kỹ thuật và công cụ: Mô hình hóa yêu cầu sử dụng các kỹ thuật và công cụ khác nhau để tạo
ra biểu đồ biểu diễn yêu cầu. Một số kỹ thuật mô hình hóa phổ biến bao gồm:
Biểu đồ Use Case: Biểu đồ Use Case mô tả các tương tác giữa các bên tác động (người
dùng, hệ thống hoặc các thành phần bên ngoài) và hệ thống để hoàn thành các mục tiêu
hoặc nhiệm vụ cụ thể.
Sơ đồ luồng dữ liệu (Data Flow Diagram - DFD): Sơ đồ luồng dữ liệu mô tả cách dữ liệu
chảy qua hệ thống và cách nó được xử lý hoặc biến đổi bởi các thành phần khác nhau.
Biểu đồ hoạt động (Activity Diagram): Biểu đồ hoạt động hiển thị quy trình hoạt động
hoặc quy trình làm việc trong hệ thống, bao gồm các nhánh, song song và điểm quyết
định.
Biểu đồ trạng thái (State Machine Diagram): Biểu đồ trạng thái biểu diễn các trạng thái
khả thi của một đối tượng hoặc hệ thống và cách nó chuyển đổi từ trạng thái này sang
trạng thái khác dựa trên các sự kiện hoặc điều kiện.
Biểu đồ lớp (Class Diagram): Biểu đồ lớp miêu tả cấu trúc tĩnh của hệ thống, bao gồm
các lớp, thuộc tính, mối quan hệ và phương thức của chúng.
Biểu đồ trình tự (Sequence Diagram): Biểu đồ trình tự mô tả trình tự các tương tác giữa
các đối tượng hoặc thành phần trong hệ thống theo thời gian.
Sơ đồ thực thể - mối quan hệ (Entity-Relationship Diagram - ERD): ERD được sử dụng để
mô hình hóa cấu trúc và mối quan hệ giữa các thực thể dữ liệu trong hệ thống.
3. Lợi ích: Mô hình hóa yêu cầu mang lại nhiều lợi ích, bao gồm:
Hiểu rõ hơn: Biểu đồ giúp các bên liên quan hiểu và xác nhận yêu cầu, từ đó cải thiện
việc giao tiếp vàxác thực yêu cầu.
Phát hiện vấn đề sớm: Mô hình hóa giúp phát hiện những không nhất quán, mơ hồ hoặc
yêu cầu thiếu, giúp phát hiện và giải quyết vấn đề sớm.
Theo dõi yêu cầu: Các mô hình cung cấp một con đường rõ ràng để theo dõi yêu cầu,
giúp phân tích tác động và quản lý thay đổi yêu cầu.
Tài liệu và tạo tài liệu: Các mô hình là tài liệu thể hiện có thể chia sẻ, xem xét và cập nhật
trong suốt quá trình phát triển phần mềm. Chúng cũng có thể được sử dụng để tạo ra
các tài liệu khác như tài liệu sử dụng, hướng dẫn và tài liệu kiểm thử.
5.2.3. System Modeling Tools
1. Enterprise Architect: Enterprise Architect là một công cụ mô hình hóa
hệ thống mạnh mẽ và đa nền tảng. Nó hỗ trợ nhiều kỹ thuật mô hình
hóa, bao gồm UML, BPMN, SysML và các biểu đồ khác. Nó cung cấp
tính năng hợp tác nhóm, quản lý yêu cầu, và tích hợp với các công cụ
phát triển phần mềm khác.
2. MagicDraw: MagicDraw là một công cụ mô hình hóa hệ thống phổ
biến, tương thích với các tiêu chuẩn UML, SysML và BPMN. Nó cung
cấp các tính năng mạnh mẽ để tạo và quản lý các biểu đồ UML, mô
hình hóa hệ thống và phân tích yêu cầu. MagicDraw có tích hợp với
các công cụ quản lý yêu cầu và hỗ trợ việc xuất bản tài liệu.
3. Rational Rose: Rational Rose của IBM là một công cụ mô hình hóa hệ
thống UML phổ biến. Nó cung cấp các tính năng đa dạng để tạo ra
các biểu đồ lớp, biểu đồ hoạt động, biểu đồ trạng thái và nhiều biểu
đồ khác. Rational Rose hỗ trợ tích hợp với các công cụ phát triển
phần mềm khác trong quá trình phát triển.
4. Sparx Systems Enterprise Architect: Enterprise Architect của Sparx
Systems là một công cụ mô hình hóa hệ thống UML, SysML và BPMN.
Nó cung cấp một giao diện đồ họa dễ sử dụng cho việc tạo và quản lý
mô hình hóa hệ thống. Công cụ này hỗ trợ tích hợp với các công cụ
quản lý yêu cầu và hỗ trợ việc phát triển phần mềm.
5. Visual Paradigm: Visual Paradigm là một công cụ mô hình hóa hệ
thống linh hoạt hỗ trợ nhiều ngôn ngữ mô hình hóa như UML, BPMN,
SysML và ERD. Nó cung cấp các tính năng phong phú để thiết kế và
phân tích yêu cầu, tạo và quản lý mô hình hóa hệ thống. Công cụ này
cũng hỗ trợ tích hợp với các công cụ phát triển phần mềm và quản lý
yêu cầu.
5.3. Common Architectures
5.3.1.
1. Kiến trúc phần mềm là một bản thiết kế kỹ thuật mô tả cách hệ thống sẽ được cấu trúc
và tổ chức. Nó định nghĩa cách các thành phần của hệ thống tương tác với nhau và cung
cấp một khung làm việc để phát triển, triển khai và duy trì phần mềm.
2. Một hệ thống phần mềm có kiến trúc rõ ràng giúp cho việc phát triển phần mềm trở nên
dễ dàng hơn bằng cách tách riêng các thành phần và chức năng khác nhau. Nó giúp đảm
bảo sự phân chia rõ ràng của trách nhiệm và chức năng trong hệ thống, giúp dễ dàng
quản lý, bảo trì và mở rộng.
3. Kiến trúc phần mềm cũng mô tả cách các thành phần của hệ thống tương tác với nhau,
bao gồm cách chúng truyền thông qua giao diện và cơ chế truyền thông. Nó cung cấp
một cái nhìn tổng quan về cấu trúc tổng thể của hệ thống và giúp các nhà phát triển hiểu
rõ hơn về sự tương tác và phụ thuộc giữa các thành phần.
4. Ngoài ra, kiến trúc phần mềm cũng đề cập đến các nền tảng và công nghệ được sử dụng
trong hệ thống, bao gồm cách các thành phần được triển khai trên các môi trường cụ
thể.
5. Mỗi thành phần của kiến trúc phần mềm có thể thực hiện một mô hình / mẫu kiến trúc
cụ thể, như kiến trúc client-server, kiến trúc 3-tầng hoặc kiến trúc MVC. Những mô hình
này cung cấp các hướng dẫn và quy tắc cho việc thiết kế và triển khai các thành phần
trong hệ thống phần mềm.
5.3.2. Client-Server Architecture
Kiến trúc client-server là một mô hình phân tán trong đó một máy chủ (server) cung cấp các
dịch vụ và tài nguyên cho nhiều máy khách (client) thông qua mạng. Trong mô hình này, máy
chủ đóng vai trò là trung tâm điều khiển và quản lý các tài nguyên, trong khi máy khách sử dụng
các ứng dụng hoặc giao diện để truy cập và tương tác với máy chủ.
Máy chủ là một máy tính hoặc ứng dụng chạy trên máy tính, có khả năng cung cấp các dịch vụ
như lưu trữ dữ liệu, xử lý yêu cầu, thực hiện tính toán phức tạp, và đáp ứng các yêu cầu từ các
máy khách. Máy khách là các ứng dụng hoặc thiết bị mà người dùng sử dụng để truy cập và
tương tác với máy chủ. Các máy khách có thể là máy tính cá nhân, điện thoại di động, máy tính
bảng, hoặc bất kỳ thiết bị nào khác có khả năng kết nối mạng.
Trong mô hình client-server, máy chủ cung cấp các dịch vụ và tài nguyên như cơ sở dữ liệu, ứng
dụng web, dịch vụ web, hoặc tệp tin được lưu trữ trên máy chủ. Các máy khách giao tiếp với
máy chủ thông qua giao thức truyền thông như HTTP (cho ứng dụng web), FTP (cho truyền tệp
tin), hoặc TCP/IP (cho giao tiếp mạng).
Mô hình client-server cung cấp nhiều lợi ích, bao gồm:
Phân chia rõ ràng giữa nhiệm vụ xử lý và hiển thị, giúp quản lý mã nguồn dễ dàng hơn và
tái sử dụng được thành phần.
Cho phép điều chỉnh dễ dàng trong việc mở rộng hệ thống bằng cách thêm máy chủ
hoặc máy khách mới.
Dễ dàng thực hiện các tính năng bảo mật như xác thực và kiểm soát truy cập từ máy
chủ.
Tính linh hoạt và khả năng mở rộng trong việc phát triển ứng dụng và triển khai trên
nhiều nền tảng khác nhau.
Ví dụ về mô hình client-server bao gồm:
Máy chủ web (ví dụ: máy chủ Apache) cung cấp các trang web cho trình duyệt web của
người dùng (ví dụ: Google Chrome).
Máy chủ email (ví dụ: Microsoft Exchange Server) cung cấp dịch vụ email cho các ứng
dụng email như Microsoft Outlook hoặc Thunderbird.
Máy chủ cơ sở dữ liệu (ví dụ: MySQL Server) cung cấp dữ liệu cho các ứng dụng client
như ứng dụng quản lý cửa hàng hoặc ứng dụng di động.
Kiến trúc client-server là một trong những mô hình phổ biến nhất trong phát triển phần
mềm và hệ thống mạng, cung cấp một cách linh hoạt và hiệu quả để xây dựng các ứng
dụng và dịch vụ phân tán.
5.3.4. 3-Tier / Multi-Tier Architectures
Kiến trúc 3-tầng (hay còn gọi là kiến trúc multi-tầng) là một mô hình kiến trúc phần mềm phân
tách ứng dụng thành ba tầng hoặc ba lớp chức năng khác nhau. Các tầng này bao gồm:
Front-end (tầng giao diện người dùng): Tầng này chịu trách nhiệm cho việc hiển thị
thông tin và tương tác với người dùng. Nó bao gồm các thành phần như trình duyệt
web, ứng dụng di động, giao diện đồ họa, hoặc bất kỳ công cụ nào mà người dùng sử
dụng để tương tác với hệ thống. Tầng này tập trung vào giao diện người dùng và hiển thị
dữ liệu một cách hấp dẫn và thân thiện.
Middle tier (tầng trung gian/ tầng logic nghiệp vụ): Tầng này là nơi xử lý logic nghiệp vụ
của ứng dụng. Nó chịu trách nhiệm cho việc xử lý yêu cầu từ front-end và tương tác với
back-end. Tầng này chứa các thành phần như các dịch vụ web, logic xử lý dữ liệu, quản lý
luồng công việc, và các thành phần xử lý nghiệp vụ khác. Nhiệm vụ chính của tầng trung
gian là xử lý logic nghiệp vụ và chuyển tiếp dữ liệu giữa front-end và back-end.
Back-end (tầng dữ liệu): Tầng này chịu trách nhiệm quản lý và lưu trữ dữ liệu. Nó bao
gồm cơ sở dữ liệu (database) và các hệ thống quản lý cơ sở dữ liệu (DBMS) như MySQL,
Oracle, MongoDB, và nhiều hơn nữa. Tầng này xử lý yêu cầu từ tầng trung gian, thực
hiện truy vấn và cập nhật dữ liệu trong cơ sở dữ liệu và trả về kết quả cho tầng trung
gian.
Kiến trúc 3-tầng giúp phân tách rõ ràng giữa các phần khác nhau của ứng dụng và tạo ra sự tách
biệt giữa giao diện người dùng, logic nghiệp vụ và dữ liệu. Điều này giúp tăng tính linh hoạt, khả
năng bảo trì và mở rộng của hệ thống. Nó cũng cho phép phát triển độc lập của các tầng, cho
phép sử dụng lại và thay thế các thành phần một cách dễ dàng.
Ví dụ về kiến trúc 3-tầng bao gồm:
Một ứng dụng web: Front-end là trình duyệt web, middle tier chứa các dịch vụ web và
logic nghiệp vụ, back-end chứa cơ sở dữ liệu để lưu trữ thông tin.
Một ứng dụng di động: Front-end là ứng dụng di động, middle tier xử lý logic nghiệp vụ
và tương tác với các dịch vụ web, back-end chứa cơ sở dữ liệu để lưu trữ dữ liệu.
Lợi ích của kiến trúc 3-tầng bao gồm:
Phân tách rõ ràng: Kiến trúc này giúp phân tách rõ ràng giữa giao diện người dùng, logic
nghiệp vụ và dữ liệu, làm cho mã nguồn dễ quản lý và bảo trì hơn.
Tính mở rộng: Các tầng có thể được mở rộng độc lập nhau. Ví dụ, có thể thêm nhiều
máy chủ ứng dụng hoặc máy chủ cơ sở dữ liệu để tăng khả năng xử lý hoặc lưu trữ.
Tái sử dụng: Phân tách rõ ràng các tầng cho phép tái sử dụng các thành phần và logic
nghiệp vụ. Ví dụ, cùng một ứng dụng giao diện người dùng có thể được sử dụng cho
nhiều ứng dụng khác nhau.
5.3.4. MVC (Model-View-Controller)
MVC (Model-View-Controller) là một mô hình kiến trúc phần mềm phổ biến được sử dụng trong
phát triển ứng dụng. Nó tách biệt ứng dụng thành ba phần khác nhau: Model (Mô hình), View
(Giao diện) và Controller (Bộ điều khiển).
Model: Mô hình đại diện cho dữ liệu và logic nghiệp vụ của ứng dụng. Nó biểu diễn các
đối tượng, lớp, hoặc cấu trúc dữ liệu mà ứng dụng hoạt động với. Model chịu trách
nhiệm cho việc lấy dữ liệu từ nguồn dữ liệu (như cơ sở dữ liệu) và cung cấp các phương
thức để thao tác với dữ liệu đó. Nó không biết gì về giao diện người dùng hoặc cách dữ
liệu được hiển thị.
View: Giao diện đại diện cho cách dữ liệu được hiển thị cho người dùng. Nó là phần giao
diện người dùng mà người dùng tương tác và nhìn thấy. View nhận dữ liệu từ Model và
sắp xếp nó để hiển thị cho người dùng. View không chứa bất kỳ logic nghiệp vụ nào, chỉ
đơn giản là hiển thị dữ liệu.
Controller: Bộ điều khiển làm trung gian giữa Model và View. Nó nhận các yêu cầu từ
người dùng thông qua giao diện người dùng (View) và xử lý chúng. Controller chịu trách
nhiệm điều hướng luồng công việc, xử lý logic nghiệp vụ và tương tác với Model để lấy
và cập nhật dữ liệu. Sau đó, nó chuyển dữ liệu đã xử lý và kết quả đến View để hiển thị
cho người dùng.
MVC tạo ra sự phân tách rõ ràng giữa dữ liệu, giao diện người dùng và logic nghiệp vụ. Điều này
giúp cải thiện tính bảo trì, mở rộng và tái sử dụng của ứng dụng. Nó cũng giúp tăng tính hiệu
quả trong việc phát triển ứng dụng bằng cách phân chia công việc thành các phần độc lập và
cho phép các nhóm phát triển làm việc đồng thời trên các phần khác nhau của ứng dụng.
Quy trình hoạt động của MVC thường là như sau:
1. Người dùng tương tác với giao diện người dùng (View), ví dụ như nhấp vào một nút
hoặc nhập dữ liệu.
2. Giao diện người dùng (View) gửi yêu cầu tương ứng cho bộ điều khiển (Controller).
3. Bộ điều khiển (Controller) nhận yêu cầu, xử lý logic nghiệp vụ và tương tác với Model
nếu cần.
4. Model cung cấp dữ liệu cho bộ điều khiển (Controller).
5. Bộ điều khiển (Controller) chuyển dữ liệu đã xử lý đến giao diện người dùng (View).
6. Giao diện người dùng (View) nhận dữ liệu và hiển thị nó cho người dùng.
5.4. Design Process
5.4.1. Design Process
Overview: Giới thiệu tổng quan về quy trình thiết kế.
Purpose: Mô tả mục đích của quy trình thiết kế, bao gồm việc phát triển giải pháp cho các yêu
cầu và tạo ra các tài liệu thiết kế cấp cao và chi tiết.
Software Requirement Specification: Mô tả yêu cầu phần mềm để phát triển giải pháp.
Select from alternative solutions: Lựa chọn giải pháp từ các phương án thay thế.
Develop design documents: Phát triển các tài liệu thiết kế.
Review design documents: Xem xét và đánh giá các tài liệu thiết kế.
Alternative Design solutions: Các giải pháp thiết kế thay thế.
Evaluation Criteria: Tiêu chí đánh giá giải pháp thiết kế.
DAR report: Báo cáo về quyết định thiết kế đã được chấp thuận.
ADD, HLD, DDD: Các tài liệu thiết kế cấp cao (ADD), thiết kế cấp cao (HLD), và tài liệu thiết kế chi
tiết (DDD).
Approved Design Documents: Các tài liệu thiết kế đã được chấp thuận.
Develop the design: Quy trình phát triển thiết kế.
AD/HLD, DD: Bước và hoạt động liên quan đến thiết kế cấp cao (AD/HLD) và thiết kế chi tiết
(DD).
Review and approve high-level design: Xem xét và chấp thuận thiết kế cấp cao.
Detail design: Thiết kế chi tiết.
5.4.2. Design Workflow
Overview: Tổng quan về quy trình thiết kế.
A, B: Các bước trong quy trình thiết kế.
5.4.3. Design Documents:
High-Level Design:
Overview: Tổng quan về thiết kế cấp cao.
A High-Level Design: Một tài liệu thiết kế cấp cao cung cấp cái nhìn tổng quan về một giải
pháp, nền tảng, hệ thống, sản phẩm, dịch vụ hoặc quy trình.
High-Level Design Document Sample: Mẫu tài liệu thiết kế cấp cao.
Detailed Designs:
Screen Design Document: Tài liệu thiết kế màn hình, mô tả cấu trúc màn hình hoặc
chuyển tiếp giữa các màn hình và bao gồm danh sách các thành phần của màn hình và
hình ảnh minh họa.
Data Design Document: Tài liệu thiết kế dữ liệu, mô tả các sơ đồ mối quan hệ thực thể,
cấu trúc bảng, cấu trúc trường và cấu trúc tệp tin.
Class Design Document: Tài liệu thiết kế lớp, mô tả các gói COMMON, xử lý lỗi, ghi log,
tối ưu hiệu suất, sơ đồ lớp và sơ đồ trình tự, giao diện bên ngoài và khai báo phương
thức.
5.5. Code Design
5.5.1. Algorithmic Problem Solving
What is an algorithm? (Thuật toán là gì?): Phần này giải thích khái niệm về thuật toán, tức là
danh sách các bước để thực hiện một nhiệm vụ cụ thể.
Pseudo Code (Mã giả): Mã giả là một mô tả chi tiết và dễ đọc (bằng tiếng Anh đơn giản) về việc
một chương trình máy tính hoặc thuật toán cần làm gì.
Flowchart (Sơ đồ luồng): Sơ đồ luồng là biểu đồ minh họa cho chuỗi các hoạt động cần thực
hiện để giải quyết một vấn đề.
The Structure Theorem (Định lý cấu trúc): Phần này giới thiệu về các nguyên tắc cơ bản của cấu
trúc thuật toán, bao gồm tuần tự (sequence), lựa chọn (selection) và lặp (repetition).
5.5.2. Pseudo Code
What is Pseudo Code? (Mã giả là gì?): Phần này cung cấp hướng dẫn về việc viết mã giả và các
nguyên tắc hướng dẫn để tạo mã giả chính xác.
Guidelines for writing Pseudo Code (Hướng dẫn viết mã giả):
Phần này đưa ra các hướng dẫn cụ thể về cách viết mã giả, bao gồm các quy tắc và cấu trúc.
Basic computer operations (Các hoạt động cơ bản của máy tính):
Phần này liệt kê sáu hoạt động cơ bản mà máy tính có thể thực hiện.
Keywords and control structures (Từ khóa và cấu trúc điều khiển):
Phần này giới thiệu các từ khóa và cấu trúc điều khiển được sử dụng trong mã giả.
Indentation and subprograms (Thụt lề và các chương trình con): Phần này giải thích cách sử
dụng thụt lề để chỉ ra cấu trúc trong mã giả và cách sử dụng chương trình con (subprograms).
5.5.3. Flowchart
1. Overview (Sơ đồ luồng - Tổng quan):
Phần này cung cấp một cái nhìn tổng quan về sơ đồ luồng, bao gồm mục đích và lợi ích của việc
sử dụng sơ đồ luồng trong lập trình và giao tiếp giữa các nhà phát triển và người dùng kinh
doanh.
2. Basic Flowchart Symbols (Sơ đồ luồng - Các biểu tượng cơ bản):
Phần này giới thiệu các biểu tượng cơ bản được sử dụng trong sơ đồ luồng, bao gồm hộp tròn
(rounded box), hình chữ nhật (rectangle or box), hình thoi (diamond) và hình tròn (circle). Mỗi
biểu tượng đại diện cho một loại hoạt động hoặc quyết định trong quá trình giải quyết vấn đề.
3. Sample (Sơ đồ luồng - Mẫu):
5.5.4. The Structure Theorem
4. Sequential Structure (Cấu trúc tuần tự): Phần này giải thích về cấu trúc tuần tự trong
thuật toán, trong đó các câu lệnh được thực hiện theo thứ tự từ trên xuống dưới. Nó
bao gồm các ví dụ và hướng dẫn cách sử dụng cấu trúc tuần tự để giải quyết các vấn đề
cụ thể.
5. Selection Structure (Cấu trúc lựa chọn): Phần này giới thiệu về cấu trúc lựa chọn trong
thuật toán, trong đó một quyết định được đưa ra dựa trên một điều kiện. Nó bao gồm
các biểu thức điều kiện, cú pháp, và ví dụ về cách sử dụng cấu trúc lựa chọn để xử lý các
tình huống khác nhau.
6. Repetition Structure (Cấu trúc lặp): Phần này trình bày về cấu trúc lặp trong thuật toán,
cho phép thực hiện một tập hợp các câu lệnh nhiều lần dựa trên một điều kiện lặp. Nó
bao gồm các loại lặp, cú pháp và ví dụ về cách sử dụng cấu trúc lặp để giải quyết các vấn
đề có tính lặp lại.
7. Nesting Structures (Cấu trúc lồng nhau): Phần này giải thích về cách kết hợp cấu trúc
tuần tự, lựa chọn và lặp lại trong thuật toán bằng cách lồng chúng vào nhau. Nó cung
cấp các ví dụ về việc sử dụng cấu trúc lồng nhau để giải quyết các vấn đề phức tạp hơn.
5.6. Coding Process
5.6.1. Coding Process
Nơi thực hiện lập trình: Phần này giải thích nơi mà quá trình lập trình diễn ra.
Luồng làm việc trong quy trình lập trình: Mô tả các bước cơ bản trong quy trình lập trình, bao
gồm lập kế hoạch, xây dựng module thư viện, xây dựng module chức năng, tích hợp các thành
phần, tạo mô tả hệ thống và hoàn thành công việc.
5.6.2. Code Review Process
Kiểm tra mã lệnh: Mô tả quá trình kiểm tra kỹ thuật và logic từng dòng mã lệnh, tìm và sửa các
lỗi trong mã.
Lợi ích của việc kiểm tra mã lệnh: Đề cập đến những lợi ích của việc kiểm tra mã lệnh, bao gồm
khả năng tăng tốc độ và chất lượng phát triển, giảm lỗi và sự trùng lặp, cải thiện giao tiếp trong
nhóm và tăng sự đồng lòng của nhóm.
Các bước trong quy trình kiểm tra mã lệnh: Mô tả các bước cần thiết trong quy trình kiểm tra
mã lệnh, bao gồm chuẩn bị cho kiểm tra, tiến hành kiểm tra, đánh giá kết quả kiểm tra và tiếp
tục làm việc sau kiểm tra.
Vai trò và trách nhiệm của các thành viên trong quy trình kiểm tra mã lệnh: Đề cập đến vai trò
và trách nhiệm của các thành viên như người lãnh đạo, người viết mã, người kiểm tra và người
phê duyệt trong quy trình kiểm tra mã lệnh.
Đầu vào và đầu ra của quy trình kiểm tra mã lệnh: Mô tả các yếu tố cần thiết để thực hiện quy
trình kiểm tra mã lệnh, bao gồm mục tiêu kiểm tra, mã nguồn cần kiểm tra và các thành phần
liên quan khác như tài liệu, ca kiểm thử, lịch trình dự án và thay đổi yêu cầu.
5.6.3. Common Defects & Practices
Các lỗi phổ biến và thực hành: Liệt kê và mô tả các lỗi phổ biến trong quá trình lập trình và
những thực hành tốt để tránh các lỗi đó, bao gồm việc tránh sử dụng hằng số hard code, chỉ số
mảng bắt đầu từ 0.
5.7. Unit Testing Basics
5.7.1. Unit Test - What and Who?
Unit Test - Định nghĩa:
Định nghĩa về kiểm thử đơn vị: Kiểm thử đơn vị là một kỹ thuật kiểm thử phần mềm tập
trung vào việc kiểm thử từng đơn vị hoặc thành phần riêng lẻ của một hệ thống.
Ai thực hiện kiểm thử đơn vị?
Trách nhiệm của các vai trò khác nhau trong kiểm thử đơn vị: Kiểm thử đơn vị chủ yếu
do các nhà phát triển hoặc lập trình viên thực hiện. Họ chịu trách nhiệm tạo ra và duy trì
các bài kiểm tra đơn vị.
Sự cộng tác giữa nhà phát triển và nhóm kiểm thử: Nhóm kiểm thử cũng có thể đóng
góp vào công việc kiểm thử đơn vị bằng cách đưa ra các trường hợp kiểm thử, xem xét
phạm vi kiểm thử và hỗ trợ trong việc tự động hóa kiểm thử.
Sự tham gia của nhóm đảm bảo chất lượng (QA): Nhóm QA có thể cùng nhà phát triển
thiết lập các tiêu chuẩn, hướng dẫn và các quy tắc tốt nhất cho kiểm thử đơn vị. Họ cũng
có thể xem xét kết quả kiểm thử đơn vị và đưa ra phản hồi.
Lợi ích của kiểm thử đơn vị:
Nâng cao chất lượng mã nguồn: Kiểm thử đơn vị giúp phát hiện và sửa lỗi sớm trong quá
trình phát triển, từ đó nâng cao chất lượng mã nguồn.
Phát hiện lỗi sớm: Kiểm thử đơn vị có thể phát hiện lỗi và vấn đề ở giai đoạn sớm, ngăn
chặn chúng lan rộng đến các cấp kiểm thử cao hơn.
Giảm thời gian sửa lỗi và khắc phục sự cố: Kiểm thử đơn vị giúp thu hẹp phạm vi gỡ lỗi,
giúp tìm kiếm và sửa lỗi dễ dàng hơn.
Hỗ trợ bảo trì mã nguồn và tái cấu trúc: Kiểm thử đơn vị đóng vai trò như một mạng an
toàn khi thay đổi mã nguồn, đảm bảo tính chính xác của các chức năng hiện có.
Hỗ trợ tài liệu và chia sẻ kiến thức: Các bài kiểm thử đơn vị được coi như tài liệu có thể
thực thi, giới thiệu cách sử dụng mã nguồn và cung cấp thông tin về hành vi kỳ vọng.
Mối quan hệ giữa kiểm thử đơn vị và các cấp kiểm thử khác:
Sự khác biệt giữa kiểm thử đơn vị và các cấp kiểm thử khác: Kiểm thử đơn vị tập trung
vào kiểm thử từng đơn vị độc lập, trong khi các cấp kiểm thử khác (như kiểm thử tích
hợp và kiểm thử hệ thống) kiểm tratính tương tác và tích hợp giữa các thành phần.
Vai trò của kiểm thử đơn vị trong quá trình kiểm thử: Kiểm thử đơn vị là bước đầu tiên
và quan trọng trong quá trình kiểm thử phần mềm. Nó giúp xác định và khắc phục các lỗi
ở mức đơn vị trước khi tiến xa hơn vào các cấp kiểm thử khác.
Cách liên kết với các cấp kiểm thử khác: Kết quả của kiểm thử đơn vị sẽ cung cấp thông
tin cần thiết cho các bước kiểm thử tiếp theo, như kiểm thử tích hợp và kiểm thử hệ
thống. Các lỗi được phát hiện trong quá trình kiểm thử đơn vị cần được sửa chữa trước
khi tiến hành các bước kiểm thử khác.
Các phương pháp và kỹ thuật trong kiểm thử đơn vị:
Kỹ thuật phân tích giá trị biên (Boundary Value Analysis): Phương pháp này tập trung vào
việc kiểm tra các giá trị biên và giá trị gần biên của đầu vào để phát hiện các lỗi liên quan
đến ranh giới biên.
Kỹ thuật kiểm tra điều kiện (Condition Testing): Phương pháp này kiểm tra các điều kiện
logic trong mã nguồn để đảm bảo rằng tất cả các nhánh điều kiện được thực hiện đúng.
Kỹ thuật kiểm tra đường dẫn (Path Testing): Phương pháp này tập trung vào việc kiểm
tra tất cả các đường dẫn có thể trong mã nguồn để đảm bảo rằng tất cả các đường dẫn
đã được thực hiện và kiểm tra các trạng thái khác nhau của chương trình.
Kỹ thuật kiểm tra dự đoán (Equivalence Partitioning): Phương pháp này chia các tập hợp
dữ liệu đầu vào thành các phân vùng tương đương và chỉ kiểm tra một số trường hợp
biểu diễn cho từng phân vùng.
Đơn vị kiểm thử tự động (Automated Unit Testing): Sử dụng các framework và công cụ
kiểm thử đơn vị tự động như JUnit (cho Java) hoặc NUnit (cho .NET) để tạo và chạy các
bài kiểm thử đơn vị tự động.
Thực hiện kiểm thử đơn vị trong quy trình phát triển phần mềm:
Định nghĩa tác vụ kiểm thử đơn vị: Xác định các tác vụ và trách nhiệm cụ thể liên quan
đến kiểm thử đơn vị trong quy trình phát triển phần mềm.
Thiết lập môi trường kiểm thử đơn vị: Đảm bảo rằng môi trường kiểm thử đơn vị được
thiết lập đúng, bao gồm cài đặt và cấu hình các công cụ kiểm thử đơn vị cần thiết.
Xác định và tạo bài kiểm thử đơn vị: Xác định các trường hợp kiểm thử, tạo các bài kiểm
thử đơn vị theo các kỹ thuật và phương pháp đã được đề cập.
Thực hiện kiểm thử đơn vị: Chạy các bài kiểm thử đơn vị và ghi lại kết quả kiểm thử.
Theo dõi và gỡ lỗi các lỗi được phát hiện trong quá trình kiểm thử.
Tối ưu hóa và duy trì bài kiểm thử đơn vị: Cải thiện và điều chỉnh các bài kiểm thử đơn vị
dựa trên kinh nghiệm và phản hồi từ quá trình kiểm thử trước đó. Duy trì các bài kiểm
thử đơn vị theo sự thay đổi và bảo trì mã nguồn.
Các thách thức và lưu ý khi thực hiện kiểm thử đơn vị:
Tính phủ kiểm thử đơn vị: Đảm bảo rằng tất cả các đườngdẫn và trạng thái trong mã
nguồn được kiểm tra, để đảm bảo tính phủ kiểm thử đơn vị cao.
Sự phụ thuộc và giả lập: Kiểm thử đơn vị có thể gặp khó khăn khi các đơn vị phụ thuộc
chưa hoàn thiện hoặc không sẵn có. Trong trường hợp này, cần sử dụng kỹ thuật giả lập
để kiểm thử đơn vị một cách cô lập.
Tính cân nhắc và hiệu quả: Chọn các bài kiểm thử đơn vị quan trọng và hiệu quả để tối
ưu thời gian và nguồn lực trong quá trình kiểm thử.
Dễ dàng bảo trì và mở rộng: Thiết kế các bài kiểm thử đơn vị sao cho dễ dàng bảo trì và
mở rộng trong tương lai, khi mã nguồn được thay đổi hoặc mở rộng.
Tích hợp với quy trình CI/CD: Tự động hóa quá trình kiểm thử đơn vị và tích hợp nó vào
quy trình CI/CD giúp đảm bảo tính liên tục và nhanh chóng của việc phát triển phần
mềm.
5.7.2. Unit Test - Why?
1. Phát hiện lỗi sớm:
Kiểm thử đơn vị giúp phát hiện lỗi và vấn đề trong giai đoạn đầu của quá trình phát
triển.
Bằng cách viết các bài kiểm thử cho từng đơn vị mã nguồn (như hàm hoặc phương
thức), các nhà phát triển có thể phát hiện và sửa lỗi trước khi chúng lan rộng sang
các phần khác của hệ thống.
Điều này giảm tổng chi phí và công sức cần thiết cho việc sửa lỗi.
2. Đảm bảo chất lượng mã nguồn:
Kiểm thử đơn vị là một cơ chế đảm bảo chất lượng cho từng đơn vị mã nguồn. Nó
giúp đảm bảo rằng mỗi đơn vị hoạt động đúng và tạo ra kết quả dự kiến.
Bằng cách xác minh hành vi của từng đơn vị, các nhà phát triển có thể tin tưởng hơn
về tính chính xác của mã nguồn của mình.
3. Giúp dễ dàng gỡ lỗi và tái cấu trúc:
Khi một bài kiểm thử đơn vị không thành công, nó cung cấp một chỉ báo rõ ràng rằng
có điều gì đó không đúng với mã nguồn.
Kiểm thử đơn vị đóng vai trò là một "lưới an toàn" trong quá trình gỡ lỗi, giúp xác
định đơn vị cụ thể gây ra vấn đề.
Ngoài ra, kiểm thử đơn vị cho phép các nhà phát triển tự tin tái cấu trúc mã nguồn
mà không gây ra lỗi mới, bởi vì họ có thể chạy lại các bài kiểm thử để đảm bảo rằng
mã nguồn được tái cấu trúc hoạt động đúng như mong đợi.
4. Hỗ trợ sự cộng tác:
Kiểm thử đơn vị đóng vai trò như tài liệu sống cho mã nguồn. Nó cung cấp thông tin
về cách một đơn vị cụ thể nên hoạt động và có thể giúp các nhà phát triển mới hiểu
chức năng của mã nguồn hiện có.
Bằng cách có một bộ bài kiểm thử đơn vị toàn diện, các nhà phát triển có thể cộng
tác hiệu quả hơn, đảm bảo rằng các thay đổi được thực hiện bởi một người không
làm hỏng chức năng được mong đợi bởi những người khác.
5. Hỗ trợ việc bảo trì mã nguồn:
Kiểm thử đơn vị làm cho mã nguồn dễ bảo trì hơn trong tương lai. Khi mã nguồn
tiến triển và phát triển, kiểm thử đơn vị đóng vai trò như một "lưới an toàn" chống
lại những thay đổi không cố ý hoặc lỗi mới.
Nó giúp đảm bảo rằng các sửa đổi hoặc cải tiến cho mã nguồnđều không gây ra lỗi
mới hoặc làm hỏng chức năng hiện có.
6. Giảm thời gian phát triển:
Mặc dù viết kiểm thử đơn vị yêu cầu một khoản đầu tư thời gian ban đầu, nhưng nó
có thể giảm đáng kể thời gian phát triển trong dài hạn.
Kiểm thử đơn vị giúp nhà phát triển phát hiện sớm các vấn đề, giảm thời gian làm
việc trên gỡ lỗi và làm lại công việc.
Hơn nữa, có một bộ bài kiểm thử đơn vị toàn diện giúp cho việc thay đổi mã nguồn
nhanh hơn và tự tin hơn, vì nhà phát triển có thể kiểm tra lại các bài kiểm thử để
đảm bảo rằng chức năng hiện có vẫn hoạt động như mong đợi.
5.7.3. Unit Test - How? (method, technique)
Kiểm thử hộp đen (Black-box testing): Phương pháp này không quan tâm tới cấu trúc nội bộ và
chi tiết cài đặt của mã nguồn. Các trường hợp kiểm thử được thiết kế dựa trên các đầu vào và
kết quả mong đợi của đơn vị đang được kiểm thử. Trọng tâm là kiểm thử chức năng của đơn vị.
Kiểm thử chức năng (Functional testing): Kỹ thuật này đảm bảo rằng mỗi đơn vị hoạt
động đúng theo thiết kế và yêu cầu chức năng.
Kiểm thử kinh doanh (Business testing): Kỹ thuật này đảm bảo rằng phần mềm hoạt
động đúng theo yêu cầu của người dùng và quy tắc kinh doanh.
Kiểm thử hộp trắng (White-box testing): Phương pháp này xem xét cấu trúc nội bộ và chi
tiết cài đặt của mã nguồn. Các trường hợp kiểm thử được thiết kế để kiểm tra các
đường đi và điều kiện khác nhau trong đơn vị. Trọng tâm là kiểm thử logic và phạm vi
mã nguồn.
Do chính lập trình viên thực hiện: Lập trình viên thực hiện kiểm thử hộp trắng bằng cách
kiểm tra cú pháp của mã nguồn, chạy chế độ gỡ lỗi, kiểm tra cấu trúc dữ liệu cục bộ và
kiểm tra các điều kiện biên và xử lý lỗi.
Các kỹ thuật được áp dụng trong kiểm thử hộp trắng bao gồm:
Độ bao phủ câu lệnh (Statement coverage): Đảm bảo rằng mỗi câu lệnh trong mã nguồn
được thực thi ít nhất một lần trong quá trình kiểm thử.
Độ bao phủ quyết định (Decision coverage): Đảm bảo rằng tất cả các kết quả quyết định
có thể xảy ra (nhánh điều kiện) được kiểm thử.
Độ bao phủ đường đi (Path coverage): Đảm bảo rằng tất cả các đường đi có thể xảy ra
trong mã nguồn được kiểm thử.
Cả kiểm thử hộp đen và kiểm thử hộp trắng đều có những ưu điểm riêng và được sử
dụng trong các tình huống khác nhau. Kiểm thử hộp đen tập trung hơn vào chức năng và
hành vi bên ngoài của đơn vị, trong khi kiểm thử hộp trắng đi sâu vào cài đặt nội bộ và
logic của mã nguồn.
~~End~~
| 1/23

Preview text:

4. Common defect checklist 4.1. Exception
Lỗi Exception trong lập trình là một tình huống bất thường xảy ra trong quá trình thực thi
chương trình. Khi một Exception xảy ra, chương trình hiện tại sẽ dừng lại và tìm kiếm một xử lý
(handler) cho Exception đó. Nếu không có xử lý phù hợp, chương trình sẽ kết thúc và thông báo lỗi cho người dùng.
Exceptions được sử dụng để xử lý các tình huống đặc biệt, như lỗi logic, lỗi chia cho 0, truy cập
mảng vượt quá chỉ số, hoặc lỗi không xử lý dữ liệu đầu vào không hợp lệ. Khi một Exception xảy
ra, nó sẽ tạo ra một đối tượng Exception chứa thông tin về lỗi và ném ra (throw) cho phần code gọi đến.
Trong ngôn ngữ lập trình, để xử lý Exceptions, chúng ta sử dụng các khối try-catch. Khối try bao
bọc các dòng code có thể gây ra Exception. Nếu một Exception xảy ra trong khối try, nó sẽ được
ném ra (throw) và các khối catch liên quan sẽ được kiểm tra để tìm xem có xử lý Exception đó
hay không. Nếu một khối catch phù hợp được tìm thấy, nó sẽ được thực thi để xử lý Exception.
Ví dụ, trong Java, một đoạn code xử lý Exception có thể trông như sau: try {
// Các dòng code có thể gây ra Exception } catch (ExceptionType1 e1) { // Xử lý ExceptionType1 } catch (ExceptionType2 e2) { // Xử lý ExceptionType2 } finally {
// Mã được thực thi sau khi try-catch kết thúc (tùy chọn) }
Trong ví dụ trên, các khối catch sẽ kiểm tra xem Exception có phù hợp với loại nào và xử lý
tương ứng. Nếu không có khối catch phù hợp, Exception sẽ được ném ra tiếp theo để kiểm tra
tại các phạm vi gọi đến khác.
Xử lý Exceptions giúp chương trình có khả năng xử lý các tình huống bất thường và tránh việc
chương trình bị dừng do lỗi. 4.2. Syntax Error
Lỗi Syntax Error là một loại lỗi trong lập trình xảy ra khi mã nguồn không tuân thủ cú pháp của
ngôn ngữ lập trình. Điều này có nghĩa là bạn đã viết một cấu trúc, một từ khóa hoặc một phần
tử không đúng cách trong mã nguồn của bạn.
Ví dụ, trong ngôn ngữ Java, nếu bạn quên dấu chấm phẩy (;) ở cuối mỗi dòng lệnh, hoặc không
đóng các dấu ngoặc ({}) đúng cách, bạn sẽ gặp lỗi Syntax Error. Dưới đây là một số ví dụ về lỗi Syntax Error: 
Quên dấu chấm phẩy (;) ở cuối dòng lệnh: int a = 5 
Không đóng dấu ngoặc nhọn ({}): for (int i = 0; i < 10; i++ { // Code xử lý } 
Sử dụng từ khóa không đúng cách: int int = 10; 
Sử dụng cú pháp không hợp lệ: if (x > 5) then { // Code xử lý }
Khi gặp lỗi Syntax Error, trình biên dịch hoặc môi trường phát triển tích hợp (IDE) sẽ thông báo
lỗi cụ thể và chỉ ra vị trí mà lỗi xảy ra trong mã nguồn. Để khắc phục lỗi này, bạn cần xem xét lại
cú pháp và sửa chữa mã nguồn để tuân thủ cú pháp của ngôn ngữ lập trình đang sử dụng. 4.3. Runtime Error
Lỗi Runtime Error (Lỗi Thời gian chạy) là một loại lỗi trong lập trình xảy ra khi chương trình đang
thực thi và gặp phải một vấn đề không mong muốn. Lỗi này không phải là lỗi cú pháp và không
được phát hiện trong quá trình biên dịch, mà chỉ xảy ra khi chương trình đang chạy.
Dưới đây là một số ví dụ về lỗi Runtime Error: 
Lỗi Chia cho 0 (Divide By Zero Error): Khi chúng ta chia một số cho 0, lỗi này sẽ xảy ra. Ví dụ: x = 10 / 0 
Lỗi Truy cập Mảng Vượt quá chỉ số (Array Index Out of Bounds Error): Khi chúng ta truy
cập vào một phần tử trong mảng bằng một chỉ số không hợp lệ, lỗi này sẽ xảy ra. Ví dụ: int[] array = {1, 2, 3};
int element = array[5]; // Lỗi vượt quá chỉ số mảng 
Lỗi Null Pointer (Null Pointer Exception): Khi chúng ta cố gắng truy cập vào một đối
tượng null hoặc không được khởi tạo, lỗi này xảy ra. Ví dụ: String str = null;
int length = str.length(); // Lỗi null pointer 
Lỗi Stack Overflow: Khi chúng ta gọi đệ quy một cách vô hạn hoặc có quá nhiều lời gọi
hàm chồng chất, lỗi này sẽ xảy ra. Ví dụ: def recursive_function(): recursive_function()
recursive_function() # Lỗi stack overflow 
Lỗi Type Error: Khi chúng ta thực hiện một phép toán không hợp lệ hoặc không tương
thích với kiểu dữ liệu, lỗi này sẽ xảy ra. Ví dụ:
var result = "Hello" + 5; // Lỗi type error
Khi một lỗi Runtime Error xảy ra, chương trình sẽ dừng lại và thông báo lỗi. Để khắc phục lỗi
này, chúng ta cần xem xét và sửa chữa mã nguồn, kiểm tra các giá trị đầu vào, xử lý các trường
hợp đặc biệt và đảm bảo rằng chương trình không gặp phải các tình huống không mong muốn trong quá trình thực thi. 4.4. Memory Management Error
Lỗi Quản lý bộ nhớ (Memory Management Error) là một loại lỗi trong lập trình xảy ra khi quá
trình quản lý bộ nhớ không được thực hiện đúng cách. Các lỗi quản lý bộ nhớ có thể gây ra các
vấn đề như rò rỉ bộ nhớ (memory leak), truy cập vào bộ nhớ không hợp lệ, hoặc gây ra hiện
tượng "double free" (giải phóng bộ nhớ hai lần).
Dưới đây là một số lỗi quản lý bộ nhớ phổ biến: 
Rò rỉ bộ nhớ (Memory Leak): Lỗi này xảy ra khi một phần của bộ nhớ được cấp phát
không được giải phóng sau khi không còn cần thiết. Điều này dẫn đến việc tiêu tốn
nguồn tài nguyên và có thể gây ra sự suy giảm hiệu suất hoặc hết bộ nhớ. 
Truy cập vào bộ nhớ không hợp lệ (Invalid Memory Access): Lỗi này xảy ra khi chúng ta
cố gắng truy cập vào một vùng bộ nhớ không được cấp phát hoặc đã được giải phóng.
Kết quả có thể là crash chương trình hoặc dữ liệu không chính xác. 
Double Free: Lỗi này xảy ra khi chúng ta giải phóng một vùng bộ nhớ hai lần. Điều này có
thể dẫn đến sự xáo trộn trong việc quản lý bộ nhớ và gây ra lỗi không xác định hoặc crash chương trình. 
Derefencing Null Pointer: Lỗi này xảy ra khi chúng ta cố gắng truy cập vào một con trỏ
null. Khi một con trỏ không được khởi tạo hoặc được gán giá trị null, việc truy cập vào nó sẽ gây ra lỗi. 
Buffer Overflow: Lỗi này xảy ra khi chúng ta ghi dữ liệu ngoài giới hạn vùng nhớ được
cấp phát. Điều này có thể dẫn đến việc ghi đè dữ liệu quan trọng hoặc ghi đè lên bộ nhớ khác. 
Để tránh lỗi quản lý bộ nhớ, cần tuân thủ các quy tắc và phương pháp quản lý bộ nhớ
đúng cách. Điều này bao gồm cấp phát và giải phóng bộ nhớ theo đúng thứ tự, sử dụng
các hàm và công cụ quản lý bộ nhớ một cách chính xác, và kiểm tra và xử lý các lỗi liên
quan đến bộ nhớ một cách cẩn thận.
Để tránh lỗi quản lý bộ nhớ, cần tuân thủ các quy tắc và phương pháp quản lý bộ nhớ đúng
cách. Điều này bao gồm cấp phát và giải phóng bộ nhớ theo đúng thứ tự, sử dụng các hàm
và công cụ quản lý bộ nhớ một cách chính xác, và kiểm tra và xử lý các lỗi liên quan đến bộ
nhớ một cách cẩn thận. 4.5. Logic Error
Lỗi Logic (Logic Error) là một loại lỗi trong lập trình xảy ra khi chương trình không hoạt động
chính xác vì có sai sót trong logic của mã. Lỗi này không phải là lỗi cú pháp hoặc lỗi thời gian
chạy, mà là do cách mà chương trình đã được thiết kế và triển khai.
Dưới đây là một số ví dụ về lỗi Logic Error: 
Sai điều kiện trong câu lệnh rẽ nhánh (Conditional Statement): Lỗi này xảy ra khi
chúng ta không đặt các điều kiện đúng trong câu lệnh rẽ nhánh if, else if hoặc switch.
Điều này có thể dẫn đến việc thực thi sai mã hoặc bỏ qua các trường hợp quan trọng. 
Lỗi Toán tử (Operator Error): Lỗi này xảy ra khi chúng ta sử dụng toán tử không đúng
hoặc không áp dụng đúng logic. Điều này có thể dẫn đến kết quả không chính xác hoặc không mong muốn. 
Lỗi Vòng lặp (Loop Error): Lỗi này xảy ra khi vòng lặp không được kiểm soát hoặc
điều kiện thoát khỏi vòng lặp không đúng. Điều này có thể dẫn đến lặp vô hạn hoặc không đủ lặp. 
Lỗi Hàm (Function Error): Lỗi này xảy ra khi chúng ta triển khai hàm không đúng hoặc
không trả về kết quả chính xác. Điều này có thể dẫn đến việc lỗi tính toán hoặc kết quả không chính xác. 
Lỗi Xử lý Dữ liệu (Data Handling Error): Lỗi này xảy ra khi chúng ta không xử lý dữ liệu
đúng cách, bao gồm việc gán giá trị sai cho biến, không kiểm tra giá trị đầu vào hoặc
không xử lý các trường hợp đặc biệt.
Để khắc phục lỗi Logic Error, chúng ta cần xem xét và sửa chữa logic của mã. Điều này bao
gồm kiểm tra và xác định các lỗi logic, sử dụng các điều kiện và toán tử đúng, kiểm tra và
sửa đổi vòng lặp, kiểm tra kết quả hàm, và đảm bảo xử lý đúng dữ liệu. Gỡ rối (debugging)
và kiểm thử (testing) cũng là phần quan trọng trong việc tìm và sửa lỗi logic. 4.6. File Handling Error
Lỗi xử lý tệp tin (File Handling Error) là một loại lỗi trong lập trình xảy ra khi chương trình
gặp vấn đề trong việc đọc, ghi hoặc xử lý tệp tin. Các lỗi xử lý tệp tin có thể gây ra việc mất
dữ liệu, không thể truy cập tệp tin hoặc không thực hiện được các thao tác mong muốn trên tệp tin.
Dưới đây là một số ví dụ về lỗi xử lý tệp tin: 
Lỗi không tìm thấy tệp tin (File Not Found Error): Lỗi này xảy ra khi chương trình
không thể tìm thấy tệp tin được yêu cầu. Có thể do đường dẫn không chính xác, tên
tệp tin sai hoặc tệp tin không tồn tại. 
Lỗi không thể mở tệp tin (File Open Error): Lỗi này xảy ra khi chương trình không thể
mở tệp tin để đọc hoặc ghi. Nguyên nhân có thể là tệp tin bị khóa bởi một quy trình
khác, quyền truy cập bị từ chối hoặc tệp tin bị hỏng. 
Lỗi ghi tệp tin (File Write Error): Lỗi này xảy ra khi chương trình không thể ghi dữ liệu
vào tệp tin. Có thể do tệp tin bị khóa chỉ cho phép đọc, không đủ quyền ghi hoặc
không đủ không gian trên ổ đĩa. 
Lỗi đọc tệp tin (File Read Error): Lỗi này xảy ra khi chương trình không thể đọc dữ
liệu từ tệp tin. Có thể do tệp tin bị hỏng, không đủ quyền truy cập hoặc định dạng dữ liệu không đúng. 
Lỗi đóng tệp tin (File Close Error): Lỗi này xảy ra khi chương trình không thể đóng tệp
tin sau khi hoàn thành thao tác. Điều này có thể dẫn đến rò rỉ tài nguyên hoặc không
thể truy cập tệp tin sau này.
Để khắc phục lỗi xử lý tệp tin, chúng ta cần kiểm tra và xử lý các điều kiện đặc biệt như tệp
tin không tồn tại, quyền truy cập bị từ chối hoặc tệp tin bị hỏng. Sử dụng các phương pháp
xử lý ngoại lệ (exception handling) cũng là cách hiệu quả để xử lý lỗi xử lý tệp tin. Đảm bảo
rằng các tệp tin được đóng đúng cách sau khi hoàn thành các thao tác cũng là một yếu tố
quan trọng để tránh lỗi xử lý tệp tin. 4.7. Error Handling Errors
Lỗi xử lý lỗi (Error Handling Errors) là một loại lỗi xảy ra khi việc xử lý lỗi trong chương trình
không được thực hiện đúng cách hoặc bị bỏ qua. Điều này có thể gây ra các vấn đề như
không hiển thị thông báo lỗi, không phục hồi được từ lỗi hoặc không xử lý các trường hợp
ngoại lệ một cách đúng đắn.
Dưới đây là một số ví dụ về Error Handling Errors: 
Bỏ qua lỗi: Đây là trường hợp khi lỗi xảy ra nhưng chương trình không kiểm tra hoặc
không xử lý lỗi một cách đúng đắn. Thay vì hiển thị thông báo lỗi hoặc thực hiện các
biện pháp phục hồi, chương trình tiếp tục thực thi mà không có hành động phù hợp.
Điều này có thể gây ra các lỗi tiềm ẩn và gây khó khăn trong việc tìm ra nguyên nhân gốc rễ của vấn đề. 
Xử lý lỗi không đúng: Đây là trường hợp khi chương trình xử lý lỗi một cách không
đúng đắn. Ví dụ, chương trình có thể hiển thị thông báo lỗi không rõ ràng, không
cung cấp thông tin chi tiết về lỗi, hoặc thực hiện các biện pháp phục hồi không chính
xác. Điều này có thể làm cho việc gỡ lỗi và sửa lỗi trở nên khó khăn hơn. 
Không phục hồi được từ lỗi: Đây là trường hợp khi chương trình không thể phục hồi
từ lỗi và tiếp tục thực thi một cách bất thường. Thay vì thực hiện các biện pháp phục
hồi hoặc thoát khỏi chương trình một cách an toàn, chương trình có thể gây ra các
lỗi tiếp theo hoặc dẫn đến trạng thái không ổn định.
Khắc phục Error Handling Errors: 
Sử dụng cấu trúc điều kiện để kiểm tra và xử lý lỗi một cách đúng đắn. 
Hiển thị thông báo lỗi rõ ràng và cung cấp thông tin chi tiết về lỗi. 
Ghi lại các lỗi trong tệp nhật ký (log file) để dễ dàng gỡ lỗi và xác định nguyên nhân gốc rễ. 
Xử lý các trường hợp ngoại lệ bằng cách sử dụng cơ chế xử lý ngoại lệ như try-catch. 
Đảm bảo rằng mã chương trình được kiểm tra và xử lý lỗi trong các kịch bản kiểm thử đa dạng. 
Sử dụng các thư viện hoặc framework hỗ trợ xử lý lỗi một cách hiệu quả, chẳng hạn
như thư viện log, thư viện xử lý ngoại lệ, hoặc framework kiểm thử tự động.
Bằng cách tuân thủ các quy tắc và quy ước lập trình tốt, nhà phát triển có thể giảm thiểu số
lượng lỗi xử lý lỗi và tăng tính ổn định và đáng tin cậy của chương trình. 4.8. String Handling Errors
Lỗi xử lý chuỗi (String Handling Errors) là các lỗi xảy ra trong quá trình xử lý chuỗi trong
chương trình. Đây là một vấn đề phổ biến trong lập trình và có thể dẫn đến các hậu quả như
lỗi logic, kết quả không chính xác hoặc sự cố chương trình.
Dưới đây là một số lỗi phổ biến liên quan đến xử lý chuỗi: 
Lỗi truy cập ngoài giới hạn mảng: Đây là trường hợp khi chúng ta cố gắng truy cập
vào một vị trí không hợp lệ trong chuỗi, ví dụ như truy cập vào một chỉ số âm hoặc
vượt quá kích thước của chuỗi. Điều này có thể dẫn đến lỗi chương trình hoặc kết quả không chính xác. 
Lỗi cấp phát bộ nhớ không đủ: Khi làm việc với chuỗi động (dynamic string), chúng ta
có thể gặp phải lỗi khi cấp phát bộ nhớ không đủ cho chuỗi. Điều này xảy ra khi
chúng ta không kiểm tra được kích thước của chuỗi hoặc không xử lý các trường hợp
cấp phát bộ nhớ không thành công. 
Lỗi xử lý ký tự đặc biệt: Trong xử lý chuỗi, có thể xảy ra lỗi khi không xử lý đúng các
ký tự đặc biệt như dấu nháy kép, ký tự backslash (), hoặc ký tự đặc biệt trong mã
Unicode. Điều này có thể gây ra sai sót trong các xử lý như ghi hoặc đọc chuỗi từ tệp tin. 
Lỗi mã hóa và giải mã: Khi làm việc với các chuỗi có mã hóa hoặc giải mã đặc biệt
như UTF-8, UTF-16, hoặc Base64, có thể xảy ra lỗi khi không xử lý chính xác quá trình
mã hóa hoặc giải mã. Điều này có thể dẫn đến kết quả không chính xác hoặc lỗi trong việc xử lý dữ liệu. 
Lỗi định dạng chuỗi: Khi chúng ta thực hiện các thao tác định dạng chuỗi như ghép
nối (concatenation), định dạng (formatting) hoặc phân tách (splitting), có thể xảy ra
lỗi nếu không xử lý đúng các quy tắc và định dạng của chuỗi. Ví dụ, việc sử dụng sai
ký tự định dạng hoặc thứ tự các đối số trong định dạng chuỗi có thể dẫn đến lỗi kết quả.
Để khắc phục các lỗi xử lý chuỗi, hãy áp dụng những phương pháp và quy ước lập trình tốt sau: 
Kiểm tra và xử lý kích thước và giới hạn mảng khi làm việc với chuỗi. 
Đảm bảo cấp phát đủ bộ nhớ cho chuỗi động và xử lý các trường hợp cấp phát bộ nhớ không thành công. 
Xử lý chính xác các ký tự đặc biệt và mã hóa/giải mã chuỗi khi cần thiết. 
Tuân thủ các quy tắc và định dạng chuỗi khi thực hiện các thao tác như ghép nối,
định dạng hoặc phân tách chuỗi. 4.9. 4.10.
5. Thu hoạch kết thúc môn học
5.1. How to work in Software Project ?
5.1.1 Software Project Activities Quản lý dự án: 
Planning: Lập kế hoạch dự án, xác định các bước tiến hành và lịch trình. 
Tracking: Theo dõi tiến độ dự án, đảm bảo thực hiện đúng kế hoạch. 
Closure: Hoàn thành dự án, đánh giá kết quả và rút kinh nghiệm. Kỹ thuật: 
Requirements Analyzing: Phân tích yêu cầu của dự án phần mềm. 
Designing: Thiết kế các thành phần và cấu trúc của phần mềm. 
Coding: Lập trình, viết mã nguồn cho phần mềm. 
Testing: Kiểm thử phần mềm để đảm bảo chất lượng và tính năng hoạt động đúng. 
Configuration Management: Quản lý các phiên bản và thay đổi trong quá trình phát triển phần mềm. 
Deployment (Installation): Triển khai và cài đặt phần mềm trên môi trường thực tế. 
Maintenance: Bảo trì, sửa chữa và nâng cấp phần mềm sau khi triển khai. 
Customer Support: Hỗ trợ khách hàng sử dụng và giải quyết vấn đề liên quan đến phần mềm.
5.1.2. Software Project Lifecycle
Dự án phát triển phần mềm: 
Khởi đầu (Inception): Xác định nhu cầu và mục tiêu của dự án, đánh giá tính khả thi và xác định phạm vi. 
Định nghĩa (Definition): Thu thập yêu cầu, phân tích, thiết kế khối và xác định cấu trúc tổ chức. 
Giải pháp (Solution): Xây dựng, kiểm tra và kiểm soát quy trình phát triển phần mềm. 
Xây dựng (Construction): Lập trình, kiểm thử và tích hợp các thành phần phần mềm. 
Chuyển giao (Transition): Triển khai, huấn luyện, hỗ trợ và chuyển giao phần mềm cho khách hàng. 
Kết thúc (Closure): Đánh giá dự án, rút kinh nghiệm và hoàn thành các công việc cuối cùng.
Dự án bảo trì phần mềm: 
Phân tích (Analysis): Phân tích yêu cầu bảo trì, xác định vấn đề và thiết kế giải pháp. 
Thiết kế (Design): Thiết kế các thay đổi, xác định phạm vi và tạo kế hoạch bảo trì. 
Triển khai (Implementation): Thực hiện các thay đổi, kiểm thử và tích hợp vào phần mềm hiện có. 
Kiểm tra (Testing): Kiểm tra phần mềm sau các thay đổi để đảm bảo tính năng và chất lượng. 
Phân phối (Delivery): Triển khai, chuyển giao và cung cấp phiên bản phần mềm đã bảo trì. 
Kết thúc (Closure): Đánh giá quá trình bảo trì, rút kinh nghiệm và hoàn thành các công việc cuối cùng.
5.1.3. Project Roles & Responsibilities Tổ chức dự án: 
Project Manager: Quản lý toàn bộ dự án, lập kế hoạch, theo dõi tiến độ và đảm bảo đạt được mục tiêu dự án. 
Technical/Team Leader: Đứng đầu nhóm kỹ thuật, phân công nhiệm vụ, giám sát công
việc và hỗ trợ thành viên nhóm. 
Business Analyst (BA): Phân tích yêu cầu của khách hàng, xác định nhu cầu và thiết kế giải pháp phần mềm. 
Developer: Lập trình, viết mã nguồn và xây dựng các thành phần của phần mềm. 
Tester: Kiểm thử phần mềm, tìm lỗi và đảm bảo chất lượng sản phẩm. 
Quality Assurance (QA): Đảm bảo tính chính xác và đáng tin cậy của phần mềm, thực
hiện kiểm tra và kiểm soát chất lượng.
Các vai trò khác trong dự án: 
Technical Architect: Thiết kế kiến trúc phần mềm và hướng dẫn việc triển khai. 
Database Administrator (DBA): Quản lý cơ sở dữ liệu, đảm bảo hiệu suất và bảo mật. 
User Interface (UI)/User Experience (UX) Designer: Thiết kế giao diện người dùng hấp dẫn và tương tác tốt. 
System Administrator: Quản lý môi trường phát triển và triển khai phần mềm. 
Technical Writer: Tạo tài liệu hướng dẫn sử dụng và tài liệu kỹ thuật. 
Customer/Client: Người đại diện cho khách hàng, cung cấp yêu cầu và phản hồi.
5.1.4. Tasks to be done in each stage
Giai đoạn khởi đầu (Inception): 
Xác định nhiệm vụ và mục tiêu của dự án. 
Phân tích tính khả thi và xác định phạm vi dự án. 
Lập kế hoạch tổng quan cho dự án. 
Xác định các rủi ro ban đầu và tiến hành đánh giá rủi ro. 
Xác định các bên liên quan và thiết lập mối quan hệ với khách hàng.
Giai đoạn định nghĩa (Definition): 
Thu thập yêu cầu của khách hàng và đưa ra đặc tả yêu cầu. 
Phân tích yêu cầu, xác định chức năng và phi chức năng. 
Thiết kế kiến trúc tổng quan cho phần mềm. 
Xác định các thành phần chính và xác định các phụ thuộc giữa các thành phần. 
Xác định phạm vi dự án chi tiết và lập kế hoạch chi tiết cho giai đoạn tiếp theo.
Giai đoạn giải pháp (Solution): 
Xây dựng các thành phần phần mềm. 
Kiểm thử và tích hợp các thành phần. 
Đánh giá và giám sát hiệu suất của phần mềm. 
Thực hiện kiểm tra chất lượng phần mềm. 
Đảm bảo tuân thủ quy trình và quy định phát triển phần mềm.
Giai đoạn xây dựng (Construction): 
Lập trình và viết mã nguồn cho các thành phần phần mềm. 
Kiểm thử và sửa lỗi trong quá trình xây dựng. 
Tích hợp các thành phần và kiểm tra tính tương thích. 
Xây dựng và kiểm tra giao diện người dùng. 
Đảm bảo mã nguồn và tài liệu được quản lý và bảo mật.
Giai đoạn chuyển giao (Transition): 
Triển khai phần mềm trong môi trường thực tế. 
Huấn luyện người dùng và cung cấp hỗ trợ. 
Đảm bảo tính ổn định và hiệu suất của phần mềm. 
Tiếp nhận phản hồi từ người dùng và xử lý các vấn đề phát sinh. 
Hoàn thiện tài liệu và báo cáo dự án.
Giai đoạn kết thúc (Closure): 
Đánh giá kết quả của dự án và so sánh với mục tiêu đề ra. 
Rút kinh nghiệm từ dự án và tạo báo cáo tổng kết. 
Đảm bảo việc hoàn thành các công việc cuối cùng và giao nộp tài liệu. 
Lập kế hoạch cho việc bảo trì và hỗ trợ sau triển khai. 
Tổ chức buổi họp cuối cùng với khách hàng để đánh giá sự hài lòng và thu thập phản hồi.
5.1.5. Communication in Projects
1. Kế hoạch giao tiếp: Đây là quá trình lập kế hoạch cho các hoạt động giao tiếp trong dự
án. Kế hoạch này bao gồm xác định các bên liên quan, phương tiện giao tiếp, lịch trình và phạm vi giao tiếp.
2. Các phương tiện giao tiếp: Các dự án sử dụng nhiều phương tiện giao tiếp khác nhau,
bao gồm cuộc họp trực tiếp, email, cuộc gọi điện thoại, tin nhắn, công cụ giao tiếp trực
tuyến như Slack hay Microsoft Teams, và các công cụ quản lý dự án như Jira hay Trello.
3. Truyền thông nội bộ: Giao tiếp trong dự án bao gồm cả truyền thông nội bộ trong nhóm
dự án. Điều này bao gồm việc chia sẻ thông tin, ý kiến và thông báo giữa các thành viên
trong nhóm để đảm bảo hiểu rõ mục tiêu, nhiệm vụ và tiến độ dự án.
4. Giao tiếp với khách hàng: Giao tiếp với khách hàng là một phần quan trọng để hiểu và
đáp ứng yêu cầu của họ. Điều này có thể bao gồm cuộc họp, báo cáo tiến độ, thảo luận
với khách hàng để xác định yêu cầu mới hoặc thay đổi, và cung cấp các bản cập nhật về dự án.
5. Giao tiếp hiệu quả: Giao tiếp hiệu quả là khả năng truyền đạt thông tin một cách rõ ràng
và đảm bảo sự hiểu biết đúng đắn. Điều này bao gồm việc lựa chọn phương tiện giao
tiếp phù hợp, sử dụng ngôn ngữ rõ ràng và tránh nhầm lẫn, lắng nghe và hiểu quan điểm
của người khác và kiểm tra lại sự hiểu biết.
6. Giao tiếp trong văn bản: Việc lưu trữ thông tin dự án trong văn bản là rất quan trọng.
Đảm bảo rằng tài liệu, báo cáo, biên bản cuộc họp và email được ghi lại một cách rõ ràng
và có thể tra cứu sau này.
7. Giao tiếp không chính thức: Ngoài giao tiếp chính thức, giao tiếp không chính thức như
trò chuyện bên lề, giao tiếp qua các kênh xã hội nội bộ và các hoạt động giao tiếp không
chính thức khác có thể giúp tạo ra môi trường làm việc thoải mái và tăng cường sự gắn kết trong nhóm dự án.
5.2. Software Requirement Concepts 5.2.1. Requirement Concepts
1. Định nghĩa yêu cầu: Yêu cầu được định nghĩa là một tuyên bố về dịch vụ mà hệ thống
phải thực hiện hoặc ràng buộc mà hệ thống phải đáp ứng.
2. Lý do chúng ta cần yêu cầu: Đề mục này giải thích vì sao chúng ta cần yêu cầu phần
mềm. Yêu cầu giúp xác định và giới hạn phạm vi dự án phần mềm, là cơ sở để đưa ra
hợp đồng và tạo ra các kế hoạch phát triển.
3. Mục đích của yêu cầu: Yêu cầu thường phục vụ như là cơ sở cho việc đấu thầu hợp
đồng, do đó phải được mô tả ở mức cao để mở ra nhiều cách hiểu. Ngoài ra, yêu cầu
cũng phải được chi tiết hóa để trở thành cơ sở cho hợp đồng chính thức.
4. Những gì không phải là yêu cầu: Đề mục này nêu rõ những điều không phải là yêu cầu.
Điều này bao gồm các chi tiết thiết kế hoặc triển khai (ngoại trừ ràng buộc đã biết),
thông tin về kế hoạch dự án và thông tin về kiểm thử.
5. Phân loại yêu cầu: Đề mục này giới thiệu về phân loại yêu cầu. Yêu cầu có thể được phân
loại là chức năng và phi chức năng. Yêu cầu chức năng mô tả các dịch vụ mà hệ thống
phải thực hiện, trong khi yêu cầu phi chức năng mô tả các ràng buộc mà hệ thống phải tuân thủ. 5.2.3. Requirement Modeling
1. Mục đích: Mục đích chính của mô hình hóa yêu cầu là ghi lại, phân tích và biểu diễn yêu cầu
phần mềm một cách cấu trúc và có tổ chức. Nó giúp các bên liên quan có cái nhìn rõ ràng về
những gì hệ thống cần phải thực hiện.
2. Kỹ thuật và công cụ: Mô hình hóa yêu cầu sử dụng các kỹ thuật và công cụ khác nhau để tạo
ra biểu đồ biểu diễn yêu cầu. Một số kỹ thuật mô hình hóa phổ biến bao gồm: 
Biểu đồ Use Case: Biểu đồ Use Case mô tả các tương tác giữa các bên tác động (người
dùng, hệ thống hoặc các thành phần bên ngoài) và hệ thống để hoàn thành các mục tiêu
hoặc nhiệm vụ cụ thể. 
Sơ đồ luồng dữ liệu (Data Flow Diagram - DFD): Sơ đồ luồng dữ liệu mô tả cách dữ liệu
chảy qua hệ thống và cách nó được xử lý hoặc biến đổi bởi các thành phần khác nhau. 
Biểu đồ hoạt động (Activity Diagram): Biểu đồ hoạt động hiển thị quy trình hoạt động
hoặc quy trình làm việc trong hệ thống, bao gồm các nhánh, song song và điểm quyết định. 
Biểu đồ trạng thái (State Machine Diagram): Biểu đồ trạng thái biểu diễn các trạng thái
khả thi của một đối tượng hoặc hệ thống và cách nó chuyển đổi từ trạng thái này sang
trạng thái khác dựa trên các sự kiện hoặc điều kiện. 
Biểu đồ lớp (Class Diagram): Biểu đồ lớp miêu tả cấu trúc tĩnh của hệ thống, bao gồm
các lớp, thuộc tính, mối quan hệ và phương thức của chúng. 
Biểu đồ trình tự (Sequence Diagram): Biểu đồ trình tự mô tả trình tự các tương tác giữa
các đối tượng hoặc thành phần trong hệ thống theo thời gian. 
Sơ đồ thực thể - mối quan hệ (Entity-Relationship Diagram - ERD): ERD được sử dụng để
mô hình hóa cấu trúc và mối quan hệ giữa các thực thể dữ liệu trong hệ thống.
3. Lợi ích: Mô hình hóa yêu cầu mang lại nhiều lợi ích, bao gồm: 
Hiểu rõ hơn: Biểu đồ giúp các bên liên quan hiểu và xác nhận yêu cầu, từ đó cải thiện
việc giao tiếp vàxác thực yêu cầu. 
Phát hiện vấn đề sớm: Mô hình hóa giúp phát hiện những không nhất quán, mơ hồ hoặc
yêu cầu thiếu, giúp phát hiện và giải quyết vấn đề sớm. 
Theo dõi yêu cầu: Các mô hình cung cấp một con đường rõ ràng để theo dõi yêu cầu,
giúp phân tích tác động và quản lý thay đổi yêu cầu. 
Tài liệu và tạo tài liệu: Các mô hình là tài liệu thể hiện có thể chia sẻ, xem xét và cập nhật
trong suốt quá trình phát triển phần mềm. Chúng cũng có thể được sử dụng để tạo ra
các tài liệu khác như tài liệu sử dụng, hướng dẫn và tài liệu kiểm thử. 5.2.3. System Modeling Tools
1. Enterprise Architect: Enterprise Architect là một công cụ mô hình hóa
hệ thống mạnh mẽ và đa nền tảng. Nó hỗ trợ nhiều kỹ thuật mô hình
hóa, bao gồm UML, BPMN, SysML và các biểu đồ khác. Nó cung cấp
tính năng hợp tác nhóm, quản lý yêu cầu, và tích hợp với các công cụ
phát triển phần mềm khác.
2. MagicDraw: MagicDraw là một công cụ mô hình hóa hệ thống phổ
biến, tương thích với các tiêu chuẩn UML, SysML và BPMN. Nó cung
cấp các tính năng mạnh mẽ để tạo và quản lý các biểu đồ UML, mô
hình hóa hệ thống và phân tích yêu cầu. MagicDraw có tích hợp với
các công cụ quản lý yêu cầu và hỗ trợ việc xuất bản tài liệu.
3. Rational Rose: Rational Rose của IBM là một công cụ mô hình hóa hệ
thống UML phổ biến. Nó cung cấp các tính năng đa dạng để tạo ra
các biểu đồ lớp, biểu đồ hoạt động, biểu đồ trạng thái và nhiều biểu
đồ khác. Rational Rose hỗ trợ tích hợp với các công cụ phát triển
phần mềm khác trong quá trình phát triển.
4. Sparx Systems Enterprise Architect: Enterprise Architect của Sparx
Systems là một công cụ mô hình hóa hệ thống UML, SysML và BPMN.
Nó cung cấp một giao diện đồ họa dễ sử dụng cho việc tạo và quản lý
mô hình hóa hệ thống. Công cụ này hỗ trợ tích hợp với các công cụ
quản lý yêu cầu và hỗ trợ việc phát triển phần mềm.
5. Visual Paradigm: Visual Paradigm là một công cụ mô hình hóa hệ
thống linh hoạt hỗ trợ nhiều ngôn ngữ mô hình hóa như UML, BPMN,
SysML và ERD. Nó cung cấp các tính năng phong phú để thiết kế và
phân tích yêu cầu, tạo và quản lý mô hình hóa hệ thống. Công cụ này
cũng hỗ trợ tích hợp với các công cụ phát triển phần mềm và quản lý yêu cầu. 5.3. Common Architectures 5.3.1.
1. Kiến trúc phần mềm là một bản thiết kế kỹ thuật mô tả cách hệ thống sẽ được cấu trúc
và tổ chức. Nó định nghĩa cách các thành phần của hệ thống tương tác với nhau và cung
cấp một khung làm việc để phát triển, triển khai và duy trì phần mềm.
2. Một hệ thống phần mềm có kiến trúc rõ ràng giúp cho việc phát triển phần mềm trở nên
dễ dàng hơn bằng cách tách riêng các thành phần và chức năng khác nhau. Nó giúp đảm
bảo sự phân chia rõ ràng của trách nhiệm và chức năng trong hệ thống, giúp dễ dàng
quản lý, bảo trì và mở rộng.
3. Kiến trúc phần mềm cũng mô tả cách các thành phần của hệ thống tương tác với nhau,
bao gồm cách chúng truyền thông qua giao diện và cơ chế truyền thông. Nó cung cấp
một cái nhìn tổng quan về cấu trúc tổng thể của hệ thống và giúp các nhà phát triển hiểu
rõ hơn về sự tương tác và phụ thuộc giữa các thành phần.
4. Ngoài ra, kiến trúc phần mềm cũng đề cập đến các nền tảng và công nghệ được sử dụng
trong hệ thống, bao gồm cách các thành phần được triển khai trên các môi trường cụ thể.
5. Mỗi thành phần của kiến trúc phần mềm có thể thực hiện một mô hình / mẫu kiến trúc
cụ thể, như kiến trúc client-server, kiến trúc 3-tầng hoặc kiến trúc MVC. Những mô hình
này cung cấp các hướng dẫn và quy tắc cho việc thiết kế và triển khai các thành phần
trong hệ thống phần mềm.
5.3.2. Client-Server Architecture
Kiến trúc client-server là một mô hình phân tán trong đó một máy chủ (server) cung cấp các
dịch vụ và tài nguyên cho nhiều máy khách (client) thông qua mạng. Trong mô hình này, máy
chủ đóng vai trò là trung tâm điều khiển và quản lý các tài nguyên, trong khi máy khách sử dụng
các ứng dụng hoặc giao diện để truy cập và tương tác với máy chủ.
Máy chủ là một máy tính hoặc ứng dụng chạy trên máy tính, có khả năng cung cấp các dịch vụ
như lưu trữ dữ liệu, xử lý yêu cầu, thực hiện tính toán phức tạp, và đáp ứng các yêu cầu từ các
máy khách. Máy khách là các ứng dụng hoặc thiết bị mà người dùng sử dụng để truy cập và
tương tác với máy chủ. Các máy khách có thể là máy tính cá nhân, điện thoại di động, máy tính
bảng, hoặc bất kỳ thiết bị nào khác có khả năng kết nối mạng.
Trong mô hình client-server, máy chủ cung cấp các dịch vụ và tài nguyên như cơ sở dữ liệu, ứng
dụng web, dịch vụ web, hoặc tệp tin được lưu trữ trên máy chủ. Các máy khách giao tiếp với
máy chủ thông qua giao thức truyền thông như HTTP (cho ứng dụng web), FTP (cho truyền tệp
tin), hoặc TCP/IP (cho giao tiếp mạng).
Mô hình client-server cung cấp nhiều lợi ích, bao gồm: 
Phân chia rõ ràng giữa nhiệm vụ xử lý và hiển thị, giúp quản lý mã nguồn dễ dàng hơn và
tái sử dụng được thành phần. 
Cho phép điều chỉnh dễ dàng trong việc mở rộng hệ thống bằng cách thêm máy chủ hoặc máy khách mới. 
Dễ dàng thực hiện các tính năng bảo mật như xác thực và kiểm soát truy cập từ máy chủ. 
Tính linh hoạt và khả năng mở rộng trong việc phát triển ứng dụng và triển khai trên
nhiều nền tảng khác nhau.
Ví dụ về mô hình client-server bao gồm: 
Máy chủ web (ví dụ: máy chủ Apache) cung cấp các trang web cho trình duyệt web của
người dùng (ví dụ: Google Chrome). 
Máy chủ email (ví dụ: Microsoft Exchange Server) cung cấp dịch vụ email cho các ứng
dụng email như Microsoft Outlook hoặc Thunderbird. 
Máy chủ cơ sở dữ liệu (ví dụ: MySQL Server) cung cấp dữ liệu cho các ứng dụng client
như ứng dụng quản lý cửa hàng hoặc ứng dụng di động. 
Kiến trúc client-server là một trong những mô hình phổ biến nhất trong phát triển phần
mềm và hệ thống mạng, cung cấp một cách linh hoạt và hiệu quả để xây dựng các ứng
dụng và dịch vụ phân tán.
5.3.4. 3-Tier / Multi-Tier Architectures
Kiến trúc 3-tầng (hay còn gọi là kiến trúc multi-tầng) là một mô hình kiến trúc phần mềm phân
tách ứng dụng thành ba tầng hoặc ba lớp chức năng khác nhau. Các tầng này bao gồm: 
Front-end (tầng giao diện người dùng): Tầng này chịu trách nhiệm cho việc hiển thị
thông tin và tương tác với người dùng. Nó bao gồm các thành phần như trình duyệt
web, ứng dụng di động, giao diện đồ họa, hoặc bất kỳ công cụ nào mà người dùng sử
dụng để tương tác với hệ thống. Tầng này tập trung vào giao diện người dùng và hiển thị
dữ liệu một cách hấp dẫn và thân thiện. 
Middle tier (tầng trung gian/ tầng logic nghiệp vụ): Tầng này là nơi xử lý logic nghiệp vụ
của ứng dụng. Nó chịu trách nhiệm cho việc xử lý yêu cầu từ front-end và tương tác với
back-end. Tầng này chứa các thành phần như các dịch vụ web, logic xử lý dữ liệu, quản lý
luồng công việc, và các thành phần xử lý nghiệp vụ khác. Nhiệm vụ chính của tầng trung
gian là xử lý logic nghiệp vụ và chuyển tiếp dữ liệu giữa front-end và back-end. 
Back-end (tầng dữ liệu): Tầng này chịu trách nhiệm quản lý và lưu trữ dữ liệu. Nó bao
gồm cơ sở dữ liệu (database) và các hệ thống quản lý cơ sở dữ liệu (DBMS) như MySQL,
Oracle, MongoDB, và nhiều hơn nữa. Tầng này xử lý yêu cầu từ tầng trung gian, thực
hiện truy vấn và cập nhật dữ liệu trong cơ sở dữ liệu và trả về kết quả cho tầng trung gian.
Kiến trúc 3-tầng giúp phân tách rõ ràng giữa các phần khác nhau của ứng dụng và tạo ra sự tách
biệt giữa giao diện người dùng, logic nghiệp vụ và dữ liệu. Điều này giúp tăng tính linh hoạt, khả
năng bảo trì và mở rộng của hệ thống. Nó cũng cho phép phát triển độc lập của các tầng, cho
phép sử dụng lại và thay thế các thành phần một cách dễ dàng.
Ví dụ về kiến trúc 3-tầng bao gồm: 
Một ứng dụng web: Front-end là trình duyệt web, middle tier chứa các dịch vụ web và
logic nghiệp vụ, back-end chứa cơ sở dữ liệu để lưu trữ thông tin. 
Một ứng dụng di động: Front-end là ứng dụng di động, middle tier xử lý logic nghiệp vụ
và tương tác với các dịch vụ web, back-end chứa cơ sở dữ liệu để lưu trữ dữ liệu.
Lợi ích của kiến trúc 3-tầng bao gồm: 
Phân tách rõ ràng: Kiến trúc này giúp phân tách rõ ràng giữa giao diện người dùng, logic
nghiệp vụ và dữ liệu, làm cho mã nguồn dễ quản lý và bảo trì hơn. 
Tính mở rộng: Các tầng có thể được mở rộng độc lập nhau. Ví dụ, có thể thêm nhiều
máy chủ ứng dụng hoặc máy chủ cơ sở dữ liệu để tăng khả năng xử lý hoặc lưu trữ. 
Tái sử dụng: Phân tách rõ ràng các tầng cho phép tái sử dụng các thành phần và logic
nghiệp vụ. Ví dụ, cùng một ứng dụng giao diện người dùng có thể được sử dụng cho
nhiều ứng dụng khác nhau.
5.3.4. MVC (Model-View-Controller)
MVC (Model-View-Controller) là một mô hình kiến trúc phần mềm phổ biến được sử dụng trong
phát triển ứng dụng. Nó tách biệt ứng dụng thành ba phần khác nhau: Model (Mô hình), View
(Giao diện) và Controller (Bộ điều khiển). 
Model: Mô hình đại diện cho dữ liệu và logic nghiệp vụ của ứng dụng. Nó biểu diễn các
đối tượng, lớp, hoặc cấu trúc dữ liệu mà ứng dụng hoạt động với. Model chịu trách
nhiệm cho việc lấy dữ liệu từ nguồn dữ liệu (như cơ sở dữ liệu) và cung cấp các phương
thức để thao tác với dữ liệu đó. Nó không biết gì về giao diện người dùng hoặc cách dữ liệu được hiển thị. 
View: Giao diện đại diện cho cách dữ liệu được hiển thị cho người dùng. Nó là phần giao
diện người dùng mà người dùng tương tác và nhìn thấy. View nhận dữ liệu từ Model và
sắp xếp nó để hiển thị cho người dùng. View không chứa bất kỳ logic nghiệp vụ nào, chỉ
đơn giản là hiển thị dữ liệu. 
Controller: Bộ điều khiển làm trung gian giữa Model và View. Nó nhận các yêu cầu từ
người dùng thông qua giao diện người dùng (View) và xử lý chúng. Controller chịu trách
nhiệm điều hướng luồng công việc, xử lý logic nghiệp vụ và tương tác với Model để lấy
và cập nhật dữ liệu. Sau đó, nó chuyển dữ liệu đã xử lý và kết quả đến View để hiển thị cho người dùng.
MVC tạo ra sự phân tách rõ ràng giữa dữ liệu, giao diện người dùng và logic nghiệp vụ. Điều này
giúp cải thiện tính bảo trì, mở rộng và tái sử dụng của ứng dụng. Nó cũng giúp tăng tính hiệu
quả trong việc phát triển ứng dụng bằng cách phân chia công việc thành các phần độc lập và
cho phép các nhóm phát triển làm việc đồng thời trên các phần khác nhau của ứng dụng.
Quy trình hoạt động của MVC thường là như sau:
1. Người dùng tương tác với giao diện người dùng (View), ví dụ như nhấp vào một nút hoặc nhập dữ liệu.
2. Giao diện người dùng (View) gửi yêu cầu tương ứng cho bộ điều khiển (Controller).
3. Bộ điều khiển (Controller) nhận yêu cầu, xử lý logic nghiệp vụ và tương tác với Model nếu cần.
4. Model cung cấp dữ liệu cho bộ điều khiển (Controller).
5. Bộ điều khiển (Controller) chuyển dữ liệu đã xử lý đến giao diện người dùng (View).
6. Giao diện người dùng (View) nhận dữ liệu và hiển thị nó cho người dùng. 5.4. Design Process 5.4.1. Design Process
Overview: Giới thiệu tổng quan về quy trình thiết kế.
Purpose: Mô tả mục đích của quy trình thiết kế, bao gồm việc phát triển giải pháp cho các yêu
cầu và tạo ra các tài liệu thiết kế cấp cao và chi tiết.
Software Requirement Specification: Mô tả yêu cầu phần mềm để phát triển giải pháp.
Select from alternative solutions: Lựa chọn giải pháp từ các phương án thay thế.
Develop design documents: Phát triển các tài liệu thiết kế.
Review design documents: Xem xét và đánh giá các tài liệu thiết kế.
Alternative Design solutions: Các giải pháp thiết kế thay thế.
Evaluation Criteria: Tiêu chí đánh giá giải pháp thiết kế.
DAR report: Báo cáo về quyết định thiết kế đã được chấp thuận.
ADD, HLD, DDD: Các tài liệu thiết kế cấp cao (ADD), thiết kế cấp cao (HLD), và tài liệu thiết kế chi tiết (DDD).
Approved Design Documents: Các tài liệu thiết kế đã được chấp thuận.
Develop the design: Quy trình phát triển thiết kế.
AD/HLD, DD: Bước và hoạt động liên quan đến thiết kế cấp cao (AD/HLD) và thiết kế chi tiết (DD).
Review and approve high-level design: Xem xét và chấp thuận thiết kế cấp cao.
Detail design: Thiết kế chi tiết. 5.4.2. Design Workflow
Overview: Tổng quan về quy trình thiết kế.
A, B: Các bước trong quy trình thiết kế. 5.4.3. Design Documents: High-Level Design: 
Overview: Tổng quan về thiết kế cấp cao. 
A High-Level Design: Một tài liệu thiết kế cấp cao cung cấp cái nhìn tổng quan về một giải
pháp, nền tảng, hệ thống, sản phẩm, dịch vụ hoặc quy trình. 
High-Level Design Document Sample: Mẫu tài liệu thiết kế cấp cao. Detailed Designs: 
Screen Design Document: Tài liệu thiết kế màn hình, mô tả cấu trúc màn hình hoặc
chuyển tiếp giữa các màn hình và bao gồm danh sách các thành phần của màn hình và hình ảnh minh họa. 
Data Design Document: Tài liệu thiết kế dữ liệu, mô tả các sơ đồ mối quan hệ thực thể,
cấu trúc bảng, cấu trúc trường và cấu trúc tệp tin. 
Class Design Document: Tài liệu thiết kế lớp, mô tả các gói COMMON, xử lý lỗi, ghi log,
tối ưu hiệu suất, sơ đồ lớp và sơ đồ trình tự, giao diện bên ngoài và khai báo phương thức. 5.5. Code Design
5.5.1. Algorithmic Problem Solving
What is an algorithm? (Thuật toán là gì?): Phần này giải thích khái niệm về thuật toán, tức là
danh sách các bước để thực hiện một nhiệm vụ cụ thể.
Pseudo Code (Mã giả): Mã giả là một mô tả chi tiết và dễ đọc (bằng tiếng Anh đơn giản) về việc
một chương trình máy tính hoặc thuật toán cần làm gì.
Flowchart (Sơ đồ luồng): Sơ đồ luồng là biểu đồ minh họa cho chuỗi các hoạt động cần thực
hiện để giải quyết một vấn đề.
The Structure Theorem (Định lý cấu trúc): Phần này giới thiệu về các nguyên tắc cơ bản của cấu
trúc thuật toán, bao gồm tuần tự (sequence), lựa chọn (selection) và lặp (repetition). 5.5.2. Pseudo Code
What is Pseudo Code? (Mã giả là gì?): Phần này cung cấp hướng dẫn về việc viết mã giả và các
nguyên tắc hướng dẫn để tạo mã giả chính xác.
Guidelines for writing Pseudo Code (Hướng dẫn viết mã giả):
Phần này đưa ra các hướng dẫn cụ thể về cách viết mã giả, bao gồm các quy tắc và cấu trúc.
Basic computer operations (Các hoạt động cơ bản của máy tính):
Phần này liệt kê sáu hoạt động cơ bản mà máy tính có thể thực hiện.
Keywords and control structures (Từ khóa và cấu trúc điều khiển):
Phần này giới thiệu các từ khóa và cấu trúc điều khiển được sử dụng trong mã giả.
Indentation and subprograms (Thụt lề và các chương trình con): Phần này giải thích cách sử
dụng thụt lề để chỉ ra cấu trúc trong mã giả và cách sử dụng chương trình con (subprograms). 5.5.3. Flowchart
1. Overview (Sơ đồ luồng - Tổng quan):
Phần này cung cấp một cái nhìn tổng quan về sơ đồ luồng, bao gồm mục đích và lợi ích của việc
sử dụng sơ đồ luồng trong lập trình và giao tiếp giữa các nhà phát triển và người dùng kinh doanh.
2. Basic Flowchart Symbols (Sơ đồ luồng - Các biểu tượng cơ bản):
Phần này giới thiệu các biểu tượng cơ bản được sử dụng trong sơ đồ luồng, bao gồm hộp tròn
(rounded box), hình chữ nhật (rectangle or box), hình thoi (diamond) và hình tròn (circle). Mỗi
biểu tượng đại diện cho một loại hoạt động hoặc quyết định trong quá trình giải quyết vấn đề.
3. Sample (Sơ đồ luồng - Mẫu): 5.5.4. The Structure Theorem
4. Sequential Structure (Cấu trúc tuần tự): Phần này giải thích về cấu trúc tuần tự trong
thuật toán, trong đó các câu lệnh được thực hiện theo thứ tự từ trên xuống dưới. Nó
bao gồm các ví dụ và hướng dẫn cách sử dụng cấu trúc tuần tự để giải quyết các vấn đề cụ thể.
5. Selection Structure (Cấu trúc lựa chọn): Phần này giới thiệu về cấu trúc lựa chọn trong
thuật toán, trong đó một quyết định được đưa ra dựa trên một điều kiện. Nó bao gồm
các biểu thức điều kiện, cú pháp, và ví dụ về cách sử dụng cấu trúc lựa chọn để xử lý các tình huống khác nhau.
6. Repetition Structure (Cấu trúc lặp): Phần này trình bày về cấu trúc lặp trong thuật toán,
cho phép thực hiện một tập hợp các câu lệnh nhiều lần dựa trên một điều kiện lặp. Nó
bao gồm các loại lặp, cú pháp và ví dụ về cách sử dụng cấu trúc lặp để giải quyết các vấn đề có tính lặp lại.
7. Nesting Structures (Cấu trúc lồng nhau): Phần này giải thích về cách kết hợp cấu trúc
tuần tự, lựa chọn và lặp lại trong thuật toán bằng cách lồng chúng vào nhau. Nó cung
cấp các ví dụ về việc sử dụng cấu trúc lồng nhau để giải quyết các vấn đề phức tạp hơn. 5.6. Coding Process 5.6.1. Coding Process
Nơi thực hiện lập trình: Phần này giải thích nơi mà quá trình lập trình diễn ra.
Luồng làm việc trong quy trình lập trình: Mô tả các bước cơ bản trong quy trình lập trình, bao
gồm lập kế hoạch, xây dựng module thư viện, xây dựng module chức năng, tích hợp các thành
phần, tạo mô tả hệ thống và hoàn thành công việc. 5.6.2. Code Review Process
Kiểm tra mã lệnh: Mô tả quá trình kiểm tra kỹ thuật và logic từng dòng mã lệnh, tìm và sửa các lỗi trong mã.
Lợi ích của việc kiểm tra mã lệnh: Đề cập đến những lợi ích của việc kiểm tra mã lệnh, bao gồm
khả năng tăng tốc độ và chất lượng phát triển, giảm lỗi và sự trùng lặp, cải thiện giao tiếp trong
nhóm và tăng sự đồng lòng của nhóm.
Các bước trong quy trình kiểm tra mã lệnh: Mô tả các bước cần thiết trong quy trình kiểm tra
mã lệnh, bao gồm chuẩn bị cho kiểm tra, tiến hành kiểm tra, đánh giá kết quả kiểm tra và tiếp
tục làm việc sau kiểm tra.
Vai trò và trách nhiệm của các thành viên trong quy trình kiểm tra mã lệnh: Đề cập đến vai trò
và trách nhiệm của các thành viên như người lãnh đạo, người viết mã, người kiểm tra và người
phê duyệt trong quy trình kiểm tra mã lệnh.
Đầu vào và đầu ra của quy trình kiểm tra mã lệnh: Mô tả các yếu tố cần thiết để thực hiện quy
trình kiểm tra mã lệnh, bao gồm mục tiêu kiểm tra, mã nguồn cần kiểm tra và các thành phần
liên quan khác như tài liệu, ca kiểm thử, lịch trình dự án và thay đổi yêu cầu.
5.6.3. Common Defects & Practices
Các lỗi phổ biến và thực hành: Liệt kê và mô tả các lỗi phổ biến trong quá trình lập trình và
những thực hành tốt để tránh các lỗi đó, bao gồm việc tránh sử dụng hằng số hard code, chỉ số mảng bắt đầu từ 0. 5.7. Unit Testing Basics
5.7.1. Unit Test - What and Who? Unit Test - Định nghĩa: 
Định nghĩa về kiểm thử đơn vị: Kiểm thử đơn vị là một kỹ thuật kiểm thử phần mềm tập
trung vào việc kiểm thử từng đơn vị hoặc thành phần riêng lẻ của một hệ thống.
Ai thực hiện kiểm thử đơn vị? 
Trách nhiệm của các vai trò khác nhau trong kiểm thử đơn vị: Kiểm thử đơn vị chủ yếu
do các nhà phát triển hoặc lập trình viên thực hiện. Họ chịu trách nhiệm tạo ra và duy trì
các bài kiểm tra đơn vị. 
Sự cộng tác giữa nhà phát triển và nhóm kiểm thử: Nhóm kiểm thử cũng có thể đóng
góp vào công việc kiểm thử đơn vị bằng cách đưa ra các trường hợp kiểm thử, xem xét
phạm vi kiểm thử và hỗ trợ trong việc tự động hóa kiểm thử. 
Sự tham gia của nhóm đảm bảo chất lượng (QA): Nhóm QA có thể cùng nhà phát triển
thiết lập các tiêu chuẩn, hướng dẫn và các quy tắc tốt nhất cho kiểm thử đơn vị. Họ cũng
có thể xem xét kết quả kiểm thử đơn vị và đưa ra phản hồi.
Lợi ích của kiểm thử đơn vị: 
Nâng cao chất lượng mã nguồn: Kiểm thử đơn vị giúp phát hiện và sửa lỗi sớm trong quá
trình phát triển, từ đó nâng cao chất lượng mã nguồn. 
Phát hiện lỗi sớm: Kiểm thử đơn vị có thể phát hiện lỗi và vấn đề ở giai đoạn sớm, ngăn
chặn chúng lan rộng đến các cấp kiểm thử cao hơn. 
Giảm thời gian sửa lỗi và khắc phục sự cố: Kiểm thử đơn vị giúp thu hẹp phạm vi gỡ lỗi,
giúp tìm kiếm và sửa lỗi dễ dàng hơn. 
Hỗ trợ bảo trì mã nguồn và tái cấu trúc: Kiểm thử đơn vị đóng vai trò như một mạng an
toàn khi thay đổi mã nguồn, đảm bảo tính chính xác của các chức năng hiện có. 
Hỗ trợ tài liệu và chia sẻ kiến thức: Các bài kiểm thử đơn vị được coi như tài liệu có thể
thực thi, giới thiệu cách sử dụng mã nguồn và cung cấp thông tin về hành vi kỳ vọng.
Mối quan hệ giữa kiểm thử đơn vị và các cấp kiểm thử khác: 
Sự khác biệt giữa kiểm thử đơn vị và các cấp kiểm thử khác: Kiểm thử đơn vị tập trung
vào kiểm thử từng đơn vị độc lập, trong khi các cấp kiểm thử khác (như kiểm thử tích
hợp và kiểm thử hệ thống) kiểm tratính tương tác và tích hợp giữa các thành phần. 
Vai trò của kiểm thử đơn vị trong quá trình kiểm thử: Kiểm thử đơn vị là bước đầu tiên
và quan trọng trong quá trình kiểm thử phần mềm. Nó giúp xác định và khắc phục các lỗi
ở mức đơn vị trước khi tiến xa hơn vào các cấp kiểm thử khác. 
Cách liên kết với các cấp kiểm thử khác: Kết quả của kiểm thử đơn vị sẽ cung cấp thông
tin cần thiết cho các bước kiểm thử tiếp theo, như kiểm thử tích hợp và kiểm thử hệ
thống. Các lỗi được phát hiện trong quá trình kiểm thử đơn vị cần được sửa chữa trước
khi tiến hành các bước kiểm thử khác.
Các phương pháp và kỹ thuật trong kiểm thử đơn vị: 
Kỹ thuật phân tích giá trị biên (Boundary Value Analysis): Phương pháp này tập trung vào
việc kiểm tra các giá trị biên và giá trị gần biên của đầu vào để phát hiện các lỗi liên quan đến ranh giới biên. 
Kỹ thuật kiểm tra điều kiện (Condition Testing): Phương pháp này kiểm tra các điều kiện
logic trong mã nguồn để đảm bảo rằng tất cả các nhánh điều kiện được thực hiện đúng. 
Kỹ thuật kiểm tra đường dẫn (Path Testing): Phương pháp này tập trung vào việc kiểm
tra tất cả các đường dẫn có thể trong mã nguồn để đảm bảo rằng tất cả các đường dẫn
đã được thực hiện và kiểm tra các trạng thái khác nhau của chương trình. 
Kỹ thuật kiểm tra dự đoán (Equivalence Partitioning): Phương pháp này chia các tập hợp
dữ liệu đầu vào thành các phân vùng tương đương và chỉ kiểm tra một số trường hợp
biểu diễn cho từng phân vùng. 
Đơn vị kiểm thử tự động (Automated Unit Testing): Sử dụng các framework và công cụ
kiểm thử đơn vị tự động như JUnit (cho Java) hoặc NUnit (cho .NET) để tạo và chạy các
bài kiểm thử đơn vị tự động.
Thực hiện kiểm thử đơn vị trong quy trình phát triển phần mềm: 
Định nghĩa tác vụ kiểm thử đơn vị: Xác định các tác vụ và trách nhiệm cụ thể liên quan
đến kiểm thử đơn vị trong quy trình phát triển phần mềm. 
Thiết lập môi trường kiểm thử đơn vị: Đảm bảo rằng môi trường kiểm thử đơn vị được
thiết lập đúng, bao gồm cài đặt và cấu hình các công cụ kiểm thử đơn vị cần thiết. 
Xác định và tạo bài kiểm thử đơn vị: Xác định các trường hợp kiểm thử, tạo các bài kiểm
thử đơn vị theo các kỹ thuật và phương pháp đã được đề cập. 
Thực hiện kiểm thử đơn vị: Chạy các bài kiểm thử đơn vị và ghi lại kết quả kiểm thử.
Theo dõi và gỡ lỗi các lỗi được phát hiện trong quá trình kiểm thử. 
Tối ưu hóa và duy trì bài kiểm thử đơn vị: Cải thiện và điều chỉnh các bài kiểm thử đơn vị
dựa trên kinh nghiệm và phản hồi từ quá trình kiểm thử trước đó. Duy trì các bài kiểm
thử đơn vị theo sự thay đổi và bảo trì mã nguồn.
Các thách thức và lưu ý khi thực hiện kiểm thử đơn vị: 
Tính phủ kiểm thử đơn vị: Đảm bảo rằng tất cả các đườngdẫn và trạng thái trong mã
nguồn được kiểm tra, để đảm bảo tính phủ kiểm thử đơn vị cao. 
Sự phụ thuộc và giả lập: Kiểm thử đơn vị có thể gặp khó khăn khi các đơn vị phụ thuộc
chưa hoàn thiện hoặc không sẵn có. Trong trường hợp này, cần sử dụng kỹ thuật giả lập
để kiểm thử đơn vị một cách cô lập. 
Tính cân nhắc và hiệu quả: Chọn các bài kiểm thử đơn vị quan trọng và hiệu quả để tối
ưu thời gian và nguồn lực trong quá trình kiểm thử. 
Dễ dàng bảo trì và mở rộng: Thiết kế các bài kiểm thử đơn vị sao cho dễ dàng bảo trì và
mở rộng trong tương lai, khi mã nguồn được thay đổi hoặc mở rộng. 
Tích hợp với quy trình CI/CD: Tự động hóa quá trình kiểm thử đơn vị và tích hợp nó vào
quy trình CI/CD giúp đảm bảo tính liên tục và nhanh chóng của việc phát triển phần mềm. 5.7.2. Unit Test - Why? 1. Phát hiện lỗi sớm: 
Kiểm thử đơn vị giúp phát hiện lỗi và vấn đề trong giai đoạn đầu của quá trình phát triển. 
Bằng cách viết các bài kiểm thử cho từng đơn vị mã nguồn (như hàm hoặc phương
thức), các nhà phát triển có thể phát hiện và sửa lỗi trước khi chúng lan rộng sang
các phần khác của hệ thống. 
Điều này giảm tổng chi phí và công sức cần thiết cho việc sửa lỗi.
2. Đảm bảo chất lượng mã nguồn: 
Kiểm thử đơn vị là một cơ chế đảm bảo chất lượng cho từng đơn vị mã nguồn. Nó
giúp đảm bảo rằng mỗi đơn vị hoạt động đúng và tạo ra kết quả dự kiến. 
Bằng cách xác minh hành vi của từng đơn vị, các nhà phát triển có thể tin tưởng hơn
về tính chính xác của mã nguồn của mình.
3. Giúp dễ dàng gỡ lỗi và tái cấu trúc: 
Khi một bài kiểm thử đơn vị không thành công, nó cung cấp một chỉ báo rõ ràng rằng
có điều gì đó không đúng với mã nguồn. 
Kiểm thử đơn vị đóng vai trò là một "lưới an toàn" trong quá trình gỡ lỗi, giúp xác
định đơn vị cụ thể gây ra vấn đề. 
Ngoài ra, kiểm thử đơn vị cho phép các nhà phát triển tự tin tái cấu trúc mã nguồn
mà không gây ra lỗi mới, bởi vì họ có thể chạy lại các bài kiểm thử để đảm bảo rằng
mã nguồn được tái cấu trúc hoạt động đúng như mong đợi.
4. Hỗ trợ sự cộng tác: 
Kiểm thử đơn vị đóng vai trò như tài liệu sống cho mã nguồn. Nó cung cấp thông tin
về cách một đơn vị cụ thể nên hoạt động và có thể giúp các nhà phát triển mới hiểu
chức năng của mã nguồn hiện có. 
Bằng cách có một bộ bài kiểm thử đơn vị toàn diện, các nhà phát triển có thể cộng
tác hiệu quả hơn, đảm bảo rằng các thay đổi được thực hiện bởi một người không
làm hỏng chức năng được mong đợi bởi những người khác.
5. Hỗ trợ việc bảo trì mã nguồn: 
Kiểm thử đơn vị làm cho mã nguồn dễ bảo trì hơn trong tương lai. Khi mã nguồn
tiến triển và phát triển, kiểm thử đơn vị đóng vai trò như một "lưới an toàn" chống
lại những thay đổi không cố ý hoặc lỗi mới. 
Nó giúp đảm bảo rằng các sửa đổi hoặc cải tiến cho mã nguồnđều không gây ra lỗi
mới hoặc làm hỏng chức năng hiện có.
6. Giảm thời gian phát triển: 
Mặc dù viết kiểm thử đơn vị yêu cầu một khoản đầu tư thời gian ban đầu, nhưng nó
có thể giảm đáng kể thời gian phát triển trong dài hạn. 
Kiểm thử đơn vị giúp nhà phát triển phát hiện sớm các vấn đề, giảm thời gian làm
việc trên gỡ lỗi và làm lại công việc. 
Hơn nữa, có một bộ bài kiểm thử đơn vị toàn diện giúp cho việc thay đổi mã nguồn
nhanh hơn và tự tin hơn, vì nhà phát triển có thể kiểm tra lại các bài kiểm thử để
đảm bảo rằng chức năng hiện có vẫn hoạt động như mong đợi.
5.7.3. Unit Test - How? (method, technique)
Kiểm thử hộp đen (Black-box testing): Phương pháp này không quan tâm tới cấu trúc nội bộ và
chi tiết cài đặt của mã nguồn. Các trường hợp kiểm thử được thiết kế dựa trên các đầu vào và
kết quả mong đợi của đơn vị đang được kiểm thử. Trọng tâm là kiểm thử chức năng của đơn vị. 
Kiểm thử chức năng (Functional testing): Kỹ thuật này đảm bảo rằng mỗi đơn vị hoạt
động đúng theo thiết kế và yêu cầu chức năng. 
Kiểm thử kinh doanh (Business testing): Kỹ thuật này đảm bảo rằng phần mềm hoạt
động đúng theo yêu cầu của người dùng và quy tắc kinh doanh. 
Kiểm thử hộp trắng (White-box testing): Phương pháp này xem xét cấu trúc nội bộ và chi
tiết cài đặt của mã nguồn. Các trường hợp kiểm thử được thiết kế để kiểm tra các
đường đi và điều kiện khác nhau trong đơn vị. Trọng tâm là kiểm thử logic và phạm vi mã nguồn. 
Do chính lập trình viên thực hiện: Lập trình viên thực hiện kiểm thử hộp trắng bằng cách
kiểm tra cú pháp của mã nguồn, chạy chế độ gỡ lỗi, kiểm tra cấu trúc dữ liệu cục bộ và
kiểm tra các điều kiện biên và xử lý lỗi.
Các kỹ thuật được áp dụng trong kiểm thử hộp trắng bao gồm: 
Độ bao phủ câu lệnh (Statement coverage): Đảm bảo rằng mỗi câu lệnh trong mã nguồn
được thực thi ít nhất một lần trong quá trình kiểm thử. 
Độ bao phủ quyết định (Decision coverage): Đảm bảo rằng tất cả các kết quả quyết định
có thể xảy ra (nhánh điều kiện) được kiểm thử.
Độ bao phủ đường đi (Path coverage): Đảm bảo rằng tất cả các đường đi có thể xảy ra
trong mã nguồn được kiểm thử. 
Cả kiểm thử hộp đen và kiểm thử hộp trắng đều có những ưu điểm riêng và được sử
dụng trong các tình huống khác nhau. Kiểm thử hộp đen tập trung hơn vào chức năng và
hành vi bên ngoài của đơn vị, trong khi kiểm thử hộp trắng đi sâu vào cài đặt nội bộ và logic của mã nguồn. ~~End~~