Có thể giữ mã đăng nhập hoàn toàn bên ngoài logic kinh doanh?


12

Với sự giúp đỡ của AOP, tôi có thể xóa mã đăng nhập khỏi logic kinh doanh của mình. Nhưng tôi nghĩ rằng nó chỉ có thể được sử dụng để ghi lại những điều đơn giản (ví dụ: nhập / thoát phương thức và các giá trị tham số).

Tuy nhiên, điều gì sẽ xảy ra nếu tôi cần đăng nhập một cái gì đó trong logic kinh doanh của mình? ví dụ

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      Log.Warn("user is not existed");        //<----------------- Log A
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   Log.Info("Step 1 is completed");            //<----------------- Log B

   //Step 2
   while(true)
   {
       //do something
   }
   Log.Info("Step 2 is completed");            //<----------------- Log C

}

Phương pháp mẫu ở trên có thể không đủ rõ ràng, điều tôi muốn trình bày ở đây là phương thức này nên được coi là đơn vị nhỏ nhất theo quan điểm tên miền. Nó không nên được chia thành các phần nhỏ hơn.

Có thể di chuyển trên 3 mã đăng nhập ra khỏi phương thức? Thực hành tốt nhất cho tình huống như vậy là gì?


Tôi khá chắc chắn rằng nhật ký "Bước 1" và "Bước 2" của ví dụ của bạn phải là một phần của quy trình kiểm toán logic nghiệp vụ và là lần đầu tiên ghi nhật ký kỹ thuật. Trước tiên tôi sẽ sắp xếp thứ này ...
tofro

Câu trả lời:


1

Chắc chắn rồi!

Nhưng theo kinh nghiệm của tôi, có hai loại ghi nhật ký hữu ích chung :

Nhật ký mọi thứ : Nhật ký được xây dựng thông qua API định hình. Tốt để xác định các vấn đề hiệu suất và báo cáo ngoại lệ. Rất ồn ào.

Nhật ký sự kiện kinh doanh : Nhật ký được gọi trong logic kinh doanh. Bất cứ điều gì doanh nghiệp có thể quan tâm. Tiếng ồn tối thiểu. Chỉ cần sự kiện đáng chú ý, hợp lý, "kinh doanh". Tốt cho kiểm toán và KPI ...

Vì vậy, tôi rất muốn đề xuất hai điều. Đầu tiên, hãy làm những gì các công cụ giám sát khác làm, như New Relic và sử dụng API lược tả .NET 1 . Thứ hai, đăng nhập các sự kiện kinh doanh hợp lý trong logic kinh doanh của bạn . Giữ một bản ghi của các sự kiện nhất định logic kinh doanh.

Và, tôi sẽ không bình thường đề nghị AOP cho một trong hai loại đăng 2 . Theo kinh nghiệm của tôi, bạn có thể muốn mọi thứ , có nghĩa là bạn đang sử dụng một hồ sơ hoặc bạn muốn các sự kiện hợp lý / kinh doanh. Và trong trường hợp sau, tôi nghĩ đơn giản hơn là chỉ cần gọi logger trong logic nghiệp vụ.


1. Nhưng nghiêm túc, hãy tiết kiệm cho mình hàng ngàn giờ nỗ lực và chỉ cần sử dụng một công cụ trình hồ sơ hiện có ...

2. Tất nhiên, điều này giả định rằng bạn chia sẻ ý kiến ​​của tôi rằng một khía cạnh không phải là một nơi tuyệt vời để che giấu các quy tắc kinh doanh!


Tôi hoàn toàn đồng ý với "Nhật ký sự kiện kinh doanh" và giống như câu trả lời của người khác, tôi sẽ giữ mã nhật ký trong logic nghiệp vụ. Và đối với phần "Nhật ký mọi thứ", tôi thích sử dụng giải pháp AOP vì nó sẽ tuân theo SRP và không gây ô nhiễm logic kinh doanh của tôi. Dù sao, trước tiên tôi sẽ xem xét API định hình.
Charlie

10

Chắc chắn, bạn có thể dễ dàng sử dụng AOP cho việc này. Đơn giản chỉ cần cấu trúc lại các bộ phận

  • Nhận người dùng bằng Id
  • bước 1
  • bước 2

vào các phương thức riêng biệt (như bạn nên làm hoặc để làm cho mã của bạn sạch hơn). Bây giờ bạn có thể dễ dàng định cấu hình khung AOP của mình để ghi nhật ký các cuộc gọi phương thức bạn chọn ( như hiển thị ở đây ). Ngoại lệ có thể được ghi lại trực tiếp bởi người gọi, không cần sử dụng AOP để đưa điều này ra khỏi logic nghiệp vụ.

Để chỉnh sửa của bạn:

Tôi muốn chỉ ra ở đây là phương thức nên được coi là đơn vị nhỏ nhất theo quan điểm tên miền. Nó không nên được chia thành các phần nhỏ hơn

Tại sao không nên? Nếu, trong "bối cảnh logic kinh doanh", bạn muốn ghi nhật ký "thứ gì đó" đáng để ghi nhật ký và nếu "cái gì đó" này có thể được đặt tên hợp lý, trong hầu hết các trường hợp, sẽ hợp lý khi cấu trúc lại mã thành phương thức trên của riêng nó. Nếu bạn muốn sử dụng AOP, nó sẽ yêu cầu bạn cấu trúc mã theo cách mà bạn có thể đã cấu trúc nó bất kể yêu cầu đăng nhập. Bạn có thể hiểu điều này là một bất lợi của AOP hoặc bạn có thể hiểu điều này là một lợi ích, vì nó mang lại cho bạn một phản hồi trong đó cấu trúc mã của bạn có thể được cải thiện.


Thật tệ khi ví dụ của tôi không đủ rõ ràng. Điều tôi thực sự muốn chỉ ra trong ví dụ là phương thức này là đơn vị nhỏ nhất theo quan điểm miền không nên chia thành các phần nhỏ hơn.
Charlie

@Charlie: ví dụ hoàn toàn rõ ràng. Quan niệm sai lầm của bạn ở đây có lẽ là bạn nghĩ rằng có thể nên có các phương pháp lớn hơn các bước. Và đó là IMHO sai, nó không phải là một ý tưởng tốt. Có các bước khác nhau đáng ghi nhật ký là một dấu hiệu rõ ràng, các bước này nên có một sự trừu tượng hóa, một tên riêng, do đó, một phương thức riêng của nó.
Doc Brown

@Charlie không có gì ngăn bạn thực hiện 3 phương thức riêng tư được gọi bởi đơn vị hoặc công việc của bạn. Cách này từ bên ngoài vẫn giữ nguyên nhưng bây giờ bạn có sự trừu tượng cần thiết cho việc đăng nhập của bạn.
Rémi

Cách tiếp cận này là tốt nếu bạn muốn lái cấu trúc mã của mình bằng cách ghi nhật ký mối quan tâm. Đôi khi bạn muốn lái nó bằng một cái gì đó khác, mặc dù.
John Wu

@JohnWu: cấu trúc mã phải phản ánh các mối quan tâm / bước khác nhau, bất kể yêu cầu đăng nhập. Đó là những gì thúc đẩy cấu trúc mã ở đây. Khi vấn đề này được giải quyết, việc ghi nhật ký có thể được thực hiện bởi AOP, đó là "tác dụng phụ" của việc tạo cho mã một cấu trúc tốt hơn. Vì vậy, tôi nghĩ rằng đó không phải là vấn đề ghi nhật ký điều khiển cấu trúc mã, điều quan trọng hơn là việc sử dụng AOP để ghi nhật ký làm cho minh bạch hơn rằng mã bỏ qua một số cấu trúc mà nó nên có.
Doc Brown

3

Trừ khi công cụ ghi nhật ký là một phần của các yêu cầu kinh doanh thì tốt nhất, như bạn nói, để giữ cho nó hoàn toàn ra khỏi mã của bạn.

Điều đó có nghĩa là bạn thực sự không muốn đăng nhập những thứ như "hoàn thành bước 1". Mặc dù ban đầu nó có thể hữu ích cho việc gỡ lỗi, nhưng trong sản xuất, nó sẽ tạo ra hàng gigabyte rác mà bạn sẽ không bao giờ nhìn vào.

Nếu Step1Complete là một loại sự kiện kinh doanh nào đó đòi hỏi phải có hành động tiếp theo thì nó có thể được phơi bày thông qua một sự kiện lỗi thời mà không buộc bạn phải tiêm ILogger hoặc tương tự vào lớp của bạn


Đó là thứ tôi đã từng nghĩ đến. Tôi không thể đưa ra một trường hợp hợp lý để đăng nhập trong một mô hình POCO tên miền / doanh nghiệp. Ghi nhật ký là một cái gì đó có xu hướng phù hợp tự nhiên bên ngoài các mô hình kinh doanh cốt lõi, IMO.
jleach 17/03/2017

2

Bằng cách trợ giúp một số mẫu phổ biến, bạn có thể rút mã đăng nhập khỏi logic nghiệp vụ của mình. Tuy nhiên bạn có thể không thấy nó đáng để làm như vậy

Ví dụ: bằng cách sử dụng trình nghe (thủ công một hoặc sử dụng bus sự kiện, v.v.), mã của bạn sẽ trông giống như

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      listener.OnUserNotFound(userId);
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   listener.OnStep1Finished(......);

   ...

}

Bằng cách thực hiện ghi nhật ký trong trình nghe, logic ghi nhật ký không còn trong logic nghiệp vụ của bạn nữa.

Tuy nhiên, bạn có thể thấy điều này không phải lúc nào cũng thực tế vì không phải lúc nào bạn cũng có thể xác định sự kiện có ý nghĩa trong logic của mình.

Một cách tiếp cận khác là thông qua cơ chế như Dtrace trong Solaris, cho phép bạn đưa vào các quy trình đang chạy (tôi tin rằng có cách để làm điều tương tự trong C #?) Để ghi nhật ký và thu thập thống kê có thể được xác định trong thời gian chạy. Vẫn còn những nhược điểm khác.


Một vấn đề mà AOP đang cố gắng giải quyết là vấn đề về mã trở nên không thể đọc được đối với mã phi kinh doanh (như các cuộc gọi đăng nhập) đan xen với "mã doanh nghiệp". Việc thay thế "logger" bằng "trình nghe" không giải quyết được điều này, khả năng đọc mã không bị thay đổi,
Doc Brown

2

Một cách tiếp cận khác là đặt nhật ký kinh doanh và đăng nhập kỹ thuật. Sau đó, chúng ta có thể gọi ghi nhật ký kinh doanh là "Kiểm toán" và áp dụng một bộ quy tắc kinh doanh cụ thể như thời hạn lưu trữ và quy tắc xử lý như Giám sát hoạt động kinh doanh.

Mặt khác, ghi nhật ký kỹ thuật, hoặc đơn giản là "Ghi nhật ký", là phương tiện cuối cùng để lại dấu vết của sự cố kỹ thuật. Nó nên không đồng bộ, nhanh chóng, chịu đựng thất bại để duy trì thông điệp tường trình. Ngoài ra, thông điệp tường trình phải vượt qua số lượng proxy ít nhất có thể để gần với nguồn gốc của sự cố.

Logic của The Logging khá thay đổi và được kết hợp chặt chẽ với việc thực hiện, vậy bạn có thực sự cần tách nó ra khỏi mã không?

Logic của The Audit nên được coi là logic miền và được xử lý tương ứng.

Ví dụ: trong Kiến trúc lục giác có thể có cổng Kiểm toán cùng với các cổng Khách hàng, Lưu trữ và MQ (và có thể, Số liệu và Kiểm soát). Nó sẽ là cổng thứ cấp, tức là hoạt động trên cổng này được kích hoạt bởi lõi kinh doanh, chứ không phải bởi các hệ thống bên ngoài.


Tôi rất đồng ý với bạn rằng có hai loại đăng nhập. Nhưng tôi không nhận được Logic của việc ghi nhật ký khá thay đổi và được kết hợp chặt chẽ với việc thực hiện , ý bạn là đăng nhập kỹ thuật ở đây? Để ghi nhật ký kỹ thuật, tôi nghĩ rằng nó được sử dụng để ghi nhật ký nhập / xuất và các giá trị tham số của phương thức, tốt hơn là ngồi ngoài phương thức.
Charlie

@Charlie Có, bởi "Ghi nhật ký" Ý tôi là ghi nhật ký kỹ thuật. Ghi nhật ký nhập / thoát / tham số là đủ trong trường hợp hàm thuần túy. Sau đó, hoặc tất nhiên, bạn có thể sử dụng một khía cạnh hoặc đơn vị Logger. Nhưng các chức năng thuần túy là tuyệt vời ở chỗ chúng có thể kiểm tra được. Vì vậy, các vấn đề, logger được cho là theo dõi, có khả năng được giải quyết trong quá trình dev / debug. Với các hàm không tinh khiết, trong đó việc ghi nhật ký công nghệ được sử dụng nhiều nhất, bạn muốn ghi nhật ký mọi thông số / kết quả cuộc gọi hiệu quả, mọi ngoại lệ.
iTollu 17/03/2017

1

Các cách để tránh đăng nhập trực tiếp trong một lớp hoặc phương thức:

  1. Ném một ngoại lệ và đăng nhập vào một khối bắt xa hơn trên cây gọi. Nếu bạn cần nắm bắt một mức độ nhật ký, bạn có thể ném một ngoại lệ tùy chỉnh.

  2. Thực hiện cuộc gọi đến các phương thức đã được ghi nhận.


1
Việc đăng nhập có phải là một vấn đề và thậm chí còn đáng để "sửa chữa" không?
whatsisname

1

Có thực sự cần thiết để tách đăng nhập của bạn khỏi logic kinh doanh của bạn? Ghi nhật ký được thực hiện tương ứng với logic nghiệp vụ được viết và do đó có ý nghĩa trong cùng một lớp / chức năng. Quan trọng hơn, nó giúp dễ đọc mã hơn.

Tuy nhiên, trong trường hợp bạn thực sự muốn tách riêng việc ghi nhật ký khỏi logic kinh doanh của mình, bạn nên xem xét đưa ra các ngoại lệ tùy chỉnh và chuyển các ngoại lệ đó để ghi nhật ký.


0

Không, không có trong c #

OP, câu trả lời cho câu hỏi cụ thể của bạn là không, không có trong c #. Có thể có các ngôn ngữ AOP khác, nguyên bản hơn ngoài kia, nhưng tất cả các cách tiếp cận AOP trong c # mà tôi đã thấy chỉ có thể áp dụng các hành vi được mong muốn trong ngữ cảnh của một điểm nối , nghĩa là phải có sự kiểm soát giữa một khối mã và khác. Các hành vi được mong đợi sẽ không thực thi ở giữa một phương thức, ngoại trừ tất nhiên bằng cách gọi một phương thức khác.

Bạn có thể "apsect-ize" một số bit đăng nhập

Điều đó đang được nói, bạn có thể trích xuất một số mối quan tâm nhất định liên quan đến đăng nhập, chỉ cần không viết nhật ký. Ví dụ, một điểm cắt được thực thi khi nhập vào một phương thức có thể thiết lập bối cảnh ghi nhật ký và xuất tất cả các tham số đầu vào, và khi thoát có thể bắt ngoại lệ hoặc đưa nhật ký vào bộ nhớ vĩnh viễn, đại loại như vậy.

Viết nhật ký không phải là một khía cạnh, dù sao

Dù sao, tôi sẽ thêm rằng viết nhật ký không thực sự là một mối quan tâm xuyên suốt. Ít nhất là không gỡ lỗi đăng nhập. Bằng chứng của tôi cho điều này là bạn không thể viết một yêu cầu xuyên suốt giải thích đầy đủ khía cạnh này sẽ làm gì - nó cụ thể cho từng trường hợp, bởi vì mục đích của việc viết nhật ký là để phản ánh những gì đang xảy ra với logic và logic trong mỗi phương thức phải là duy nhất một cách hợp lý (xem DRY ).

Nói cách khác, có một sự phụ thuộc logic chặt chẽ giữa viết nhật ký và nội dung được viết. Bạn không thể khái quát nó.

Nhưng kiểm toán là

Nếu bạn có một số loại yêu cầu ghi nhật ký chức năng (ví dụ: đăng nhập kiểm toán hỗ trợ cho yêu cầu không thoái thác ) thì một số người sẽ tranh luận (và tôi sẽ đồng ý) rằng nếu bạn thấy mình cần phải thực hiện các ghi nhật ký này ở giữa một phương thức, bạn đã không cấu trúc mã của mình theo cách phù hợp với suy nghĩ hướng theo khía cạnh. Nếu điều này xảy ra, bạn nên trích xuất mã thành các phương thức riêng biệt cho đến khi bạn có được mức độ chi tiết bạn cần.

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.