Cách tốt nhất để tổ chức các truy vấn SQL được lưu trữ trong mã của bạn? (hoặc bạn nên?) [đóng]


13

Tôi chắc chắn rằng tôi không phải là người duy nhất cảm thấy thất vọng khi họ thấy một trang mã chứa đầy các truy vấn SQL. ActiveRecord và các mẫu ORM khác giúp giảm thiểu một lượng SQL tốt được sử dụng trong một dự án, nhưng trong nhiều trường hợp truy vấn phức tạp, việc sử dụng SQL dường như là không thể tránh khỏi.

Tôi đang tìm kiếm ý kiến ​​về cách tổ chức các truy vấn SQL với phần còn lại của mã (hoặc bên ngoài nó) để giữ cho nó không bị phân tán khắp nơi? Một ý tưởng rõ ràng là việc sử dụng Chế độ xem, nhưng thường thì Chế độ xem có thể là nguồn gốc của các vấn đề về hiệu suất khi xử lý nhiều bảng được lập chỉ mục lớn, v.v.

EDIT 1 - Tôi giả sử bạn đã tách nó thành lớp mô hình


3
Câu hỏi này chắc chắn phù hợp ở đây - tổ chức mã: 'truyền cảm hứng cho những câu trả lời giải thích về lý do tại sao và cách làm thế nào. và là của các đối tượng 'Mẫu thiết kế' và 'Kiến trúc' (từ Faq )
Michael K

1
Tôi chỉ định hỏi câu hỏi tương tự. Tôi ước có nhiều câu trả lời hơn ở đây.
Michael Kristofik

Câu trả lời:


10

Đối với tôi, SQL là một phần cơ bản (trong rất nhiều trường hợp, phần lớn) của mã logic nghiệp vụ. Nếu bạn cố tách nó ra khỏi mã hoạt động trên dữ liệu được trả về, bạn sẽ dễ bị mất cân bằng về tính dễ hiểu và khả năng duy trì của mã.

Khi tôi nhìn vào nó, đọc dữ liệu, xử lý dữ liệu, ghi dữ liệu, tìm kiếm dữ liệu ... chúng đều là các hoạt động tương tự và tốt nhất được giữ ở cùng một nơi.

Nếu bạn bắt đầu cảm thấy sự trùng lặp các nỗ lực với các truy vấn, thì có lẽ bạn cần một chế độ xem cơ sở dữ liệu hoặc một đối tượng có thể gói gọn khía cạnh đó của truy cập cơ sở dữ liệu.

Một mẹo khác là thực sự có một phương pháp truy vấn cơ sở dữ liệu tốt. Trong phần mềm tôi viết (PostgreSQL, MySQL, SQL Server), tôi đã đảm bảo rằng phần lớn các hoạt động truy vấn của tôi có thể diễn ra dưới dạng một câu lệnh mã.

GetValue(SQL, [transaction], [array_of_params])
GetRow(SQL, [transaction], [array_of_params])
GetRowList(SQL, [transaction], [array_of_params])
GetValueList(SQL, [transaction], [array_of_params])
Execute(SQL, [transaction], [array_of_params])

Đó là (đại khái) các lệnh gọi hàm chính mà tôi đảm bảo là một phần của "đối tượng kết nối" của tôi. Nó phụ thuộc vào ngôn ngữ, những gì bạn thực sự thực hiện, nhưng quan điểm của tôi là giữ cho nó thực sự, thực sự đơn giản và không đau.

Tóm lại, coi SQL như một phần bản địa của lập trình và không trừu tượng vì mục đích trừu tượng.


1
một câu trả lời tuyệt vời có lẽ tôi chỉ cần lùi lại và bắt đầu xem SQL như một phần của mã, không chỉ nằm rải rác trong đó.
Jellyfishtree

1
"không trừu tượng vì lợi ích trừu tượng" - Điểm hay. Tóm tắt vì lợi ích của mã dễ hiểu hơn.
Jason Baker

'Một mẹo khác là thực sự có một phương pháp truy vấn cơ sở dữ liệu tốt': Tôi chắc chắn đồng ý. Nó giúp ích rất nhiều khi chỉ có một nơi để sửa đổi mã khi logic nghiệp vụ thay đổi.
Michael K

1
Nơi nào bạn đặt SQL? Có phải nó được biên dịch vào ứng dụng và được gửi bằng các phương thức trên không?
johnny

Dựa trên nhận xét của OP về câu trả lời của Jason Baker, "nhìn chằm chằm vào một truy vấn SQL khổng lồ ...", làm thế nào để giải quyết vấn đề đọc các khối lớn văn bản SQL?
JeffO

0

Nói chung, có một lớp mô hình riêng biệt là cách tiếp cận tốt nhất. Có một số mẫu thiết kế doanh nghiệp đưa ra cách để kiến ​​trúc sư này.


xin lỗi, tôi nên nói cụ thể hơn ... Tôi đã giả sử rằng bạn đã tách chúng thành một lớp mô hình. Nhưng một lớp mô hình vẫn có thể trở nên khá phân tán với mã SQL. Có lẽ điều này là không thể tránh khỏi. Một thứ khác làm tôi bối rối trong mã mô hình là mã "xây dựng truy vấn SQL" dựa trên một số logic ... có lẽ điều này nên được tách ra thành nhà máy riêng của nó hoặc một cái gì đó ...
Jellyfishtree

2
@jellyfishtree - Tôi sợ tôi không hiểu vấn đề là gì. Ý tôi là, bạn sợ lớp mô hình của bạn có thể kết thúc với quá nhiều mã mô hình?
Jason Baker

một phản bác hợp lệ. Tôi lo ngại về khả năng đọc. Mã mô hình tốt thường khá dễ hiểu, nhưng nhìn chằm chằm vào một truy vấn SQL khổng lồ không chính xác có nghĩa là nó nhảy ra khỏi bạn. Rõ ràng điều đầu tiên cần làm là nhận xét đúng các truy vấn đó, nhưng nó không giống với mã tự viết tài liệu tốt và các loại phần này được phân tán trên mô hình. Tôi chấp nhận nó, nhưng tôi đã tự hỏi liệu có cách nào tốt hơn để cô lập hoặc tổ chức các câu lệnh SQL điên rồ trong mô hình không ...
Jellyfishtree

0

Có thể nên tách lớp mô hình của bạn thành 3 lớp phụ - "thực thể", "kho lưu trữ" và "dịch vụ". Điều này sẽ giúp bạn tách các mối quan tâm và thu thập SQL ở một nơi, ra khỏi logic kinh doanh của bạn.

Trong kịch bản này, tất cả các mã truy xuất dữ liệu, bao gồm cả SQL phức tạp - sẽ được đặt trong các kho lưu trữ. Vì vậy, mục tiêu của kho lưu trữ là để ẩn các câu lệnh SQL phức tạp đằng sau các phương thức tự giải thích như thế nào getUsersWithActiveSubscription().

Thực thể trừu tượng hóa tên trường của bảng DB thực với getters và setters, có thể cung cấp một số chuyển đổi dữ liệu giữa các loại trường DB và các loại có sẵn trong ngôn ngữ lập trình / ứng dụng của bạn. Nếu ORM của bạn hỗ trợ điều đó - các thực thể có thể xử lý các hiệp hội.

Lớp dịch vụ là nơi dành cho logic kinh doanh. Dịch vụ truy xuất các thực thể bằng cách sử dụng các kho lưu trữ, hành động trên chúng và lưu trữ chúng trở lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.