Có phải cái gọi là mối quan tâm xuyên suốt của Hồi giáo là một cái cớ hợp lệ để phá vỡ RẮN / DI / IoC?


43

Các đồng nghiệp của tôi muốn nói "ghi nhật ký / lưu trữ / v.v. là mối quan tâm xuyên suốt" và sau đó tiến hành sử dụng đơn lẻ tương ứng ở mọi nơi. Tuy nhiên, họ yêu thích IoC và DI.

Có thực sự là một cái cớ hợp lệ để phá vỡ nguyên tắc SOLI D ?


27
Tôi đã thấy rằng các nguyên tắc RẮN hầu như chỉ hữu ích cho những người đã có kinh nghiệm cần thiết để vô tình tuân theo chúng.
Svidgen

1
Tôi đã tìm thấy thuật ngữ "mối quan tâm xuyên suốt" là một thuật ngữ khá cụ thể (gắn liền với các khía cạnh) và không nhất thiết phải đồng nghĩa với singleton. Ghi nhật ký có thể là mối quan tâm xuyên suốt theo nghĩa đôi khi bạn muốn ghi nhật ký một tin nhắn chung ở nhiều nơi theo cùng một cách (ví dụ: ghi nhật ký mọi cuộc gọi đến một phương thức dịch vụ với người thực hiện cuộc gọi hoặc ghi nhật ký loại kiểm toán khác). Tuy nhiên, tôi sẽ lập luận rằng việc đăng nhập (theo nghĩa chung) không phải là mối quan tâm xuyên suốt chỉ vì nó được sử dụng ở mọi nơi. Tôi nghĩ rằng đây là một "mối quan tâm phổ biến" mặc dù đó không thực sự là một thuật ngữ tiêu chuẩn.
Pace

4
@svidgen các nguyên tắc RẮN cũng hữu ích khi những người không biết họ xem lại mã của bạn và hỏi bạn tại sao bạn lại làm như vậy. Thật tuyệt khi có thể chỉ ra một nguyên tắc và nói, "đó là lý do tại sao"
candied_orange

1
Bạn có bất kỳ ví dụ tại sao bạn nghĩ rằng đăng nhập là một trường hợp đặc biệt? Đây là kênh khá đơn giản để chuyển hướng một số dữ liệu, thường là một phần của bất kỳ khung X nào bạn đang sử dụng.
ksiimson

Câu trả lời:


42

Không.

RẮN tồn tại như hướng dẫn để giải thích cho sự thay đổi không thể tránh khỏi. Bạn có thực sự sẽ không bao giờ thay đổi thư viện đăng nhập, hoặc nhắm mục tiêu, hoặc lọc hoặc định dạng hoặc ...? Bạn có thực sự sẽ không thay đổi thư viện bộ nhớ đệm, hoặc mục tiêu, hoặc chiến lược, hoặc phạm vi, hoặc ...?

Tất nhiên rồi. Ít nhất , bạn sẽ muốn chế giễu những điều này một cách lành mạnh để cô lập chúng để thử nghiệm. Và nếu bạn muốn cô lập chúng để thử nghiệm, có khả năng bạn sẽ gặp phải một lý do kinh doanh nơi bạn muốn cô lập chúng vì lý do thực tế.

Và sau đó bạn sẽ nhận được lập luận rằng chính logger sẽ xử lý thay đổi. "Ồ, nếu mục tiêu / lọc / định dạng / chiến lược thay đổi, thì chúng ta sẽ thay đổi cấu hình!" Đó là rác. Giờ đây, bạn không chỉ có một Đối tượng Thần xử lý tất cả những điều này, mà bạn còn viết mã bằng XML (hoặc tương tự) khi bạn không nhận được phân tích tĩnh, bạn không bị lỗi thời gian biên dịch và bạn không ' t thực sự có được bài kiểm tra đơn vị hiệu quả.

Có trường hợp nào vi phạm các hướng dẫn RẮN? Chắc chắn rồi. Đôi khi mọi thứ sẽ không thay đổi (mà không yêu cầu viết lại hoàn toàn dù sao). Đôi khi một vi phạm nhẹ của LSP là giải pháp sạch nhất. Đôi khi làm một giao diện bị cô lập không cung cấp giá trị.

Nhưng ghi nhật ký và lưu trữ (và các mối quan tâm xuyên suốt phổ biến khác) không phải là những trường hợp đó. Chúng thường là những ví dụ tuyệt vời về các vấn đề về khớp nối và thiết kế mà bạn gặp phải khi bạn bỏ qua các hướng dẫn.


22
Bạn có sự thay thế nào sau đó? Tiêm một ILogger vào mỗi lớp bạn viết? Viết một trang trí cho mỗi lớp cần một logger?
Robert Harvey

16
Vâng. Nếu một cái gì đó là một phụ thuộc làm cho nó một phụ thuộc . Và nếu điều đó có nghĩa là quá nhiều phụ thuộc hoặc bạn đang chuyển một logger ở đâu đó thì không nên - tốt , giờ bạn có thể sửa thiết kế của mình.
Telastyn


20
Vấn đề thực sự tôi có với giáo điều IoC là khá nhiều tất cả đang hiện đại phụ thuộc vào một cái gì đó mà không được tiêm cũng không trừu tượng đi. Nếu bạn viết C #, ví dụ, bạn không thường xuyên đi đến trừu tượng Stringhoặc Int32hoặc thậm chí Listra khỏi mô-đun của bạn. Chỉ có một mức độ hợp lýlành mạnh để lên kế hoạch thay đổi. Và, ngoài các loại "cốt lõi" rõ ràng nhất, nhận ra những gì bạn có thể thay đổi thực sự chỉ là vấn đề kinh nghiệm và phán đoán.
Svidgen

6
@svidgen - Tôi hy vọng bạn đã không đọc câu trả lời của tôi khi ủng hộ IoC giáo điều. Và chỉ vì chúng tôi không trừu tượng hóa các loại cốt lõi này (và những thứ khác mà thận trọng) không có nghĩa là không có Danh sách / Chuỗi / Int / vv toàn cầu.
Telastyn

38

Đúng

Đây là toàn bộ quan điểm của thuật ngữ "mối quan tâm xuyên suốt" - nó có nghĩa là một cái gì đó không phù hợp gọn gàng trong nguyên tắc RẮN.

Đây là nơi chủ nghĩa duy tâm gặp gỡ với thực tế.

Những người bán mới cho RẮN và xuyên suốt thường gặp phải thử thách tinh thần này. Không sao đâu, đừng hoảng sợ. Cố gắng đặt mọi thứ vào điều khoản của RẮN, nhưng có một vài nơi như ghi nhật ký và lưu vào bộ đệm trong đó RẮN chỉ không có ý nghĩa. Cắt ngang là anh em của RẮN, họ song hành cùng nhau.


9
Một câu trả lời hợp lý, thực tế, không giáo điều.
dùng1936

11
Bạn có thể vui lòng cho chúng tôi biết lý do tại sao tất cả năm nguyên tắc RẮN bị phá vỡ bởi mối quan tâm xuyên suốt? Tôi có vấn đề để hiểu điều đó.
Doc Brown

4
Vâng. Tôi có khả năng có thể nghĩ ra một lý do chính đáng để "phá vỡ" từng nguyên tắc; nhưng không phải là một lý do duy nhất để phá vỡ cả 5!
Svidgen

1
Nó sẽ là lý tưởng cho tôi để không phải đập đầu vào tường mỗi khi tôi cần phải chế nhạo một logger / bộ đệm đơn để kiểm tra đơn vị. Hãy tưởng tượng nó sẽ như thế nào khi đơn vị kiểm tra một ứng dụng web mà không có HttpContextBase(được giới thiệu chính xác vì lý do này). Tôi biết chắc chắn rằng thực tế của tôi sẽ thực sự chua chát nếu không có lớp học này.
devnull

2
@devnull có lẽ đó là vấn đề sau đó, chứ không phải là mối quan tâm xuyên suốt ...
Boris Spider

25

Để đăng nhập tôi nghĩ rằng nó là. Ghi nhật ký là phổ biến và thường không liên quan đến chức năng dịch vụ. Đó là phổ biến và được hiểu rõ để sử dụng các mẫu singleton khung đăng nhập. Nếu bạn không, bạn đang tạo và tiêm logger ở mọi nơi và bạn không muốn điều đó.

Một vấn đề ở trên là ai đó sẽ nói 'nhưng làm cách nào tôi có thể kiểm tra đăng nhập?' . Suy nghĩ của tôi là tôi thường không kiểm tra việc ghi nhật ký, ngoài việc khẳng định rằng tôi thực sự có thể đọc các tệp nhật ký và hiểu chúng. Khi tôi thấy đăng nhập được kiểm tra, thường là do ai đó cần phải xác nhận rằng một lớp đã thực sự làm điều gì đó và họ đang sử dụng thông điệp tường trình để nhận phản hồi đó. Tôi thà đăng ký một số người nghe / người quan sát vào lớp đó và khẳng định trong các bài kiểm tra của tôi được gọi. Sau đó, bạn có thể đặt nhật ký sự kiện của mình trong người quan sát đó.

Tôi nghĩ rằng bộ nhớ đệm là một kịch bản hoàn toàn khác nhau, tuy nhiên.


3
Bây giờ tôi đã hiểu được một chút về FP Tôi đã có một sự quan tâm lớn trong việc sử dụng thành phần chức năng (có thể là đơn nguyên) để nhúng các công cụ như ghi nhật ký, xử lý lỗi, v.v. xem fsharpforfunandprofit.com/rop )
sara

5
Ghi nhật ký không nên phổ biến. Nếu đúng như vậy, thì bạn đang đăng nhập quá nhiều và bạn chỉ tạo ra tiếng ồn cho chính mình khi bạn thực sự cần phải xem xét các nhật ký đó. Bằng cách tiêm phụ thuộc vào logger, bạn buộc phải suy nghĩ xem liệu bạn có thực sự cần phải đăng nhập một cái gì đó hay không.
RubberDuck

12
@RubberDuck - Hãy nói với tôi rằng "đăng nhập không nên lan tỏa" khi tôi nhận được báo cáo lỗi từ trường và khả năng gỡ lỗi duy nhất tôi phải tìm hiểu xem điều gì đã xảy ra là tệp nhật ký mà tôi không muốn tạo ra. Bài học rút ra, đăng nhập nên "lan tỏa", rất phổ biến.
Dunk

15
@RubberDuck: Với phần mềm máy chủ, đăng nhập là cách duy nhất để tồn tại. Đó là cách duy nhất để tìm ra một lỗi xảy ra 12 giờ trước thay vì ngay bây giờ trên máy tính xách tay của bạn. Đừng lo lắng về tiếng ồn. Sử dụng phần mềm quản lý nhật ký để bạn có thể truy vấn nhật ký của mình (lý tưởng nhất là bạn cũng nên thiết lập báo thức sẽ gửi email cho bạn trên nhật ký lỗi)
slebetman

6
Nhân viên hỗ trợ của chúng tôi gọi cho tôi và nói với tôi "khách hàng đang nhấp vào một số trang và một lỗi xuất hiện." Tôi hỏi họ những gì lỗi nói, họ không biết. Tôi hỏi những gì cụ thể khách hàng đã nhấp, họ không biết. Tôi hỏi nếu họ có thể sinh sản, họ không thể. Tôi đồng ý đăng nhập chủ yếu có thể đạt được với các logger được triển khai tốt ở một vài điểm bản lề chính nhưng các thông điệp kỳ lạ nhỏ ở đây và cũng có giá trị. Sợ đăng nhập dẫn đến phần mềm chất lượng thấp hơn. Nếu bạn kết thúc với quá nhiều dữ liệu, hãy tỉa lại. Đừng tối ưu hóa sớm.
Pace

12

2 xu của tôi ...

Có và không.

Bạn không bao giờ nên thực sự vi phạm các nguyên tắc bạn áp dụng; nhưng, các nguyên tắc của bạn phải luôn luôn mang sắc thái và được áp dụng để phục vụ cho mục tiêu cao hơn. Vì vậy, với sự hiểu biết có điều kiện đúng đắn, một số vi phạm rõ ràng có thể không phải là vi phạm thực sự đối với "tinh thần" hay "cơ thể của các nguyên tắc nói chung".

Các nguyên tắc RẮN nói riêng, ngoài việc đòi hỏi nhiều sắc thái, cuối cùng còn phụ thuộc vào mục tiêu "cung cấp phần mềm làm việc, có thể bảo trì". Vì vậy, việc tuân thủ bất kỳ nguyên tắc RẮN cụ thể nào là tự đánh bại và tự mâu thuẫn khi làm như vậy mâu thuẫn với các mục tiêu của RẮN. Và ở đây, tôi thường lưu ý rằng việc cung cấp khả năng duy trì trumps .

Vì vậy, những gì về D trong RẮN ? Chà, nó góp phần tăng khả năng bảo trì bằng cách làm cho mô-đun tái sử dụng của bạn tương đối không tin vào bối cảnh của nó. Và chúng ta có thể định nghĩa "mô-đun có thể tái sử dụng" là "một tập hợp mã bạn dự định sử dụng trong một bối cảnh riêng biệt khác." Và điều đó áp dụng cho một chức năng, lớp, tập hợp lớp và chương trình.

Và vâng, việc thay đổi triển khai logger có thể đặt mô-đun của bạn vào một "bối cảnh khác biệt khác".

Vì vậy, hãy để tôi cung cấp hai cảnh báo lớn của tôi :

Thứ nhất: Vẽ các dòng xung quanh các khối mã tạo thành "mô-đun có thể tái sử dụng" là một vấn đề của sự đánh giá chuyên nghiệp. Và phán đoán của bạn nhất thiết phải giới hạn trong kinh nghiệm của bạn.

Nếu bạn không hiện kế hoạch sử dụng một mô-đun trong bối cảnh khác, đó là lẽ OK cho nó phụ thuộc vô vọng vào nó. Thông báo trước để cảnh báo: Kế hoạch của bạn có thể sai - nhưng điều đó cũng ổn. Bạn viết mô-đun sau mô-đun càng lâu, ý thức của bạn sẽ càng trực quan và chính xác hơn về việc "tôi sẽ cần điều này một lần nữa vào một ngày nào đó". Nhưng, có lẽ bạn sẽ không bao giờ có thể hồi tưởng lại, "Tôi đã mô đun hóa và tách rời mọi thứ đến mức lớn nhất có thể, nhưng không thừa ."

Nếu bạn cảm thấy có lỗi về phán đoán của mình, hãy đi xưng tội và tiếp tục ...

Thứ hai: Kiểm soát đảo ngược không bằng phụ thuộc tiêm .

Điều này đặc biệt đúng khi bạn bắt đầu tiêm phụ thuộc vào quảng cáo . Dependency Injection là một chiến thuật hữu ích cho chiến lược bao quát IoC. Nhưng, tôi cho rằng DI có hiệu quả kém hơn so với một số chiến thuật khác - như sử dụng giao diện và bộ điều hợp - các điểm tiếp xúc duy nhất với bối cảnh từ bên trong mô-đun.

Và hãy thực sự tập trung vào điều này trong một giây. Bởi vì, ngay cả khi bạn tiêm một Logger nauseam quảng cáo , bạn cần phải viết mã trên Loggergiao diện. Bạn không thể bắt đầu sử dụng mới Loggertừ một nhà cung cấp khác có các tham số theo thứ tự khác. Khả năng đó đến từ mã hóa, trong mô-đun, đối với một giao diện tồn tại trong mô-đun và có một mô hình con (Adaptor) duy nhất trong đó để quản lý sự phụ thuộc.

Và nếu bạn đang mã hóa bộ điều hợp, cho dù bộ Loggerđiều hợp đó được đưa vào Bộ điều hợp đó hay Bộ điều hợp được phát hiện nói chung là khá đáng kể đối với mục tiêu bảo trì tổng thể. Và quan trọng hơn, nếu bạn có Bộ điều hợp cấp mô-đun, có lẽ thật vô lý khi tiêm nó vào bất cứ thứ gì. Nó được viết cho mô-đun.

tl; dr - Đừng lo lắng về các nguyên tắc mà không xem xét lý do tại sao bạn sử dụng các nguyên tắc. Và, thực tế hơn, chỉ cần xây dựng một Adaptercho mỗi mô-đun. Sử dụng phán đoán của bạn khi quyết định nơi bạn vẽ ranh giới "mô-đun". Từ trong mỗi mô-đun, hãy tiếp tục và tham khảo trực tiếp đến Adapter. Và chắc chắn, tiêm logger thực sự vào Adapter- nhưng không phải vào mọi thứ nhỏ có thể cần nó.


4
Man ... Tôi đã có một câu trả lời ngắn hơn, nhưng tôi không có thời gian.
Svidgen

2
+1 để sử dụng Bộ chuyển đổi. Bạn cần cách ly sự phụ thuộc vào các thành phần của bên thứ 3 để cho phép chúng được thay thế bất cứ khi nào có thể. Ghi nhật ký là một mục tiêu dễ dàng cho việc này - nhiều triển khai ghi nhật ký tồn tại và hầu hết có các API tương tự, vì vậy việc triển khai bộ điều hợp đơn giản có thể cho phép bạn thay đổi chúng rất dễ dàng. Và với những người nói rằng bạn sẽ không bao giờ thay đổi nhà cung cấp đăng nhập của mình: Tôi đã phải làm điều này và nó đã gây ra một nỗi đau thực sự vì tôi không sử dụng bộ chuyển đổi.
Jules

"Các nguyên tắc RẮN nói riêng, ngoài việc đòi hỏi nhiều sắc thái, cuối cùng vẫn phụ thuộc vào mục tiêu" cung cấp phần mềm hoạt động, có thể bảo trì. "" - Đây là một trong những tuyên bố tốt nhất tôi từng thấy. Là một lập trình viên OCD nhẹ, tôi đã có những chia sẻ về cuộc đấu tranh với chủ nghĩa lý tưởng so với năng suất.
DVK

Mỗi lần tôi thấy +1 hoặc nhận xét về một câu trả lời cũ, tôi lại đọc câu trả lời của mình và khám phá lại rằng tôi là một nhà văn vô tổ chức và không rõ ràng ... Tôi đánh giá cao bình luận đó, @DVK.
Svidgen

Bộ điều hợp là bộ tiết kiệm cuộc sống, chúng không tốn nhiều chi phí và làm cho cuộc sống của bạn dễ dàng hơn rất nhiều, đặc biệt khi bạn muốn áp dụng RẮN. Kiểm tra là một làn gió với họ.
Alan

8

Ý tưởng rằng việc đăng nhập phải luôn luôn được thực hiện như một người độc thân là một trong những lời nói dối đã được nói rất thường xuyên, nó đã đạt được lực kéo.

Từ lâu, các hệ điều hành hiện đại đã được công nhận rằng bạn có thể muốn đăng nhập vào nhiều nơi tùy thuộc vào bản chất của đầu ra .

Các nhà thiết kế hệ thống nên liên tục đặt câu hỏi về hiệu quả của các giải pháp trong quá khứ trước khi mù quáng đưa chúng vào những giải pháp mới. Nếu họ không thực hiện sự siêng năng như vậy, thì họ sẽ không làm việc của họ.


2
Giải pháp đề xuất của bạn là gì? Có phải nó đang tiêm ILogger vào mỗi lớp bạn viết không? Điều gì về việc sử dụng một mẫu trang trí?
Robert Harvey

4
Không thực sự trả lời câu hỏi của tôi bây giờ, phải không? Tôi đã nêu các mẫu chỉ đơn thuần là ví dụ ... Nó không phải là những mẫu nếu bạn có ý tưởng tốt hơn.
Robert Harvey

8
Tôi không thực sự hiểu câu trả lời này, về bất kỳ đề xuất cụ thể nào
Brian Agnew

3
@RobbieDee - Vì vậy, bạn đang nói rằng Ghi nhật ký nên được thực hiện theo cách dễ gây phiền toái và bất tiện nhất bởi "cơ hội" mà chúng ta có thể muốn đăng nhập vào nhiều nơi? Ngay cả khi một thay đổi như vậy xảy ra, bạn có thực sự nghĩ rằng việc thêm chức năng đó vào đối tượng Logger hiện tại sẽ hiệu quả hơn tất cả nỗ lực để chuyển Logger đó giữa các lớp và thay đổi giao diện khi bạn quyết định bạn có muốn Logger hay không hàng tá dự án mà việc đăng nhập nhiều nơi sẽ không bao giờ xảy ra?
Dunk

2
Re: "bạn có thể muốn đăng nhập vào nhiều nơi tùy thuộc vào bản chất của đầu ra": Chắc chắn, nhưng cách tốt nhất để xử lý đó là trong khung ghi nhật ký , thay vì cố gắng tiêm nhiều phụ thuộc ghi nhật ký riêng biệt. (Các khung ghi nhật ký chung đã hỗ trợ điều này.)
ruakh

4

Đăng nhập thực sự là một trường hợp đặc biệt.

@Telastyn viết:

Bạn có thực sự sẽ không bao giờ thay đổi thư viện đăng nhập, hoặc nhắm mục tiêu, hoặc lọc hoặc định dạng hoặc ...?

Nếu bạn dự đoán rằng bạn có thể cần thay đổi thư viện ghi nhật ký của mình, thì bạn nên sử dụng mặt tiền; tức là SLF4J nếu bạn đang ở trong thế giới Java.

Đối với phần còn lại, một thư viện ghi nhật ký tốt sẽ thay đổi việc ghi nhật ký, sự kiện nào được lọc, cách các sự kiện nhật ký được định dạng bằng các tệp cấu hình logger và (nếu cần) các lớp plugin tùy chỉnh. Có một số lựa chọn thay thế ngoài kệ.

Nói tóm lại, đây là những vấn đề được giải quyết ... để đăng nhập ... và do đó không cần phải sử dụng Dependency Injection để giải quyết chúng.

Trường hợp duy nhất mà DI có thể có lợi (trên các phương pháp ghi nhật ký tiêu chuẩn) là nếu bạn muốn ghi nhật ký ứng dụng của mình vào kiểm tra đơn vị. Tuy nhiên, tôi nghi ngờ hầu hết các nhà phát triển sẽ nói rằng việc đăng nhập không phải là một phần của chức năng lớp và không phải là thứ cần được kiểm tra.

@Telastyn viết:

Và sau đó bạn sẽ nhận được lập luận rằng chính logger sẽ xử lý thay đổi. "Ồ, nếu mục tiêu / lọc / định dạng / chiến lược thay đổi, thì chúng ta sẽ thay đổi cấu hình!" Đó là rác. Giờ đây, bạn không chỉ có một Đối tượng Thần xử lý tất cả những điều này, mà bạn còn viết mã bằng XML (hoặc tương tự) khi bạn không nhận được phân tích tĩnh, bạn không bị lỗi thời gian biên dịch và bạn không ' t thực sự có được bài kiểm tra đơn vị hiệu quả.

Tôi sợ rằng đó là một ripost rất lý thuyết. Trong thực tế, hầu hết các nhà phát triển và nhà tích hợp hệ thống THÍCH thực tế là bạn có thể định cấu hình ghi nhật ký thông qua tệp cấu hình. Và họ THÍCH thực tế là họ không mong đợi đơn vị kiểm tra ghi nhật ký của mô-đun.

Chắc chắn, nếu bạn xử lý các cấu hình ghi nhật ký thì bạn có thể gặp sự cố, nhưng chúng sẽ biểu hiện là ứng dụng bị lỗi trong khi khởi động hoặc đăng nhập quá nhiều / quá ít. 1) Những sự cố này có thể dễ dàng khắc phục bằng cách sửa lỗi trong tệp cấu hình. 2) Thay thế là một chu trình xây dựng / phân tích / kiểm tra / triển khai hoàn chỉnh mỗi khi bạn thay đổi mức ghi nhật ký. Điều đó không được chấp nhận.


3

Không !

Có: Tôi nghĩ thật hợp lý khi các hệ thống con khác nhau (hoặc các lớp hoặc thư viện ngữ nghĩa hoặc các khái niệm khác của gói mô-đun) mỗi chấp nhận (cùng hoặc) có khả năng ghi nhật ký khác nhau trong quá trình khởi tạo thay vì tất cả các hệ thống con đều sử dụng cùng một đơn chung .

Tuy nhiên,

Không: đồng thời không hợp lý khi tham số hóa việc ghi nhật ký trong mọi đối tượng nhỏ (theo phương thức khởi tạo hoặc phương thức cá thể). Để tránh sự phình to không cần thiết và vô nghĩa, các thực thể nhỏ hơn nên sử dụng bộ ghi đơn lẻ trong bối cảnh kèm theo của chúng.


Đây là một lý do trong số nhiều người khác nghĩ về tính mô đun theo các mức: các phương thức được gói vào các lớp, trong khi các lớp được gói vào các hệ thống con và / hoặc các lớp ngữ nghĩa. Những bó lớn hơn là những công cụ trừu tượng có giá trị; chúng ta nên đưa ra những cân nhắc khác nhau trong các ranh giới mô-đun hơn là khi vượt qua chúng.


3

Đầu tiên, nó bắt đầu với bộ đệm đơn singleton, những thứ tiếp theo bạn thấy là các singleton mạnh cho lớp cơ sở dữ liệu giới thiệu trạng thái toàn cầu, API không mô tả của classes và mã không thể kiểm chứng.

Nếu bạn quyết định không có một singleton cho cơ sở dữ liệu, thì có lẽ không nên có một singleton cho bộ đệm, sau tất cả, chúng đại diện cho một khái niệm rất giống nhau, lưu trữ dữ liệu, chỉ sử dụng các cơ chế khác nhau.

Sử dụng một singleton trong một lớp sẽ biến một lớp có một số lượng phụ thuộc cụ thể thành một lớp có, theo lý thuyết , một số lượng vô hạn của chúng, bởi vì bạn không bao giờ biết điều gì thực sự ẩn đằng sau phương thức tĩnh.

Trong thập kỷ qua tôi đã dành lập trình, chỉ có một trường hợp tôi chứng kiến ​​nỗ lực thay đổi logic ghi nhật ký (sau đó được viết là singleton). Vì vậy, mặc dù tôi thích tiêm phụ thuộc, đăng nhập thực sự không phải là một mối quan tâm lớn như vậy. Cache, mặt khác, tôi chắc chắn sẽ luôn luôn làm như một phụ thuộc.


Có, đăng nhập hiếm khi thay đổi và thường không phải là một mô-đun có thể trao đổi. Tuy nhiên, tôi đã từng thử kiểm tra đơn vị một lớp trình trợ giúp ghi nhật ký, có phụ thuộc tĩnh vào hệ thống ghi nhật ký. Tôi đã quyết định cơ chế đơn giản nhất để làm cho nó có thể kiểm tra được là chạy lớp đang thử nghiệm trong một quy trình riêng biệt, định cấu hình bộ ghi của nó để ghi vào STDOUT và phân tích đầu ra trong trường hợp thử nghiệm của tôi _ಠ Tôi đã có trải nghiệm tương tự với đồng hồ nơi bạn ' Rõ ràng là không bao giờ muốn bất cứ điều gì ngoài thời gian thực, phải không? Trừ khi kiểm tra múi giờ / trường hợp cạnh DST, tất nhiên ...
amon

@amon: Đồng hồ giống như đăng nhập vào đó đã có một cơ chế khác phục vụ cùng mục đích với DI, đó là Joda-Time và nhiều cổng của nó. (Không có gì sai khi sử dụng DI thay vào đó, nhưng sử dụng Joda-Time trực tiếp đơn giản hơn là cố gắng viết một bộ chuyển đổi tiêm tùy chỉnh và tôi chưa bao giờ thấy ai hối tiếc khi làm như vậy.)
ruakh

@amon "Tôi đã có trải nghiệm tương tự với đồng hồ, nơi bạn rõ ràng không bao giờ muốn bất cứ thứ gì ngoài thời gian thực, phải không? Ngoại trừ khi kiểm tra các trường hợp cạnh múi giờ / DST, tất nhiên là" - hoặc khi bạn nhận ra rằng có một lỗi làm hỏng cơ sở dữ liệu của bạn và hy vọng duy nhất lấy lại được là phân tích nhật ký sự kiện của bạn và phát lại nó bắt đầu từ bản sao lưu cuối cùng ... nhưng đột nhiên bạn cần tất cả mã của mình để hoạt động dựa trên dấu thời gian của mục nhật ký hiện tại thay vì hiện tại thời gian.
Jules

3

Có và Không, nhưng chủ yếu là Không

Tôi giả sử hầu hết các cuộc hội thoại dựa trên trường hợp tĩnh so với tiêm. Không ai đề xuất rằng đăng nhập phá vỡ SRP tôi giả sử? Chúng tôi chủ yếu nói về "nguyên tắc đảo ngược phụ thuộc". Tôi không đồng ý với câu trả lời của Telastyn.

Khi nào thì sử dụng statics? Bởi vì rõ ràng đôi khi nó ổn. Câu trả lời đúng có về lợi ích của sự trừu tượng và câu trả lời "không" chỉ ra rằng chúng là thứ bạn phải trả cho. Một trong những lý do khiến công việc của bạn khó khăn là không có một câu trả lời nào bạn có thể viết ra và áp dụng cho tất cả các tình huống.

Lấy: Convert.ToInt32("1")

Tôi thích điều này hơn:

private readonly IConverter _converter;

public MyClass(IConverter converter)
{
   Guard.NotNull(converter)
   _converter = conveter
}

.... 
var foo = _converter.ToInt32("1");

Tại sao? Tôi chấp nhận rằng tôi sẽ cần cấu trúc lại mã nếu tôi cần sự linh hoạt để trao đổi mã chuyển đổi. Tôi chấp nhận rằng tôi sẽ không thể chế nhạo điều này. Tôi tin rằng sự đơn giản và căng thẳng là giá trị thương mại này.

Nhìn vào đầu kia của quang phổ, nếu IConverterlà một SqlConnection, tôi sẽ khá kinh hoàng khi thấy đó là một cuộc gọi tĩnh. Những lý do tại sao là rõ ràng hàng ngày. Tôi đã chỉ ra rằng một từ SQLConnectioncó thể khá "xuyên suốt" trong một tràng pháo tay, vì vậy tôi sẽ không sử dụng những từ chính xác đó.

Là đăng nhập giống như một SQLConnectionhoặc Convert.ToInt32? Tôi muốn nói nhiều hơn như 'SQLConnection`.

Bạn nên chế giễu Đăng nhập . Nó nói chuyện với thế giới bên ngoài. Khi viết một phương thức bằng cách sử dụng Convert.ToIn32, tôi đang sử dụng nó như một công cụ để tính toán một số đầu ra có thể kiểm tra riêng biệt khác của lớp. Tôi không cần kiểm tra Convertđã được gọi chính xác khi kiểm tra xem "1" + "2" == "3". Ghi nhật ký là khác nhau, đó là một đầu ra hoàn toàn độc lập của lớp. Tôi cho rằng đó là một đầu ra có giá trị với bạn, nhóm hỗ trợ và doanh nghiệp. Lớp của bạn không hoạt động nếu việc ghi nhật ký không đúng, vì vậy các bài kiểm tra đơn vị không nên vượt qua. Bạn nên kiểm tra những gì lớp học của bạn đăng nhập. Tôi nghĩ rằng đây là đối số sát thủ, tôi thực sự có thể chỉ dừng lại ở đây.

Tôi cũng nghĩ rằng đó là một thứ hoàn toàn có khả năng thay đổi. Ghi nhật ký tốt không chỉ in chuỗi, đó là xem ứng dụng của bạn đang làm gì (Tôi là một fan hâm mộ lớn của ghi nhật ký dựa trên sự kiện). Tôi đã thấy đăng nhập cơ bản biến thành UI báo cáo khá công phu. Rõ ràng là dễ dàng hơn rất nhiều để đi theo hướng này nếu đăng nhập của bạn trông giống _logger.Log(new ApplicationStartingEvent())và ít thích Logger.Log("Application has started"). Người ta có thể lập luận rằng điều này đang tạo ra hàng tồn kho cho một tương lai có thể không bao giờ xảy ra, đây là một cuộc gọi phán xét và tôi tình cờ nghĩ rằng nó đáng giá.

Trong thực tế trong một dự án cá nhân của tôi, tôi đã tạo ra một giao diện người dùng không đăng nhập hoàn toàn bằng cách sử dụng _loggerđể tìm ra ứng dụng đang làm gì. Điều này có nghĩa là tôi đã không phải viết mã để tìm ra ứng dụng đang làm gì và tôi đã kết thúc với việc ghi nhật ký vững chắc. Tôi cảm thấy nếu thái độ của tôi đối với việc đăng nhập là nó đơn giản và không thay đổi, ý tưởng đó sẽ không xảy ra với tôi.

Vì vậy, tôi đồng ý với Telastyn cho trường hợp đăng nhập.


Đây là cách tôi đăng nhập ngẫu nhiên . Tôi muốn liên kết đến một bài viết hoặc một cái gì đó, nhưng tôi không thể tìm thấy một bài viết. Nếu bạn đang ở trong thế giới .NET và tìm kiếm nhật ký sự kiện, bạn sẽ tìm thấy Semantic Logging Application Block. Đừng sử dụng nó, giống như hầu hết các mã được tạo bởi nhóm "mẫu và pratice" của MS, trớ trêu thay, đó là một phản mẫu.
Nathan Cooper

3

Mối quan tâm cắt chéo đầu tiên không phải là các khối xây dựng chính và không nên được coi là phụ thuộc trong một hệ thống. Một hệ thống sẽ hoạt động nếu ví dụ Logger không được khởi tạo hoặc bộ đệm không hoạt động. Làm thế nào bạn sẽ làm cho hệ thống ít kết nối và gắn kết? Đó là nơi mà RẮN xuất hiện trong thiết kế hệ thống OO.

Giữ đối tượng là singleton không liên quan gì đến RẮN. Đó là vòng đời đối tượng của bạn trong bao lâu bạn muốn đối tượng sống trong bộ nhớ.

Một lớp cần một phụ thuộc để khởi tạo không nên biết liệu thể hiện của lớp được cung cấp là đơn lẻ hay tạm thời. Nhưng tldr; nếu bạn đang viết Logger.Instance.Log () trong mọi phương thức hoặc lớp thì mã có vấn đề (mùi mã / khớp nối cứng) là một thứ thực sự lộn xộn. Đây là thời điểm khi mọi người bắt đầu lạm dụng RẮN. Và các nhà phát triển đồng nghiệp như OP bắt đầu đặt câu hỏi chính hãng như thế này.


2

Tôi đã giải quyết vấn đề này bằng cách sử dụng kết hợp tính kế thừa và đặc điểm (còn được gọi là mixins trong một số ngôn ngữ). Đặc điểm là siêu tiện dụng để giải quyết loại mối quan tâm xuyên suốt này. Mặc dù đây thường là một tính năng ngôn ngữ nên tôi nghĩ câu trả lời thực sự là nó phụ thuộc vào các tính năng ngôn ngữ.


Hấp dẫn. Tôi chưa bao giờ thực hiện bất kỳ công việc quan trọng nào bằng cách sử dụng ngôn ngữ hỗ trợ các đặc điểm, nhưng tôi đã cân nhắc sử dụng các ngôn ngữ đó cho một số dự án trong tương lai, vì vậy sẽ hữu ích cho tôi nếu bạn có thể mở rộng về điều này và cho thấy các đặc điểm giải quyết vấn đề như thế nào.
Jules
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.