程序集范围的多播属性。他们是邪恶的吗?
我正在开发一个项目,其中我们在 AssemblyInfo.cs 中有多个属性,这些属性被多播到特定类的方法。
[assembly: Repeatable(
AspectPriority = 2,
AttributeTargetAssemblies = "MyNamespace",
AttributeTargetTypes = "MyNamespace.MyClass",
AttributeTargetMemberAttributes = MulticastAttributes.Public,
AttributeTargetMembers = "*Impl", Prefix = "Cls")]
我不喜欢这一点的是,它将一段逻辑放入 AssemblyInfo(Info,请注意!),对于初学者来说,它根本不应该包含任何逻辑。最糟糕的部分是,实际的 MyClass.cs 在文件中的任何位置都没有该属性,并且完全不清楚此类的方法是否可能具有它们。从我的角度来看,它极大地损害了代码的可读性(更不用说过度使用 PostSharp 会让调试成为一场噩梦)。特别是当您有多个多播属性时。
这里的最佳实践是什么?有人使用这样的 PostSharp 属性吗?
I am working on a project where we have several attributes in AssemblyInfo.cs, that are being multicast to methods of a particular class.
[assembly: Repeatable(
AspectPriority = 2,
AttributeTargetAssemblies = "MyNamespace",
AttributeTargetTypes = "MyNamespace.MyClass",
AttributeTargetMemberAttributes = MulticastAttributes.Public,
AttributeTargetMembers = "*Impl", Prefix = "Cls")]
What I don't like about this, is that it puts a piece of logic into AssemblyInfo (Info, mind you!), which for starters should not contain any logic at all. The worst part of it, is that the actual MyClass.cs does not have the attribute anywhere in the file, and it is completely unclear that methods of this class might have them. From my perspective it greatly hurts readability of the code (not to mention that overuse of PostSharp can make debugging a nightmare).Especially when you have multiple multicast attributes.
What is the best practice here? Is anyone out there is using PostSharp attributes like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
让我首先回答 Max:确实,方面并不是良好的 OOP 模式的替代品。它们是一个补充。任何好的 AOP 设计都始于好的 OOP 设计。但 OOP 模式有时会迫使您手动编写大量管道代码。对于这些情况,方面可以用于自动化 OOP 模式的实现,而不是来取代它们。
当你智能地使用AOP时,你的解决方案可以变得更容易理解(业务代码不与维护代码混合),更容易测试(你可以独立于业务代码测试切面,即你不必测试任何业务方法跟踪)正确地),改变(当你想改变模式时,你只需要改变方面,而不是改变模式的每个实现)。现在,如果您滥用 AOP,如果您将其用作黑客工具,如果您之前没有考虑 OOP 模式,那么您从 AOP 中获得的成本将大于收益。与任何利器一样,AOP 应该被明智地使用。
回到原来的问题。
谁告诉你应该将方面放在 AssemblyInfo.cs 中?您可以创建一个名为 GlobalAspects.cs 的新文件,并将所有程序集级方面放入其中。您是对的,AssemblyInfo.cs 应该仅用于程序集级元数据。
但和你一样,我不喜欢装配级方面。我认为应该避免。汇编级方面的主要问题是它们依赖于命名约定,这是邪恶的。 (这种邪恶在学术 AOSD 社区中被称为切入点脆弱性。)事实上,当您重命名类或名称空间时,您会更改该方面所应用的方法集,这很快就会成为一场噩梦。这就是为什么我自己从不使用基于命名约定的方面。
代码可读性怎么样?在很大程度上,我认为可读的代码是短代码。如果我有一个名为 CreateProduct 的业务方法,我可能只想查看创建产品的代码。大多数时候,我对处理事务、异常或跟踪的代码不感兴趣。如果我知道某些方面可以为我处理这个问题就足够了。
我怎么知道?有了 PostSharp,您就拥有了 Visual Studio 扩展。有了 AspectJ,您就拥有了 Eclipse 的 AspectJ 插件 (AJDT)。它们在 IDE 内向您展示哪些方面应用于您当前看到的代码。如果您确实想查看详细信息(但您很少真正想要),则可以使用调试器单步执行方面,或使用 Reflector 查看生成的代码。
总结:
Let me first answer to Max: indeed, aspects are not an alternative to good OOP patterns. They are a complement. Any good AOP design starts with a good OOP design. But OOP patterns sometimes force you to write a lot of plumbing code manually. For these cases, aspects can be used to automate the implementation of OOP pattern, not to replace them.
When you use AOP intelligently, your solution can become easier to understand (business code is not mixed with maintenance code), to test (you can test the aspect independently from business code, i.e. you don't have to test that any business method traces properly), change (you just have to change the aspect when you want to change the pattern, instead of changing every implementation of the pattern). Now, if you abuse from AOP, if you use it as a hacking tool, if you do not think in terms of OOP patterns before, then your're going to get more costs than benefits from AOP. As any sharp tool, AOP should be used intelligently.
Back to the original question.
Who tells you should put aspects in AssemblyInfo.cs? You could create a new file called GlobalAspects.cs and put all assembly-level aspects there. You're right that AssemblyInfo.cs should just be for assembly-level metadata.
But like you, I don't like assembly-level aspects. I think there should be avoided. The principal problem with assemly-level aspects is that they rely on naming conventions, and this is evil. (This evil is called pointcut fragility in the academic AOSD community.) Indeed, when you rename a class or namespace, you change the set of methods to which the aspect applies, and this can quickly become a nightmare. That's why I never use aspects based on naming conventions for myself.
What about code readibility? To a great extent, I think readable code is short code. If I have a business method called CreateProduct, I probably want to see just the code creating the product. Most of the time, I am not interested in code that handles transactions, exceptions, or tracing. It's enough if I know that some aspects handle that for me.
And how do I know? With PostSharp, you have the Visual Studio Extension. With AspectJ, you have the AspectJ plug-in for Eclipse (AJDT). They show you, inside the IDE, which aspects are applied to the code you currently see. And if you really want to see details (but you seldom really want), you can use the debugger to step into aspects, or use Reflector to see produced code.
Summary:
我确信这将是一个不受欢迎的答案,但也许我可以获得我的同侪压力徽章......
你的直觉是正确的。将逻辑放入任何类型的元数据中都是一种非常非常可怕的罪恶,人们会因此在不可维护性的地狱之火中永远燃烧。
我这样说并没有不尊重的意思,尽管我确信它会被以其他方式解释。
最佳实践是不要使用“面向方面的编程”工具,这些工具是导致不良设计和测试实践瘫痪的拐杖。相反,看看你的设计并问自己“为什么”。
一旦你牢牢掌握了问题,就去学习《设计模式解释》(Shalloway 和 Trott)或《Head First 设计模式》(Freeman、Robson、Bates 和 & Trott)。塞拉)。
最终,面向模式的解决方案将更容易理解、更容易测试、更容易更改。唯一的额外成本是掌握设计模式的一次性费用,而不是每次做出更改时试图弄清楚所有这些方面在哪里、它们如何组合在一起以及它们如何相互影响的经常性费用。
I'm sure this will be an unpopular answer but maybe I can get my peer pressure badge...
Your instincts are correct. Putting logic in metadata of any kind is a horrible, horrible sin for which one burns eternally in the hellfire of unmaintainability.
I mean no disrespect by this although I'm certain it will be interpreted otherwise.
The best practice would be to not use "aspect-oreinted programming" tools, which are crutches that enable the lameness of poor design and testing practices. Instead, look at your design and ask yourself "why."
Once you have a firm grasp of the problem, go pick up Design Patterns Explained (Shalloway & Trott) or Head First Design Patterns (Freeman, Robson, Bates, & Sierra).
In the end, a pattern-oriented solution will be easier to understand, easier to test, and easier to change. The only additional cost will be the one-time fee of mastering design patterns in place of the recurring charge of trying to figure out where all these aspects are, how they fit together, and how they influence one another every time you make a change.