Questions tagged «design»

有关通过软件设计解决问题和计划解决方案的问题。

5
向UI报告进度的最佳策略-回调应该如何发生?
有时,用户会启动一项扩展的技术操作,该操作需要一段时间才能执行。在这些情况下,通常最好显示某种进度条以及有关当前正在执行哪个任务的信息。 为了避免UI和逻辑层之间的紧密耦合,通常最好通过某种代理进行通信。也就是说,后端不应该操纵自己的UI元素,甚至不应该直接与中介层进行交互。 显然,必须在某处进行一些回调才能使此工作正常进行。我通常以两种方式之一实现它: 将可变对象传递给后端,并让后端在进行时对其进行更改。发生更改时,对象会通知前端。 传递形式void f(ProgressObject)或后端调用的回调函数ProgressObject -> unit。在这种情况下,后端构造了ProgressObject,并且完全是被动的。我认为,每次要报告进度时,它都必须构造一个新对象。 这些方法的缺点和优点是什么?有没有商定的最佳使用方法?有不同的使用环境吗? 是否有完全不同的报告进度的技术被我忽略了?

2
仅具有一个实例的Python类:何时创建(单个)类实例以及何时使用该类?
给定一个仅实例化一次的Python类,即该类中只有一个对象。我想知道在什么情况下创建单个类实例而不是直接与该类一起工作才有意义。 有一个类似的问题,但重点不同: 它是关于将全局变量和函数分组为一个类, 它不是特定于Python的。后者意味着它不考虑(在Python中)类也是对象的事实。 更新: 在Python中,我可以对类和对象执行以下操作: class A(object): pass A.some_state_var = True # Then later A.some_state_var = False my_a = A() my_a.some_state_var = True # Then later my_a.some_state_var = False 因此,我看不到在类和该类的实例之间进行选择如何与状态有关(在Python中)。我可以通过两者之一来保持状态。 此外,创建我的类/类实例的动机与执行Singleton要求无关。 另外,创建新的Type并不需要太多。 这样做的动机是将相关的代码和数据进行分组,并为其提供接口。这就是为什么我最初在类图中将其建模为类的原因。仅当涉及到实现时,我才开始怀疑是否要实例化此类。


5
是否应该始终完全封装内部数据结构?
请考虑此类: class ClassA{ private Thing[] things; // stores data // stuff omitted public Thing[] getThings(){ return things; } } 此类将用于存储数据的数组公开给任何感兴趣的客户端代码。 我是在正在开发的应用中完成此操作的。我有一个ChordProgression存储序列Chords的类(并执行其他一些操作)。它有一个Chord[] getChords()返回和弦数组的方法。当必须更改数据结构(从数组更改为ArrayList)时,所有客户端代码都将中断。 这让我思考-也许以下方法更好: class ClassA{ private Thing[] things; // stores data // stuff omitted public Thing[] getThing(int index){ return things[index]; } public int getDataSize(){ return things.length; } public void setThing(int …

6
哪些更改太大而无法通过适当的设计轻松实现?
这是一个相当模糊的问题,但这是我在阅读有关适当设计的内容时从未感到满意的答案。 通常,在学习面向对象的编程,抽象,分解等方法时,设计的圣杯以及它们始终声称您使用的是开发技术的原因是,这将使您的程序“易于更改” ,“可维护的”,“灵活的”或用于表达这种有效果的概念的任何同义词。通过将ivars标记为私有,将代码拆分为许多小的自包含方法,使接口保持通用,可以使您完全轻松自如地修改程序。 对于较小的更改,这对我来说效果很好。改变类以提高性能所用的内部数据结构从来都不是主要困难,而且独立于API的用户界面端也没有改变,例如重新设计文本输入系统或检修游戏元素的图形。 所有这些更改似乎天生就是独立的。就所涉及的外部代码而言,它们均不涉及对要修改的程序组件的行为或设计进行任何更改。无论您是以程序编写还是以OO样式编写(具有大型功能还是小型功能),即使您只有中等程度的设计,也可以轻松进行这些更改。 但是,每当更改变得繁琐而繁琐时(即,对API进行更改),我的所有宝贵“模式”都无法挽救。巨大的变化仍然很大,受影响的代码仍然受到影响,并且大量的错误产生工作摆在我面前。 所以,我的问题是这个。适当的设计声称能够促进多大的变化?是否有一些其他的设计技术,或者对我来说是未知的,或者是我没有实现,确实确实使粘滞性修改变得简单,还是那个承诺(我听说过这么多不同的范例)仅仅是一个好主意,完全脱离了软件开发的一成不变的真理?我可以添加到工具栏中的“更改工具”吗? 具体来说,导致我进入论坛的问题是:我一直在努力实现一种解释性编程语言(在D中实现,但这无关紧要),并且我决定将闭包的参数设为基于关键字,而不是当前的位置。这就需要修改所有现有的调用匿名函数的代码,幸运的是,这很小,因为我很早就开发了我的语言(<2000行),但是如果我稍后再做出决定,那将是巨大的。在这种情况下,是否可以通过适当的预见性设计使修改变得更容易,或者确定(大多数)变化本质上影响深远?我很好奇这是否是我自己的设计技能的失败-如果是的话,我 明确地说,我绝不怀疑OOP或其他常用的模式。但是,对我而言,它们的优点在于代码库的原始编写而不是维护。继承使您可以很好地抽象出重复的模式,多态性使您可以通过人类理解的函数(哪个类)而不是由机器理解的效果(switch语句的哪个分支)来分离代码,而小的独立函数可以让您以一种非常愉快的“自下而上”的风格写作。但是,我对他们的灵活性表示怀疑。

4
命令模式设计
我有Command模式的旧实现。这是通过所有DIOperation实现传递一个Context的方法,但是后来我意识到,在学习过程中(永远不会停止),这并不是最佳的。我也认为这里的“访问”并不适合,只会造成混乱。 我实际上是在考虑重构我的代码,这也是因为一个Command对其他命令一无所知,并且现在它们都共享相同的键值对。很难维护哪个类拥有哪个键值,有时会导致变量重复。 用例示例:假设CommandB需要由CommandA设置的UserName。CommandA是否应该设置键UserNameForCommandB = John?还是应该共享一个公共的UserName = John键值?如果用户名被第三个命令使用怎么办? 如何改善设计?谢谢! class DIParameters { public: /** * Parameter setter. */ virtual void setParameter(std::string key, std::string value) = 0; /** * Parameter getter. */ virtual std::string getParameter(std::string key) const = 0; virtual ~DIParameters() = 0; }; class DIOperation { public: /** * Visit before …

5
我应该使用抽象方法还是虚拟方法?
如果我们假设不希望基类成为纯接口类,并使用下面的两个示例,那么使用抽象或虚拟方法类定义是更好的方法吗? “抽象”版本的优点是它看起来更简洁,并强制派生类提供希望的有意义的实现。 “虚拟”版本的优点是可以轻松地由其他模块插入并用于测试,而无需像抽象版本那样添加大量底层框架。 摘要版本: public abstract class AbstractVersion { public abstract ReturnType Method1(); public abstract ReturnType Method2(); . . public abstract ReturnType MethodN(); ////////////////////////////////////////////// // Other class implementation stuff is here ////////////////////////////////////////////// } 虚拟版本: public class VirtualVersion { public virtual ReturnType Method1() { return ReturnType.NotImplemented; } public virtual ReturnType Method2() …
11 c#  design 

3
在视图模型中使用业务对象
使用可重用的业务对象时,在构建视图模型时什么是最佳实践? 我们使用调用的对象Builder来构建视图模型。每个视图逻辑单元(订单,用户等)的一个构建器,其中每个单元可以包含许多不同的视图模型(订单包含摘要,订单行等)。 建造者可以通过一个或多个标准业务对象提取数据,以建立视图模型。 在视图模型中使用业务对象/模型时,什么被认为是更好的做法? 方法1 允许在视图模型中使用业务对象? //Business object in some library public class Order { public int OrderNum; public int NumOrderLines; //... } //Order builder in website public class OrderBuilder { public OrderSummary BuildSummaryForOrder(int OrderNum) { Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum); //Any exception handling, additional logic, or whatever OrderSummary obModel = …

3
try-catch-finally块中无关的代码“有多糟糕”?
这是一个相关的问题: 在返回不良样式/危险之后,使用finally子句进行工作吗? 在引用的Q中,最终代码与所使用的结构和预取的必要性有关。我的问题有所不同,我认为这与广大受众密切相关。我的特定示例是C#winform应用程序,但这同样适用于C ++ / Java。 我注意到很多try-catch-finally块,其中有很多与异常无关的代码以及埋在该块中的异常处理/清除。而且,我会偏向于使用非常紧密的try-catch-finally块,并将其代码与异常和处理紧密相关。这是我所看到的一些示例。 尝试块将设置许多初步调用和变量,从而导致可能引发的代码。日志信息将被设置并在try块中运行。 最后,块将具有表单/模块/控件格式化调用(尽管应用程序即将终止,如catch块所示),以及创建新对象(例如面板)。 大致: methodName(...) { 尝试 { //该方法的大量代码... //可能抛出的代码... //该方法还有更多代码和返回值... } 抓住(某物) {//处理异常} 最后 { //由于异常而进行一些清理,将事情关闭 //有关所创建内容的更多代码(忽略任何异常都可能引发)... //可能会创建更多对象 } } 该代码有效,因此具有一定的价值。它没有很好地封装,逻辑有点混乱。我(痛苦地)熟悉了代码移位和重构的风险,因此我的问题归结为想要了解其他人对类似结构的代码的经验。 不良的风格是否有理由进行更改?有没有人被类似的情况严重烧死?您是否愿意分享糟糕经历的细节?别说是因为我反应过度,风格还不错吗?获得整理事物的维护利益?

4
C ++中的术语“接口”
Java对class和进行了明确区分interface。(我相信C#也可以,但是我没有经验)。但是,在编写C ++时,类和接口之间没有语言强制的区分。 因此,我一直将接口视为解决Java中缺乏多重继承的一种解决方法。在C ++中做出这样的区分是任意的,毫无意义的。 我一直倾向于使用“以最明显的方式编写东西”的方法,因此,如果在C ++中,我得到了Java中所谓的接口,例如: class Foo { public: virtual void doStuff() = 0; ~Foo() = 0; }; 然后,我决定大多数的实现者Foo都想共享一些我可能会写的通用功能: class Foo { public: virtual void doStuff() = 0; ~Foo() {} protected: // If it needs this to do its thing: int internalHelperThing(int); // Or if it doesn't need the …

5
编写可测试代码与避免投机性
我今天早上在看一些博客文章,偶然发现了这一篇: 如果唯一实现Customer接口的类是CustomerImpl,那么您实际上就没有多态性和可替代性,因为实际上在运行时没有什么可以替代。这是假的普遍性。 这对我来说很有意义,因为实现接口会增加复杂性,而且,如果只有一种实现,则可能会争辩说它会增加不必要的复杂性。编写比需要的抽象要抽象得多的代码通常被认为是被称为“投机性一般性”的代码气味(在文章中也提到了)。 但是,如果我遵循TDD,那么如果没有这种推测性的普遍性(无论是接口实现形式还是我们的其他多态选项),就无法(轻松)创建测试双打,从而使类可继承且其方法是虚拟的。 那么,我们如何协调这种权衡呢?以投机性方式推广测试/ TDD是否值得?如果您使用的是测试双打,是否将这些视为第二种实现方式,从而使普遍性不再具有推测性?您是否应该考虑一个更重的模拟框架,该框架可以模拟具体的协作者(例如,C#世界中的Moles与Moq)?或者,您应该使用具体的类进行测试,并编写什么可以被视为“集成”测试,直到您的设计自然需要多态性之前? 我很想阅读其他人对此事的看法-预先感谢您的意见。

3
使用Scala和LWJGL的简化游戏的函数式编程方法
我是一名Java命令程序员,我想了解如何基于功能性编程设计原则(特别是引用透明性)生成简单版本的Space Invaders。但是,每当我尝试考虑一种设计时,我都会迷失在极端可变性的泥潭中,而这种可变性是函数式编程纯粹主义者所避免的。 为了学习函数式编程,我决定尝试使用LWJGL在Scala中创建一个非常简单的2D交互式游戏Space Invader(注意缺少复数形式)。以下是基本游戏的要求: 用户在屏幕底部分别通过“ A”和“ D”键向左和向右移动 用户发射的子弹由空格键直接向上发射,两次射击之间的最小间隔为0.5秒 两次射击之间的随机时间为0.5到1.5秒,直接发射外星飞弹 在原始游戏中故意遗漏的是WxH外星人,可降解的防御屏障x3,屏幕顶部的高速飞碟船。 好的,现在到实际的问题域。对我来说,所有确定性部分都是显而易见的。那些不确定的部分似乎阻碍了我思考方法的能力。确定性部分是子弹一旦存在的轨迹,外星人的连续运动以及由于击中玩家的船或外星人(或两者)而引起的爆炸。对我来说,不确定的部分正在处理用户输入流,处理用于确定外来子弹射击的随机值以及处理输出(图形和声音)。 这些年来,我可以做(并且已经做过很多)这类游戏。但是,所有这些都来自命令式范式。而且LWJGL甚至提供了一个非常简单的Java版的“太空侵略者”(我开始使用Scala作为Java(不带分号)将其迁移到Scala)。 以下是围绕该领域讨论的一些链接,似乎没有一个人以Java / Imperative编程人员会理解的方式直接处理这些想法: 纯功能复古游戏,第1部分,詹姆斯·海格(James Hague) 类似的堆栈溢出帖子 Clojure / Lisp游戏 Haskell游戏堆栈溢出 Yampa(在Haskell中)功能响应式编程 It appears that there are some ideas in the Clojure/Lisp and Haskell games (with source). Unfortunately, I am not able to read/interpret the code into mental models …

6
与单一责任原则作斗争
考虑以下示例: 我有一个网站。它允许用户发布帖子(可以是任何内容)并添加描述帖子的标签。在代码中,我有两个代表帖子和标签的类。让我们称这些类Post和Tag。 Post负责创建帖子,删除帖子,更新帖子等。 Tag负责创建标签,删除标签,更新标签等。 缺少一项操作。标签到帖子的链接。我正在努力与谁应该执行此操作。它在任何一个类别中都同样适用。 一方面,Post该类可以具有一个将a Tag作为参数的函数,然后将其存储在标签列表中。另一方面,Tag该类可以具有将a Post作为参数并将链接Tag到的函数Post。 以上只是我的问题的一个示例。实际上,我遇到了多个相似的类。两者都可以很好地融合在一起。除了实际上在两个类中都包含功能之外,还存在哪些约定或设计风格可以帮助我解决此问题。我假设必须要挑选一个呢? 也许将它们放在两个类中都是正确的答案?

8
如果您在诸如敏捷或XP的进化方法中达到设计死胡同,该怎么办?
当我阅读马丁·福勒(Martin Fowler)著名的博客文章《设计死了吗?,我得到的惊人印象之一是,鉴于在敏捷方法论和极限编程中,设计和编程都是进化的,总有一些地方需要重构。 当程序员的水平很好并且他们了解设计的含义并且没有犯严重错误时,代码可能会继续发展。但是,在正常情况下,在这种情况下的地面现实是什么? 通常情况下,产品会进行重大开发,而当需求发生重大变化时,这是否不是我们想要多大的期望就不能修改基本设计方面的约束呢?(而不会丢弃大部分代码)。在设计和要求方面的任何进一步改进方面,人们不太可能走到尽头吗? 我不是在这里提倡任何非敏捷实践,但我想向实践敏捷,迭代或进化发展方法的人们了解他们的真实经验。 你有没有遇到这样的死胡同?您如何避免或逃脱了它?还是有措施确保设计在发展过程中保持清洁和灵活?
11 design  agile 

1
绘图线程交互
我想以UML(类似)表示法绘制(笔和铅笔)线程交互。我并不坚持使用UML,任何对读者来说显而易见的事情都应该做。 我从顺序图开始,但我不认为这是实现此目的的最佳方法。一直以来,屏幕外都会有“行动发起人”,这有点违反了SSD的想法。我继承了一个中等大小的代码库,每个线程都有一个状态机,大约有9-10个线程,我试图弄清楚它是如何工作的。 我应该如何可视化线程交互?

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.