我知道日志记录是AOP的主要用例.此外,日志记录包装器也可以作为您希望使用DI的示例,以便类不与特定的日志记录实现相结合.但是,有些人认为日志包装器是一种反模式.首先,这样的视图是因为在大多数情况下,包装器往往是简单的并且删除了特定于日志框架的许多特征.如果您实现这些特定功能,为什么不直接使用框架.
我知道Common.Logging外观试图为您提取log4Net,EntLib,NLog的大量功能.但是,即使在这里,我们仍然依赖于Common.Logging.不是关于接口等的代码/单元测试方式,但如果项目死亡(自上次发布以来已超过一年)或者您希望后者切换到不支持的记录器,则可能导致问题.
也就是说,如果通过AOP实现日志记录,是否有必要使用DI作为日志记录依赖项(即为什么不直接引用说NLog)?是的,AOP部分代码将紧密耦合,但是想要进行单元测试的类的逻辑缺乏记录依赖性(至少在编织发生之前).在这一点上,我有点迷失(我还没有尝试过AOP).编织后,没有使用DI作为AOP代码会导致单元测试被测方法的问题吗?或者可以在不编织AOP代码的情况下测试一个单元吗?
除非日志记录是软件用户的要求,否则我不确定测试日志是否与模拟有关是多么有用.我认为被测方法的业务逻辑是大多数人对测试感兴趣的东西.最后,如果想要使用TDD/BDD,是否必须在AOP代码中使用DI来记录日志依赖?或者只是不测试驱动 AOP方面的东西?
正如您所看到的,我正在尝试了解最实用的方法是开发一个应用程序,该应用程序将AOP用于横切关注点,DI用于设计/测试.由于AOP相对较新,而日志记录是最常见的例子,推荐的方法是什么?
迈克尔·费瑟斯(Michael Feathers)在第13-14页的"有效使用遗产代码"中提到:
运行1/10秒的单元测试是一个缓慢的单元测试...如果[单元测试]运行速度不快,则它们不是单元测试.
我可以理解为什么如果一个人有30,000次测试,每秒1/10太慢,因为它需要将近一个小时才能运行.但是,这是否意味着1/11秒更好?不,不是真的(因为它只快5分钟).因此,一个严格的快速规则可能并不完美.
因此,当考虑单位测试的速度有多慢时,或许我应该重新解释这个问题.开发人员等待单元测试套件完成需要多长时间?
举一个测试速度的例子.看看几个MSTest单元测试持续时间:
0.2637638 seconds
0.0589954
0.0272193
0.0209824
0.0199389
0.0088322
0.0033815
0.0028137
0.0027601
0.0008775
0.0008171
0.0007351
0.0007147
0.0005898
0.0004937
0.0004624
0.00045
0.0004397
0.0004385
0.0004376
0.0003329
Run Code Online (Sandbox Code Playgroud)
所有21个单元测试的平均值为0.019785秒.请注意,最慢的测试是由于它使用Microsoft Moles来模拟/隔离文件系统.
因此,使用此示例,如果我的单元测试套件增长到10,000个测试,则运行可能需要3分钟.
在Microsoft .NET Architecting Applications for the Enterprise一书中的第374页上,有一个关于表示层模式演变及其对平台影响的图表(图7-14).
除了展示从最初的MVC模式到更现代的变体的演变之外,该图表还显示以下现代模式可以应用于以下技术:
注意:最近没有出现在另一个最近感兴趣的模式是Presenter First(MVP),它被设想为更加适应TDD.
根据我的理解,如果使用WPF开发,那么MVVM模式是事实上的选择(类似于Model2用于Web开发).也就是说,似乎没有什么能阻止人们在WPF应用程序中使用Passive View,Supervising Controller或Presenter First.这种方法会导致应用程序无法真正关心前端是WPF,WinForms还是Web.看来这些MVP变体允许更大的灵活性.
但是,针对UI平台无关的灵活性(可能不需要)的目的是使WPF开发变得更加困难并且失去WPF提供的部分功能/功能吗?这么多,成本超过了收益?
换句话说,MVVM是如此之大,以至于人们不应该考虑WPF应用程序中的其他替代方案?
Noob问题,使用Win7 64位,Clojure 1.2.0,Java 1.6.0_22
当我从命令行启动clojure时,pprint函数很容易获得.
user=> pprint
#<pprint$pprint clojure.pprint$pprint@16dfa45>
user=> (pprint "hi")
"hi"
nil
user=>
Run Code Online (Sandbox Code Playgroud)
但是当我尝试从文件中使用pprint时,我收到错误.无论是否使用命名空间(ns ...:require ...)都会发生这种情况,如pprint文档中所示
clj文件如下:
(ns whatevah
(:require clojure.pprint))
(pprint "hi")
Run Code Online (Sandbox Code Playgroud)
错误如下:
C:\Users\mischw\code\Clojure>java -cp ";c:\users\mischw\code\clojure\classes\*;c:\Program Files (x86)\Java\SWT;c:\users\mischw\code\clojure\classes\bookcode\*" clojure.main swinglearn.clj
Exception in thread "main" java.lang.Exception: Unable to resolve symbol: pprint in this context (swinglearn.clj:14)
... 21 more
Output completed (0 sec consumed) - Normal Termination
Run Code Online (Sandbox Code Playgroud)
我不明白这里发生了什么的一般想法.为什么一个工作而另一个工作?这与名称空间有关吗?类路径?其他一些简单的修复?显然noob问题,但我发现这发生在一堆例子中......即使导入/使用/ require/include它们似乎很简单,我也无法运行它们.
我是设计模式的新手,所以我有一个关于Builder模式的问题.今天我听说Builder Pattern与StringBuilder
Java中的类C#不同.我知道Builder Pattern的主要目标是在几个步骤中创建复杂的对象......我认为这是StringBuilder
用它的方法制作的Append
...所以我很难找到差异......
你能告诉我是否真的有什么不同,如果是......它是什么:)?
编辑:忘了包含我的环境信息... Win7x64,RubyInstaller Ruby v1.9.1-p378
编辑2:刚刚更新到v1.9.1,补丁429,仍然得到同样的错误.
编辑3:在Ruby v1.8.7,补丁249中运行相同的代码,工作正常.所以它的v1.9.1明显打破了它.
我是新手使用ERB,我能找到的样品......嗯......不太有帮助......和ERB玩了大约一个小时,我得到了一些基本的例子(最后),但我有不明白为什么这不起作用......
require 'ostruct'
require 'erb'
data = {:bar => "bar"}
vars = OpenStruct.new(data)
template = "foo "
erb = ERB.new(template)
vars_binding = vars.send(:binding)
puts erb.result(vars_binding)
Run Code Online (Sandbox Code Playgroud)
此代码生成以下错误:
irb(main):007:0> puts erb.result(vars_binding) NameError: undefined local variable or method `bar' for main:Object from (erb):1 from C:/Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb:753:in `eval' from C:/Ruby/v1.9.1/lib/ruby/1.9.1/erb.rb:753:in `result' from (irb):7 from C:/Ruby/v1.9.1/bin/irb:12:in `'
为什么要看main:Object
绑定?我告诉它通过传入来使用OpenStruct的绑定vars_binding
有人可以告诉我为什么它不起作用,并帮助我让它工作?
如何创建一个流畅的界面而不是更传统的方法?这是一种传统的方法:
接口:
interface IXmlDocumentFactory<T>
{
XmlDocument CreateXml() //serializes just the data
XmlDocument CreateXml(XmlSchema schema) //serializes data and includes schema
}
interface IXmlSchemaFactory<T>
{
XmlSchema CreateXmlSchema() //generates schema dynamically from type
}
Run Code Online (Sandbox Code Playgroud)
用法:
var xmlDocFactory = new XmlDocumentFactory<Foo>(foo);
var xmlDocument = xmlDocFactory.CreateXml();
//or...
var xmlDocFactory = new XmlDocumentFactory<Foo>(foo);
var xmlSchemaFactory = new XmlSchemaFactory<Foo>();
var xmlDocument = xmlDocFactory.CreateXml(xmlSchemaFactory.CreateXmlSchema());
Run Code Online (Sandbox Code Playgroud)
我想能够说:
var xmlDocument = new XmlDocumentFactory<Foo>(foo).CreateXml().IncludeSchema();
//or...
var xmlDocument = new XmlDocumentFacotry<Foo>(foo).CreateXml();
Run Code Online (Sandbox Code Playgroud)
最后,这种情况是否适合流畅的界面?或者更传统的方法会更有意义吗?
在Xcode 3.2.5中,我使用"Build and Archive"创建一个没有任何问题的IPA文件.我怎么能在Xcode 4中做到这一点?我想我必须使用"Product - > Archive",但我在three20框架中收到了100多条错误消息.大多数是"没有这样的文件或目录".("产品 - >构建 - >构建存档"工作.没有错误.)
例如,这是第一条错误消息:
../scripts/Protect.command: line 23: cd: /Users/[USERNAME]/Library/Developer/Xcode/DerivedData/[PROJECTNAME]-blabla/ArchiveIntermediates/[PROJECTNAME]/BuildProductsPath/Release-iphoneos/../three20/Three20Core: No such file or directory
Run Code Online (Sandbox Code Playgroud)
该路径"/[PROJECTNAME]/BuildProductsPath/three20/"
确实不存在,但此路径存在:"/[PROJECTNAME]/three20/"
我能做什么?
在.NET中,TypeMock Isolator和Microsoft Moles允许隔离任何类,属性或方法 - 无论是密封的,静态的,受保护的还是非虚拟的.所以在Moq或Rhino Mocks中不可能嘲笑,现在不再是这样了.
我总是对使用接口只是为了能够允许模拟的想法感到厌恶,否则只有具体的类存在.在这个视图中我并不孤单(见这里,这里和这里).在后者中暗示"现代"模拟框架不再需要用于测试或依赖注入的接口.
然而,虽然我不能说TypeMock Isolator,但我可以说在Microsoft Moles中使用Mocks非常慢.在单元测试中使用如下代码会使测试速度太慢而无法经常使用:
MFile.ReadAllLinesString = (s) => csvDataCorrectlyFormatted;
MDirectoryInfo.AllInstances.GetFilesString = (di,fi) => fileInfoArray;
MFileInfo.AllInstances.NameGet = (fi) => "Doesn't Matter";
Run Code Online (Sandbox Code Playgroud)
我敢肯定,如果正在测试的方法被编程到接口或抽象基类(以便文件系统代码可以在各种包装中抽象出来),那么使用像Moq这样的框架来进行存根或模拟最终会更快.但是,我们又回到了基本上增加单元测试能力的生产代码复杂性的情况.
我倾向于认为Isolator和Moles只有在不能用传统的模拟框架模拟时才能使用.然而,为了测试,我仍然为添加生产代码复杂性这一概念而苦苦挣扎.
我很好奇社区其他人的想法.
更新10/06/10:通过说我为了测试而增加了生产代码复杂性的概念,我指的是在不需要时添加接口(或抽象类),例如,当使具体类非密封时,虚拟方法会做.后者仍然允许接缝进行测试.即使后来发现需要为多个实现使用接口,他们也不能从类中提取它吗?但除非出现这种需要,否则为什么不跟随YAGNI.
我全都采用SOLID原则,它们使程序的体系结构更易于维护.我不认为在每种情况下都需要虔诚地遵循这些原则.我认为咒语"它总是取决于",多次发挥作用.否则,即使只有一个实现,也会留下具有接口或抽象基类的每个具体类型.
最后,我不是说,因为Isolator和Moles允许人们在基于动态代理的框架中克服隔离限制,人们不应该将架构设计为可维护的.在许多情况下,SOLID原则是最好的,因此不需要隔离器或摩尔.这是接口仅用于我正在质疑的测试的情况.我也提出了关于速度的另一个观点.如果选择使用隔离器和摩尔,它似乎会带来速度惩罚.所以我当然不认为他们使基于动态代理的框架过时了.
我写了一个Thread.descendent类,并在execute方法中我放了一个无限循环来监听一个com事件,被认为是一个糟糕的线程练习使用无限循环来做到这一点?应用程序工作正常,不冻结,总是响应,我只是回答因为我想使用最好的方法来线程化.
procedure TMyThread.Execute;
begin
while True and not Terminated do
begin
AResult:= FListener.GetResult(Param1,Param2,5000);
if not VarIsNull(AResult) then
Synchronize(Process);
end;
end;
Run Code Online (Sandbox Code Playgroud)