10. Tối thiểu biến toàn cục và dữ liệu chia sẻ chung

Estimated reading: 6 minutes 284 views

Tóm tắt

Chia sẻ dữ liệu gây ra tranh chấp: Hạn chế sử dụng dữ liệu dùng chung, đặc biệt là dữ liệu toàn cục. Dữ liệu dùng chung làm tăng mức độ liên kết giữa các phần của chương trình, khiến mã nguồn khó bảo trì hơn và thường ảnh hưởng đến hiệu suất.

Thảo luận

Nguyên tắc này mang tính tổng quát hơn so với nội dung của Mục 18, vốn chỉ tập trung vào một khía cạnh cụ thể.

  • Tránh sử dụng dữ liệu có liên kết bên ngoài (external linkage) ở phạm vi không gian tên (namespace scope) hoặc thành viên tĩnh của lớp (static class objects). Những kiểu dữ liệu này làm phức tạp logic chương trình; gây liên kết chặt chẽ hơn giữa các phần khác nhau (thậm chí là giữa các phần cách xa nhau) trong chương trình.
  • Dữ liệu dùng chung làm giảm tính hiệu quả của kiểm thử đơn vị (unit test), bởi vì tính đúng đắn của một đoạn mã sử dụng dữ liệu dùng chung sẽ phụ thuộc vào lịch sử thay đổi của dữ liệu đó. Ngoài ra, nó cũng ảnh hưởng đến các đoạn mã khác chưa xác định trong tương lai, những đoạn mã có thể sử dụng cùng dữ liệu.
  • Các đối tượng nằm trong không gian tên toàn cục cũng gây ra hiện tượng ô nhiễm không gian tên (namespace pollution).

Nếu bạn bắt buộc phải sử dụng đối tượng (dữ liệu) toàn cục; đối tượng trong phạm vi không gian tên hoặc thành viên tĩnh của lớp; hãy đảm bảo rằng chúng được khởi tạo một cách cẩn thận.

  • Thứ tự khởi tạo các đối tượng này trong các đơn vị biên dịch khác nhau là không xác định và cần có các kỹ thuật đặc biệt để xử lý đúng (xem tài liệu tham khảo).
  • Các quy tắc về thứ tự khởi tạo khá tinh vi và phức tạp; vì vậy, tốt nhất là tránh sử dụng dữ liệu toàn cục. Nếu buộc phải sử dụng, hãy tìm hiểu kỹ và áp dụng chúng một cách thận trọng.

Ảnh hưởng đến hiệu suất và tính mở rộng:

  • Dữ liệu ở phạm vi không gian tên, thành viên tĩnh (static members) hoặc dữ liệu được chia sẻ giữa các thread / process sẽ làm giảm tính song song (parallelism) trong các môi trường đa luồng (multithreading) và đa xử lý (multiprocessing).
  • Chúng thường là nguyên nhân chính gây ra các điểm nghẽn hiệu suất (performance bottlenecks) và hạn chế khả năng mở rộng (scalability). (Xem Mục 7)
  • Hãy cố gắng tuân theo nguyên tắc “không chia sẻ gì cả” (shared-nothing); thay vì chia sẻ dữ liệu chung, hãy sử dụng các phương thức giao tiếp khác như hàng đợi thông điệp (message queues)…
  • Ưu tiên thiết kế mã code với mức độ liên kết thấp (low coupling) và tối thiểu hóa sự phụ thuộc giữa các lớp (class). (Xem [Cargill92].)

Ngoại lệ

  • Các tiện ích dùng chung trên toàn chương trình như cin, cout và cerr là các trường hợp đặc biệt và đã được hiện thực một cách đặc biệt.
  • Factory pattern thường phải duy trì một bảng đăng ký (registry) để xác định hàm nào cần gọi để tạo một kiểu đối tượng cụ thể. Thông thường, chỉ có một bảng đăng ký duy nhất trong toàn bộ chương trình, nhưng tốt nhất là nó nên được đóng gói bên trong factory thay vì là một đối tượng toàn cục dùng chung (xem Mục 11). → Giải thích chi tiết kèm ví dụ
  • Nếu bắt buộc phải chia sẻ dữ liệu giữa các luồng (multithreading), luôn phải đảm bảo rằng mọi thao tác truy cập đều được tuần tự hóa (serialized access) để tránh lỗi cạnh tranh tài nguyên (race conditions). (Xem Mục 12 và [Sutter04c].)

Tham khảo

[Cargill92] pp. 126.136, 169-173 • [DewhurstO3] §3 • [Lakos96] §2.3.1 • [McConnell93] §5.1-4 • [Stroustrup00] §C.10.1 • [Sutter00] §47 • [SutterO2] §16, Appendix A • [Sutter04c] • [SuttHysl03]

Link

Leave a Comment

Chia sẻ:

10. Tối thiểu biến toàn cục và dữ liệu chia sẻ chung

Or copy link

CONTENTS