Questions tagged «object-oriented-design»

面向对象的设计是规划用于解决软件问题的交互对象系统的过程。

4
我编写的每个类都应该坚持一个接口吗?
我正在用Typescript编写游戏,并决定继续尝试坚持“ 基于接口的编程 ” 的思想,在该思想中,您基于对象的接口而不是实现来编写代码。 我写了很多接口和实现它们的类,然后退后一步,意识到这些类足够简单,以至于我可能永远不需要更改实现,因为实际上只有一种方法可以完成班级确实做到了(Phaser.Sprite以受限方式移动坦克就像坦克一样)。 然后,我记得几年前读过有关YAGNI的想法,这基本上是您不应过度设计代码以包含您可能永远不会使用的东西。 遵循最佳实践,每个类都应该实现一个接口,还是应该将其限制为您希望将来可能替换掉的类?

3
是否存在用于管理深层多对多关系的设计模式?
我在定义这个数据模式时遇到了麻烦,在多个应用程序上工作时遇到了麻烦。 它包括: 由许多对象本身组成的对象类型 第二种对象类型,其中每个实例“具有很多”第一个对象 并且,每个对象的每个关联都可以将第一对象的每个子对象修改为第二对象类型。 一个简单的示例可能是: 一门编程课程,包含一组课程 这些课程由一组作业组成。 可以将课程分配给学生。 但是,一旦将课程分配给学生,则可以通过删除和添加为该学生定制每个课程和/或作业,以至于原始课程可能无法识别。 在我的解决方案中,结果是: 将课程分配给学生后,该课程将加载到内存中。然后,对于每个子对象,使用适当的元数据生成学生/子对象关系对象。本质上,我使用原始对象作为模板来生成所需的可自定义对象。 随着子对象变得更加复杂和编号,这将导致大量数据。我想知道是否存在一些优化或模式,以减少处理此数据模式所需的逻辑/复杂度。

1
什么时候应该在Python中继承异常?
在我的代码中,大约有七个地方会引发异常。所有这些异常的处理方式相同:将错误输出到日志文件,将软件状态恢复为默认状态并退出。 在代码审查期间,我非常重视的高级工程师说,我应该将所有这些异常归为一类。他的论点是,将来我们可能希望以不同的方式处理异常,这将更加容易。 我的观点是当前它只会使我们的代码混乱,并且由于我们不知道我们是否会以不同的方式处理异常,因此我们应该将代码保持简洁,并且如果时间到了,那么我们应该将其子类型化。 我想听听每种情况的论点。

3
干净的代码和混合对象以及功能嫉妒
因此,我最近对代码进行了一些重大的重构。我试图做的主要事情之一就是将类分为数据对象和辅助对象。除其他外,这是由“ 清洁代码”的这一部分启发的: 杂种 这种混乱有时会导致不幸的混合数据结构,即一半对象和一半数据结构。它们具有执行重要功能的函数,也具有公共变量或公共访问器和更改器,它们出于所有意图和目的,将私有变量公开,从而诱使其他外部函数以程序程序将要使用的方式使用这些变量。数据结构。 这样的混合体很难添加新功能,但是也很难添加新的数据结构。他们是两全其美的。避免创建它们。它们表示设计混乱,其作者不确定(或者更糟,是无知)他们是否需要保护功能或类型。 最近,我正在查看我的一个工作对象(恰好实现了Visitor模式)的代码,并看到了: @Override public void visit(MarketTrade trade) { this.data.handleTrade(trade); updateRun(trade); } private void updateRun(MarketTrade newTrade) { if(this.data.getLastAggressor() != newTrade.getAggressor()) { this.data.setRunLength(0); this.data.setLastAggressor(newTrade.getAggressor()); } this.data.setRunLength(this.data.getRunLength() + newTrade.getLots()); } 我立即对自己说:“功能令人羡慕!这种逻辑应该在Data类中-特别是在handleTrade方法中。handleTrade并且updateRun应该始终一起发生”。但是后来我想到“数据类仅仅是一个public数据结构,如果我开始这样做,那么它将成为一个混合对象!” 有什么更好的,为什么?您如何决定该做什么?

2
遵循SRP时,应如何处理验证和保存实体?
最近,我一直在阅读Clean Code和各种有关SOLID的在线文章,而我阅读的内容越多,我感觉自己一无所知。 假设我正在使用ASP.NET MVC 3构建Web应用程序。假设我有一个类似这样UsersController的Create操作: public class UsersController : Controller { public ActionResult Create(CreateUserViewModel viewModel) { } } 在这种操作方法中,如果输入的数据有效,我想将用户保存到数据库中。 现在,根据“单一责任原则”,对象应具有单一责任,并且该责任应由类完全封装。它的所有服务都应严格地与这一责任保持一致。由于验证和保存到数据库是两个单独的职责,我想我应该创建一个单独的类来像这样处理它们: public class UsersController : Controller { private ICreateUserValidator validator; private IUserService service; public UsersController(ICreateUserValidator validator, IUserService service) { this.validator = validator; this.service= service; } public ActionResult Create(CreateUserViewModel viewModel) { ValidationResult …

3
长参数列表与长状态变量列表
在C ++书中,作者说我们不再需要带有长参数列表的函数,因为大多数参数都可以重构为类中的状态变量。另一方面,一本功能性的编程书说状态变量是有害的,因为它会引起副作用,导致副作用,导致易错和难以并行化代码。我很困惑。代码是否应该通过将其状态变量移到函数参数列表中来避免尽可能多地依赖状态变量?


3
如何重构具有多个切换案例的应用程序?
我有一个应用程序,它使用整数作为输入,并基于输入调用不同类的静态方法。每次添加新数字时,我们需要添加另一种情况,并调用不同类的不同静态方法。交换机中现在有50个案例,每当我需要添加另一个案例时,我都会发抖。有一个更好的方法吗。 我做了一些思考,想到了这个主意。我使用策略模式。我没有交换条件,而是有一个策略对象映射,键为输入整数。调用方法后,它将查找对象并为该对象调用通用方法。这样,我可以避免使用switch case结构。 你怎么看?

2
只有吸气剂的接口有代码气味吗?
(我已经看到了这个问题,但是第一个答案更多的是关于自动属性而不是设计,而第二个答案则是向使用者隐藏数据存储代码,我不确定这是我想要的/我的代码做了什么,所以我想听听其他意见) 我有两个非常相似的实体,HolidayDiscount和RentalDiscount,它们表示长度折扣,即“如果至少持续numberOfDays使用percent折扣,则适用”。这些表有不同的父实体,并且在不同的地方使用,但是在使用它们的地方,有一种通用的逻辑来获取最大的适用折扣。例如,a HolidayOffer具有多个HolidayDiscounts,在计算其成本时,我们需要找出适用的折扣。租金和相同RentalDiscounts。 由于逻辑相同,因此我想将其放在一个地方。这就是以下方法,谓词和比较器的作用: Optional<LengthDiscount> getMaxApplicableLengthDiscount(List<LengthDiscount> discounts, int daysToStay) { if (discounts.isEmpty()) { return Optional.empty(); } return discounts.stream() .filter(new DiscountIsApplicablePredicate(daysToStay)) .max(new DiscountMinDaysComparator()); } public class DiscountIsApplicablePredicate implements Predicate<LengthDiscount> { private final long daysToStay; public DiscountIsApplicablePredicate(long daysToStay) { this.daysToStay = daysToStay; } @Override public boolean test(LengthDiscount discount) { return daysToStay >= …

5
太多的抽象使得代码难以扩展
我在代码库中感觉到太多抽象(或者至少是处理它)时遇到了问题。代码库中的大多数方法已被抽象为采用代码库中最高的父级A,但是此父级的子级B具有新属性,该属性会影响其中某些方法的逻辑。问题在于这些属性无法在那些方法中检查,因为输入被抽象为A,而A当然没有此属性。如果我尝试创建一个新的方法来不同地处理B,则会被调用以进行代码复制。我的技术负责人的建议是创建一个使用布尔参数的共享方法,但是这样做的问题是,有些人将其视为“隐藏的控制流”,其中共享方法具有的逻辑对于将来的开发人员可能并不明显。 ,并且即使需要添加将来的属性,即使将其分解为较小的共享方法,该共享方法也会变得过于复杂/复杂。这也增加了耦合,降低了凝聚力,并且违反了我团队中有人指出的单一责任原则。 本质上,此代码库中的许多抽象有助于减少代码重复,但是当使它们采用最高抽象时,这会使扩展/更改方法变得更加困难。在这种情况下我该怎么办?尽管其他人不能就他们认为的好事达成共识,但我还是要怪罪于我,这最终伤害了我。

4
在复杂的以域为中心的应用程序中,用于基本CRUD操作的DDD方法
我的公司正在从头开始重写我们的Web应用程序。它是大型企业级应用程序,在金融行业中具有复杂的领域。 我们使用ORM(实体框架)进行持久化。 本质上,我们的应用程序的一半集中在从用户那里收集原始数据,进行存储,然后包含大部分实际域逻辑的应用程序的另一半使用原始数据来创建我们的域图片,该域图片与原始数据有很大的不同原始输入,并将其传递到calc引擎,运行calcs,并吐出结果,然后将结果显示给用户。 在使用层的DDD方法中,CRUD操作似乎遍历域层。但至少在我们看来,这似乎没有道理。 例如,当用户转到编辑屏幕以更改投资帐户时,屏幕上的字段是存储在数据库中的确切字段,而不是以后用于计算的域表示形式。那么,当编辑屏幕需要数据库表示形式(原始输入)时,为什么要加载投资帐户的域表示形式呢? 在用户单击投资帐户屏幕上的“完成”,并对控制器执行POST之后,控制器现在几乎具有需要保存的投资帐户的确切数据库表示形式。但是出于某种原因,我应该加载域表示以进行修改,而不是仅将控制器模型直接映射到数据库模型(实体框架模型)? 因此,从本质上讲,我是将数据模型映射到域模型,以便可以将其映射回数据模型以持久化。这有什么意义?

1
业务逻辑与服务层
我读了这个答案:https : //softwareengineering.stackexchange.com/a/234254/173318请更正我的理解。 业务规则是指现实世界中的业务步骤列表(无代码)。 业务逻辑是指将业务规则转换为代码的过程,并将这些代码束/种类称为“业务逻辑”。 服务层的用途是什么?如果我读了这个答案,听起来与业务逻辑没什么不同https://stackoverflow.com/a/4817935/4190539 服务层是业务逻辑和存储库相遇的地方吗?

2
是什么使迭代器成为设计模式?
我一直在想,与其他类似构造相比,使Iterator变得特别的原因是什么,并且使“ 四人帮”将其列为设计模式。 迭代器基于多态性(具有公共接口的集合的层次结构)和关注点分离(对集合的迭代应独立于数据的结构方式)。 但是,如果我们将集合的层次结构替换为例如数学对象的层次结构(整数,浮点数,复数,矩阵等),而迭代器由代表这些对象的某些相关操作(例如幂函数)的类替换,该怎么办?类图将是相同的。 我们可能会发现更多类似的示例,例如Writer,Painter,Encoder和更好的示例,它们的工作方式相同。但是,我从未听说过其中任何一种称为设计模式。 那么,什么使Iterator特别呢? 是否因为需要可变状态来将当前位置存储在集合中而变得更加复杂,这是事实吗?但是,通常不认为可变状态是理想的。 为了阐明我的观点,让我举一个更详细的例子。 这是我们的设计问题: 假设我们有一个类的层次结构,并且在这些类的对象上定义了一个操作。每个类的操作接口相同,但实现方式可以完全不同。还假定对同一对象(例如具有不同的参数)多次应用该操作是有意义的。 这是解决我们设计问题的明智解决方案(实际上是迭代器模式的概括): 为了分离关注点,不应将操作的实现作为功能添加到原始类层次结构(操作数对象)中。由于我们想在同一个操作数上多次应用该操作,因此它应该由一个持有对该操作数的引用的对象来表示,而不仅仅是由函数表示。因此,操作数对象应提供一个函数,该函数返回表示操作的对象。该对象提供执行实际操作的功能。 一个例子: 有一个基类或接口MathObject(愚蠢的名字,我知道,也许有人有更好的主意。)与派生类MyInteger和MyMatrix。对于每个MathObject操作,Power都应定义一个允许计算平方,立方等的运算。所以我们可以写(用Java): MathObject i = new MyInteger(5); Power powerOfFive = i.getPower(); MyInteger square = powerOfFive.calculate(2); // should return 25 MyInteger cube = powerOfFive.calculate(3); // should return 125

4
如何清楚定义边界上下文的边界
经过一个月左右的阅读和研究DDD,我决定开始自己的项目,并使用这些有限的上下文创建DDD。 客户群 产品展示 命令 开票 每个有界上下文都有其余的API作为表示层,域层,持久层。 到目前为止,代码运行顺利,但是来自一个单一的世界,我仍在尝试找出以下内容: 当我想创建一个新客户时,发出新发票,创建我想要的新订单,例如访问国家列表。我要: a)在每个卑诗省创建一个国家列表 b)创建一个国家BC-> API并使用它来获取可用国家的列表 c)使用第三方API并通过每个BC中的反腐败层提取数据 当使用反腐败层或适配器层与第三方API集成时,我的域模型中必须包含哪些数据?例如,如果我想将zendesk API与Client BC集成在一起。我是否仅需要我域中的ticketID,还是必须从Zendesk中提取要在Client BC中访问和使用的所有数据? 如果我的MVC应用程序实际上是从API(我的受限上下文的表示层)获取数据的,那么我很难清楚地定义每个BC的边界。这是否意味着经过适当设计的BC可以为单个MVC控制器提供服务,而无需使用其他API?

1
何时使用特质,而不是继承和组合?
关于OOP,有三种常见的方法AFAIK实现可重用性 继承:通常代表is-一种关系(鸭子is-鸟) 组成:通常代表有一个关系(汽车有一个引擎) 特性(例如PHP中的trait关键字):...对此不确定 虽然在我看来特质可以实现has-a和is-a关系,但我真的不确定它打算用于哪种建模。特征是针对哪种情况设计的?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.