我正在阅读维基百科对依赖性倒置原则的定义,它使用两个术语高级模块和低级模块,我无法弄清楚.
他们是什么,依赖倒置原则与他们有什么关系?
language-agnostic dependencies module inversion-of-control dependency-inversion
我们知道memento模式没有违反封装,捕获和外化对象的内部状态,并且可以在不知道原始状态的情况下稍后进行回收.
我的问题在这里java.io.Serializable是如何进入这种模式的,因为当我们序列化任何私有变量并将对象状态同时写入文件时,私有变量的值对世界开放并且封装似乎在这里失败.
从Ruby 1.9.3开始,我们可以创建私有常量:
module M
class C; end
private_constant :C
end
Run Code Online (Sandbox Code Playgroud)
关于它的作用是否有良好的文档?有没有办法获得类似于调用的私有常量的名称constants
我有一个这样的测试用例:
describe WorkCardsController do
it "something" do
work_card = instance_double(WorkCard, {:started?=>true} )
#some more code
end
end
Run Code Online (Sandbox Code Playgroud)
当我运行RSpec时,我收到一个错误:
undefined method 'instance_double' for #<Rspec::Core::ExampleGroup::Nested_1::Nested_8::Nested_3:0x007f0788b98778>
Run Code Online (Sandbox Code Playgroud)
根据http://rubydoc.info/github/rspec/rspec-mocks/RSpec/Mocks/ExampleMethods,此方法存在.所以我尝试通过以下方式直接访问它:
describe WorkCardsController do
it "something" do
work_card = RSpec::Mocks::ExampleMethods::instance_double(WorkCard, {:started?=>true} )
#some more code
end
end
Run Code Online (Sandbox Code Playgroud)
然后我得到了一个非常令人惊讶的错误:
undefined method 'instance_double' for Rspec::Mocks::ExampleMEthods:Module
Run Code Online (Sandbox Code Playgroud)
这与我上面链接的文档相反.
我错过了什么?
我的班级有依赖,我在单元测试中嘲笑.我在一个对我没有多大意义的地方得到了一个空引用异常.
我刚才意识到这是因为我没有设置我的模拟依赖.此依赖项已经过测试,但它不会连接到文件系统或数据源之类的任何内容.
我只想在这个新类中测试我的新代码,但我想在这种情况下最好不要去模拟.
这个结论是否正确?
如果我想使用DIP开发一个假设的模块化C++项目.由于模块化,我选择在一个库中完全实现一个特定功能A.另一个库B(或两个或三个......)正在使用此功能(例如,日志记录机制):
class ILogger
{
virtual void log(const std::string& s) = 0;
};
Run Code Online (Sandbox Code Playgroud)
我应该把这个界面放在哪里?一些博主似乎建议,因为界面属于其用户(因为DIP),你应该将界面放在用户端(或这里).这也可以提高可测试性,因为您不需要任何实现链接到测试.
这意味着,库A本身不会编译,因为它缺少接口.这也意味着,如果库C也将使用日志记录工具,它还会引入一个接口ILogger,这将打破ODR?这可以通过引入仅包含接口的额外包层库来解决.但主要问题仍然存在:
在哪里放置界面?我阅读了关于DIP 的原始论文,但我不同意解释,我不应该将接口放入库中.我觉得这篇论文是作为如何思考开发的指导原则(因为"用户正在定义界面而不是实现者").它是否正确?你如何使用依赖倒置原则?
想象一下以下人为的例子:
public class LoginController {
private readonly IValidate _validator;
private readonly IAuthenticate _authenticator;
public LoginController(IValidate validator, IAuthenticate authenticator) {
_validator = validator;
_authenticator = authenticator;
}
public HttpStatusCode Login(LoginRequest request) {
if (!_validator.IsValid(request)) {
return HttpStatusCode.BadRequest;
}
if (!_authenticator.IsAuthenticated(request.Email, request.Password)) {
return HttpStatusCode.Unauthorized;
}
return HttpStatusCode.OK;
}
}
public class LoginRequest {
public string Email {get; set;}
public string Password {get; set;}
}
public interface IValidate {
bool IsValid(LoginRequest request);
}
public interface IAuthenticate {
bool IsAuthenticated(string email, string password); …Run Code Online (Sandbox Code Playgroud) 考虑以下访问者的简单语言解释器.
public interface Visitor{
void visit( VarStat vs);
void visit( Ident i);
void visit( IntLiteral a);
void visit( Sum s);
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,我添加了一些代码,提供了必要的实现细节(您可以跳过并直接阅读问题).
public interface Visitable{
void accept( Visitor v);
}
public class VarStat implements Visitable{
Ident i;
Exp e;
public VarStat(Ident id, Exp ex){
i = id;
e = ex;
}
public Ident getIdent() { return i; }
public Exp getExp() { return e; }
@Override
public void accept( Visitor v){
v.visit( this);
}
}
public interface Exp extends Visitable{ …Run Code Online (Sandbox Code Playgroud) 在使用稳定抽象原理(SAP)阅读此维基之后,我想知道是否有人知道取决于抽象而不是混凝土的任何缺点(我认为,这超过了优势).
SAP声明包越稳定,它应该越抽象.这意味着如果包装不太稳定(更有可能改变),那么它应该更具体.我真的不明白为什么会出现这种情况.当然,在所有情况下,无论稳定性如何,我们都应该依赖于抽象并隐藏具体实现?
我的IComposerc#项目中有一个界面:
public interface IComposer
{
string GenerateSnippet(CodeTree tree);
}
Run Code Online (Sandbox Code Playgroud)
CodeTree是一个基类,包含一个List<CodeTree>继承自的类CodeTree.例如:
public class VariablesDecleration : CodeTree
{
//Impl
}
public class LoopsDecleration : CodeTree
{
//Impl
}
Run Code Online (Sandbox Code Playgroud)
我可以有几个实现的类,IComposer每个我都有GenerateSnippet循环List<CodeTree>,基本上做:
foreach (CodeTree code in tree.Codes)
{
if (code.GetType() == typeof(VariablesDecleration))
{
VariablesDecleration codeVariablesDecleration = (VariablesDecleration) code;
// do class related stuff that has to do with VariablesDecleration
}
else if (code.GetType() == typeof(LoopsDecleration))
{
LoopsDecleration codeLoopsDecleration = (LoopsDecleration) code;
// …Run Code Online (Sandbox Code Playgroud) unit-testing ×3
dependencies ×2
java ×2
ruby ×2
visitor ×2
architecture ×1
bdd ×1
c# ×1
c++ ×1
code-design ×1
constants ×1
deployment ×1
memento ×1
mocking ×1
modularity ×1
module ×1
oop ×1
private ×1
rspec ×1
rspec-mocks ×1
ruby-1.9.3 ×1
serializable ×1
tdd ×1
testing ×1