为什么要使用后编译器?

发布于 2024-08-06 05:54:37 字数 294 浏览 4 评论 0原文

我正在努力理解为什么需要像 PostSharp 这样的后编译器?

我的理解是,它只是在原始代码中插入代码,那么为什么开发人员不自己编写代码呢?

我希望有人会说它更容易编写,因为您可以在方法上使用属性,然后不会使它们混乱的样板代码,但这可以使用 DI 或反射以及一些深思熟虑来完成,而无需后期编译器。我知道,既然我已经说过反射,那么性能大象现在将进入 - 但我不关心这里的相对性能,因为大多数场景的绝对性能微不足道(亚毫秒到毫秒)。

I am battling to understand why a post compiler, like PostSharp, should ever be needed?

My understanding is that it just inserts code where attributed in the original code, so why doesn't the developer just do that code writing themselves?

I expect that someone will say it's easier to write since you can use attributes on methods and then not clutter them up boilerplate code, but that can be done using DI or reflection and a touch of forethought without a post compiler. I know that since I have said reflection, the performance elephant will now enter - but I do not care about the relative performance here, when the absolute performance for most scenarios is trivial (sub millisecond to millisecond).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

宫墨修音 2024-08-13 05:54:37

让我们尝试从架构角度来看待这个问题。假设您是一名建筑师(每个人都想成为一名建筑师;)
您需要将架构交付给您的团队:
一组选定的库、架构模式和设计模式。作为设计的一部分,您说:“我们将使用以下设计模式实现缓存:”

string key = string.Format("[{0}].MyMethod({1},{2})", this, param1, param2 );
T value;
if ( !cache.TryGetValue( key, out value ) )
{
   using ( cache.Lock(key) )
   {
      if (!cache.TryGetValue( key, out value ) )
      {
         // Do the real job here and store the value into variable 'value'.
         cache.Add( key, value );
      }
   }
}

这是进行跟踪的正确方法。开发人员将要实现该模式数千次,因此您需要编写一个漂亮的 Word 文档,告诉您希望如何实现该模式。是的,一个Word文档。您有更好的解决方案吗?恐怕你不知道。经典的代码生成器没有帮助。函数式编程(委托)?它在某些方面工作得相当好,但在这里不行:您需要将方法参数传递给模式。那么还剩下什么呢?用自然语言描述模式并相信开发人员会实现它们。

会发生什么?

首先,一些初级开发人员会查看代码并告诉他们“嗯。两次缓存查找。有点没用。一次就足够了。” (这不是玩笑——请向 DNN 团队询问这个问题)。并且您的模式不再是线程安全的。

作为架构师,您如何确保正确应用该模式?单元测试?很公平,但是您很难通过这种方式检测到线程问题。代码审查?这也许就是解决方案。

现在,您决定改变什么模式?例如,您检测到缓存组件中的错误并决定使用您自己的?您要编辑数千个方法吗?这不仅仅是重构:如果新组件具有不同的语义怎么办?

如果您决定不再缓存某个方法怎么办?删除缓存代码有多困难?

AOP 解决方案(无论框架是什么)与纯代码相比具有以下优点:

  1. 减少了代码行数
  2. 减少了组件之间的耦合,因此当您决定更改日志组件时不必更改太多内容(只需更新方面),因此它提高了源的容量随着时间的推移,代码可以应对新的需求
  3. 由于代码较少,因此给定功能集出现错误的可能性较低,因此 AOP 提高了代码质量

因此,如果将所有这些放在一起:

方面可以降低软件的开发成本和维护成本。

我有一个关于这个主题的 90 分钟演讲,您可以在 http://vimeo.com/2116491 观看。

同样,AOP 的架构优势与您选择的框架无关。框架之间的差异(也在本视频中讨论)主要影响您可以在代码中应用 AOP 的程度,这不是这个问题的重点。

Let's try to take an architectural point on the issue. Say you are an architect (everyone wants to be an architect ;)
You need to deliver the architecture to your team:
a selected set of libraries, architectural patterns, and design patterns. As a part of your design, you say: "we will implement caching using the following design pattern:"

string key = string.Format("[{0}].MyMethod({1},{2})", this, param1, param2 );
T value;
if ( !cache.TryGetValue( key, out value ) )
{
   using ( cache.Lock(key) )
   {
      if (!cache.TryGetValue( key, out value ) )
      {
         // Do the real job here and store the value into variable 'value'.
         cache.Add( key, value );
      }
   }
}

This is a correct way to do tracing. Developers are going to implement this pattern thousands of times, so you write a nice Word document telling how you want the pattern to be implemented. Yeah, a Word document. Do you have a better solution? I'm afraid you don't. Classic code generators won't help. Functional programming (delegates)? It works fairly well for some aspects, but not here: you need to pass method parameters to the pattern. So what's left? Describe the pattern in natural language and trust developers will implement them.

What will happen?

First, some junior developer will look at the code and tell "Hm. Two cache lookups. Kinda useless. One is enough." (that's not a joke -- ask the DNN team about this issue). And your patterns cease to be thread-safe.

As an architect, how do you ensure that the pattern is properly applied? Unit testing? Fair enough, but you will hardly detect threading issues this way. Code review? That's maybe the solution.

Now, what is you decide to change the pattern? For instance, you detect a bug in the cache component and decide to use your own? Are you going to edit thousands of methods? It's not just refactoring: what if the new component has different semantics?

What if you decide that a method is not going to be cached any more? How difficult will it be to remove caching code?

The AOP solution (whatever the framework is) has the following advantages over plain code:

  1. It reduces the number of lines of code.
  2. It reduces the coupling between components, therefore you don't have to change much things when you decide to change the logging component (just update the aspect), therefore it improves the capacity of your source code to cope with new requirements over time.
  3. Because there is less code, the probability of bugs is lower for a given set of features, therefore AOP improves the quality of your code.

So if you put it all together:

Aspects reduce both development costs and maintenance costs of software.

I have a 90 min talk on this topic and you can watch it at http://vimeo.com/2116491.

Again, the architectural advantages of AOP are independent of the framework you choose. The differences between frameworks (also discussed in this video) influence principally the extent to which you can apply AOP to your code, which was not the point of this question.

金兰素衣 2024-08-13 05:54:37

假设您已经有一个设计良好、经过良好测试等的类。您希望轻松地在某些方法上添加一些计时。是的,您可以使用依赖注入,创建一个装饰器类,它代理原始的但每个方法都有时间 - 但即使该类也将是一团重复......

或者您可以添加反射到混合中并使用某种描述的动态代理,它允许您编写一次计时代码,但要求您获得正确的反射代码 - 这并不像想象的那么容易,特别是在涉及泛型的情况下。

...或者您可以向每个想要计时的方法添加一个属性,编写一次计时代码,并将其作为编译后步骤应用。

我知道哪个对我来说更优雅 - 并且在阅读代码时更明显。即使在 DI 不合适的情况下(它确实不适合系统中的每个类)并且其他地方没有其他更改,它也可以应用。

Suppose you already have a class which is well-designed, well-tested etc. You want to easily add some timing on some of the methods. Yes, you could use dependency injection, create a decorator class which proxies to the original but with timing for each method - but even that class is going to be a mess of repetition...

... or you can add reflection to the mix and use a dynamic proxy of some description, which lets you write the timing code once, but requires you to get that reflection code just right -which isn't as easy as it might be, especially if generics are involved.

... or you can add an attribute to each method that you want timed, write the timing code once, and apply it as a post-compile step.

I know which seems more elegant to me - and more obvious when reading the code. It can be applied even in situations where DI isn't appropriate (and it really isn't appropriate for every single class in a system) and with no other changes elsewhere.

鸵鸟症 2024-08-13 05:54:37

AOP (PostSharp) 用于从一个位置将代码附加到应用程序中的各种点,因此您不必将其放置在那里。

您无法实现 PostSharp 使用 Reflection 所做的事情。

我个人认为它在生产系统中没有太大用处,因为大多数事情都可以通过其他更好的方式(日志记录等)来完成。

您可能想查看有关此问题的其他主题:

AOP (PostSharp) is for attaching code to all sorts of points in your application, from one location, so you don't have to place it there.

You cannot achieve what PostSharp can do with Reflection.

I personally don't see a big use for it, in a production system, as most things can be done in other, better, ways (logging, etc).

You may like to review the other threads on this matter:

雨轻弹 2024-08-13 05:54:37

方面拿走了所有的副本和内容。粘贴代码并加快添加新功能的速度。

例如,我最讨厌的就是不得不一遍又一遍地编写同一段代码。 Gael 在他的网站 (www.postsharp.net) 上有一个关于 INotifyPropertyChanged 的​​非常好的示例。

这正是 AOP 的用途。忘记技术细节,只需实现您所要求的即可。

从长远来看,我认为我们都应该告别现在编写软件的方式。编写样板代码并手动迭代是乏味且明显愚蠢的。

未来属于由面向对象框架结合在一起的声明式、函数式风格,以及由方面处理的横切关注点。

我想唯一不会很快得到它的人是那些仍然为代码行付费的人。

Aspects take away all the copy & paste - code and make adding new features faster.

I hate nothing more than, for example, having to write the same piece of code over and over again. Gael has a very nice example regarding INotifyPropertyChanged on his website (www.postsharp.net).

This is exactly what AOP is for. Forget about the technical details, just implement what you are being asked for.

In the long run, I think we all should say goodbye to the way we are writing software now. It's tedious and plainly stupid to write boilerplate code and iterate manually.

The future belongs to declarative, functional style being held together by an object oriented framework - and the cross cutting concerns being handled by aspects.

I guess the only people who will not get it soon are the guys who are still payed for lines of code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文