在阅读并观察了很多关于SOLID原理之后,我非常希望在我的工作中使用这些原则(主要是C++开发),因为我认为它们是很好的原则,并且它们确实会为我的代码质量,可读性,可测试性带来很多好处. ,重用和可维护性.但我真的很难用'D'(依赖倒置).该主要说明:
A.高级模块不应该依赖于低级模块.两者都应该取决于抽象.
B.抽象不应该依赖于细节.细节应取决于抽象.
让我举例说明:
让我说我写的是以下界面:
class SOLIDInterface {
//usual stuff with constructor, destructor, don't copy etc
public:
virtual void setSomeString(const std::string &someString) = 0;
};
Run Code Online (Sandbox Code Playgroud)
(为了简单起见,请忽略"正确接口"所需的其他内容,例如非虚拟公共,私有虚拟等,这不是问题的一部分.)
注意,setSomeString()采用std :: string.
但是这打破了上面的原则,因为std :: string是一个实现.
Java和C#没有这个问题,因为该语言提供了所有复杂常见类型(如字符串和容器)的接口.
C++不提供这一点.
现在,C++提供了编写这个接口的可能性,我可以编写一个'IString'接口,它将采用任何支持使用类型擦除的std :: string接口的实现
(非常好的文章:http:// www.artima.com/cppsource/type_erasure.html)
所以实现可以使用STL(std :: string)或Qt(QString),或者我自己的字符串实现或其他东西.
喜欢它应该.
但这意味着,如果我(不仅是我而是所有C++开发人员)想要编写遵循SOLID设计原则(包括'D')的C++ API,我将不得不实现大量代码以适应所有常见的非自然类型.
除了在努力方面不现实之外,这个解决方案还有其他一些问题,例如 - 如果STL发生了变化?(对于这个例子)
并且它不是真正的解决方案,因为STL没有实现IString,而IString正在抽象STL,所以即使我是创建这样一个接口,主要问题仍然存在.
(我甚至没有遇到这样的问题,这会增加多态开销,对某些系统而言,取决于大小和硬件要求可能是不可接受的)
所以可能会问:
我在这里遗漏了什么(我猜这是真正的答案,但是什么?),是否有一种方法可以在C++中使用依赖性反转,而无需以实际方式为常见类型编写全新的接口层- 或者我们注定要编写始终依赖于某些实现的API?
谢谢你的时间!
编辑:从我到目前为止收到的前几条评论中我认为需要澄清:std :: string的选择只是一个例子.它可能是QString - 我只是采用STL,因为它是标准.它的字符串类型甚至不重要,它可以是任何常见类型.
EDIT2:我选择Corristo的答案不是因为他明确地回答了我的问题,而是因为广泛的帖子(加上其他答案)让我能够隐含地从中提取答案,意识到讨论倾向于偏离实际问题是:当你使用基本的复杂类型(如字符串和容器)以及任何有意义的STL时,你能用C++实现依赖性反转吗?(最后一部分是问题的一个非常重要的元素).也许我应该明确地指出我在运行时多态性之后没有编译时间.明确的答案是否定的,这是不可能的.如果STL将抽象接口暴露给它们的实现(如果确实存在阻止STL实现从这些接口派生的原因(比如性能)),那么它可能是可能的,那么它仍然可以简单地维护这些抽象接口以匹配实现).
对于我完全可以控制的类型,是的,实现DIP没有技术问题.但很可能任何这样的接口(我自己的)仍将使用字符串或容器,迫使它使用STL实现或其他.以下所有建议的解决方案要么在运行时不是多态的,要么/并且在界面周围强制安静一些编码 - 当你认为你必须为所有这些常见类型执行此操作时,实际情况就不存在了.
如果你认为你知道的更好,并且你说我可以拥有上面描述的内容,那么只需发布证明它的代码即可.我赌你!:-)
我面临以下问题:
我正在尝试配置 GitLab CI pipline(shell)。
我的存储库包含两个子模块。
这两个子模块与包含它们的超级存储库位于同一台 GitLab 服务器上。
该克隆是 SSH 克隆,我已在本地配置了密钥,并将密钥添加到了 GitLab。
在安装运行程序的计算机上,我可以毫无问题地克隆所有内容,包括子模块。
但是,当运行程序尝试克隆时,它会返回“主机密钥验证失败”,但仅限于子模块。
我尝试使用其自己的用户和我的用户配置跑步者:
sudo gitlab-runner install --user=<user>
Run Code Online (Sandbox Code Playgroud)
没有效果。
最让我困惑的是,错误仅针对子模块,即使它们与包含它们的超级存储库位于同一服务器上,并且超级存储库可以毫无问题地克隆(当我关闭子模块递归变量时) yml 文件):
GIT_SUBMODULE_STRATEGY: recursive
Run Code Online (Sandbox Code Playgroud)
但当然我没有子模块。
如果您有任何有关检查或尝试内容的建议,我将不胜感激!