退出痛区-使用NDepend进行静态分析

There's a great discussion going on over at Jeff Atwood's blog about Coding Smaller, modularizing properly, and refactoring often. In the comments, Jae wishes that more apps were "modularized properly," and I wholly agree.

Jeff Atwood的博客上正在进行有关Coding Smaller的大量讨论,它们正确地模块化并经常进行重构。 在评论中, Jae希望“适当地模块化”更多应用程序,我完全同意。

He/she says:

他/她说:

I think a lot of projects are dived into too willy-nilly (especially by neophyte/ novice/ hobbyist programmers) with no pre-planning of what the thing should do and how to logically code it. [Jae]

我认为很多项目都被随意地(特别是新手/新手/业余程序员)所淹没,而没有预先计划该做什么以及如何对其进行逻辑编码。 [ Jae ]

I'll use this comment, lifted from Jeff's post, to kick of discussion here. I think that pre-planning is part of it, but there's only so much Big Design Up Front (BDUF) you can do. More and more, as I work on larger and larger projects (and product suites) I realize that refactoring effectively and often is as or more valuable as pre-planning.

我将使用从Jeff的帖子中摘录的此评论在此处进行讨论。 我认为预先计划是其中的一部分,但是您只能做很多大的预先设计( BDUF )。 随着我从事越来越大的项目(和产品套件)的工作越来越多,我意识到有效地进行重构通常与进行预规划一样有价值。

There's lots of create Refactoring Tools out there, certainly Resharper and Refactor Pro leap to mind, that can help you improve your code, and to some extent, your design, with their dozens of refactorings. Both also include some code analysis tools that illustrate hotspots in your files.

那里有很多创建的重构工具, ResharperRefactor Pro一定会引起您的注意,它们可以通过数十种重构帮助您改进代码,并在某种程度上改善您的设计。 两者还包括一些代码分析工具,这些工具可以说明文件中的热点。

<confession>At my company, sometimes I feel less like Chief Architect, and more like Chief Debugger or Chief Code Reader. Sometimes I get to caught up in trying to read code in order to understand the big picture. This is my own failing, as I often try to use a microscope when I need a telescope.</confession>

<confession>在我的公司中,有时我不太喜欢首席架构师,而更喜欢首席调试器或首席代码读取器。 有时我会陷入尝试阅读代码的过程中,以理解全局。 这是我自己的失败,因为当我需要望远镜时,我经常尝试使用显微镜。 </ confession>

While trying to improve design, manage dependencies and coupling within our product suite, I've been leaning more and more on static analysis tools. Some tools are pretty UI-free, like libcheck, a tool for managing the churn of the public "surface area" of a group (or framework) of assemblies.

在尝试改进产品套件中的设计,管理依赖关系和耦合时,我越来越依赖静态分析工具。 一些工具非常不依赖UI,例如libcheck ,这是一个用于管理一组程序集(或框架)的公共“表面积”流失的工具。

There's lots of tools out there for analysis of code, for many languages, all with good science behind them. I remember doing some static analysis on C++ code back in the day, but until .NET's rich meta data, doing this kind of analysis was more a parsing exercise that created Excel spreadsheets of numbers - the data just wasn't very accessible. That, combined with the fact that a lot of .NET developers now never worked in a language before .NET that enabled real solid analysis (VBScript/ASP, VB, and I don't remember a lot of MFC/C++ folks doing analysis like this) means that perhaps a majority of .NET developers haven't been introduced to the power of tools like this.

有许多工具可用于多种语言的代码分析,所有这些工具背后都有很好的科学依据。 我记得我曾经在C ++代码上进行过一些静态分析,但是直到.NET丰富的元数据,进行这种分析才是创建Excel数字电子表格的解析练习-数据不是很容易访问 结合这样的事实,很多.NET开发人员现在从未使用过.NET之前的语言来启用真正的固体分析(VBScript / ASP,VB,而且我不记得很多MFC / C ++的人在做诸如()),这可能意味着尚未向大多数.NET开发人员介绍这种工具的强大功能。

I've been spending time with NDepend more and more lately. I used it a while back when it first came out, but version 2 is out and it's giving me insight into my applications that I haven't had before.

我最近越来越多地与NDepend在一起。 我第一次使用它时就已经使用了它,但是版本2已经发布了,它使我能够深入了解以前从未有过的应用程序。

One of the problems with applications like NDepend and static analysis apps is that they are couched in the complex or "inaccessible" language of Computer Science. Many programmers haven't gone through a formal "CompSci" program and aren't interested in an analysis application with a steep learning curve.

NDepend和静态分析应用程序之类的应用程序存在的问题之一是,它们被计算机科学的复杂或“无法访问”的语言所困扰。 许多程序员都没有经过正式的“ CompSci”程序,并且对学习曲线陡峭的分析应用程序不感兴趣。

Like PowerShell, the first 10 minutes of NDepend is the hardest. It has to click first. There's the whole "what the hell am I looking at" process, often followed by the "screw this" declaration, followed by a quick uninstallation and a sense of "what happened."

PowerShell一样,NDepend的前10分钟是最难的。 它必须先单击。 整个过程是“我到底在看什么”,通常接着是“拧下这个”声明,然后是快速卸载和“发生了什么”。

I'm not going to even attempt to try to improve on, or replace, the good documentation that's already up on the NDepend site. One of the things that NDepend's site has lots of is screencasts, do check them out.

我什至不打算尝试改进或替换NDepend网站上已经提供的优质文档。 屏幕录像是NDepend站点上有很多的东西,请检查一下。

What I'd like to do is try to introduce some of the basics of the kinds of analyses that are possible to the average programmer or the architect who hasn't considered this kind of analysis as an important part of the development process. Additionally, I know that many of you are using FxCop as a code analysis tool. I think that NDepend intersects FxCop in some ways, but presents the data in a totally different way, and allows you to drill in so much more deeply.

我想做的是尝试向尚未将这种分析视为开发过程中重要组成部分的普通程序员或架构师介绍一些分析的基础知识。 另外,我知道你们中的许多人都在使用FxCop作为代码分析工具。 我认为NDepend的相交的FxCop在某些方面,但呈现的数据在一个完全不同的方式,并允许您在这么多深钻。

I can't use Corillian's software for my example here, so I'll use DasBlog, an ASP.NET blogging engine with which I have some association, instead. As seen in the picture below, you startup the NDepend Project application and either point it at your Visual Studio Solution, or just add your assemblies automatically. Then you save the NDepend Project as an XML file, and hit the "Play" button (the green arrow pointing to the right) and NDepend launches it's console app that chews for a while.

在这里,我不能使用Corillian的软件,因此,我将使用DasBlog (一个与我有关联的ASP.NET博客引擎)。 如下图所示,您启动了NDepend Project应用程序并将其指向Visual Studio解决方案,或者只是自动添加了程序集。 然后,将NDepend Project保存为XML文件,然后单击“播放”按钮(指向右侧的绿色箭头),NDepend将启动它的控制台应用程序,并进行一会儿咀嚼。

Next, you can either view an HTML Report - you can run the reports as often as you like and NDepend will keep a history of the reports. Using a static analysis tool can be confusing because it tells you SO much information all at once...trying to sip from the fire hose can be a challenge. 

接下来,您可以查看HTML报告-您可以随意运行报告,NDepend将保留报告的历史记录。 使用静态分析工具可能会造成混乱,因为它会一次告诉您太多信息……尝试从消防水带中饮可能是一个挑战。

Let's start by looking at the dependency diagram that was generated by the report. These are easy to read when there is a small number of assemblies. Those of you who use Reflector Add-Ins will recognize the library style as Peli's - in fact NDepend uses the same graphics library.

让我们从查看报告生成的依赖关系图开始。 当组件数量少时,这些易于阅读。 那些使用Reflector加载项的人会认识到Pel​​i的库样式-实际上NDepend使用相同的图形库。

This graph is really the simplest thing that NDepend can tell you - it just scratches the surface of what this tool can do. We can learn a few important things that we may or may not have known (I didn't really grok at least) about our application. 

该图实际上是NDepend可以告诉您的最简单的事情-它只是在摸索此工具可以做什么的表面。 我们可以学习一些关于我们的应用程序的重要知识,这些知识我们可能知道,也可能不知道(至少我并不是真的不满意)。

Let's explore, for this example, the Custom Macro facilities in DasBlog and if there are design problems.

对于本示例,让我们研究DasBlog中的Custom Macro工具以及是否存在设计问题。

Note the "FooMacroPlugin" - it's the sample plugin that shows how to write DasBlog Custom Macros. Note that it depends on two assemblies. This exposes very clearly a lameness in the DasBlog custom Macro model - largely my fault - in that it requires a reference to two different assemblies, but Web.Core needs Runtime anyway. We can also see later that it uses concrete classes rather than Interfaces, so it's, frankly, a plugin model with problems. If DasBlog had a formal Interface assembly with defined interfaces for interacting with the system we would see different linkage.

注意“ FooMacroPlugin”-它是示例插件,显示了如何编写DasBlog自定义宏。 请注意,它取决于两个程序集。 这暴露了很清楚的DasBlog自定义宏模型跛行-主要是我的错-因为它需要两个不同的程序集的引用,但Web.Core需要运行反正。 稍后我们还可以看到它使用具体的类而不是接口,因此坦率地说,它是一个有问题的插件模型。 如果DasBlog具有正式的Interface程序集,该程序集具有用于与系统交互的已定义接口,则将看到不同的链接。

Now that we know that a custom macro links to to different assemblies, let's take a look at exactly how linked the Macro dll is to the rest of the system. We open up Visual NDepend and are barraged with a LOT of information. This is a crazy busy interface, but in that is a great deal of power. The interface is by and large modeless, and clicking in one area changes values in all the others.

现在我们知道,一个自定义宏链接到不同的组件,让我们来看看宏DLL究竟是如何连接是对系统的其余部分。 我们打开Visual NDepend,并被很多信息所困扰。 这是一个疯狂忙碌的界面,但功能强大。 界面基本上是无模式的,单击一个区域会更改所有其他区域的值。

In this screenshot I've clicked on the intersection in the Dependency Matrix of the FooMacroPlugin and the Web.Core assembly. Note in the lower left corner there's Plain English generated telling me "1 method of the assembly FooMacroPlugin" is using 1 member of Web.Core." 

在此屏幕快照中,我单击了FooMacroPlugin的Dependency Matrix和Web.Core程序集的交集。 请注意,在左下角有一个普通的英语生成,告诉我“组装FooMacroPlugin的一种方法是使用Web.Core的1个成员。”

Looking along the horizontal I can see the number 1, then 2, indicating that Foomacro is using 1 method of the Core and 2 within the RunTime.  (The axis can be opened up by clicking the + sign to see more text) Now I'm getting a better idea of how linked my Macros are with my other two Assemblies.

沿水平方向看,我看到的是数字1,然后是2,表示Foomacro在运行时中使用的是Core的1方法,而在运行时是2。 (可以通过单击+号打开轴,以查看更多文本)现在,我对宏与其他两个程序集的链接有了更好的了解。

I can left-click on the number 2 to see what two methods I'm using in the Runtime. A "boxes and arrows" diagram is generated telling me that my Macros (there are two in FooMacroPlugin) are calling into a property on the an Entry (a blog Entry) and getting the count of an EntryCollection.

我可以在数字2上单击鼠标左键,以查看我在运行系统中使用的是哪种两种方法。 生成一个“框和箭头”图,告诉我,我的宏(FooMacroPlugin中有两个)正在调用Entry(博客Entry)上的属性并获取EntryCollection的计数。

Now I'm starting to see what the impact would be if I were to refactor the Macro plugin mechanism in DasBlog, and I would repeat this analysis on a more complex Custom Macro, probably from the community. Even better, I could drop in EVERY custom Macro I could find to get a really 20,000 foot view - a wide perspective - on how Macros are being used...without reading the code.

现在,我开始了解如果要重构DasBlog中的Macro插件机制会产生什么影响,我将在更复杂的Custom Macro(可能来自社区)上重复此分析。 甚至更好的是,我可以放入每个自定义宏,我可以找到关于使用宏的方式的真正视角为20,000英尺-宽视角-无需阅读代码。

NDepend really shines in it's use of CQL - Code Query Language - an NDepend invention, but public spec. Basically it's SQL for Reflection. I can write queries using this SQL-like syntax to ask questions about assemblies, types, methods, whatever within my solution. Here's some examples:

NDepend的真正亮点在于它使用CQL(代码查询语言),这是NDepend的一项发明,但是是公共规范。 基本上是用于反射SQL 。 我可以使用类似于SQL的语法编写查询,以询问有关程序集,类型,方法等问题的任何信息。 这里有一些例子:

Detect Unused Methods:

检测未使用的方法:

WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE MethodCa == 0 AND !IsPublic AND !IsEntryPoint AND !IsExplicitInterfaceImpl AND !IsClassConstructor AND !IsFinalizer

如果在选择前10个方法中的方法计数> 0且MethodCa == 0且!IsPublic和!IsEntryPoint和!IsExplicitInterfaceImpl和!IsClassConstructor和!IsFinalizer

I ran this CQL query without the "TOP 10" qualifier on some code on one project and found 292 methods that weren't being used.

我在一个项目的某些代码上运行了没有“ TOP 10”限定符的CQL查询,发现了292个未使用的方法。

Detect Overly Complicated Methods

检测过于复杂的方法

WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE
( NbILInstructions > 200 OR
ILCyclomaticComplexity > 50 OR
NbParameters > 5 OR
NbVariables > 8)
AND
// Here is a way to avoid to take account of generated methods.
// Another way would be to use the SELECT METHODS FROM or SELECT METHODS OUT OF facilities.
!( NameLike "InitializeComponent" OR NameLike "Generated")

如果在选择的前10种方法中计数> 0则警告(NbIL指令> 200或ILCyclomaticComplexity> 50或NbParameters> 5或Nb变量> 8) //这是一种避免考虑生成的方法的方法。 //另一种方法是使用设施中的选择方法或设施中的选择方法。 !(NameLike“ InitializeComponent”或NameLike“ Generated”)

Here's a great one. This gives methods that have over 200 instructions or a complexity of over 50 (REALLY complex), or have too many variables or parameters, but includes a trick to exclude both generated code and that crap that the WinForms designer creates in InitializeComponent. 

这是一个很棒的。 这给出的方法具有200多个指令或50多个复杂度(非常复杂),或变量或参数太多,但包括一个技巧,既要排除生成的代码,又要排除WinForms设计器在InitializeComponent中创建的废话。

These are just some of the dozens of rules and examples that it includes. I personally find writing this kind of CQL to be WAY more intuitive and flexible than writing FxCop rules/plugins.

这些只是其中包含的许多规则和示例中的一部分。 我个人觉得编写这种CQL比编写FxCop规则/插件要更加直观和灵活。

If you select any CQL query, it runs instantly as you select it and the Tree Map at the top updates automatically, lighting up the result of the query. The toolbox in the upper left corner shows the result of the query in a table. You can then click on any of the methods and NDepend will open Visual Studio and take you there.

如果选择任何CQL查询,则它会在您选择时立即运行并且顶部的树形图会自动更新,从而点亮查询结果。 左上角的工具箱在表格中显示查询结果。 然后,您可以单击任何一种方法,NDepend将打开Visual Studio并将您带到那里。

The TreeMap in the diagram below acts like a "heat map" showing the hot spots discovered. The blue area on the left side of the map shows the methods that came back as a result of my query. Above the TreeMap is a combo box that indicates what metric the TreeMap is using to determine the size of the squares. In this screen shot I'm using # of IL instructions so the larger the square, the more instructions. I could use lines of code, or cyclomatic complexity, or whatever to find the "fat" parts of my application.

下图中的TreeMap就像一个“热图”,显示发现的热点。 地图左侧的蓝色区域显示了由于查询而返回的方法。 TreeMap上方是一个组合框,用于指示TreeMap使用什么度量来确定正方形大小。 在此屏幕快照中,我使用了#条IL指令,因此正方形越大,指令越多。 我可以使用代码行或循环复杂性,或使用任何查找应用程序“胖”部分的方法。

CQL queries can these can include "WARN" at the beginning so they can be used within a Continuous Integration build. NDepend includes a NAnt Task and an MSBUILD Task, as well as stylesheets and plugins for Cruise Control.NET so I can add constraints to keep our applications in line as changes are checked in. The rules (the CQL) is really easy to read and the editor includes intellisense. 

CQL查询可以在开始时包含“ WARN”,因此可以在持续集成构建中使用它们。 NDepend包括一个NAnt任务和一个MSBUILD任务,以及Cruise Control.NET的样式表和插件,因此我可以添加约束以使我们的应用程序在更改被检入时保持一致。规则(CQL)非常易于阅读和编辑器包括智能感知。

Another nice diagram that is produced by NDepend is the chart of Abstractness vs. Instability. It says a lot, and it's easy to take the data as a value judgement directed towards your code. As if your assembly appears in Red, you're a Bad Person.

NDepend生成的另一个不错的图表是“抽象性与不稳定性”图表。 它说明了很多,并且很容易将数据作为针对代码的价值判断。 就像您的装配体显示为红色一样,您是一个坏人。

The Y-axis indicates how Abstract your assembly is - that is, is it able to be extended without recompile. The X-axis is instability. Now, "instability" carries a value judgement in itself. They aren't saying that stable is good and instable isn't. Stable means that the public surface area of your assemblies "can't" change because there are a lot of assemblies that are dependent on it. An instable assembly has fewer, or no, dependant assemblies upstream. Take a look at Page 8 of this document on Principles of Package Design. A number between 0 and 1 is assigned for each axis based on those equations and your assembly is plotted accordingly.

Y轴表示您的程序集的摘要程度-即它是否可以扩展而无需重新编译。 X轴不稳定。 现在,“不稳定”本身具有价值判断。 他们并不是说稳定是好的,而不稳定不是。 稳定意味着程序集的公共表面积“不能”更改,因为有很多程序集都依赖它。 不稳定的程序集在上游具有较少或没有从属程序集。 请看本文档第8页“包装设计原理” 。 根据这些方程式,为每个轴分配0到1之间的数字,并相应地绘制装配图。

Here's the trick in reading the chart:

这是阅读图表的技巧:

  • If an assembly is very stable (that is, lots of folks depend on it) and it's not extensible (no abstract classes, no virtuals, etc) then you're in the lower-left quadrant of the chart in the well-named Zone of Pain.

    如果一个程序集非常稳定(也就是说,很多人都依赖它)并且它是不可扩展的(没有抽象类,没有虚函数等),那么您将在图表的左下象限中,位于命名区域中的痛苦。

  • If an assembly is very abstract, very extensible, but no one depends on it (it's not really being used) then it moves towards the Zone of Uselessness.

    如果一个程序集非常抽象,非常可扩展,但是没有人依赖它(它并没有真正被使用),那么它就会走向无用区。

Notice how many of the assemblies are in the Zone of Pain? So many, in fact, that you can't even read the words Zone of Pain any more. If you read the assembly names, you'll see that the ones that have made their way over into that portion of the chart are most of the 3rd party assemblies we use. This makes sense because these assemblies are Stable - lots of folks depend on them - and they were designed for some specific function, not for extensibility. Over there are things like the SharpZip lib, the FreeTextBox, and SubText's Akismet library. Is it bad that there are libraries over there? It's less something to panic about then it is something to have increased awareness about. Charts like this can give you a lot of insight into how hard it would be to replace a 3rd party component if you needed, or just to extend one. Here's a screencast on doing an impact analysis on replacing a 3rd party component within NDepend itself.

注意疼痛区中有多少个装配体? 实际上,如此之多,以至于您甚至再也看不到“ Zone of Pain”一词。 如果您阅读了程序集名称,您会发现进入图表该部分的是我们使用的大多数第三方程序集。 这是有道理的,因为这些程序集是稳定的-许多人都依赖它们-并且它们是为某些特定功能而非扩展性而设计的。 上面有诸如SharpZip库,FreeTextBox和SubText的Akismet库之类的东西。 那边有图书馆很不好吗? 与其说是惊慌,不如说是恐慌。 这样的图表可以让您深入了解如果需要或替换一个第三方组件将有多困难。 这是有关在NDepend本身中替换第3方组件进行影响分析截屏视频

We can also note that both the DasBlog Runtime and Web.Core assemblies are edging their way over into the Zone of Pain. That implies that more and more we are depending on those assemblies in unhealthy ways because they aren't well-factored for use by both the application itself and the Plugins. All this equals opportunity to possibly modify our design.

我们还可以注意到,DasBlog Runtime和Web.Core程序集都进入了痛苦区。 这意味着我们越来越多地以不健康的方式依赖那些程序集,因为它们没有被应用程序本身和插件使用的良好构造。 所有这些都等于有机会修改我们的设计。

I will point out, just as a bit of interest, that when Patrick and I ran this same chart on Corillian's Voyager SDK - an SDK that has had more eyes on it, perhaps, than DasBlog - we had only one assembly in the "Zone of Pain" and none in the Zone of Uselessness. We felt OK about that.

我要指出的是,只是有点兴趣,当Patrick和我在Corillian的Voyager SDK(可能比DasBlog关注更多的SDK)上运行相同的图表时,“区域”中只有一个程序集的痛苦”,在“无用之地”中都没有。 我们对此感到满意。

Wrap up

结语

I'm really just touching on the beginnings over what a good static analysis tool can do. But you have to integrate a tool like this not only into your life, but into your build process and your company's software development process. You can't just drop the tool into your word and expect instant results. If you have a fairly mature process - agile or not - and developers who are enthusiastic to this kind of very hard-numbers input, you can begin by integrating this data into your existing code reviews. Start up a working group or study group to talk about what the information means - you don't even need to take action, just talk amongst peers. After your team starts to get a sense of where the metrics are not only taking them, but when to ignore the metrics and why, then you can start adding custom queries and warnings and integrating them into your continuous build.

我真的只是在谈一个好的静态分析工具可以做什么的开端。 但是,您不仅必须将这样的工具集成到您的生活中,而且还必须将其集成到您的构建过程和公司的软件开发过程中。 您不能只是随便说一下该工具并期望立即得到结果。 如果您有一个相当成熟的过程(无论敏捷与否),并且开发人员都热衷于这种非常困难的数字输入,则可以将这些数据集成到现有的代码审查中来开始。 建立一个工作组或研究组来讨论信息的含义-您甚至不需要采取行动,而只是在同龄人之间进行交谈。 在您的团队开始了解度量不仅在哪里使用它们,而且何时忽略度量以及为什么时,您可以开始添加自定义查询和警告并将它们集成到您的连续构建中。

NOTE: One last thing, to be clear. I don't know the guy from NDepend personally. I did chat him on Skype to answer some of my more esoteric questions. I'm not paid for being a reviewer of this product, in this case I'm just a massive FanBoy, much like I am about CodeRush. Neither of them has ever given me a penny.

注意:最后一件事要弄清楚。 我个人不认识NDepend的那个人。 我确实在Skype上与他聊天,回答了我一些更深奥的问题。 我并没有因为担任该产品的审阅者而获得报酬,在这种情况下,我只是一个庞大的FanBoy ,就像我对CodeRush一样。 他们俩都没有给我一分钱。

I'm writing this because I want folks to think about their designs, not just up front, but all through the design...before, during, after. Think about complexity, think about supportability. Realize that your code, your app, your suite is very likely more complex than can be held in your head, and if you take the time - both in your day, and scheduled into your project - to review your design, truly understand what's going on, and use your analysis to make substantive changes to improve the quality of your company's code. Tools like NDepend or one of the many code analysis tools out there like Lattix, can really give you a great deal of insight and perspective on how your applications fit together, if you just take a few hours to get over the initial "hump of difficulty."

我之所以这样写,是因为我希望人们不仅在设计之前,而且在设计之前,之中,之后考虑他们的设计。 考虑复杂性,考虑可支持性。 意识到您的代码,您的应用程序和套件可能比您想像中的要复杂得多,并且如果您花时间-无论是白天还是计划中的时间-查看设计,真正了解正在发生的事情并使用您的分析进行实质性更改以提高公司代码的质量。 如果您仅花费几个小时来克服最初的“难题”,那么像NDepend这样的工具或Lattix这样的众多代码分析工具之一就可以真正为您提供有关应用程序组合方式的大量见解和观点。 。”

Once I realized the depth and breadth of the information I was looking at it, I was like a kid in a candy shop. It was the first time I discovered JetBrains dotTrace profiler - "and now I can see."

当我意识到要查看的信息的深度和广度时,我就像糖果店里的孩子。 这是我第一次发现JetBrains dotTrace分析器-“现在可以看到。

Go check out NDepend. There is a FREE/ACADEMIC version that you can try out and use on your Open Source apps, and the full Pro Version is about US$400 with steep discounts if you buy in quantity. Most companies would only need 1 or 2 copies for a lead "code analyst" I think, so it's reasonably priced. Run it on your companies application and show your boss a few graphs - and explain what he's looking at - and I'm sure he or she will give you the money. ;) I recommend trying to stay out of the Zone of Pain.

去看看NDepend 。 有一个免费/学术版本,您可以在开放源代码应用中试用并使用,完整的Pro版本约为400美元,如果您购买批量购买,将有很大的折扣。 我认为大多数公司只需要1或2份就可以成为主要的“代码分析师”,因此价格合理。 在您的公司应用程序上运行它,并向您的老板展示一些图表-并解释他在看什么-我相信他或她会给您钱。 ;)我建议您尽量避免进入痛苦区域

翻译自: https://www.hanselman.com/blog/exiting-the-zone-of-pain-static-analysis-with-ndepend

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值