Questions tagged «object-oriented»

一种使系统能够建模为一组对象的方法论,这些对象可以模块化方式进行控制和操作

6
实体方法调用上的DDD注入服务
问题的简短格式 在DDD和OOP的最佳实践中,是否可以在实体方法调用上注入服务? 长格式示例 假设我们在DDD中有一个经典的Order-LineItems案例,其中有一个称为Order的域实体,它也充当聚合根,并且该实体不仅由其Value Objects组成,而且还包含Line Item的集合实体。 假设我们希望在应用程序中使用流利的语法,以便我们可以做类似的事情(请注意第2行中的语法,在此称为getLineItems方法): $order = $orderService->getOrderByID($orderID); foreach($order->getLineItems($orderService) as $lineItem) { ... } 我们不想将任何LineItemRepository注入OrderEntity,因为这违反了我能想到的几个原则。但是,语法的流畅性是我们真正想要的,因为它易于阅读和维护以及测试。 考虑下面的代码,指出该方法getLineItems中OrderEntity: interface IOrderService { public function getOrderByID($orderID) : OrderEntity; public function getLineItems(OrderEntity $orderEntity) : LineItemCollection; } class OrderService implements IOrderService { private $orderRepository; private $lineItemRepository; public function __construct(IOrderRepository $orderRepository, ILineItemRepository $lineItemRepository) { $this->orderRepository …

1
使用Python的方法解析顺序进行依赖注入-这样不好吗?
我观看了Raymond Hettinger在Pycon上发表的“超级被认为是超级”的演讲,并了解了一些Python的MRO(方法解析顺序),该方法以确定性方式线性化了“父”类。像下面的代码一样,我们可以利用它来发挥优势,进行依赖注入。因此,自然而然地,我现在想使用super所有功能! 在下面的示例中,User该类通过从LoggingService和继承来声明其依赖项UserService。这不是特别特殊。有趣的是,我们可以使用“方法解析顺序”来模拟单元测试期间的依赖关系。下面的代码创建一个MockUserService从继承UserService并提供我们要模拟的方法的实现。在下面的示例中,我们提供的实现validate_credentials。为了MockUserService处理任何呼叫,validate_credentials我们需要先将其UserService放置在MRO中。这通过创建一个包装类各地进行User所谓的MockUser和有它继承User和MockUserService。 现在,当我们执行MockUser.authenticate该操作时,它依次调用方法解析顺序中的super().validate_credentials() MockUserServicebefore UserService,因为它提供了validate_credentials该实现的具体实现。是的-我们已经UserService在单元测试中成功模拟了。考虑到这样UserService做可能会导致一些昂贵的网络或数据库调用-我们刚刚删除了此延迟因素。也没有UserService接触实时/生产数据的风险。 class LoggingService(object): """ Just a contrived logging class for demonstration purposes """ def log_error(self, error): pass class UserService(object): """ Provide a method to authenticate the user by performing some expensive DB or network operation. """ def validate_credentials(self, username, password): print('> UserService::validate_credentials') return username == …

2
面向对象的后期绑定
在Alan Kays的“面向对象的定义”中,有部分我不理解的定义: 对我而言,OOP意味着仅消息传递,本地保留和保护以及状态过程的隐藏以及所有事物的极端LateBinding。 但是“ LateBinding”是什么意思?如何在C#之类的语言上应用它?为什么这如此重要?

6
实施SRP的实际方法是什么?
人们简单地检查班级是否违反单一责任原则的实用技术是什么? 我知道一个班级应该只有一个改变的理由,但是那句话在某种程度上缺乏真正实现这一改变的实用方法。 我发现的唯一方法是使用句子“……本身应该……”。其中第一个空格是类名称,第二个空格是方法(职责)名称。 但是,有时很难确定责任是否确实违反了SRP。 还有更多检查SRP的方法吗? 注意: 问题不在于SRP意味着什么,而是关于检查和实施SRP的实用方法或一系列步骤。 更新 我添加了一个明显违反SRP的示例类。如果人们可以以此为例来说明他们如何遵循单一责任原则,那将是很好的。 这个例子是从这里开始的。

1
OOP ECS与纯ECS
首先,我知道这个问题与游戏开发主题相关,但是我决定在这里提出这个问题,因为它实际上归结为一个更一般的软件工程问题。 在过去的一个月中,我阅读了很多有关实体组件系统的信息,现在对这个概念相当满意。但是,似乎有一个方面似乎缺少明确的“定义”,并且不同的文章提出了根本不同的解决方案: 这是ECS是否应该破坏封装的问题。换句话说,其OOP风格的ECS(组件是具有状态和行为的对象,它们封装了特定于它们的数据)与纯ECS(组件是c样式的结构,仅具有公共数据,并且系统提供了功能)。 请注意,我正在开发框架/ API /引擎。因此,目标是无论使用它的人都可以轻松扩展它。这包括添加新类型的渲染或碰撞组件之类的东西。 OOP方法的问题 组件必须访问其他组件的数据。例如,渲染组件的draw方法必须访问变换组件的位置。这将在代码中创建依赖项。 组件可以是多态的,这进一步引入了一些复杂性。例如,可能有一个Sprite渲染组件,它会覆盖渲染组件的虚拟绘制方法。 纯方法的问题 由于必须在某个地方实现多态行为(例如,用于渲染),因此它只是外包给了系统。(例如,精灵渲染系统创建一个继承渲染节点的精灵渲染节点,并将其添加到渲染引擎中) 系统之间的通信可能很难避免。例如,碰撞系统可能需要根据任何具体的渲染组件计算出的边界框。这可以通过让他们通过数据进行通信来解决。但是,这会删除即时更新,因为渲染系统将更新边界框组件,然后碰撞系统将使用它。如果未定义调用系统更新功能的顺序,则可能导致问题。存在一个事件系统,该事件系统允许系统引发其他系统可以订阅其处理程序的事件。但是,这仅适用于告诉系统该怎么做,即无效函数。 还需要其他标志。以图块地图组件为例。它将具有大小,图块大小和索引列表字段。瓦片贴图系统将处理相应的顶点数组,并根据组件的数据分配纹理坐标。然而,每帧重新计算整个图块地图是昂贵的。因此,将需要一个列表来跟踪所有更改,然后在系统中对其进行更新。以OOP方式,这可以由图块地图组件封装。例如,SetTile()方法将在调用顶点数组时对其进行更新。 尽管我看到了纯方法的美妙之处,但我真的不明白与传统OOP相比它将带来什么样的具体好处。组件之间的依赖性仍然存在,尽管被系统隐藏了。同样,我将需要更多的类来实现相同的目标。在我看来,这似乎是一种过度设计的解决方案,但这从来都不是一件好事。 此外,我对性能的关注并不那么深,所以面向数据设计和现金遗漏的整个想法对我来说并不重要。我只想要一个好的架构^^ 尽管如此,我阅读的大多数文章和讨论都建议使用第二种方法。为什么? 动画 最后,我想问一个问题:如何在纯ECS中处理动画。目前,我已将动画定义为根据0到1之间的进度操纵实体的函子。动画组件具有一个动画列表,该列表包含一个动画列表。然后,在其更新功能中,它将当前激活的任何动画应用于实体。 注意: 我刚刚读了这篇文章实体组件系统体系结构对象是否按定义导向?可以比我更好地解释问题。尽管基本上是同一主题,但对于纯数据方法为何更好,仍然没有给出任何答案。

6
如何避免在次优设计中无休止地迭代?
因此,可能像许多人一样,我经常发现自己对设计问题感到头疼,例如,有些设计模式/方法似乎可以直观地解决问题并具有预期的好处。通常会有一些警告,如果没有某种工作就很难实施模式/方法,而这周围的工作否定了模式/方法的好处。我可以很轻松地结束许多模式/方法的迭代,因为可以预见的是,几乎所有的模式/方法在现实世界中都存在一些非常重要的警告,在这些情况下,根本没有一个简单的解决方案。 例: 我将给您一个假设的示例,大致基于我最近遇到的一个真实示例。假设我想在继承上使用合成,因为过去继承层次结构阻碍了代码的可伸缩性。我可能会重构代码,但随后发现在某些上下文中,超类/基类只是需要在子类上调用功能,尽管尝试避免这样做。 下一个最好的方法似乎是实现一半委托/观察者模式和一半组合模式,以便超类可以委托行为,或者子类可以观察超类事件。然后,该类的可伸缩性和可维护性较差,因为它不清楚应如何扩展,而且扩展现有的侦听器/代理也很棘手。同样,信息也隐藏得不好,因为人们开始需要了解实现以了解如何扩展超类(除非您非常广泛地使用注释)。 因此,在此之后,我可能会选择完全使用观察者或委托人来避免因混淆大量方法而带来的弊端。但是,这有其自身的问题。例如,我可能会发现我最终需要观察者或代表来应对越来越多的行为,直到我几乎需要针对每种行为的观察者/代表。一种选择可能是只为所有行为提供一个大的侦听器/代理,但是实现类最终会带有许多空方法等。 然后,我可以尝试另一种方法,但是与此同时存在很多问题。然后是下一个,然后是下一个,依此类推。 当每种方法似乎都存在其他问题时,这种迭代过程将非常困难,并导致某种设计决策瘫痪。无论使用哪种设计模式或方法,都很难接受代码最终同样会带来问题。如果我最终陷入这种情况,是否意味着问题本身需要重新考虑?别人遇到这种情况时会做什么? 编辑: 似乎有一些我想清除的问题的解释: 我将OOP完全排除在问题之外,因为事实证明它实际上并不是特定于OOP的,而且很容易误解我在传递OOP时所做的一些评论。 有些人声称我应该采取迭代的方法并尝试不同的模式,或者当它停止工作时我应该放弃一个模式。这是我首先要参考的过程。我认为这个例子很清楚,但是我可以更清楚一点,所以我编辑了问题。

6
将大多数类划分为仅数据字段类和仅方法类(如果可能的话)是好的还是反模式的?
例如,一个类通常具有类成员和方法,例如: public class Cat{ private String name; private int weight; private Image image; public void printInfo(){ System.out.println("Name:"+this.name+",weight:"+this.weight); } public void draw(){ //some draw code which uses this.image } } 但是在阅读了有关“单一职责原则”和“开放封闭原则”之后,我更喜欢仅使用静态方法将类分为DTO和辅助类,例如: public class CatData{ public String name; public int weight; public Image image; } public class CatMethods{ public static void printInfo(Cat …

3
将一组相关的属性包装到其自己的struct / class中是一种好习惯吗?
用Swift编写User对象,尽管我的问题与任何强类型语言有关。用户可以拥有一堆链接(FacebookProfile,InstagramProfile等)。有关此问题。 将链接包装在其自己的对象中是一种好习惯吗? struct用户{ var firstName:字符串 var lastName:字符串 var email:string var链接:链接 } 结构链接{ var facebook:字符串 var instagram:字串 var twitter:字符串 } 还是应该松散?从技术上讲,我知道这两种方法都很好,但是总体上想知道是否有推荐的方法,尤其是为了提高可读性。 struct User { var firstName: string var lastName: string var email: string var facebookLink: string var twitterLink: string var instagramLink: string } 在这种情况下,链接应该是集合/列表吗?我认为它不应该是一个列表,因为有固定数量的链接选项可用,并且数量不会增加。我的想法对吗? 将我的网络方法放置在User对象(例如getUsers,getUser,updateUser)内是否是一种好习惯? 我知道这些可能是主观的,但是我试图了解在类似情况下的最佳实践是什么。将不胜感激任何指针。

3
接口隔离原则是否适用于具体方法?
由于接口隔离原则表明,不应强迫任何客户端依赖其不使用的方法,因此客户端不应为其接口方法实现空方法,否则应将此接口方法放入另一个接口。 但是具体方法呢?我应该分开不是每个客户都会使用的方法吗?考虑以下类别: public class Car{ .... public boolean isQualityPass(){ ... } public int getTax(){ ... } public int getCost(){ ... } } public class CarShop{ ... public int getCarPrice(int carId){ Car car=carList[carId]; int price=car.getTax() + car.getCost()... (some formula); return price; } } 在上面的代码中,CarShop根本不在Car中使用方法isQualityPass(),我应该将isQualityPass()分离到一个新类中: public class CheckCarQualityPass{ public boolean isQualityPass(Car car){ …

6
在编码之前设计OOP系统的简单过程是什么?
每当需要构建项目时,我总是设法进行构建,而不是事先设计计划或设计,而是在首先编写了需要的类之后,从下至上充实整个项目。现在,我知道这不是创建软件的正确方法,但是对我来说,将其包裹在所谓的面向对象的分析和设计上并不容易。我可以更容易地理解自上而下的程序设计,因为它只包含将任务分解为子任务,这些子任务在代码,功能上与之相对。但是我不容易理解面向对象的分析和设计,因为我不理解人们如何知道他们将需要哪些类以及它们将如何交互,除非他们知道如何对它们进行编码。 因为一旦在设计过程中引入了类和对象的概念,就不能再自上而下进行设计,因为我们不再将问题分解为可以作为过程实现的事物。相反,根据我对该主题的了解,我们必须确定需要哪些类,并在统一建模语言中创建各种工件,然后在实现软件时就可以使用这些工件。但是这种设计过程我不明白。除非他们已经构思了整个系统,否则如何知道他们将需要哪些类以及它们将如何交互? 这就是我的问题。尽管我确实了解面向对象编程的概念,但是我不了解如何设计面向对象的系统,并且可以在我知道的任何面向对象编程语言中使用这些概念。因此,我需要有人向我解释可以使用对我来说有意义的方式设计面向对象系统的简单过程。

4
面向对象编程中的主要职责是什么?
我是面向对象编程的新手,但我不明白主对象的目的是什么。 是的,我读到它是程序的“入口点”,但是我不明白的是程序的主要内容是什么?它的职责是什么? 可能会发生将主体编写的内容封装到另一个对象中的情况,但是您应该使用这种方法多少呢? 这是我用Java编写的第一个主语言,它很简单,但是可能会让您更好地理解我的疑问。我有一个抽象类Animal,它由“ Cat”和“ Dog”扩展。我使用main来创建一些对象,并使用它作为与用户的“接口”,确实如您所见,我使用了一些条件指令来“询问用户”他想做什么。 我的问题来自于这样一个事实,即接口可以封装在另一个对象中,而不是把责任交给主要对象。 public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("What type of animal do you want to create? \n dog cat"); String type = input.nextLine(); if ( Objects.equals(type, "dog")){ System.out.println("Enter the animal's age: "); int age = input.nextInt(); // Scans the …

2
创建唯一目的是隐式转换为另一个类的类是否不好?
想象一下一种情况,我们正在使用一个允许您创建Circle对象的库,您可以在其中指定半径和圆心来定义它。但是,由于某些原因,它也需要一个必需的flavour参数。现在,我们确实需要Circle在自己的应用程序中使用,但是出于我的应用程序的目的,我可以将风味设置为Flavours.Cardboard每次。 为了“解决”这一问题,我Circle在另一个命名空间中创建了自己的类,该命名空间仅将radius和center作为参数,但具有一个隐式转换器,可以直接转换为Circle仅创建Circle(this.radius, this.center, Flavours.Cardboard)对象的外部库类。因此,在任何需要其他类型的的地方Circle,我都会进行自动转换。 创建这样一个类的后果是什么?有更好的解决方案吗?如果我的应用程序是在此外部库的基础上构建的供其他程序员使用的API,会有所不同吗?

3
使用接口进行松耦合代码
背景 我有一个项目,该项目取决于某种类型的硬件设备的使用情况,但是只要该硬件设备执行我需要的操作,则由谁来制造该硬件设备并不重要。话虽这么说,即使两个本来应该做同样事情的设备,如果不是由同一家制造商生产的,它们也会有差异。因此,我正在考虑使用一个接口将应用程序与所涉及设备的特定制造商/型号分离开,而使该接口仅涵盖最高级别的功能。这就是我在想我的体系结构的外观: 在一个C#项目中定义一个接口IDevice。 在另一个C#项目中定义的库中有一个具体的东西,它将用来表示设备。 有具体的设备实现IDevice接口。 该IDevice接口可能具有类似GetMeasurement或的方法SetRange。 使应用程序了解具体的知识,并将具体的知识传递给利用(而非实现)IDevice设备的应用程序代码。 我非常确定这是正确的做法,因为这样我就可以在不影响应用程序的情况下更改正在使用的设备(这似乎有时会发生)。换句话说,具体的实现方式GetMeasurement或SetRange实际操作方式并不重要(设备制造商之间可能会有所不同)。 我唯一的疑问是,现在应用程序和设备的具体类都依赖于包含IDevice接口的库。但是,这是一件坏事吗? 我也看不到应用程序不需要知道设备的方式,除非设备与设备IDevice位于相同的名称空间中。 题 这似乎是实现接口以解耦应用程序与所使用设备之间的依赖关系的正确方法吗?

3
责任分担后如何管理单一责任?
我有两堂课,Operation和Trigger。每个类都有许多专门用于某些类型的操作或触发器的子类。一个Trigger可以触发特定的Operation。虽然Operation可以由特定触发Trigger。 我需要编写将给定映射Operation到给定Trigger(反之亦然)的代码,但是我不确定将其放置在何处。 在这种情况下,代码显然不属于一个类或另一类。因此,就单一职责原则而言,我不确定代码应属于何处。 我可以看到三个选项都可以使用。虽然1和2似乎只是语义的选择,但3和3完全代表了一种不同的方法。 触发时,例如bool Triggers(Operation o)。 关于操作,例如bool TriggeredBy(Trigger t)。 在管理映射的全新类中,例如bool MappingExists(Trigger t, Operation o)。 我应该如何根据单一责任原则决定将共享映射代码放置在何处? 责任分担后如何管理单一责任? 编辑1。 因此,实际代码如下所示。所有属性,或者是一string,Guid,collection<string>,或enum。它们基本上只是代表一小部分数据。 编辑2。 返回布尔类型的原因。另一个类将使用Trigger和的集合Operation。它需要知道在Trigger和之间存在映射Operation。它将使用该信息来创建报告。

2
Python的继承是“ is-a”继承样式还是组合样式?
考虑到Python允许多重继承,Python中的惯用继承是什么样的? 在具有单一继承的语言(例如Java)中,当您可以说一个对象是另一个对象的“是”并且想要在对象之间共享代码(从父对象到子对象)时,将使用继承。例如,您可以说这Dog是一个Animal: public class Animal {...} public class Dog extends Animal {...} 但是由于Python支持多重继承,我们可以通过将许多其他对象组合在一起来创建对象。考虑下面的示例: class UserService(object): def validate_credentials(self, username, password): # validate the user credentials are correct pass class LoggingService(object): def log_error(self, error): # log an error pass class User(UserService, LoggingService): def __init__(self, username, password): self.username = username self.password = password …

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.