Questions tagged «design»

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

10
在编写简单网站(例如通讯录)时,什么是好的(简洁的)架构?
当我建立一个简单的网站(例如可以在其中添加,删除和更新联系人的通讯录)时,我会创建一个index.php文件,在该文件中,如果用户未登录,则要求用户输入密码,如果用户输入正确的密码,则分配了会话,并可以与联系人进行某些操作。 我有两个文件: 第一个(contacts.php)用于显示HTML代码。在HTML代码上方,我包括第二个文件并创建类。 第二个(contacts_class.php)包含添加,删除和更新的所有方法。 我认为可以,但是在实施大型项目时,我应该怎么做?我是否必须为每个页面创建文件夹并将文件放入其中(如上面的HTML和类),我应该怎么做?什么是一个好的且整洁的体系结构,用于构建其他程序员都能完全理解的大型项目?

9
您如何组织高度定制的软件?
我正在从事一个大型软件项目,该项目针对世界各地的各种客户进行了高度定制。这意味着我们可能有80%的代码在各个客户之间是通用的,但是还有很多代码必须从一个客户转换到另一个客户。过去,我们是在单独的存储库(SVN)中进行开发的,而当一个新项目开始时(我们的客户很少,但客户众多),我们根据过去的项目中最能满足我们需求的代码创建了另一个存储库。过去一直有效,但是我们遇到了几个问题: 在一个存储库中修复的错误不会在其他存储库中修补。这可能是组织问题,但我发现很难在5个不同的存储库中修复和修补错误,请记住,维护该存储库的团队可能位于世界的另一部分,并且我们没有测试环境,既不知道他们的时间表,也不知道他们有什么要求(一个国家的“错误”可能是另一个国家的“功能”)。 为一个项目进行的功能和改进可能对另一项目也可能有用,或者丢失了这些功能或进行了改进,或者如果将这些功能和改进用在另一个项目中,则经常导致将它们从一个代码库合并到另一个代码库的麻烦(因为两个分支可能已经独立开发了一年) )。 如果必须在分支之间合并所有这些更改,则在一个开发分支中进行的重构和代码改进可能会丢失或造成的危害大于弊。 我们现在正在讨论如何解决这些问题,到目前为止,我们提出了以下解决方案: 将开发保持在单独的分支中,但是要通过建立一个中央存储库来更好地组织它,其中将常规错误修复程序合并到其中,并使所有项目定期(例如每天)将来自该中央存储库的更改合并到自己的更改中。这需要庞大的纪律和分支之间的合并工作。因此,我不相信这会奏效,并且我们可以保持这一纪律,尤其是在时间压力加大的情况下。 放弃单独的开发分支,并建立一个中央代码存储库,我们所有的代码都将存在于此,并通过具有可插拔模块和配置选项进行自定义。我们已经在使用Dependency Injection容器来解析代码中的依赖关系,并且我们在大多数代码中都遵循MVVM模式,以将业务逻辑与UI完全分开。 第二种方法似乎更优雅,但是这种方法有很多未解决的问题。例如:如何处理模型/数据库中的更改/添加。我们将.NET与Entity Framework结合使用来拥有强类型化的实体。我看不到如何处理一个客户所需的属性,而又另一个客户无用的属性而又不会弄乱我们的数据模型。我们正在考虑通过使用卫星表(有一个单独的表,其中特定实体的额外列与原始实体1:1映射在一起)解决数据库中的问题,但这仅是数据库。您如何在代码中处理此问题?我们的数据模型位于一个中央库中,使用该方法我们将无法为每个客户扩展。 我敢肯定,我们不是唯一一个在这个问题上苦苦挣扎的团队,我很震惊地发现关于该主题的资料很少。 所以我的问题如下: 您对高度定制的软件有什么经验,选择了哪种方法以及它如何为您工作? 您推荐哪种方法,为什么?有没有更好的方法? 您是否可以推荐有关该主题的好书或文章? 您对我们的技术环境(.NET,实体框架,WPF,DI)有具体建议吗? 编辑: 感谢所有的建议。大多数构想与我们团队中已有的构想相符,但了解您对它们的经验以及更好地实施它们的提示确实很有帮助。 我仍然不确定我们会走哪条路,也没有做出决定(单独做出),但是我会在团队中传递这一点,并且我相信这会有所帮助。 目前,男高音似乎是一个使用各种客户特定模块的单一存储库。我不确定我们的体系结构是否达到这个目标,或者我们需要投入多少资金才能使其适应要求,因此有些事情可能会在单独的存储库中保留一段时间,但是我认为这是唯一可行的长期解决方案。 因此,再次感谢您的所有回复!

2
谁应该阅读Exception.Message(如果有的话)?
在设计异常时,我应该编写用户或开发人员应该理解的消息吗?谁真正应该是异常消息的阅读者? 我发现异常消息根本没有用,我总是很难编写它们。按照约定,异常的类型应该已经告诉我们为什么某些事情不起作用,并且自定义属性可能会添加更多信息,例如文件名,索引,键等。那么为什么在消息本身中重复它呢?自动生成的消息也可以执行此操作,它所必须包含的就是带有其他属性列表的异常名称。这和手写文本一样有用。 根本不编写消息,而是使用特殊的异常渲染器来处理可能创建于不同语言中的有意义的消息,而不是用代码对其进行硬编码,这会更好吗? 我被问到这些问题中的任何一个是否都可以回答我的问题: 如何编写好的异常消息 为什么许多异常消息不包含有用的详细信息? 我读过他们两个,但对他们的回答感到不满意。他们通常谈论用户,并着重于消息本身的内容,而不是收件人,事实证明,至少可以有两个用户:最终用户和开发人员。我永远不知道在编写异常消息时应该和哪个人说话。 我什至认为这条著名的消息根本没有任何真正的价值,因为它只是用不同的词来重复异常类型的名称,所以为什么还要费心编写它们呢?我可以完美地自动生成它们。 对我而言,异常消息缺乏读者的区分。一个完美的例外将需要提供至少两个消息版本:一个针对最终用户,一个针对开发人员。仅将其称为消息太笼统了。然后,应该用英语编写开发人员消息,但最终用户的消息可能需要翻译成其他语言。仅用一条消息是不可能实现所有这些的,因此异常将需要为最终用户消息提供一些标识符,正如我刚才所说的,该标识符可能以不同的语言提供。 当我阅读所有其他链接的问题时,我得到的印象是,异常消息的确是由最终用户而非开发人员阅读的……一条消息就像也要吃蛋糕一样。

7
函数式编程是否忽略了“关于将系统分解为模块所用的准则”(数据隐藏)所带来的好处?
我第一次读过一篇经典的文章,名为《关于将系统分解为模块的标准》。这对我来说很有意义,并且可能是OOP所基于的那些文章之一。结论: 我们试图通过这些示例来证明,根据流程图将系统分解为模块几乎总是不正确的。...然后每个模块都被设计为对其他模块隐藏这样的决定 以我未受过教育和缺乏经验的观点,函数式编程与本文完全相反。我的理解是函数式编程使数据流变得惯用了。数据从一个函数传递到另一个函数,每个函数都密切了解数据并在此过程中“更改”它。而且我想我已经看过Rich Hickey的演讲,他在演讲中谈到数据隐藏是如何被高估或不必要的,但我不确定。 首先,我想知道我的评估是否正确。FP范式和本文在哲学上是否不一致? 假设他们不同意,FP如何“弥补”缺乏数据隐藏的能力?也许他们牺牲了数据隐藏,但获得了X,Y和Z。我想知道为什么X,Y和Z比数据隐藏更有益的原因。 或者,假设他们不同意,也许FP认为数据隐藏很糟糕。如果是这样,为什么会认为数据隐藏不好? 假设他们同意,我想知道什么是FP数据隐藏实现。很明显在OOP中看到了这一点。您可以拥有一个private班级以外的人无法访问的字段。在FP中,没有明显的比喻。 我觉得还有其他问题要问,但我不知道我要问。也可以随意回答。 更新资料 我发现尼尔·福特(Neal Ford)的演讲中有一个非常相关的幻灯片。我将屏幕截图嵌入此处:

4
原型继承实际上与经典继承有何不同?
继承,多态性和封装是OOP的三个最不同的重要特征,从它们来看,继承如今具有很高的使用统计。我正在学习JavaScript,在这里,他们都说它具有原型继承,而且各地的人们都说它与经典继承大不相同。 但是,从实际使用的角度来看,我不明白它们有什么区别?换句话说,当您定义基类(原型)然后从中派生一些子类时,您都可以访问基类的功能性对象,并且可以在派生类上扩展功能。如果我们认为我所说的是继承的预期结果,那么为什么我们要使用原型还是经典版本呢? 为了使自己更加清楚,我认为原型继承和经典继承的有用性和使用方式没有区别。这导致我没有兴趣去了解它们为何不同的原因,因为它们都导致同一件事,OOAD。原型继承实际上(不是理论上)与经典继承有何不同?

9
从用户界面解耦类
关于编写可能必须了解用户界面的类的最佳实践是什么?知道如何绘制自身的类不会因为依赖于用户界面(控制台,GUI等)而打破了一些最佳做法吗? 在许多编程书籍中,我都遇到了显示继承的“ Shape”示例。基类形状具有一个draw()方法,该方法会覆盖每个形状,例如圆形和正方形。这允许多态性。但是draw()方法不是非常依赖于用户界面是什么吗?如果我们将此类写为Win Forms,则不能将其用于控制​​台应用程序或Web应用程序。它是否正确? 这个问题的原因是,我发现自己总是陷入困境,并且挂在如何归纳类上,因此它们是最有用的。这实际上对我不利,我想知道我是否在“努力”。
27 design 

12
SOLID与避免过早抽象
我了解SOLID在模块化很重要且其目标显然有用的情况下应定期完成并使用的功能。但是,有两点使我无法在代码库中一致地应用它: 我想避免过早的抽象。以我的经验,绘制没有具体用例(现在或可预见的将来)的抽象线会导致将它们绘制在错误的位置。当我尝试修改此类代码时,抽象行会妨碍您的工作,而不是有所帮助。因此,我倾向于不画任何抽象线,直到我对它们的用处有了一个很好的认识。 我发现很难证明增加模块化本身是合理的,如果它使我的代码更冗长,更难理解等,并且不能消除任何重复。我发现有时,简单,紧密耦合的过程或God对象代码比构造良好的馄饨代码更易于理解,因为流程简单且线性。编写起来也容易得多。 另一方面,这种心态常常导致神的对象。我通常会保守地重构它们,仅在看到清晰的模式出现时才添加清晰的抽象线条。如果您显然不需要更多的模块化,没有大量重复且代码可读性强,那么上帝对象和紧密耦合的代码怎么办? 编辑:就个别SOLID原则而言,我想强调的是,Liskov Substitution是IMHO的常识形式化,应在所有地方应用,因为如果不是这样的话,抽象是没有意义的。同样,每个类都应该在某个抽象级别上担负单个责任,尽管这可能是一个很高的级别,将实现细节都塞进一个庞大的2,000行类中。基本上,您的抽象应该在您选择抽象的地方有意义。在模块化不是很有用的情况下,我所质疑的原则是开放式,接口隔离,尤其是依赖关系倒置,因为这些都是关于模块化的,而不仅仅是让抽象有意义。

11
哄骗商务人士?
哪种方法似乎最能哄骗非技术业务人员的需求? 我正在与一个团队一起努力为项目制定规格。每次我们见面时,都达到下次会议的期望,我们要求业务人员重新提出他们的要求。他们通常会这样回答:“好吧,您认为你们可以提出一个原型,以便我们下周看到我们喜欢的东西吗……您知道,因为它是一个原型,所以没有任何数据或任何东西,只有功能。”这是一个耗时6个月的项目,因此这显然是不可行的(我们将不得不开发整个产品!),而且,如果没有某种规范,我们甚至不知道要原型制作什么。坦率地说,我认为像大多数人一样,他们对自己想要的东西有所了解,只是他们没有以收集真正需求所必需的集中方式进行思考。除了简单地告诉他们,“给我们您想要的东西,或者我们不能/不会做任何工作”(我们希望他们对结果满意),有没有办法帮助他们决定他们想要什么?例如,我们可以告诉他们: “绘制一些屏幕(在Powerpoint中,在餐巾纸上,等等),显示想要的用户界面以及所有要查看的数据,并在页边空白处描述功能。由此,我们将完善它,并根据这组行为要求构建后端。” 要么 “不必担心它现在的外观(数字1会挂断)。只要给我们列出您想要的有关程序跟踪的每件事的所有数据的列表。因此,对于“客户”,您可以列出:名称,地址,电话号码,订单等。它不一定是完美的数据库结构,但是我们可以从中得出一些信息,并了解您的需求” 这些替代方法中的任何一种都可以使业务人员专注于他们想要的东西是否有意义?您在行动中是否有其他选择?

2
圈复杂度范围[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 圈复杂度的类别是什么?例如: 1-5:易于维护 6-10:困难 11-15:非常困难 20+:接近不可能 多年以来,我一直认为10是极限。除此之外的任何事情都是不好的。我正在分析解决方案,并且正在尝试确定代码的质量。当然,圈复杂度不是唯一的衡量标准,但可以提供帮助。有些方法的圈复杂度为200+。我知道这很糟糕,但是我很想知道下限范围,就像上面的例子一样。 我发现了: 卡内基梅隆大学的上述参考值定义了圈复杂度值的四个粗略范围: 1至10之间的方法被认为简单易懂 10到20之间的值表示更复杂的代码,可能仍然可以理解;但是由于代码可能会占用更多的分支,因此测试变得更加困难 20或更高的值是具有大量潜在执行路径的典型代码,只有非常困难和努力才能完全掌握和测试 方法甚至更高,例如> 50,肯定是无法维护的 在为解决方案运行代码指标时,结果在25以下的所有项目均显示为绿色。我不同意这一点,但我希望得到其他输入。 是否有普遍接受的范围复杂性的范围列表?

5
如何解释为什么设计选择好?[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 4年前关闭。 随着我成为一名更好的开发人员,我发现我的许多设计技能更多地来自于直觉而非机械分析。这很棒。它使我可以阅读代码并更快地体会到它。它使我可以轻松地在语言和抽象之间转换设计。它使我可以更快地完成工作。 缺点是,我发现很难向队友(更糟糕的是,管理层)解释为什么特定的设计是有利的。特别是在最佳实践方面落后于时代的队友。“这种设计更具可测试性!” 或“与继承相比,您应该更偏向于组成。” 直奔他们的脑袋,进入我的兔子洞,试图让所有人都了解软件工程的最新进展。 我当然会在实践上做得更好,但是与此同时,这会浪费很多时间和/或糟糕的设计(这将导致以后浪费时间进行修复)。当好处对听众来说并不完全明显时,我该如何更好地解释为什么某种设计会更好?

11
被多线程错误困扰
在我管理的新团队中,我们的大部分代码是平台,TCP套接字和http网络代码。所有C ++。其中大多数来自离开团队的其他开发人员。团队中目前的开发人员非常聪明,但从经验来看大多是初级的。 我们最大的问题:多线程并发错误。我们的大多数类库都通过使用某些线程池类而被编写为异步的。类库中的方法通常将长时间运行的任务从一个线程排队到线程池中,然后在另一个线程上调用该类的回调方法。结果,我们有很多涉及错误线程假设的边缘错误。这导致了一些细微的错误,这些错误不仅仅具有关键部分和锁以防止并发问题。 使这些问题更难解决的是,修复尝试通常是不正确的。我发现团队在尝试(或在遗留代码本身中)尝试犯的一些错误包括以下内容: 常见错误#1-通过仅对共享数据进行锁定来解决并发问题,但是忘记了当方法未按预期顺序调用时会发生什么情况。这是一个非常简单的示例: void Foo::OnHttpRequestComplete(statuscode status) { m_pBar->DoSomethingImportant(status); } void Foo::Shutdown() { m_pBar->Cleanup(); delete m_pBar; m_pBar=nullptr; } 因此,现在有了一个错误,其中在OnHttpNetworkRequestComplete发生时可以调用Shutdown。测试人员找到错误,捕获故障转储,并将错误分配给开发人员。他反过来修复了这样的错误。 void Foo::OnHttpRequestComplete(statuscode status) { AutoLock lock(m_cs); m_pBar->DoSomethingImportant(status); } void Foo::Shutdown() { AutoLock lock(m_cs); m_pBar->Cleanup(); delete m_pBar; m_pBar=nullptr; } 除非您意识到还有一个更微妙的边缘情况,否则上面的修补程序看起来不错。如果在调用OnHttpRequestComplete 之前调用Shutdown,会发生什么情况?我的团队拥有的真实示例更加复杂,并且在代码审查过程中很难发现边缘情况。 常见错误#2-通过盲目退出锁来解决死锁问题,等待另一个线程完成,然后重新进入锁-但是没有处理对象只是被另一个线程更新的情况! 常见错误#3-即使对象是引用计数,关闭序列也会“释放”它的指针。但是忘记等待仍在运行的线程释放它的实例。这样,组件将完全关闭,然后在不希望再有任何调用的状态下在对象上调用伪造或较晚的回调。 还有其他边缘情况,但最重要的是: 即使对于聪明人,多线程编程也很难。 当我发现这些错误时,我会花时间与每个开发人员讨论这些错误,以开发更合适的修复程序。但是我怀疑,由于“正确的”解决方案涉及到大量遗留代码,因此他们常常对如何解决每个问题感到困惑。 我们将很快发货,并且我确定我们正在应用的补丁将在即将发布的版本中保留。之后,我们将有一些时间来改善代码库并在需要时进行重构。我们将没有时间重新编写所有内容。而且大多数代码还不错。但是我希望重构代码,以便可以完全避免线程问题。 我正在考虑的一种方法是这种方法。对于每个重要的平台功能,请使用专用的单线程,将所有事件和网络回调整理到其中。与Windows中使用消息循环的COM公寓线程相似。长阻塞操作仍然可以分派到工作池线程,但是完成回调在组件的线程上调用。组件甚至可能共享同一线程。然后,可以在单个线程世界的假设下编写线程中运行的所有类库。 在走这条路之前,如果还有其他标准技术或设计模式来处理多线程问题,我也非常感兴趣。我必须强调-除了描述互斥量和信号量基础知识的书以外的内容。你怎么看? 我也对其他用于重构过程的方法感兴趣。包括以下任何一项: 有关线程周围设计模式的文献或论文。除了互斥量和信号量介绍之外,还有其他内容。我们也不需要大规模的并行性,只需设计对象模型以正确处理来自其他线程的异步事件的方法即可。 …


3
是否有要在新系统中保留的常用用户名列表?
此问题是从Stack Overflow 迁移而来的,因为可以在Software Engineering Stack Exchange上回答。 迁移 8年前。 我需要在新网站中保留用户名。 这些通常分为三类 1)没有一个人名(例如:admin,user,service,help,root等) 2)我们可能想保留的超级著名人物或公司的名称 3)我们直接指定的其他名称。 如果前两个类别的用户名列表存在于某个地方,我可以使用它们,那将非常有帮助。 有人知道这样的名单吗?

8
您如何在Scrum中处理设计?
您如何在Scrum中处理设计?对于每次Scrum迭代,您是否还有写得很好的设计文档?您是否只是以UML图为特色进行设计说明?或者,您是否拥有注释良好的代码? 每次迭代都可能涉及更改设计,所以我只想知道人们是如何捕捉到这一点的,因此新开发人员可以轻松地了解领域并尽快入职。
26 design  scrum 

4
您如何处理多个用户在Webapp中编辑同一条数据?
我正在处理的一个项目正在寻找一个Web应用程序,该应用程序将管理多个用户之间的任务列表。这是一个主任务列表,其任务项由授权用户分发。每个用户都有自己的帐户来登录和查看分配给他们的任务;多个用户可能有一个共同的任务。 我试图将项目的详细信息排除在外,因为我将更多地与如何处理以下情况的整体概念作斗争,但是如果有帮助,我将使用Java,EclipseLink和GWT,并实现RequestFactory。该数据库是PostgreSQL。 因此,我尝试解决的概念性问题如下: 如果多个用户共有的单个任务以任何方式更改(例如任务完成,删除等),则具有此任务的所有用户的任务列表都将更新。有哪些设计模式可帮助实现此功能? 我查看过的某些模式是“观察员”和“调解员”-在这些模式上是否应该考虑其他模式? 假设有两个用户同时更改同一任务。 首先,我应该允许这种情况发生还是在某个人完成更改之前将其锁定? 其次,如果不加锁,我该如何调和接受谁的更改?这涉及1中的情况,因为用户1可以提交数据,并且在用户2接收更新的数据之前,他/她可能已经前进并提交了他/她的更改。 我真的在寻找您可以提供的有关如何在此Web应用程序的多个实例之间正确同步数据的任何指导点,建议或技巧。我将不胜感激!

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.