Giải quyết thực tế là các khóa chính không phải là một phần của lĩnh vực kinh doanh của bạn


25

Trong hầu hết mọi trường hợp, khóa chính không phải là một phần của miền doanh nghiệp của bạn. Chắc chắn, bạn có thể có một số đối tượng quan trọng đối với người dùng với các chỉ số duy nhất ( UserNamecho người dùng hoặc OrderNumbercho đơn đặt hàng) nhưng trong hầu hết các trường hợp, không có doanh nghiệp nào cần phải xác định công khai các đối tượng miền bằng một giá trị hoặc tập hợp giá trị cho bất kỳ ai, nhưng có lẽ là một người dùng hành chính. Ngay cả trong những trường hợp đặc biệt đó, đặc biệt nếu bạn đang sử dụng số nhận dạng duy nhất toàn cầu (GUID) , bạn sẽ muốn hoặc muốn sử dụng khóa thay thế thay vì để lộ khóa chính.

Vì vậy, nếu sự hiểu biết của tôi về thiết kế theo hướng tên miền là chính xác, các khóa chính không cần và do đó không nên bị lộ, và câu đố tốt. Chúng xấu xí và tù túng phong cách của tôi. Nhưng nếu chúng ta chọn không bao gồm các khóa chính trong mô hình miền, sẽ có hậu quả:

  1. Rõ ràng, các đối tượng truyền dữ liệu (DTO) xuất phát từ các tổ hợp mô hình miền sẽ không có khóa chính
  2. Sắp tới DTO sẽ không có khóa chính

Vì vậy, có an toàn không khi nói rằng nếu bạn thực sự giữ nguyên trạng thái và loại bỏ các khóa chính trong mô hình miền của mình, bạn nên chuẩn bị để có thể xử lý mọi yêu cầu theo các chỉ số duy nhất trên khóa chính đó?

Nói cách khác, giải pháp nào sau đây là cách tiếp cận chính xác để xử lý việc xác định các đối tượng cụ thể sau khi loại bỏ PK trong các mô hình miền?

  1. Có thể xác định các đối tượng bạn cần xử lý bằng các thuộc tính khác
  2. Lấy khóa chính trở lại trong DTO; tức là loại bỏ PK khi ánh xạ từ kiên trì sang miền, sau đó kết hợp lại PK khi ánh xạ từ miền sang DTO?

EDIT: Hãy làm cho bê tông này.

Giả sử mô hình tên miền của tôi là VoIPProviderbao gồm các trường như Name, Description, URL, cũng như tài liệu tham khảo thích ProviderType, PhysicalAddressTransactions.

Bây giờ hãy nói rằng tôi muốn xây dựng một dịch vụ web cho phép người dùng đặc quyền quản lý VoIPProviders.

Có lẽ một ID thân thiện với người dùng là vô dụng trong trường hợp này; xét cho cùng, các nhà cung cấp VoIP là các công ty có tên có xu hướng khác biệt theo nghĩa máy tính và thậm chí đủ khác biệt theo nghĩa con người vì lý do kinh doanh. Vì vậy, có thể đủ để nói rằng một duy nhất VoIPProviderhoàn toàn được xác định bởi (Name, URL). Vì vậy, bây giờ hãy nói rằng tôi cần một phương pháp PUT api/providers/voipđể người dùng đặc quyền có thể cập nhật VoIPnhà cung cấp. Họ gửi lên một VoIPProviderDTO, bao gồm nhiều nhưng không phải tất cả các lĩnh vực từ VoIPProvider, bao gồm cả một số khả năng làm phẳng. Tuy nhiên, tôi không thể đọc được suy nghĩ của họ và họ vẫn cần cho tôi biết chúng tôi đang nói về nhà cung cấp nào.

Có vẻ như tôi có 2 (có thể 3) tùy chọn:

  1. Bao gồm khóa chính hoặc khóa thay thế trong mô hình miền của tôi và gửi nó đến DTO và ngược lại
  2. Xác định nhà cung cấp mà chúng tôi quan tâm thông qua chỉ mục duy nhất, như (Name, Url)
  3. Giới thiệu một số loại đối tượng trung gian luôn có thể ánh xạ giữa lớp, miền và DTO theo cách không phơi bày chi tiết triển khai về lớp lưu giữ - nói bằng cách giới thiệu một định danh tạm thời trong bộ nhớ khi đi từ miền sang DTO và ngược lại,

1
Điểm đáng suy ngẫm: thường thì giao tiếp với các chuyên gia tên miền trở nên nghèo nàn khi PK thay thế được sử dụng khi có khóa kinh doanh tốt. Có vẻ như chúng tôi cuối cùng làm việc cho khung ORM, thay vì cách khác.
Tulains Córdova

@ user61852 tốt bất kể ORM, ngay cả khi bạn thực sự ở mức độ thấp, bạn vẫn cần một khóa chính trong việc thực hiện lớp cơ sở dữ liệu. Vì vậy, tôi đồng ý rằng PK thay thế mang lại cho bạn lợi thế so với PK thực tế được sử dụng bởi một cơ chế kiên trì cụ thể, nhưng nếu PK đó thực sự đại diện cho một đối tượng kinh doanh có ý nghĩa, thì nó nhất thiết phải là duy nhất và do đó có ít nhất một thuộc tính liên quan đến kinh doanh duy nhất nó không có?
tacos_tacos_tacos

1
Tất cả những lợi thế của người thay thế đều liên quan đến máy tính và không liên quan đến con người.
Tulains Córdova

2
@ user61852: Tôi đồng ý 100% (tôi có viết gì khác không?). Đối với phương tiện liên lạc, sử dụng "khóa kinh doanh". Thêm các chống chỉ định duy nhất cho bất kỳ khóa kinh doanh là tốt. Nhưng tránh sử dụng các khóa nghiệp vụ để thực sự tham khảo cơ sở dữ liệu của bạn.
Doc Brown

2
khóa kinh doanh là duy nhất vĩnh viễn - cho đến khi chúng không. Nếu bạn đang sử dụng khóa doanh nghiệp làm chính khi điều này xảy ra thì sự thay đổi trong quy tắc kinh doanh sẽ phá vỡ nhiều thứ hơn.
psr

Câu trả lời:


31

Đây là cách chúng tôi giải quyết vấn đề này (từ hơn 15 năm trước, khi mà ngay cả thuật ngữ "thiết kế hướng tên miền" cũng không được phát minh):

  • khi ánh xạ mô hình miền sang triển khai cơ sở dữ liệu hoặc mô hình lớp bằng ngôn ngữ lập trình cụ thể, bạn có một quy tắc nhất quán, đơn giản như "đối với mỗi đối tượng miền được ánh xạ tới bảng quan hệ, khóa chính là" TablenameID ".
  • khóa chính này hoàn toàn nhân tạo, nó luôn có cùng loại và không có ý nghĩa kinh doanh - chỉ là khóa thay thế
  • "phiên bản đồ họa" của mô hình miền của bạn (phiên bản bạn sử dụng để nói chuyện với các chuyên gia tên miền) không chứa các khóa chính. Bạn không tiếp xúc chúng trực tiếp với các chuyên gia (nhưng bạn tiếp xúc chúng với bất kỳ ai thực sự triển khai mã cho hệ thống).

Vì vậy, bất cứ khi nào bạn cần một khóa chính cho các mục đích kỹ thuật (như ánh xạ quan hệ vào cơ sở dữ liệu), bạn có sẵn một khóa, nhưng miễn là bạn không muốn "nhìn thấy nó", hãy thay đổi mức độ trừu tượng của bạn thành "mô hình chuyên gia tên miền ". Và bạn không phải duy trì "hai mô hình" (một mô hình có PK và một mô hình không có); thay vào đó, chỉ duy trì một mô hình không có PK và sử dụng trình tạo mã để tạo DDL cho DB của bạn, tự động thêm PK theo quy tắc ánh xạ.

Lưu ý rằng điều này không cấm thêm bất kỳ "khóa doanh nghiệp" nào như "Số thứ tự" bổ sung, bên cạnh việc thay thế OrderID. Về mặt kỹ thuật, các khóa nghiệp vụ này trở thành khóa thay thế khi ánh xạ vào cơ sở dữ liệu của bạn. Chỉ cần tránh sử dụng những thứ này để tạo tham chiếu đến các bảng khác, luôn thích sử dụng các khóa thay thế nếu có thể, điều này sẽ khiến mọi thứ dễ dàng hơn rất nhiều.

Đối với nhận xét của bạn: sử dụng khóa thay thế để xác định hồ sơ là không có hoạt động liên quan đến kinh doanh, đó là một hoạt động kỹ thuật hoàn toàn. Để làm rõ điều này, hãy xem ví dụ của bạn: miễn là bạn không xác định các ràng buộc độc đáo bổ sung, có thể có hai đối tượng VoIPProvider có cùng kết hợp (tên, url), nhưng các VoIPProviderID khác nhau.


Thế còn bước lấy đối tượng miền từ đối tượng kiên trì được trả về (thực thể hoặc mô hình hàng của bảng hoặc bất cứ thứ gì), đi đến DTO, và đưa nó trở lại, và quay lại tồn tại? Có phải điều này chỉ được thực hiện thông qua khóa thay thế (nghĩa là định nghĩa duy nhất theo định hướng kinh doanh) đòi hỏi một giải pháp cho mỗi hoạt động kiên trì?
tacos_tacos_tacos

1
@tacos_tacos_tacos: hãy theo dõi ví dụ VoIPProvider của bạn. Tôi thực sự sẽ thêm "VoIPProviderID" vào DTO của bạn, ít nhất là ở "phía triển khai" (nếu bạn cũng có phiên bản đồ họa cho các chuyên gia tên miền của mình, tôi có thể sẽ không hiển thị ở đó). Để cập nhật mục đích, cách tiêu chuẩn để xác định một VoIPProvider cụ thể phải là "VoIPProviderID" mà bạn đã truy xuất khi lấy dữ liệu từ cơ sở dữ liệu. Nếu người dùng API của bạn thích nhận dạng theo (tên, URL), hãy cung cấp thêm. ...
Doc Brown

... Và nếu hiệu suất dường như trở thành một vấn đề thực sự, có thể đo lường được, bạn cũng có thể xem xét để lưu bộ đệm ánh xạ (tên, url) vào VoIPProviderID ở đâu đó. Nhưng tôi sẽ không đề xuất thực hiện tối ưu hóa như vậy trước đó, sớm.
Doc Brown

1
Các khóa tự nhiên đôi khi có vẻ thực sự hấp dẫn nhưng quá dễ bị đốt cháy (ví dụ: "Rất tiếc, hiện tôi có nhiều người thuê và điều đó không còn là duy nhất").
Casey

1
@corsiKa: trong bối cảnh OP yêu cầu, tôi thực sự khuyên bạn nên có khóa "OrderID" hoàn toàn tự động (không được in trên bất kỳ biên lai nào, mà chỉ được sử dụng cho những thứ nội bộ như tham chiếu cơ sở dữ liệu) và một khóa doanh nghiệp riêng "OrderNumber" (ví dụ, có thể chứa thứ gì đó như năm hiện tại, có thể được sử dụng để sắp xếp và lọc, có thể được thay đổi / sửa chữa sau đó và có thể được in trên biên lai). OP đã yêu cầu "Thiết kế hướng tên miền", "OrderNumber" là một phần của mô hình miền, trong khi "OrderID" chỉ là một chi tiết triển khai.
Doc Brown

4

Bạn cần có khả năng xác định nhiều đối tượng bằng một số chỉ mục duy nhất và không phải là khóa chính là gì (hoặc ít nhất là ngụ ý một đối tượng có mặt).

Các chỉ mục duy nhất có sẵn để bạn có thể hạn chế thêm lược đồ DB của mình, không phải là một thay thế bán buôn cho PK. Nếu bạn không phơi bày PK vì chúng xấu, nhưng thay vào đó là lộ một khóa duy nhất ... bạn thực sự không làm gì khác. (Tôi cho rằng bạn không nhận được PK và cột nhận dạng trộn lẫn ở đây?)


Khi tôi muốn thực hiện một thao tác liên quan đến một thể hiện cụ thể của một đối tượng miền vẫn tồn tại, tôi cần có thể đưa vào DTO một cách rõ ràng (thông qua một số loại khóa, hoặc ID thân thiện với người dùng thay thế duy nhất với bảng đó và cũng có thể là một chỉ mục trên bảng) hoặc ngầm (thông qua một số kết hợp các trường có giá trị xác định duy nhất một bản ghi cụ thể) ... và hơn nữa, theo nghĩa thực tế, tôi sẽ cần gửi lên DTO một số hình thức theo dõi thay đổi nếu tôi thực hiện theo cách khác (OriginalVal so với NewVal cho tất cả các trường xác định bản ghi), phải không?
tacos_tacos_tacos

không phải là câu hỏi v rõ ràng cùng một sự khác biệt? Bạn có thể có một PK kéo dài nhiều cột, giống như một chỉ mục duy nhất. Tôi không thấy có bất kỳ sự khác biệt giữa chúng cho mục đích của bạn.
gbjbaanb

Chắc chắn, chúng ta có thể có một PK trên nhiều cột chẳng hạn. Nhưng đối với tôi, nó đang rò rỉ một cái gì đó về databaswe (bộ lưu trữ) mà KHÔNG cần phải làm gì với trái tim & linh hồn, thực thể kinh doanh. Nếu một số bộ trường thực thể kinh doanh xảy ra để mở rộng PK cho DB, thì thật tuyệt. Nhưng nó không nhất thiết phải là cách khác, phải không?
tacos_tacos_tacos

Bạn đang xem xét lại nó. Một chỉ mục duy nhất giống như một tạo tác của lược đồ DB giống như PK. Hãy nghĩ về nó theo cách này - PK chỉ là chỉ số duy nhất (hoặc chính) đầu tiên. nó 'đặc biệt' vì bạn thường chỉ cần 1 chỉ số như vậy.
gbjbaanb

Đúng, nhưng bất kỳ đối tượng miền có ý nghĩa nào cũng phải được xác định chính xác từ ít nhất một trong các lĩnh vực liên quan đến kinh doanh của nó, phải không? Thực tế là điều này xác định một chỉ mục trong DB nhiều hơn vì lý do hiệu năng hơn là được sử dụng để truy vấn DB một cách dễ dàng ... Tôi thích PK một cột hơn chỉ mục duy nhất 6 cột và chúng thực sự phục vụ các mục đích khác nhau - một PK (hoặc chỉ mục có số lượng trường nhỏ) cũng có sẵn để thuận tiện cho DBA / DBD, phải không?
tacos_tacos_tacos

4

Không có khóa chính trong frontend, không có cách nào dễ dàng để phụ trợ biết bạn đang gửi gì. Để khắc phục rằng bạn sẽ cần rất nhiều công việc phân tích dữ liệu, điều này sẽ làm giảm hiệu suất và có thể mất nhiều thời gian hơn và xấu hơn so với việc gắn một khóa cho mỗi mục.

Ví dụ: giả sử tôi muốn chỉnh sửa tin nhắn trong ứng dụng; Làm thế nào để ứng dụng biết thông báo nào tôi muốn chỉnh sửa mà không có khóa chính được đính kèm? Chỉnh sửa các đối tượng xảy ra mọi lúc và làm điều đó mà không có phím là không thể. Nhưng nếu bạn có các đối tượng không cần chỉnh sửa thì hãy bỏ qua khóa nếu bạn nghĩ rằng nó gây mất tập trung, nhưng có các khóa chính có thể cải thiện hiệu suất ở đây.


Vâng, thông điệp là một ví dụ cực đoan, nhưng thậm chí sau đó chúng ta sẽ biết MessageSender, MessageRecipient, TimeSent- đó phải là duy nhất.
tacos_tacos_tacos

1
@tacos_tacos_tacos, vậy làm thế nào để bạn tạo FK cho các bảng khác? Nó phải là MessageSenderId, có thể ánh xạ tới bảng Người dùng trên UserId. Bạn sẽ không muốn sử dụng Tên người dùng làm chìa khóa giữa các bảng vì điều đó có thể thay đổi và trở thành cơn ác mộng bảo trì. Đây là lý do tại sao bạn thường chỉ tham gia các bảng bằng Khóa chính chứ không phải cột khác (chắc chắn có ngoại lệ). Cấu trúc db này vẫn phải được thi hành. Bây giờ bạn luôn có thể đi đến một mô hình CQRS cho ứng dụng của mình ... trong trường hợp đó các quy tắc thay đổi. Đặc biệt nếu bạn cũng sử dụng Nguồn sự kiện.
CaffGeek

4

Lý do chúng tôi sử dụng PK không liên quan đến kinh doanh là để đảm bảo rằng hệ thống của chúng tôi có một phương pháp dễ dàng và nhất quán để xác định những gì người dùng muốn.

Tôi thấy bạn đã trả lời với một bình luận: MessageSender, MessageRecipient, TimeSent (cho một tin nhắn). Bạn có thể VẪN có sự mơ hồ theo cách này (ví dụ, với các thông báo được tạo bởi hệ thống kích hoạt trên một cái gì đó xảy ra thường xuyên). Và làm thế nào bạn sẽ xác nhận MessageSender và MessageRecipient ở đây? Giả sử bạn xác thực chúng bằng FirstName, Lastname, DateOfBirth, cuối cùng bạn sẽ gặp phải tình huống bạn có 2 người sinh ra trong cùng một ngày với cùng một tên. Chưa kể rằng bạn sẽ gặp phải một tình huống mà bạn có một tin nhắn được đặt tên tacostacostacos-America-1980-Doc Brown-France-1965-23/5/2014-11:43:54.003UTC+200. Đó là một con quái vật của một cái tên, và bạn vẫn không có gì đảm bảo bạn sẽ chỉ có 1 trong số đó.

Lý do chúng tôi sử dụng khóa chính là vì chúng tôi BIẾT nó sẽ là duy nhất trong suốt vòng đời của phần mềm, bất kể dữ liệu nào được nhập và chúng tôi BIẾT nó sẽ là định dạng có thể dự đoán được (điều gì xảy ra nếu khóa trên của bạn có dấu gạch ngang trong một tên người dùng? toàn bộ hệ thống của bạn đi shit).

Bạn không cần phải hiển thị ID của mình cho người dùng của bạn. Bạn có thể ẩn điều đó (trong tầm nhìn rõ ràng nếu cần thiết, thông qua URL).

Một lý do khác khiến PK rất hữu ích là một thứ bạn có thể suy ra từ trên: PK làm cho nó để bạn không phải buộc máy tính diễn giải mã do người dùng tạo. Nếu người dùng Trung Quốc sử dụng mã của bạn và nhập vào một loạt các ký tự tiếng Trung, mã của bạn đột nhiên không cần phải làm việc với các mã này trong nội bộ, nhưng đơn giản là có thể sử dụng Hướng dẫn mà hệ thống tạo ra. Nếu bạn có một người dùng tiếng Ả Rập nhập văn bản tiếng Ả Rập, hệ thống của bạn không phải đối phó với nội bộ đó, nhưng về cơ bản có thể bỏ qua rằng họ đang ở đó.

Như những người khác đã nói, Guid là thứ có thể được lưu trữ bên trong với kích thước cố định. Bạn biết những gì bạn làm việc với và đó là một cái gì đó có thể được sử dụng phổ biến. Bạn không cần tạo quy tắc thiết kế về cách bạn tạo một số nhận dạng nhất định và lưu nó. Nếu hệ thống của bạn chỉ nhận 10 chữ cái đầu tiên của tên, thì nó không thấy bất kỳ sự khác biệt nào giữa Michael Guggenheimer và Michael Gugstein, và nó sẽ gây nhầm lẫn cho 2. Nếu bạn cắt nó ở bất kỳ độ dài tùy ý nào, bạn có thể gặp nhầm lẫn. Nếu bạn giới hạn đầu vào của người dùng, bạn có thể gặp phải các vấn đề với giới hạn người dùng.

Khi tôi xem xét các hệ thống hiện có như Dynamics CRM, họ cũng sử dụng khóa bên trong (PK) cho người dùng để gọi một bản ghi. Nếu người dùng có một truy vấn không liên quan đến ID, họ sẽ trả về một loạt các câu trả lời có thể và cho phép người dùng chọn từ đó. Nếu có bất kỳ cơ hội mơ hồ nào, họ sẽ đưa ra lựa chọn cho người dùng.

Cuối cùng, nó cũng có sự bảo mật thông qua che khuất. Nếu bạn không biết ID hồ sơ, lựa chọn duy nhất của bạn là đoán nó. nếu ID dễ đoán (vì thông tin được tạo ra công khai), bất kỳ ai cũng có thể thay đổi. Bạn thậm chí có thể khiến người dùng thay đổi nó thông qua các phương thức CSRF hoặc XSS cổ điển. Bây giờ, rõ ràng bảo mật của bạn đã được xử lý và giảm thiểu trước khi xuất bản phiên bản trực tiếp, nhưng bạn vẫn nên làm cho việc lạm dụng tiềm năng khó xảy ra hơn.


1

Khi cấp mã định danh cho hệ thống bên ngoài, bạn chỉ nên cung cấp URI hoặc thay thế một khóa hoặc một bộ khóa có cùng thuộc tính với URI, thay vì trực tiếp hiển thị khóa chính của cơ sở dữ liệu (từ đây trở đi cả URI hoặc khóa hoặc một tập hợp các khóa có cùng thuộc tính với URI giống như URI, nói cách khác, URI dưới đây không nhất thiết có nghĩa là RFC 3986 URI).

Một URI có thể có hoặc không chứa khóa chính của đối tượng và nó thực sự có thể hoặc không bao gồm các khóa thay thế. Nó không thực sự quan trọng. Vấn đề là chỉ có hệ thống tạo URI mới được phép phân tách hoặc kết hợp URI để hình thành sự hiểu biết về đối tượng được đề cập là gì. Các hệ thống bên ngoài phải luôn sử dụng URI làm định danh mờ. Sẽ không có vấn đề gì nếu người dùng con người có thể xác định rằng một phần của URI thực sự là khóa thay thế cơ sở dữ liệu hoặc nó bao gồm một số khóa nghiệp vụ được gộp lại với nhau hoặc đó thực sự là một cơ sở của 64 giá trị đó. Những điều này không liên quan. Vấn đề là hệ thống bên ngoài không cần phải được yêu cầu để hiểu định nghĩa có nghĩa là gì để sử dụng định danh. Không bao giờ cần phải có hệ thống bên ngoài để phân tích các thành phần trong mã định danh hoặc kết hợp một mã định danh với các mã định danh khác để chỉ một cái gì đó trong hệ thống của bạn.

Việc sử dụng GUID đáp ứng một số tiêu chí này, tuy nhiên, số nhận dạng như GUID có thể khó quay trở lại đối tượng ngay cả trong hệ thống của bạn, do đó, các khóa mờ đối với ngay cả hệ thống của bạn như GUID chỉ nên được sử dụng nếu máy khách phân tích URI / định danh thực sự đặt ra một rủi ro bảo mật.

Quay lại ví dụ VoIP của bạn, giả sử rằng nhà cung cấp VoIP có thể được xác định duy nhất bằng (VoIPProviderID) hoặc bởi (Tên, URL) hoặc bởi (GUID). Khi một bên ngoài nhu cầu hệ thống để cập nhật các nhà cung cấp VoIP, nó chỉ có thể vượt qua một PUT / nhà cung cấp / by-id / 1234 hay PUT /provider/foo-voip/bar-domain.comhay PUT /3F2504E0-4F89-41D3-9A0C-0305E82C3301và hệ thống của bạn sẽ hiểu rằng các hệ thống bên ngoài muốn cập nhật VoIPProvider. Các URI này được tạo bởi hệ thống của bạn và chỉ hệ thống của bạn cần hiểu rằng tất cả chúng đều có nghĩa giống nhau. Hệ thống bên ngoài chỉ nên coi bất cứ thứ gì trong URI là cơ bản a PUT <whatever>.

Giả sử rằng bạn có dữ liệu cho các nhà cung cấp VoIP khác nhau được lưu trữ trong các bảng khác nhau với các lược đồ khác nhau (do đó, bộ khóa hoàn toàn khác nhau xác định mỗi nhà cung cấp VoIP dựa trên bảng mà họ được lưu trữ). Khi bạn có URI, chúng có thể được truy cập thống nhất bởi hệ thống bên ngoài, mà không liên quan đến cách hệ thống của bạn xác định nhà cung cấp VoIP cụ thể. Đối với hệ thống bên ngoài, tất cả chỉ là con trỏ mờ.

Khi hệ thống của bạn sử dụng URI để chỉ các đối tượng theo cách như vậy, bạn sẽ không rò rỉ bất cứ điều gì liên quan đến cách bạn triển khai hệ thống của mình. Bạn tạo URI và khách hàng chỉ cần chuyển lại cho bạn.


0

Tôi sẽ phải nhắm mục tiêu tuyên bố ngây thơ và không chính xác này:

Có lẽ một ID thân thiện với người dùng là vô dụng trong trường hợp này; xét cho cùng, các nhà cung cấp VoIP là các công ty có tên có xu hướng khác biệt theo nghĩa máy tính và thậm chí đủ khác biệt theo nghĩa con người vì lý do kinh doanh.

Tên là khủng khiếp như chìa khóa, vì chúng thường xuyên thay đổi. Một công ty có thể có nhiều tên trong suốt cuộc đời của mình, công ty có thể hợp nhất, tách ra, sáp nhập lại, tạo ra một công ty con riêng biệt cho các mục đích thuế cụ thể có 0 nhân viên nhưng tất cả các khách hàng sau đó thuê nhân viên từ một công ty con hoàn toàn khác.

Sau đó, chúng ta đi vào thực tế rằng tên công ty thậm chí không phải là duy nhất từ ​​xa, như được thể hiện bởi mốc Apple so với Apple .

Một đối tượng tốt mapper quan hệ hoặc khuôn khổ nên họ trừu tượng các phím chính đi và làm cho những vô hình, nhưng ở đó, và họ thường sẽ là chỉ cách để nhận diện một đối tượng trong cơ sở dữ liệu của bạn.

Để tham khảo, tôi thích cách django xử lý việc này:

class VoipProvider(models.Model):
    name=fields.TextField()
    address=fields.TextField()

class Customer(models.Model):
    name=fields.TextField()
    address=fields.TextField()
    voipProvider=fields.ForeignKeyField(VoipProvider)

Theo cách này, các chi tiết của nhà cung cấp của khách hàng có thể được truy cập bằng mã bằng cách sử dụng:

myCustomer.voipProvider.name #returns the name of the customers VOIP Provider.

Mặc dù các khóa Chính / Ngoại không hiển thị, nhưng chúng ở đó và có thể được sử dụng để truy cập các mục, nhưng bị trừu tượng hóa.


Bạn hoàn toàn đúng, nhưng tôi đoán tôi có nghĩa là "trong một số miền, có thể có một bộ giá trị tự nhiên luôn là duy nhất" Nếu chúng thay đổi, nhưng chúng vẫn là duy nhất, chúng vẫn xác định một bản ghi.
tacos_tacos_tacos

0

Tôi nghĩ rằng chúng ta vẫn thường nhìn không chính xác vấn đề này từ góc độ của DB: oh, không có khóa tự nhiên, vì vậy chúng ta cần tạo một khóa thay thế. Ồ không, chúng tôi không thể đưa khóa thay thế trở lại vào các đối tượng miền, điều đó bị rò rỉ, v.v.

Tuy nhiên, đôi khi một thái độ tốt hơn là: nếu một đối tượng (miền) doanh nghiệp không có khóa tự nhiên, thì có lẽ nó nên được cung cấp. Đây là một vấn đề miền kinh doanh hai lần: Thứ nhất, mọi thứ cần một bản sắc, ngay cả khi không có cơ sở dữ liệu. Thứ hai, mặc dù chúng tôi cố gắng giả vờ kiên trì là một số ý tưởng trừu tượng vô hình đối với miền, nhưng thực tế là sự kiên trì vẫn là một khái niệm kinh doanh. Rõ ràng, có một số vấn đề trong đó khóa tự nhiên được chọn không được DB hỗ trợ làm khóa chính (ví dụ: GUID trên một số hệ thống) - trong trường hợp này, bạn sẽ cần thêm khóa thay thế.

Do đó, bạn kết thúc ở một nơi rất giống nhau, ví dụ: khách hàng của bạn có ID số nguyên, nhưng thay vì cảm thấy bị bệnh vì đã bị rò rỉ từ DB sang tên miền, bạn cảm thấy hạnh phúc vì doanh nghiệp đã đồng ý rằng tất cả khách hàng sẽ được chỉ định ID và bạn đang duy trì điều đó với DB, như bạn phải. Bạn vẫn được tự do giới thiệu người thay thế, ví dụ: để hỗ trợ đổi tên ID khách hàng.

Cách tiếp cận này cũng có nghĩa là nếu một đối tượng miền chạm vào lớp lưu giữ và không có ID, thì đó có thể là một loại đối tượng giá trị, vì vậy không cần ID.

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.