首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找OO输入,这些代码中的任何一个是好的OO还是我都做错了?

寻找OO输入,这些代码中的任何一个是好的OO还是我都做错了?
EN

Code Review用户
提问于 2011-12-31 08:48:26
回答 4查看 218关注 0票数 2

对于股票系统,我有两种方法来处理这些代码,看看它们是否正确,如果正确,哪一种比另一种更好。

代码语言:javascript
复制
public interface Order {
    public void processed(AllocationResponse response);
}

我脑子里有两个解决方案

代码语言:javascript
复制
public class Warehouse {

    public void allocate(Order order){
        AllocationResponse response = calculateAllocation(order.getQuantity());
        order.processed(response)
    }

    private AllocationResponse calculateAllocation(int quantity){
    // code
    }

}

public class AllocationResponse {

    int quantityAllocated = 0;
    int quantityBackOrdered = 0;
}

Order order = // get order
new Warehouse().allocate(order)

代码语言:javascript
复制
public class Warehouse {

    public AllocationResponse allocate(int quantity){
        return calculateAllocation(quantity);
    }

    private AllocationResponse calculateAllocation(int quantity){
        // code to generate response object
    }

}

Order order = // get order
AllocationResponse response = new Warehouse().allocate(order.getQuantity());
order.processed(response)
EN

回答 4

Code Review用户

发布于 2012-01-01 02:39:55

对部分问题的部分回答(不偏袒C#、Java或量子力学):

不变量:

  • 一些未命名的调用者需要有效地调用: order.processed(warehouse.calculateAllocation(order.getQuantity()));,其中calculateAllocation是私有的(因此,可能对调用者是不可见的)。

getQuantity()因此,让我们想象一下Order接口中的int方法。

  • 仓库实现依赖于AllocationResponse。
  • 未命名的调用者必须尽可能少地依赖Order和Warehouse的存在,并且需要某种方式来调用calculateAllocation“用于订单”。

备选案文的比较:

备选方案1的优点:

  • 除了上述最小值之外,未命名的调用方没有其他依赖项。

备选案文1的缺点:

  • 仓库现在取决于订单,Order.getQuantity和Order.processed。

备选方案2的优点:

  • 仓库没有进一步的依赖关系。

备选案文2的缺点:

  • calculateAllocation现在完全暴露于滥用的调用(通过分配),没有太多的订单在望。他们可能也是一种公共职能。然而,很可能有充分的理由将Warehouse().calculateAllocation(order.getQuantity()));定义为calculateAllocation --否则:order.processed(新的order.processed可能是选项0 )。
  • 未命名的调用者现在依赖于Order.getQuantity、Order.processed和AllocationResponse。

注意:对AllocationResponse的依赖可以降低(至少在某种意义上),而代价是可读性(您判断?)以及断点的唯一行号(通常是在需要的时候和地点):

代码语言:javascript
复制
    order.processed(new Warehouse().allocate(order.getQuantity()))

现在,这些只是表面上的权衡,但它们很可能会被这些设计选项与其他当前和可预见的代码相适应的程度所压倒。

例如,

备选案文1将在一个更广泛的系统中更为有利,该系统可能:

  • 定义基于仓库的类,这些类专门细化分配(Order)的行为,可能不会更改或对calculateAllocation(int)进行不同的更改。也就是说,仅通过精炼calculateAllocation(int)间接地细化分配(订单)将是选项1和选项2之间的相同处理。
  • 有许多相同成语的不同呼叫者: warehouse.allocate(order)
  • 需要了解仓库模块中的Order、Order.getQuantity和Order.processed (帮助调整/摊销依赖成本)。

备选案文2将在一个更广泛的系统中更为有利,该系统可能:

  • 需要或希望接触Order.getQuantity和Order.processed,并可能在未命名的调用者中使用AllocationResponse (以证明/摊销依赖成本),而不仅仅是使用成语:Order.processed

重复使用这个成语可以证明它有自己的方法--在选项2下,一个未命名调用者的本地方法,所以在选项1和选项2之间,这几乎是一样的。

在某种“二进制”意义上,Order接口已经由未命名的调用方导入,因此对方法的公开已经隐式地“免费”存在,或者更像“好的或坏的”。在这里,“二进制”具有“on或off”和“直至编译后的位”的双重含义。这种“二进制”的区别在为公共消费的库设计接口时非常重要,“将永远支持”。但从更微妙的实际意义上讲,对于一个只在实验上或在小型“内部”代码库中使用的接口来说,将函数调用隔离到即使是导入接口的模块中的一小部分,可以大大减少以后通过改进这些功能而“破坏契约”的痛苦。从这个意义上说,从未命名的调用方调用每个不同的Order方法是一个“更深”的依赖关系,而不仅仅是导入Order接口。

  • 要求或希望在仓库外接触计算分配/分配(Int)。这似乎不太可能。否则,calculateAllocation就不会被宣布为私有,或者,一旦这个设计问题出现,它就会被改变为一个膝跳式的0解决方案,而没有比这更明智的了--这就是我所说的“完全错误的做法”。
票数 3
EN

Code Review用户

发布于 2012-01-18 06:32:49

我喜欢被否决:)这个问题没有正确的OO设计。这个问题不能适应OO结构,因为它涉及到关系。不可能有两个抽象,例如“仓库”和“订单”通过"place“之类的方法进行交互(在特定的仓库上下订单)。这已经被证明了,所以不要浪费你的时间争论。这个问题被称为“协方差问题”。

要正确地解决这个问题,您必须去抽象其中的一个实体:仓库或订单必须是不变的(固定的数据类型)。仍然可以使用信息隐藏,但不能派生新实例。

在现实世界中的这类问题中,这两个概念都是不抽象的。

经典的解决方案,也是最常用的解决方案,称为关系数据库。这里所有的数据结构都是具体数据表。

这是正确的解决办法。把OO扔掉。在这里是没用的:一大堆胡言乱语的宗教垃圾。只需使用简单的旧数据结构,程序将在十分之一的时间内完成,它将工作,它将易于维护,并将快速运行。

我希望这是明确的:你在学校里被一群不懂任何理论的假学者骗了,他们试图教授二十年前理论家抛弃的思想。如果你想学习抽象和好的编程,学习一种像Ocaml或Haskell这样的语言,它是由对它的数学有很好的知识的人设计的,而不是那些几乎无法设计一个工作的烤面包机的人。

票数 1
EN

Code Review用户

发布于 2012-01-01 05:26:07

我的偏好是:

代码语言:javascript
复制
public class Warehouse {

    public void allocate(int quantity){
         // code
    }
}

public class Order {

    public void process(Warehouse warehouse)
    {
         processed(warehouse.allocate(getQuantity());
    }
}

基本上,你需要打电话:

代码语言:javascript
复制
order.processed(warehouse.allocate(order.getQuantity()))

我建议这是合乎情理的。

为什么?

  1. 告诉不要问:最好是要求订单处理,而不是提取信息,然后在其他地方处理
  2. 耦合:这三个调用中有两个是预定的。这表明代码是按顺序耦合的,很可能属于顺序。
  3. 最小化接口:处理后的函数和getQuantity()函数变得内部有序(只要它们不在其他地方使用),从而简化了这些对象的接口。

可能的问题:

  1. 订单可能已经太复杂了,加上process(Wharehouse)可能会膨胀。我认为这可能是分割代码的更好方法。
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/7336

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档