Bài toán có liên quan đến đối tượng document. Một document là một tài liệu có tiêu đề (name), version number, có ngày cập nhật cuối, người cập nhật.
Document được mô tả bởi class Document (viết bằng C#), và lưu trữ bằng RDBMS SQL Server.
public class Document {
int documentId;
string name;
string versionNumber;
DateTime lastModificationDateTime;
int lastModifierId;
}
TABLE Documents {
DocumentId INT,
Name NVARCHAR(50),
VersionNumber VARCHAR(50),
LastModificationDateTime DATETIME,
LastModifier INT
}
Để mô tả các column của table Documents, Trí tạo một enum trong source code
enum DocumentColumns {
DocumentId,
Name,
VersionNumber,
LastModificationDateTime,
LastModifier
}
Trong layer Data access, cần một hàm để lấy tất cả các Doument được sắp xếp theo một thứ tự trên một cột nào đó, prototype như sau:
public class DocumentDAO {
public DocumentCollection GetDocuments(
DocumentColums sortColumn,
OrderDirection order
) {
// Thực tế Trí dùng stored proc, nhưng đại ý giống như sau:
string sql = "SELECT * FROM Douments ORDER BY " +
sortColumn.ToString() +
" " +
order.ToString();
// thực thi sql
}
}
Tương tự trên Bussiness Layer,
public class DocumentService {
public DocumentCollection GetDocuments(
DocumentColums sortColumn,
OrderDirection order
) {
// gọi lại hàm DocumentDAO.GetDocuments()
}
}
Phía UI (asp.net) dùng DocumentService, không được dùng DocumentDAO.
Nhận xét:
- việc dùng DocumentColumns không hợp lý, vì sao ở UI, client phải CARE về các column của TABLE vốn đã được tách rồi bởi Bussiness Layer.
- Nhập nhằng giữa class design và DB design. Nếu đổi tên column mà không đổi tên enum thì lệnh
string sql = "SELECT * FROM Douments ORDER BY " + sortColumn.ToString() + " " + order.ToString();cho kết quả sai ngay. Vì sao tên của enum phụ thuộc vào tên của các column của table Doument ? - Đang sử dụng side effect của enum. Về bản chất, enum là một con số, một cách dùng khác của hằng.
Hậu quả:
- Khiến người lập trình UI phải care về database. Mất ý nghĩa của việc tách layer
- Việc sửa tên column ảnh hưởng tới code của tất cả các layer.
- Chúng ta có 2 convention, một cho RDBMS phân biệt hoa thường ở tên table/column như SQL Server; và cho RDBMS chỉ cho phép dùng chữ hoa cho tên table/ column như Oracle. Ví dụ ở Oracle sẽ là DOCUMENT_ID, NAME, VERSION_NUMBER ... Như vậy kiểu enum không còn dùng được nữa.
- Lạm dụng side effect
Một đề nghị thay đổi:
- Thực hiện ánh xạ enum sang tên column. Ví dụ
string[] readonly COLUMNS = new string[] {
"DocumentId", "Name", "VersionNumber",
"LastMidificationDateTime", "LastModifierId"
};
static string GetColumnName(DoumentColumns value) {
return COLUMNS[(int)value];
}
khi đó
public class DocumentDAO {
public DocumentCollection GetDocuments(
DocumentColums sortColumn,
OrderDirection order
) {
// Thực tế Trí dùng stored proc, nhưng đại ý giống như sau:
string sql = "SELECT * FROM Douments ORDER BY " +
GetColumnName(sortColumn) +
" " +
order.ToString();
// thực thi sql
}
}
- Đổi tên enum DocumentColumns thành DocumentProperty.
1 comment:
Post a Comment