Tôi vừa xem bài nói chuyện này của Greg Young cảnh báo mọi người về KISS: Keep It Simple St ngu.
Một trong những điều ông đề xuất là để lập trình hướng theo khía cạnh, người ta không cần một khuôn khổ .
Anh ta bắt đầu bằng cách thực hiện một ràng buộc mạnh mẽ: rằng tất cả các phương thức đều lấy một và chỉ một tham số (mặc dù anh ta thư giãn điều này một lát sau bằng cách sử dụng một phần ứng dụng ).
Ví dụ anh đưa ra là định nghĩa một giao diện:
public interface IConsumes<T>
{
void Consume(T message);
}
Nếu chúng ta muốn đưa ra một lệnh:
public class Command
{
public string SomeInformation;
public int ID;
public override string ToString()
{
return ID + " : " + SomeInformation + Environment.NewLine;
}
}
Lệnh được thực hiện như:
public class CommandService : IConsumes<Command>
{
private IConsumes<Command> _next;
public CommandService(IConsumes<Command> cmd = null)
{
_next = cmd;
}
public void Consume(Command message)
{
Console.WriteLine("Command complete!");
if (_next != null)
_next.Consume(message);
}
}
Để thực hiện đăng nhập vào bàn điều khiển, người ta chỉ cần thực hiện:
public class Logger<T> : IConsumes<T>
{
private readonly IConsumes<T> _next;
public Logger(IConsumes<T> next)
{
_next = next;
}
public void Consume(T message)
{
Log(message);
if (_next != null)
_next.Consume(message);
}
private void Log(T message)
{
Console.WriteLine(message);
}
}
Sau đó, ghi nhật ký lệnh trước, dịch vụ lệnh và ghi nhật ký lệnh sau đó chỉ là:
var log1 = new Logger<Command>(null);
var svr = new CommandService(log);
var startOfChain = new Logger<Command>(svr);
và lệnh được thực thi bởi:
var cmd = new Command();
startOfChain.Consume(cmd);
Để làm điều này, ví dụ, PostSharp , người ta sẽ chú thích CommandService
theo cách này:
public class CommandService : IConsumes<Command>
{
[Trace]
public void Consume(Command message)
{
Console.WriteLine("Command complete!");
}
}
Và sau đó phải thực hiện đăng nhập trong một lớp thuộc tính như:
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : Entered!" );
}
public override void OnSuccess( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : Exited!" );
}
public override void OnException( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : EX : " + args.Exception.Message );
}
}
Đối số mà Greg sử dụng là kết nối từ thuộc tính đến việc thực hiện thuộc tính là "quá nhiều phép thuật" để có thể giải thích những gì đang xảy ra với một nhà phát triển cơ sở. Ví dụ ban đầu là tất cả "chỉ mã" và dễ dàng giải thích.
Vì vậy, sau quá trình xây dựng khá dài, câu hỏi đặt ra là: khi nào bạn thực hiện chuyển đổi từ cách tiếp cận phi khung của Greg sang sử dụng một cái gì đó như PostSharp cho AOP?
IConsumes
. Thay vì phải sử dụng XML bên ngoài hoặc một số giao diện Fluent --- còn một điều nữa cần tìm hiểu. Người ta có thể lập luận rằng phương pháp này cũng là "một thứ khác để học".