假设我们在包A中有A类,在包B中有B类.如果类A的对象引用了类B,那么这两个类被认为在它们之间具有耦合.
为了解决耦合问题,建议在包A中定义一个接口,该接口由包B中的类实现.然后,类A的对象可以引用包A中的接口.这通常是"依赖倒置"的一个例子.
这是"在接口级别解耦两个类"的示例.如果是,那么它如何消除类之间的耦合并在两个类耦合时保留相同的功能?
我有一个模型,需要从辅助源加载外部数据.我的模型可以从(可交换)中获取数据的许多Web服务,但我不想创建难以更改服务的代码(成本因变量和固定使用而显着不同而且可能会发生变化将被要求).
我想创建一个驱动程序来执行交互(如果服务需要切换,则创建更多自定义驱动程序).不幸的是,由于驱动程序和模型的紧密耦合,将代码提取到插件或gem中是没有意义的.我已将所有代码解压缩到一个模块中(参见示例),并且当前在我的模型上面声明了代码.
module Synchronize
def refresh
self.attributes = ...
self.save
end
end
class Data < ActiveRecord::Base
include Synchronize
end
Run Code Online (Sandbox Code Playgroud)
Rails(3.0.0)是否有一个约定存储与模型紧密耦合的模块?我应该使用插件来执行此操作吗?这与'app/helpers'目录有关吗?如果没有,最适合存储代码的地方在哪里?谢谢!
我FOO()在类A中有一个方法,它从类的数据成员中获取其参数输入B(假设它们是两个浮点数和一个int).我理解这一点的方式,通常更好地实现这一点,如:
A->FOO1(B, other_data_x)
Run Code Online (Sandbox Code Playgroud)
而不是
A->FOO2(B.member1, B.member2, B.member3, other_data_x).
Run Code Online (Sandbox Code Playgroud)
我收集了一个,但不是唯一的优点是它留下了B访问哪些成员的细节,FOO1()因此有助于隐藏实现细节.
但我想知道的是,这是否真正引入了类A和之间的额外耦合B.类A在前者的情况下必须知道类B存在(通过类似include class_B_header.h),如果成员B变化或移动到不同的类或类B被完全消除,你需要修改A和FOO1()相应.相比之下,在后一种方法中,FOO2()并不关心类是否B存在,实际上它关心的是它提供了两个浮点数(在这种情况下由B.member1和组成B.member2)和一个int(B.member3).可以肯定的是,在后一个示例中也存在耦合,但是这种耦合在任何地方都可以处理FOO2()被调用或任何类正在调用FOO2(),而不是在A或的定义B.
我想这个问题的第二部分是,是否有解耦的好办法A,并B进一步当我们要实现类似的解决方案FOO1()?
让我们想象一下,我们的应用程序需要从关系数据库到另一个关系数据库的ETL(提取,转换,加载)数据.最简单(和大多数性能,恕我直言)的方式是在数据库之间建立链接并编写简单的存储过程.在这种情况下,我们使用最少的技术和组件,所有功能都是"开箱即用".
但这是SOA(面向服务的架构)的良好实践吗?紧耦合怎么样?我们是否永远将数据库强烈地相互耦合?
还有另一种方法:我们在每一侧构建2个Java应用程序,并通过SOAP Web服务进行通信.这更加SOA友好!但性能下降和额外的失败点值得吗?
在这种情况下,最佳做法是什么?ETL如何适应SOA?
我们正在制作一个相当大的Swing应用程序,它必须实现MVC模式.该应用程序目前看起来像这样:
有很多观点.它们以分层方式创建,其中一个主视图包含(并创建)多个视图,这些视图都包含它们自己的子视图集等.每个视图通过调用模型从模型独立地从其他视图中检索信息必要时的静态方法.
还有不少控制器都完全相互分离.每个控制器都属于一个视图.每个视图都创建自己的控制器,并将控制器添加为用户输入的侦听器.控制器从视图接收事件,然后通过模型静态方法修改模型.当视图调度不影响模型但仅影响视图的事件时,视图会自行处理这些事件 - 而不通知控制器事件.也就是说,控制器完全不知道视图,控制器的目的只是处理模型的操作.| 编辑:控制器目前是他们观点的附件; 它们只包含事件处理的逻辑.也就是说,控制器本身不是组件,并且不包含组件.它们的实现方式与以下示例相同:MVC示例 |
应用程序中的模型非常被动,甚至没有侦听器(它代表数据库).它从控制器接收更新.
在此示例中,视图拥有控制器.如果控制器拥有并创建视图,并且如果让视图不知道控制器而不是相反的情况,那么在一般情况下会更好吗?在那种情况下,为什么?这将如何设计?如果没有,是否有更好的设计,控制器仍然没有意识到这些观点?或者,也许是他们中最好的设计?
编辑:
"视图负责建立这种相互通信......"似乎表明视图创建了控制器,或者至少具有对控制器的初始引用,反之亦然.
所以这至少是一种可行的方法(它是一种有效的MVC模式),但主要问题仍然存在; 哪个更好,最好的设计会是怎样的?特别是在处理与其各自视图密切相关的许多控制器时?
通过设计,大多数jquery代码导致很多紧耦合,例如选择器假设html的特定结构
var mySubnav = $("#navigation a.sub-menu");
Run Code Online (Sandbox Code Playgroud)
如果相应的html发生变化,无论出于何种原因,
<a class="subMenu" .... </a>
Run Code Online (Sandbox Code Playgroud)
功能被打破了.
data-submenu="true",在html var mySubnav = $("[data-submenu]");上添加并在js端使用.$("a.sub-menu').也可以看看REST API体系结构的目标之一是将客户端和服务器分离.
我在规划REST API时遇到的一个问题是:"客户端如何知道什么是POST方法的有效负载?"
不知何故,API需要向UI传达给定资源的POST方法的有效负载.否则,我们回到依赖于使用API所需的带外知识,我们再次紧密耦合.
所以我有这样的想法,即资源上的GET的API响应将提供用于为该资源上的POST方法构造有效负载的规范.这将包括字段名称,数据类型,最大长度等.
处理这个问题的正确方法是什么?大多数人只是依赖于带外信息吗?在这个问题上,人们在现实世界中做了什么?
编辑
我想出的解决这个问题的方法如下面的序列图所示:

客户端和api服务是分开的.客户知道:
这是发生的事情:
没有魔法/元资源,不需要使用元数据的方法.一切都由API提供.
思考?
在54:53分钟的谈话中,Rich Hickey正在谈论使用队列作为解耦依赖程序部分的手段.你能给我一个例子,说明如何将下面的Java伪代码分离出来,以便改进它的设计和/或灵活性:
// Warning: Java-pseudo-code ahead
class Job {
public void doRun(A a) {
saveObjectToDatabase(a);
B b = computeB(a);
saveObjectToDatabase(b);
C c = computeC(b);
logToFile(c);
}
}
Run Code Online (Sandbox Code Playgroud)
saveObjectToDatabase并且saveObjectToDatabase可以看作具有副作用的方法,而computeB's和computeC's输出仅依赖于a.
我知道这个问题相当模糊/广泛.我想了解如何利用排队机制,而不会使我的程序大规模复杂化,并仍然确保它以正确的顺序做正确的事情.任何指向正确方向的人都会受到赞赏.
我在下面的代码中简化并重现了我的问题.我收到的错误是:参数1:无法从'System.Collections.ObjectModel.Collection'转换为'System.Collections.ObjectModel.Collection
导致这个问题的设计决策的一些背景:我已经创建了一个用于处理"IFruit"的Web服务,但由于我理解它们的SOAP和端点绑定的性质,我已经创建了具有IFruit的显式实现的方法.在业务层,为每个特定的水果实现创建一个单独的方法首先会导致大量重复的代码,其次紧密地结合业务和服务层,以便稍后在Web服务中接受新的IFruit类型也需要更改我的代码在业务层(添加冗余代码的另一个副本).这个设计是我过去使用Java成功实现的设计,但C#接口似乎只是与我不同.请指教.
public interface IFruit{
public string TakeBite();
}
public Apple : IFruit{
public string TakeBite(){
return "tasty bite of apple";
}
}
public void EatFruit(Collection<IFruit> fruits){
foreach(var fruit in fruits){
Console.WriteLine(fruit.TakeBite());
}
}
public void EatApples(Collection<Apple> apples){
this.EatFruit(apples);
}
Run Code Online (Sandbox Code Playgroud) 我试图了解真正定义紧耦合的原因.我已经阅读了很多关于这个主题的帖子,但有一件事仍然不适合我.
我理解应该使用接口而不是具体实现将类注入其他类.我也理解,如果一个类遵循一个接口,那么任何使用注入接口的类都可以调用接口中定义的公共函数并期望类似的功能.
interface iFormatter()
{
public function format(array $order): array
}
public class OrderFormatter implements iFormatter
{
public function format(array $order): array
{
// ...
return $formattedArray;
}
}
public class OrderGenerator implements iGenerator
{
private $formatter;
public function __construct(iFormatter $formatter)
{
$this->formatter = $formatter;
}
public function generate()
{
// ...
return $this->formatter->format($order);
}
}
Run Code Online (Sandbox Code Playgroud)
所以我认为在只有格式化器改变的情况下,这将被定义为松散耦合;
$example = new OrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new OrderGenerator(new VanOrderFormatter);
$example->generate();
Run Code Online (Sandbox Code Playgroud)
我不太清楚的是,当你把责任从彼此中抽离出来时,这些课程仍然紧密相连.就像是
$example = …Run Code Online (Sandbox Code Playgroud) decoupling ×10
java ×3
oop ×2
architecture ×1
c# ×1
c++ ×1
coding-style ×1
collections ×1
coupling ×1
database ×1
etl ×1
interface ×1
javascript ×1
jobs ×1
jquery ×1
php ×1
post ×1
rest ×1
ruby ×1
soa ×1
spring ×1
swing ×1