Questions tagged «class-design»

有关如何设计具有最佳行业惯例的课程的一般指南。

16
使用单一责任原则时,什么构成“责任”?
显然,“单一责任原则”并不意味着“只做一件事情”。那就是方法的目的。 public Interface CustomerCRUD { public void Create(Customer customer); public Customer Read(int CustomerID); public void Update(Customer customer); public void Delete(int CustomerID); } 鲍勃·马丁说:“班级应该只有一个改变的理由。” 但是,如果您是SOLID的新手,那么很难下定决心。 我写了另一个问题的答案,在那儿我建议责任就像职位,然后用饭店的比喻来阐明我的观点。但这仍未阐明某人可以用来定义其班级职责的一组原则。 你是怎么做到的?您如何确定每个班级应承担的责任,以及如何在SRP中定义责任?

9
讨厌多重继承吗?
我一直很喜欢在一种语言中支持多重继承的想法。尽管通常是故意放弃的,但所谓的“替换”是接口。接口根本不能涵盖所有相同的多重继承,并且这种限制有时可能会导致产生更多样板代码。 我听说过的唯一基本原因是基类的钻石问题。我就是不能接受。对我来说,它的表现非常糟糕,例如:“嗯,有可能将其弄糟,所以这自然不是一个好主意。” 但是,您可以用编程语言修改任何内容,我的意思是。我只是不能认真对待这一点,至少没有没有更彻底的解释。 仅知道这个问题就占了90%。此外,我想我几年前听说过涉及通用解决方案的问题,该解决方案涉及“信封”算法或类似的东西(有人敲响铃吗?)。 关于钻石问题,我能想到的唯一潜在的真正问题是,如果您正在尝试使用第三方库,并且看不到该库中两个看似无关的类具有共同的基类,那么除了例如,文档是一种简单的语言功能,可能要求您明确声明要创建菱形的意图,然后才能为您实际编译菱形。有了这样的功能,任何钻石的制造要么是故意的,鲁ck的,要么是因为人们没有意识到这一陷阱。 所有人都这么说... 大多数人是否有真正的理由讨厌多重继承,还是仅仅是一堆歇斯底里会造成弊大于利?有没有我在这里看不到的东西?谢谢。 例 汽车扩展了WheeledVehicle,KIASpectra扩展了汽车和电子产品,KIASpectra包含无线电。为什么KIASpectra不包含电子产品? 因为它是电子的。继承vs.组合应该始终是is-a关系vs.has-a关系。 因为它是电子的。上下都有电线,电路板,开关等。 因为它是电子的。如果冬天电池没电了,您的麻烦就好像所有车轮突然丢失一样。 为什么不使用接口?以#3为例。我不想一遍又一遍地写这个,而且我真的不想创建一些奇怪的代理帮助器类来做到这一点: private void runOrDont() { if (this.battery) { if (this.battery.working && this.switchedOn) { this.run(); return; } } this.dontRun(); } (我们不会考虑该实现的好坏。)您可以想象如何可能有一些与电子相关的功能与WheeledVehicle中的任何内容都不相关,反之亦然。 我不确定是否要解决该示例,因为那里有解释的空间。您还可以考虑从平面扩展Vehicle和FlyingObject,以及从Bird扩展Animal和FlyingObject,或者从更纯粹的示例方面进行思考。

13
如何警告其他程序员类的实现
我正在编写“必须以特定方式使用”的类(我想所有类都必须...)。 例如,我创建了一个fooManager类,该类需要调用Initialize(string,string)。而且,为了进一步推动该示例,如果我们不听其ThisHappened行为,则该类将无用。 我的意思是,我正在编写的类需要方法调用。但是,如果您不调用这些方法,它将编译得很好,并且最终将得到一个空的新FooManager。在某些时候,根据类及其作用,它要么不起作用,要么崩溃。实现我的类的程序员显然会在其中查找并意识到“哦,我没有调用Initialize!”,这很好。 但是我不喜欢那样。我理想的情况是,如果不调用该方法,则不编译该代码。我猜这根本不可能。或立即可见清晰的事物。 我发现自己对这里的当前方法感到困扰,具体方法如下: 在类中添加一个私有布尔值,并检查类是否已初始化;如果不是,我将抛出一个异常,说“该类尚未初始化,您确定要调用.Initialize(string,string)吗?”。 我对这种方法还可以,但是它会导致很多代码被编译,最终对于最终用户来说是不必要的。 另外,当有更多方法Initiliaze要调用时,有时甚至会有更多的代码。我试图让我的课程没有太多的公共方法/动作,但这并不能解决问题,只是使其合理。 我在这里寻找的是: 我的方法正确吗? 有更好的吗? 你们做什么/建议? 我是否要解决非问题?同事们告诉我,程序员在尝试使用该类之前应先检查该类。我谨对此表示不同意见,但这是我相信的另一件事。 简而言之,我试图找到一种永远不会忘记在以后重用该类或被其他人重用时实现调用的方法。 澄清说明: 要在此处澄清许多问题: 我绝对不仅在谈论类的初始化部分,而且还涉及整个生命周期。防止同事两次调用一个方法,确保他们在Y之前先调用X,以此类推。任何最终成为强制性的要求和文档中的东西,但我希望在代码中尽可能地简化和缩小。我确实很喜欢Asserts的想法,尽管我很确定我将需要混合其他一些想法,因为Asserts并非总是可能的。 我正在使用C#语言!我怎么没提到呢?我在Xamarin环境中,通常在解决方案中使用大约6到9个项目来构建移动应用程序,包括PCL,iOS,Android和Windows项目。我已经从事开发工作大约一年半(包括学校和工作在内),因此有时我会提出荒谬的陈述\问题。所有这一切可能都无关紧要,但是太多的信息并不总是一件坏事。 由于平台的限制和依赖注入的使用,我不能总是将所有必需的东西都放在构造函数中,因为除了Interfaces之外的其他参数都没有了。也许我的知识不足,这很有可能。在大多数情况下,这不是初始化问题,而是更多 我如何确定他注册了该活动? 我如何确保他不会忘记“在某个时候停止该过程” 在这里,我记得一个广告获取类。只要可见“广告”的视图,该类就会每分钟获取一个新广告。该类在构造时需要一个可以显示广告的视图,该视图显然可以包含在参数中。但是,一旦视图消失,必须调用StopFetching()。否则,该类将继续为甚至不在该视图中的视图获取广告,这很糟糕。 同样,该类具有必须被监听的事件,例如“ AdClicked”。如果不听,一切都会很好,但是如果未注册水龙头,我们将失去对分析的跟踪。不过,该广告仍然可以正常运行,因此用户和开发人员不会发现任何差异,并且分析将仅包含错误的数据。需要避免这种情况,但是我不确定开发人员如何知道他们必须注册到tao事件。虽然这是一个简化的示例,但是这里有一个想法,“确保他使用可用的公共动作”,而且当然在正确的时间!

12
通过多个层传递实例是不好的做法吗?
在程序设计中,我经常遇到必须将对象实例传递给多个类的情况。例如,如果我有一个加载音频文件的控制器,然后将其传递给播放器,然后播放器将其传递给playerRunnable,后者又将其传递到其他地方,等等。这看起来很糟糕,但我没有知道如何避免。还是可以这样做? 编辑:也许播放器示例不是最好的,因为我以后可以加载文件,但是在其他情况下不起作用。

6
如果getter对象的状态无效,是否应该抛出异常?
我经常遇到这个问题,特别是在Java中,即使我认为这是一个普遍的OOP问题。即:引发异常会揭示设计问题。 假设我有一个包含一个String name字段和一个String surname字段的类。 然后,它使用这些字段来组成一个人的全名,以便将其显示在某种文件上,例如发票。 public void String name; public void String surname; public String getCompleteName() {return name + " " + surname;} public void displayCompleteNameOnInvoice() { String completeName = getCompleteName(); //do something with it.... } 现在,我想通过displayCompleteNameOnInvoice在分配名称之前调用引发错误来增强类的行为。似乎是个好主意,不是吗? 我可以在getCompleteName方法中添加引发异常的代码。但是以这种方式,我违反了与类用户的“隐式”合同。通常,如果未设置获取方法的值,则不应将其抛出异常。好的,这不是标准的获取方法,因为它不会返回单个字段,但是从用户的角度来看,区分可能太微妙了,无法考虑它。 或者,我可以从中抛出异常displayCompleteNameOnInvoice。但是,这样做我应该直接测试name或surname字段,这样做会违反表示的抽象getCompleteName。检查并创建完整名称是此方法的责任。根据其他数据,它甚至可以决定在某些情况下足够了surname。 因此,唯一的可能性似乎是将方法的语义更改getCompleteName为composeCompleteName,这表明行为更“活跃”,并且具有抛出异常的能力。 这是更好的设计解决方案吗?我一直在寻找简单性和正确性之间的最佳平衡。有针对此问题的设计参考吗?

6
将一个类定义为自身列表的子类有什么缺点?
在我最近的项目中,我定义了一个带有以下标头的类: public class Node extends ArrayList<Node> { ... } 但是,在与我的CS教授讨论后,他说这堂课既“令人难以忘怀”又是“不良习惯”。我还没有发现第一个是特别真实的,第二个是主观的。 我这样做的理由是,我有一个对象的想法,该对象需要定义为可以具有任意深度的对象,在这种情况下,实例的行为可以通过自定义实现或几个类似对象相互作用的行为来定义。这将允许抽象对象,这些对象的物理实现将由许多相互作用的子组件组成。¹ 另一方面,我知道这可能是不好的做法。将某物定义为自身列表的想法不是简单的,也不是物理上可以实现的。 考虑到我的用法,有什么正当的理由为什么我不应该在代码中使用它? ¹如果需要进一步解释,我会很高兴;我只是想使这个问题简明扼要。

6
首选类成员还是在内部方法之间传递参数?
假设在一个类的私有部分中有一个供多个私有方法使用的值。人们喜欢将其定义为类的成员变量还是将其作为参数传递给每个方法?为什么? 一方面,我可以看到一个论点,即减少类中的状态(即成员变量)通常是一件好事,尽管如果在类的所有方法中重复使用相同的值,那似乎是一个理想的选择。表示为类状态的候选对象,以使代码看起来更清晰(如果没有其他内容)。 编辑: 为了澄清提出的一些评论/问题,我不是在谈论常量,这与任何特定情况都没有关系,而只是与其他人谈论的一种假设。 暂时忽略OOP角度,以下是我想到的特定用例(假设通过引用传递只是为了使伪代码更整洁) int x doSomething(x) doAnotherThing(x) doYetAnotherThing(x) doSomethingElse(x) 所以我的意思是,多个功能之间存在一些共同的变量-在我看来,这是由于较小功能的链接所致。在OOP系统中,如果这些都是类的所有方法(例如,由于通过从大型方法中提取方法进行重构而导致的结果),则该变量可以全部传递给它们,也可以是类成员。


4
为什么更喜欢非静态内部类而不是静态内部类?
这个问题是关于将Java中的嵌套类做成静态嵌套类还是内部嵌套类。我在这里和Stack Overflow上进行了搜索,但是实际上找不到关于此决定的设计含义的任何问题。 我发现的问题是关于静态和内部嵌套类之间的区别的,这对我来说很明显。但是,我还没有找到令人信服的理由在Java中使用静态嵌套类-匿名类除外,我不考虑这个问题。 这是我对使用静态嵌套类的影响的理解: 更少的耦合:由于类不能直接访问其外部类的属性,因此通常得到的耦合较少。较少的耦合通常意味着更好的代码质量,更容易的测试,重构等。 Single Class:类加载器不需要每次都照顾一个新类,我们创建外部类的对象。我们只是一遍又一遍地获得同一类的新对象。 对于一个内部类,我通常会发现人们认为访问外部类的属性是有利的。从设计的角度来看,我希望在这方面有所不同,因为这种直接访问意味着我们具有很高的耦合度,并且如果我们想将嵌套类提取到其单独的顶层类中,则只能在本质上转向将其转换为静态嵌套类。 所以我的问题归结为:我是否认为非静态内部类可用的属性访问会导致较高的耦合度,从而导致较低的代码质量,我是错误的,并且据此我推断(非匿名)嵌套类应一般是静态的? 或者换句话说:为什么有一个令人信服的理由为什么人们更喜欢嵌套的内部类?

5
创建另一个类的ClassCollection是一个好习惯吗?
可以说我有一Car堂课: public class Car { public string Engine { get; set; } public string Seat { get; set; } public string Tires { get; set; } } 可以说,我们正在建立一个有关停车场的系统,我将使用很多Car类,因此我们建立了一个CarCollection类,它可能有一些类似的方法FindCarByModel: public class CarCollection { public List<Car> Cars { get; set; } public Car FindCarByModel(string model) { // code here return new Car(); …

5
什么时候以及为什么要使用嵌套类?
使用面向对象编程,我们可以在一个类(嵌套类)中创建一个类,但是在我4年的编码经验中,我从未创建过嵌套类。 嵌套类有什么用处? 我知道如果嵌套一个类,则可以将其标记为私有,并且我们可以从包含的类中访问该类的所有私有成员。我们可以将变量作为私有变量包含在包含类本身中。 那么为什么要创建一个嵌套类呢? 在哪些情况下应使用嵌套类,或者在使用方面比其他技术更强大?

3
可选参数或重载的构造函数
我正在实现DelegateCommand,当我要实现构造函数时,我想到了以下两种设计选择: 1:具有多个重载的构造函数 public DelegateCommand(Action<T> execute) : this(execute, null) { } public DelegateCommand(Action<T> execute, Func<T, bool> canExecute) { this.execute = execute; this.canExecute = canExecute; } 2:只有一个带有可选参数的构造函数 public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null) { this.execute = execute; this.canExecute = canExecute; } 我不知道使用哪个,因为我不知道这两种建议的方式都有哪些优点/缺点。两者都可以这样称呼: var command = new DelegateCommand(this.myExecute); var command2 = …

10
我们可以没有构造函数吗?
假设出于某种原因,所有对象都是通过$ obj = CLASS :: getInstance()创建的。然后,我们使用setter注入依赖项,并使用$ obj-> initInstance();开始初始化。如果我们根本不使用构造函数,是否有无法解决的实际麻烦或情况? ps用这种方法创建对象的原因是,我们可以根据一些规则替换getInstance()中的类。 我在用PHP工作,如果那件事


2
提供执行相同操作的不同功能签名是一个好主意吗?
这是一个用三个值构造的C ++类。 class Foo{ //Constructor Foo(std::string, int, char); private: std::string foo; char bar; int baz; }; 所有参数类型都不同。 我可以重载构造函数,因此顺序无关紧要。 class Foo{ //Constructors Foo(std::string, char, int); Foo(std::string, int, char); Foo(char, int, std::string); Foo(char, std::string, int); Foo(int, std::string, char); Foo(int, char, std::string); private: std::string foo; char bar; int baz; }; 但这是个好主意吗? 我开始这样做是因为我知道一个类/函数需要什么东西。 我并不总是记得他们接受了什么命令。 …

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.