封装和代表逆转 - 不应该是程序员的责任

时间:2010-09-05 19:18:43

标签: c# design-patterns

1)使用封装的一个原因是,通过隐藏内部实现细节,我们可以在不破坏现有代码的情况下修改此细节 - 这非常有意义

a)但我不明白应该使用封装的论点,以防止用户将对象的内部数据设置为无效或不存在的状态。

如果我编写一个类并将其出售给其他程序员(将这个类实现到他们自己的应用程序中),那么他们是否应该负责以正确的方式访问该对象?毕竟,如果他们没有正确使用该对象,那么它只会是他们的应用程序因此而受损。

为了让其他程序员不将内部数据(无论是意外还是故意)置于不存在的状态,我必须实施封装的类比(不好的)将出售防水电视以防万一买家决定游泳带着电视机。

2)来自

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx

void Foo(Giraffe g) {}
void Bar(Animal a) {}

Action<Mammal> action1 = Foo; // illegal 
Action<Mammal> action2 = Bar; // legal
     

为什么第一次转让非法?   因为action1的调用者可以通过   老虎,但是Foo不能带老虎,   只有长颈鹿!第二个任务   是合法的,因为巴尔可以采取任何   动物。«

我理解作者对Action<Mammal> action1无法接受Foo()的原因的推理。但另一方面,程序员是否有责任不将任何注册方法无法处理的参数传递给委托?

因此,如果某些程序员注册方法Foo,那么他们也会知道:

•不要使用action1参数

以外的任何内容调用Giraffe委托

•不注册具有不同于Foo的签名的方法(除非方法将Mammal派生的类型定义为其参数)

感谢名单

5 个答案:

答案 0 :(得分:3)

你真的在这里问了两个问题,这些问题本来可以更好地分开。

听起来你真的不关心类型安全,或试图引导人们走向成功。

第二个问题很容易以一种非常具体的方式回答:

  

我理解作者对其原因的推理   Action<Mammal> action1不应该   能够接受Foo()。但另一方面   手,不应该是程序员的   不承担责任   委托任何已注册的参数   方法无法处理?

哪位程序员?创建Action<Mammal>实例的人,还是调用它的人?这些可能是两个非常不同的程序员,在完全不同的库中工作。为什么程序员使用 Action<Mammal>必须担心委托可能实际能够处理任何Mammal?类型安全的全部意义在于保证 的内容能够正常工作......你不能创建一个由于类型不匹配而会在执行时发出声明的委托。

如果您在编译时不关心类型安全性,也许您应该尝试使用动态类型语言。

答案 1 :(得分:2)

我认为您的代码应始终是类型安全的。举个例子:A人写了一个R类并将其卖给了B人.A人无法控制,B对该类做了什么。 B可以将R级扩展到另一个S级并将其出售给其他人。没有办法确保非类型安全的A类生成,适用于使用B类S的每个人。

答案 2 :(得分:1)

良好封装的一个优点是“强制”类的用户以正确的方式使用它,而不是以任何其他可能的方式。这样,用户对他必须(重新)使用的代码不那么沮丧。生产力提高(花费更少的时间来弄清楚代码中断的原因,特别是如果源代码不可用)等等。

如果我必须从某人那里购买图书馆,我必须非常小心我必须在每一步使用它,我会认为我浪费了钱。

(我排除了图书馆设计主题,稳定性,可维护性和可扩展性。我很凡人,而且涵盖这些方面的时间有限:)...)

答案 3 :(得分:1)

您的电视机类比暗示您需要预测使用代码的每种可能情况,这是不可能的。相反,想想你正在做的事情,使你的意图显而易见。你知道关于对象用法的这些细节,那么为什么不封装它们而不是把责任放在消费者身上呢?

另一个比喻是,你的门口没有门,并宣称世界有责任不进门;这不会改变开门的力量,激发人们的好奇心。一扇门意味着“你不能进入这所房子”,没有人在运行时走进去,你抛出一个AccessDeniedException。门的意图非常明显。

答案 4 :(得分:1)

我猜它最好用代码表示:所以这里(点在最后一部分的注释中)

免责声明:代码无法编译,不应该

public interface AnimalHandler
{
   Action<Mammal> Feed{get;}
}


public class CreatedInFarAwayFromYou : AnimalHandler
{
  private void Foo(Giraffe g) {}
  public Action<Mammal> Feed
  {
     return Foo;
  }
}

public class MadeByYou
{

  private IEnumerable<Tiger> tigers;
  AnimalHandler handler;
  public void FeedAll()
  {
    foreach(var animal in tigers)
    {
       //You are by your reasoning at fault here. Not the dev that made CreatedInFarAwayFromYou 
       Feed(animal); 
    }
  }
}