Đối với một ORM hỗ trợ xác thực dữ liệu, các ràng buộc có nên được thi hành trong cơ sở dữ liệu không?


13

Tôi đã luôn áp dụng các ràng buộc ở cấp cơ sở dữ liệu bên cạnh các mô hình (ActiveRecord) của mình. Nhưng tôi đã tự hỏi nếu điều này là thực sự cần thiết?

Một chút nền tảng

Gần đây tôi đã phải thử nghiệm một phương pháp tạo dấu thời gian tự động cơ bản cho một mô hình. Thông thường, thử nghiệm sẽ tạo một thể hiện của mô hình và lưu nó mà không cần xác nhận. Nhưng có các trường bắt buộc khác không có giá trị trong định nghĩa bảng, nghĩa là tôi không thể lưu cá thể ngay cả khi tôi bỏ qua xác thực ActiveRecord. Vì vậy, tôi đang suy nghĩ liệu tôi có nên loại bỏ các ràng buộc như vậy khỏi chính db và để ORM xử lý chúng không?

Những lợi thế có thể có nếu tôi bỏ qua các ràng buộc trong db, imo -

  • Có thể sửa đổi quy tắc xác thực trong mô hình mà không phải di chuyển cơ sở dữ liệu.
  • Có thể bỏ qua xác nhận trong thử nghiệm.

Bất lợi có thể xảy ra?

Nếu có thể xác thực ORM không thành công hoặc bị bỏ qua, dù sao đi nữa, cơ sở dữ liệu không kiểm tra các ràng buộc.

Bạn nghĩ sao?

EDIT Trong trường hợp này, tôi đang sử dụng Khung Yii , tạo mô hình từ cơ sở dữ liệu, do đó các quy tắc cơ sở dữ liệu cũng được tạo ra (mặc dù tôi luôn có thể tự viết chúng sau khi tạo thế hệ sau).


3
Nếu dữ liệu trong cơ sở dữ liệu của bạn có thể được sửa đổi thường xuyên mà không cần sử dụng ORM của bạn (các ứng dụng khác không có ORM của bạn hoặc tệ hơn là người dùng truy cập db trực tiếp), thì việc xác thực thực sự cần phải có trong cơ sở dữ liệu.
Marjan Venema

Câu trả lời:


16

Nguyên tắc hướng dẫn của bạn là Đừng lặp lại chính mình :

Trong công nghệ phần mềm, Đừng lặp lại chính mình (DRY) là một nguyên tắc phát triển phần mềm nhằm giảm sự lặp lại thông tin của tất cả các loại, đặc biệt hữu ích trong các kiến ​​trúc đa tầng. Nguyên tắc DRY được nêu là "Mỗi phần kiến ​​thức phải có một đại diện duy nhất, rõ ràng, có thẩm quyền trong một hệ thống."

ORM về cơ bản là một lớp bổ sung (hoặc lớp nếu bạn thích), ngồi thoải mái giữa ứng dụng của bạn và (các) bộ lưu trữ dữ liệu của bạn. Các ràng buộc của bạn phải ở một nơi và chỉ một nơi, có thể là ORM hoặc lưu trữ dữ liệu, nếu không, bạn sẽ sớm duy trì các phiên bản khác nhau của chúng. Bạn thực sự không muốn làm điều đó.

Tuy nhiên, trong thực tế, hầu hết các ORM phong nha một nửa sẽ tự động tạo ra rất nhiều mô hình của bạn từ lược đồ dữ liệu của bạn. Mặc dù vẫn có sự trùng lặp, cơ hội cho địa ngục bảo trì là rất nhỏ vì mã ORM trùng lặp được tạo theo cùng một mẫu mỗi lần. Sẽ là lý tưởng khi không có mã trùng lặp, nhưng các ràng buộc được tạo tự động là điều tốt nhất tiếp theo.

Ngoài ra, có các ràng buộc của bạn ở một nơi không nhất thiết có nghĩa là bạn nên có tất cả các ràng buộc của mình ở cùng một nơi. Một số, như các ràng buộc toàn vẹn tham chiếu, có thể phù hợp hơn cho việc lưu trữ dữ liệu (nhưng có thể bị mất nếu bạn chuyển sang lưu trữ dữ liệu khác) và một số, chủ yếu là các logic về logic kinh doanh phức tạp, phù hợp hơn với ORM của bạn. Tốt nhất là để tất cả táo của bạn trong cùng một giỏ, nhưng

Thất bại

Bạn đề cập đến ORM thất bại. Điều đó hoàn toàn không liên quan đến câu hỏi của bạn, ứng dụng của bạn nên nghĩ về ORM và (các) bộ lưu trữ dữ liệu như một thực thể duy nhất. Nếu thất bại, nó thất bại, bỏ qua ORM để nói chuyện trực tiếp với việc lưu trữ dữ liệu không phải là một ý tưởng hay.

Bỏ qua ORM cho bất cứ điều gì khác

Cũng không phải là một ý tưởng tốt. Tuy nhiên, nó có thể xảy ra vì nhiều lý do:

  1. Các phần kế thừa của ứng dụng đã được xây dựng trước khi ORM được giới thiệu.

    Đó là một vấn đề khó khăn, và chính xác là tình huống tôi đang phải đối phó ngay bây giờ , do đó tôi liên tục lặp lại về việc bảo trì địa ngục. Hoặc bạn tiếp tục duy trì các phần không phải ORM hoặc bạn viết lại chúng để sử dụng ORM. Tùy chọn thứ hai ban đầu có thể có ý nghĩa hơn, nhưng đó là một quyết định chỉ dựa trên chính xác những phần đó trong ứng dụng của bạn đang làm gì và việc viết lại hoàn chỉnh sẽ có giá trị như thế nào trong thời gian dài.

    Hãy thử thay đổi một khóa trong bảng MySQL 2 * 10 ^ 8 hàng được thiết kế kém (không có thời gian chết) và bạn sẽ hiểu tôi đến từ đâu.

  2. Các phần không kế thừa của ứng dụng hoàn toàn cần nói chuyện trực tiếp với bộ lưu trữ dữ liệu:

    Thậm chí tinh vi hơn. ORM là những công cụ ưa thích và chúng đảm nhiệm hầu hết mọi thứ, nhưng đôi khi chúng chỉ cản trở hoặc thậm chí là hoàn toàn vô dụng. Từ thông dụng (cụm từ thông dụng thực sự) không khớp với trở kháng quan hệ đối tượng , chỉ đơn giản là ORM của bạn không thể thực hiện mọi thứ mà cơ sở dữ liệu quan hệ của bạn thực hiện và đối với một số nội dung họ làm, có một hình phạt hiệu suất đáng kể.

Bình luận

Từ điểm toàn vẹn dữ liệu, các ràng buộc PHẢI có trên cơ sở dữ liệu và NÊN trên ứng dụng. Điều gì xảy ra nếu ứng dụng của bạn được truy cập từ web và ứng dụng trên máy tính để bàn, hoặc ứng dụng di động hoặc dịch vụ web? - Luiz Damim

Đây là nơi thêm một lớp bổ sung sẽ cực kỳ hữu ích và nếu chúng ta đang nói về một ứng dụng web tôi sẽ sử dụng API REST. Một thiết kế quá đơn giản cho việc này sẽ là:

nhập mô tả hình ảnh ở đây

ORM sẽ nằm giữa API và kho lưu trữ dữ liệu và mọi thứ đằng sau API (bao gồm cả API) sẽ được coi là một thực thể duy nhất từ ​​các ứng dụng khác nhau.


Thông thường, bạn sẽ xác định một lược đồ trong ORM của mình sau đó được nhân đôi vào cơ sở dữ liệu để bạn có mức độ đảm bảo thứ hai.
Josh K

2
@JoshK Bạn nói cấp độ bảo đảm thứ hai, tôi nói bảo trì địa ngục. Không nói rằng bạn không đúng, mặc dù ...
yannis

Có ý nghĩa. Tôi đang đi theo con đường này bây giờ. Cảm ơn!
na

1
Khi bạn đi qua điểm mà một hoặc hai nhà phát triển đang làm mã cơ sở dữ liệu làm việc, nó trở thành một điều ác cần thiết. Nếu bạn sử dụng ORM tốt, nó cũng sẽ tạo ra sự di chuyển cho bạn. Khi bạn phát triển đến mức có một DBA chuyên dụng, không có cách nào khác, họ sẽ không để các bảng nổi xung quanh mà không bị ràng buộc. Cách đơn giản để ngăn chặn mọi người đăng ký mà không có email đang khiến cho mức độ lưu trữ bị hạn chế.
Josh K

1
Từ điểm toàn vẹn dữ liệu, các ràng buộc PHẢI có trên cơ sở dữ liệu và NÊN trên ứng dụng. Điều gì xảy ra nếu ứng dụng của bạn được truy cập từ web và ứng dụng trên máy tính để bàn, hoặc ứng dụng di động hoặc dịch vụ web?
Luiz Damim

20

Đây thực sự là một câu hỏi rất khó trả lời và tôi đã thấy nó là một chủ đề rất gây tranh cãi.

Như Yannis Rizos đã chỉ ra trong câu trả lời của mình, việc có logic ràng buộc trong cả cơ sở dữ liệu và lớp ORM dường như vi phạm DRY, điều này "có thể dẫn đến những cơn ác mộng duy trì, bao thanh toán kém và mâu thuẫn logic".

Tuy nhiên, loại bỏ logic ràng buộc khỏi cơ sở dữ liệu và chỉ giữ nó ở lớp ORM sẽ không hoạt động nếu bạn có bất kỳ điều kiện nào sau đây:

  1. Cập nhật DB thủ công (dường như chúng xảy ra ở mọi công ty)

  2. DB cập nhật từ một hệ thống khác không thể luôn chia sẻ logic ràng buộc ORM một cách dễ dàng (ví dụ: tập lệnh Perl thực hiện các tác vụ thông thường khi lớp ORM được triển khai trong Hibernate và được ứng dụng Java sử dụng cho hoạt động hàng ngày)

Điều này sẽ gợi ý rằng bạn chỉ thêm logic ràng buộc vào DB và xóa khỏi lớp ORM của bạn để ngăn chặn vi phạm DRY. Tuy nhiên, điều này có thể dẫn đến các trường hợp mã ứng dụng không thể nắm bắt thành công sự cố và chuyển tiếp đến người dùng (mặc dù là nhà phát triển gỡ lỗi sự cố, rất có thể bạn có thể). Điều này có thể không được chấp nhận cho một số dự án.

Tùy chọn cuối cùng của bạn là tự động hóa việc tạo các ràng buộc trong ORM (và bất kỳ hệ thống nào khác) từ các ràng buộc DB (hoặc, thực sự ... ngược lại). Mặc dù cuối cùng bạn sẽ có hai hoặc nhiều triển khai các ràng buộc, nhưng nó sẽ không vi phạm nguyên tắc DRY như được mô tả trong "Lập trình viên thực dụng" khi họ khuyến nghị sử dụng việc tạo mã để tránh vi phạm DRY. Tất nhiên, điều đó không đơn giản bởi vì, ví dụ, mọi thay đổi đối với ràng buộc DB có thể buộc phải xây dựng lại và triển khai lại tất cả các ứng dụng của bạn sử dụng nó (không tầm thường để tự động hóa).

Thực sự, nó sẽ phải được đánh giá theo từng trường hợp . Tôi có thể nói với bạn rằng, đến thời điểm này, tôi đã gặp phải những ánh mắt trống rỗng khi tôi đề nghị rằng logic ràng buộc không được lặp lại.


2
Vừa mới nghỉ việc và đã nghĩ đến việc mở rộng câu trả lời của tôi thành ít nhiều những gì bạn vừa đăng. Câu trả lời tốt!
yannis

3

Tôi chắc chắn sẽ thêm các ràng buộc cho cơ sở dữ liệu như là tùy chọn mặc định của tôi. Điều này là do đối với dữ liệu doanh nghiệp là vua và chất lượng dữ liệu là tối quan trọng. @Yannis Rizos đã đưa nguyên tắc DRY vào cuộc thảo luận. Một nguyên tắc khác là Defense in Depth. Đối với dữ liệu tôi sẽ sử dụng nguyên tắc này.

Tôi đã làm việc trong các doanh nghiệp thực sự nơi DB có dữ liệu được tạo ra 30 năm trước. Nó đã và vẫn được truy cập bởi ứng dụng COBOL và bây giờ bằng ứng dụng .Net. Trong thời gian 10 năm, nó có thể là một ứng dụng của nhà cung cấp, ai biết được. Có một sự hợp nhất và hàng triệu hàng dữ liệu đã được chuyển đổi và di chuyển từ công ty khác sang cơ sở dữ liệu này bằng SQL. Không có ORM có thể làm điều này. Điểm mấu chốt là Dữ liệu vẫn còn, các ứng dụng thay đổi, cách mà Dữ liệu được tạo thay đổi. Vậy tại sao không giảm cơ hội tham nhũng dữ liệu?


2

Tôi nghĩ bạn làm cả hai đến một mức độ nào đó.

  • Các ràng buộc chính phải có trong ORM - ngôn ngữ lập trình linh hoạt hơn rất nhiều, dễ kiểm tra hơn và dễ điều chỉnh hơn khi yêu cầu thay đổi; không cần phải lo lắng về sửa lỗi DDL ít nhất. Và bạn thường tránh khó kiểm tra các vấn đề hồi quy dữ liệu.

  • Một số ràng buộc rất khó và nhanh cũng nên có trong cơ sở dữ liệu. Tôi không nói về những cái tên không thể rỗng, chẳng hạn. Tôi đang nói về những thứ như tính toàn vẹn tham chiếu hoặc yêu cầu một số định danh hoàn toàn quan trọng. Yêu cầu về cấu trúc để mã của bạn không cần phải xử lý "nếu đơn hàng có sản phẩm không tồn tại".


1

Cơ sở dữ liệu là IMO là nơi duy nhất mà DRY có thể bị vi phạm, bởi vì nếu có thứ gì đó bỏ qua ORM của bạn và có dữ liệu xấu, thì đó là. Trò chơi kết thúc. Có dữ liệu tham nhũng là đòn giết chóc.


Cơ sở dữ liệu chỉ? Tôi có thể nghĩ về nhiều trường hợp hành vi liên quan đến dữ liệu nên tồn tại trên một số lớp (logic hoặc vật lý) ngay cả khi dữ liệu không được duy trì. Đôi khi, có thể có một mã nguồn duy nhất và giảm "trùng lặp" với các dll đã triển khai.
mike30
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.