Je viens de regarder cette conférence de Greg Young avertissant les gens de KISS: Keep It Simple Stupid.
Une des choses qu'il a suggérées, c'est que pour faire de la programmation orientée aspect, on n'a pas besoin d'un cadre .
Il commence par faire une forte contrainte: que toutes les méthodes prennent un et un seul paramètre (bien qu'il assouplisse cela un peu plus tard en utilisant une application partielle ).
L'exemple qu'il donne est de définir une interface:
public interface IConsumes<T>
{
void Consume(T message);
}
Si nous voulons émettre une commande:
public class Command
{
public string SomeInformation;
public int ID;
public override string ToString()
{
return ID + " : " + SomeInformation + Environment.NewLine;
}
}
La commande est implémentée comme:
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);
}
}
Pour se connecter à la console, on implémente alors simplement:
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);
}
}
Ensuite, la journalisation pré-commande, le service de commande et la journalisation post-commande sont alors simplement:
var log1 = new Logger<Command>(null);
var svr = new CommandService(log);
var startOfChain = new Logger<Command>(svr);
et la commande est exécutée par:
var cmd = new Command();
startOfChain.Consume(cmd);
Pour ce faire dans, par exemple, PostSharp , on annoterait de CommandService
cette façon:
public class CommandService : IConsumes<Command>
{
[Trace]
public void Consume(Command message)
{
Console.WriteLine("Command complete!");
}
}
Et puis implémenter la journalisation dans une classe d'attribut quelque chose comme:
[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 );
}
}
L'argument que Greg utilise est que la connexion de l'attribut à l'implémentation de l'attribut est "trop magique" pour pouvoir expliquer ce qui arrive à un développeur junior. L'exemple initial est tout "juste du code" et facile à expliquer.
Donc, après cette accumulation plutôt longue, la question est: quand passez-vous de l'approche non-framework de Greg à l'utilisation de quelque chose comme PostSharp pour AOP?
IConsumes
pièces. Plutôt que d'avoir à utiliser du XML externe ou une interface Fluent --- encore une autre chose à apprendre. On pourrait soutenir que cette méthodologie est "une autre chose à apprendre" également.