软件工程

针对在系统开发生命周期中工作的专业人士,学者和学生的问答

3
避免构造函数有很多参数
所以我有一个工厂,可以创建不同类的对象。可能的类都是从抽象祖先派生的。工厂具有配置文件(JSON语法),并根据用户的配置来决定要创建哪个类。 为此,工厂使用boost :: property_tree进行JSON解析。他遍历ptree并决定要创建哪个具体对象。 但是,产品对象具有许多字段(属性)。根据具体的类,对象具有大约5-10个属性,将来可能会更多。 因此,我不确定对象的构造函数应如何。我可以想到两种解决方案: 1)产品的构造函数希望将每个属性作为参数,因此构造函数最终将带有10个以上的参数。这将是丑陋的,并导致较长的,不可读的代码行。但是,优点是工厂可以解析JSON并使用正确的参数调用构造函数。产品类不需要知道由于JSON配置而已创建。不需要知道完全涉及JSON或配置。 2)产品的构造函数只需要一个参数property_tree对象。然后,它可以解析所需的信息。如果配置中的信息丢失或超出范围,则每个产品类别都可以正确响应。工厂不需要知道几种产品需要哪些参数。如果配置错误,工厂也不需要知道如何应对。而且构造函数的接口是统一的,很小的。但是,缺点是,该产品需要从JSON中提取所需的信息,因此,它知道如何构造它。 我倾向于选择解决方案2)。但是,我不确定这是否是好的工厂模式。让产品知道它是用JSON配置创建的,这感觉有点不对劲。另一方面,可以很简单地介绍新产品。 有什么意见吗?

2
为何程序员要定义编程模型来代替C / POSIX进行并行处理?
新计算机体系结构的提供者经常尝试引入新的编程模型,例如,最近用于GPGPU的CUDA / OpenCL,并取代C / POSIX作为平台并行性的控制接口。(Poss&Koening,AM3:迈向面向多核的硬件Unix加速器,2015年) 为什么架构设计师尝试设计新的编程模型来代替C / POSIX进行并行计算?C / POSIX是不是非常适合多处理器,还是C / POSIX的原始作者在C / POSIX设计时就没有考虑并行计算的需求?还是程序员需要比C / POSIX所提供的功能更多的功能,从而诉诸于CUDA / OpenCL等新设计?

3
使用专用设置器存根属性以进行测试
我们有对象 public class MyObject{ protected MyObject(){} public string Property1 {get;private set;} public string Property2 {get;private set;} public string Property3 {get;private set;} public string Property4 {get;private set;} public string Property5 {get;private set;} public string Property6 {get;private set;} public string Property7 {get;private set;} public string Property8 {get;private set;} public string Property9 {get;private …

2
写时复制语义的优点
我想知道写时复制有什么优点?当然,我并不期望个人观点,而是希望在实际操作中以切实可行的方式在技术上和实践中受益。实际上,我的意思不只是节省&字符输入。 要澄清的是,此问题是在数据类型的上下文中进行的,在赋值或副本构造中创建一个隐式浅表副本,但对其进行修改会创建一个隐式深表副本,并将更改应用于它而不是原始对象。 我问的原因是,我似乎没有发现将COW作为默认隐式行为的任何优点。我使用Qt,它为许多数据类型实现了COW,实际上所有数据类型都具有一些动态分配的底层存储。但是它如何真正使用户受益呢? 一个例子: QString s("some text"); QString s1 = s; // now both s and s1 internally use the same resource qDebug() << s1; // const operation, nothing changes s1[o] = z; // s1 "detaches" from s, allocates new storage and modifies first character // s is still "some …
10 c++  qt 

2
LGPL为什么要求组合作品包含GPL的副本?
我正在阅读LGPL许可证,发现以前没有意识到过这一要求。 第4节(合并作品)规定: 如果您还执行以下每个操作,则可以传达合并的工作: a)在组合作品的每份副本中都应特别注明使用了图书馆,并且本许可证涵盖了图书馆及其使用。 b)合并作品随附GNU GPL和本许可文件的副本。 C) ... 链接到LGPL许可的图书馆时,为什么还必须传达GPL?我担心将两个许可证都包含在发行版中会使用户混淆哪个许可证适用。我的解释正确吗?如果是这样,此要求背后的原因是什么?

3
哪种数据存储最适合我的情况?
我正在开发一个涉及数据库中更新/选择查询执行非常高的应用程序。 我有一个基本表(A),该表每天将有一个实体约500条记录。对于系统中的每个用户,将根据用户的某些首选项创建此实体的变体,并将它们存储在另一个表(B)中。这是通过每天在午夜运行的Cron作业完成的。 因此,如果表A中有10,000个用户和500条记录,则该天表B中将有500万条记录。我总是将数据保留在这些表中一天,午夜将历史数据存档到HBase。此设置运行良好,到目前为止,我没有任何性能问题。 最近业务需求发生了一些变化,现在基本表A中的某些属性(对于15-20条记录)将每20秒更改一次,因此我必须重新计算表B中所有这些变化记录的某些值,全部用户。即使仅更改20条主记录,我也需要重新计算并更新200,000条用户记录,这花费了20秒钟以上的时间,然后才发生下一次更新,最终导致所有Select查询排队。我从在线用户那里得到3个获取请求/ 5秒,这导致6-9个选择查询。为了响应api请求,我总是使用表B中的字段。 我可以购买更多的处理能力来解决这种情况,但是我对拥有一个可以处理甚至一百万用户的适当缩放的系统感兴趣。 这里有人可以提出更好的选择吗?Nosql +关系数据库对我有帮助吗?是否有任何平台/数据存储可让我频繁地更新数据而不会锁定,同时又使我能够灵活地在实体的各个字段上运行选择查询?

4
查找表:它们是否在域模型中泄漏?
您正在建立一个跟踪公司的系统。这些公司有联系人。这些联系人通常都是专家,只回答某些类型的问题,例如帐单/付款,销售,订购和客户支持。 使用域驱动设计和洋葱架构,我使用以下类型对它进行了建模: 公司 有联络人 联系 有联系方式 ContactType(枚举) CompanyRepository(接口) EFCompanyRepository(在外部程序集中定义,使用EntityFramework,实现CompanyRepository) 对于如何为该应用程序建模数据库,我们的团队意见分歧。 A面:精益DDDers: 定义哪些ContactTypes对一个联系人有效是Domain的工作。向数据库中添加表以验证是否未保存未知的ContactType是域泄漏的迹象。它将逻辑传播得太远了。 将静态表添加到数据库和相应的代码是浪费的。在此应用程序中,数据库解决了一个问题:保留事物并将其还给我。编写一个额外的表和相应的CRUD代码很浪费。 更改持久性策略应尽可能容易。更改业务规则的可能性更大。如果我决定SQL Server花费太多,则不需要重新构建放在架构中的所有验证。 B面:传统主义者[这可能不是一个好名字。DBCentrists?]: 在数据库中存储没有读取代码就没有意义的数据是一个坏主意。报表和其他使用者必须自己重复值列表。 按需加载数据库类型字典的代码并不多。不用担心 如果更改的源是代码而不是数据,那么当更改时,我将不得不部署位而不是简单的SQL脚本。 哪一方都不对或错,但从长远来看,其中一方可能会更有效率,计算初始开发,错误等的开发时间。这是哪一方-还是有更好的折衷办法?其他编写这种样式的代码的团队做什么?

2
为什么DVCS似乎都具有未落实变更的不合理恐惧症?
来自SVN背景,使用DVCS系统时要适应的最困难的事情之一就是,它们似乎都将任何未提交的更改视为滴答定时炸弹。 在Mercurial中,如果您尝试获取更改,并且您的工作副本中有任何未提交的更改,则必须跳过所有步骤以使其仅合并传入的更改。尝试切换分支吗?这将迫使您搁置所有内容,然后必须立即在另一端立即搁置所有内容。(SVN在这两种情况下都没有问题。) Git大致相同。我正在与另一个项目的开发人员并肩工作,而我只是试图将他的提交之一挑进我的叉子中。它拒绝让我,因为我的工作副本中的更改尚未提交,与他提交中的更改完全不同的文件。 甚至没有合并选项。显然,我必须先隐藏我的更改! 如果一个人以这种极端的谨慎对待完全无害的东西,我会称其为“恐惧症”,这是一种非理性的恐惧,应视为精神障碍。但是Git和Mercurial是由两个不同的聪明,理性的开发人员团队设计的,所以我不得不怀疑他们是否知道我所不知道的东西。 是否有技术上的理由证明这种对待未承诺变更的态度是正确的?如果是这样,为什么问题仅在DVCS上存在?

5
视图是否应该执行验证?
我正在阅读“ 在MVC中模型应该处理验证吗? ”,因为我很好奇验证逻辑在MVC网站中的位置。最高答案中的一行如下:“控制器应处理验证,模型应处理验证”。 我很喜欢,但是让我感到奇怪的是,为什么由于以下几个原因我们不会在View中进行数据验证: 视图通常具有强大的验证支持(JS库,HTML5标签) 视图可以在本地验证,从而减少网络IO 用户界面已经考虑了数据类型(日期的日历,数字的微调框),使其距验证仅一步之遥 在多个地方进行验证与MVC隔离职责的概念背道而驰,因此“在两个地方都做”似乎不合适。仅在控制器中执行数据验证是真正的主导方法吗?
10 architecture  mvc 

2
为什么我们需要Scanner类的实例才能在Java上获得输入?
Java是面向对象的,但是,为什么我们需要从Scanner类创建一个对象来获取输入?next()例如,方法不能只是静态的吗? C相我很简单,因为你只需要使用scanf(),gets()或fgets()。我确定Java开发人员有理由创建Scanner类,但是这比仅具有正常功能来完成工作更好吗? 我发现此链接似乎在问相同的问题,但答案仅与 “您需要创建一个对象,因为它不是静态的” ... 我的猜测是:由于Java是面向对象的,因此他们决定将所有输入方法放在一个类中。他们没有执行静态方法,因此您可以在不同的对象中拥有各种不同的源(键盘输入,文件输入...)? 如果有人可以编辑问题以使其听起来更加清晰,我将不胜感激!

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

2
视图应该对模型了解多少?
我正在使用WPF和DAG支持的python包装器在python中构建应用程序。目前,我必须决定在数据和视图之间进行交互的一致方式。 据我所知,目前有两种明显的解决方案。 第一个类似于Android应用程序的结构。您有一个设置/填充视图的控制器。因此,控制器拥有该视图并仅推送将要显示的原始数据。视图只是一个愚蠢的层,不知道发生了什么以及数据来自何处。然后,如果用户与视图交互,它将向控制器发送回调(如果已注册)。 UserInfoController.py userInfoView = UserInfoView() userInfoView.onGenderChangedCallback = self.onGenderChangedCallback userInfoView.setUserGenderValue(user.getGender()) UserInfoView.py def setUserGenderValue(self, gender): self.userGender = gender def getView(self): return ui.Label(self.userGender, onEditCallback=self.onGenderChangedCallback) 第二个方法是将(引用)模型传递给视图,并让视图检索和更新数据。视图现在包含模型,因此它可以更新模型而无需对控制器进行任何其他回调。 UserInfoViewModel.py self.gender = 'Male' UserInfoView.py def getView(self): return ui.Label(self.ViewModel().getGender(), onEdited=self.genderEdited) def genderEdited(self, newValue): self.ViewModel().setGender(newValue) 所以我想我要问的是,我应该传递非常原始的数据并保持视图尽可能通用,然后使用回调并在控制器中处理业务细节。 还是应该将整个模型传递给视图,然后让视图直接更新模型。这意味着将要键入的代码更少。 PS。不要判断代码-只是为了可视化。 编辑: 另外要补充 -此应用程序将使用支持鸭型的python编写。这意味着使用第二种方法,只要模型满足所需的接口,视图仍然可以重用。
10 model  view 

4
敏捷中的语义版本控制
假设我进行了14天的sprint迭代,其中有多个新功能,改进和缺陷修复的故事。当更改准备就绪时,我也将对其进行部署,而不是等待sprint结束。 我的问题是-如何跟踪这样开发和维护的产品的语义版本控制?如果每14天发布一次,这将很容易,我将增加版本号并记下changelog中的所有更改。但是,如果不断部署变更怎么办?每次部署某些东西时都应该增加版本吗?还是我应该等到sprint结束,然后再进行“恢复”操作,并根据实际部署在每次迭代中单独增加一次版本号?敏捷中语义版本控制的最佳实践是什么? 编辑:为了更好地解释我的需求,我想首先为利益相关者提供变更日志。我认为他们在部署每次更改后都不会对changelog中的新记录感兴趣。

4
减少类的复杂性
我已经查看了一些答案并在Google上进行了搜索,但是找不到任何有用的东西(即不会产生尴尬的副作用)。 总的来说,我的问题是我有一个对象,需要对它执行长时间的操作。我将其视为一种装配线,例如制造汽车。 我相信这些对象将称为“ 方法对象”。 因此,在此示例中的某个点上,我将拥有一个CarWithoutUpholstery,然后需要在其上运行installBackSeat,installFrontSeat,installWoodenInserts(这些操作不会互相干扰,甚至可以并行执行)。这些操作由CarWithoutUpholstery.worker()执行,并产生一个新的对象,该对象将是CarWithUpholstery,然后在其上运行cleanInsides(),verifyNoUpholsteryDefects()等。 单个阶段中的操作已经是独立的,也就是说,我已经在努力应对可以按任何顺序执行的子集(可以按任何顺序安装前排和后排座椅)。 我的逻辑当前使用反射来简化实现。 也就是说,一旦有了CarWithoutUpholstery,该对象就会检查自身是否有名为performSomething()的方法。此时,它执行所有这些方法: myObject.perform001SomeOperation(); myObject.perform002SomeOtherOperation(); ... 同时检查错误和内容。虽然操作的顺序是不重要的,我已经在指定情况下,我曾经发现毕竟一些顺序很重要,一个字典顺序。这与YAGNI矛盾,但是它花费很少-简单的sort()-并且可以节省大量的方法重命名(或引入其他执行测试的方法,例如方法数组)的费用。 一个不同的例子 让我们说,除了要制造汽车外,我还必须编辑某人的秘密警察报告,并将其提交给我的邪恶霸主。我的最后一个对象将是ReadyReport。为了构建它,我首先收集基本信息(姓名,姓氏,配偶...)。这是我的A阶段。根据是否有配偶,我可能不得不进入B1或B2阶段,并收集一两个人的性行为数据。这是由对不同的Evil Minions的几个不同的查询所组成,它们控制着夜生活,街拍,性用品商店的销售收据以及不收什么。等等等等。 如果受害者没有家庭,我什至不会进入GetInformationAboutFamily阶段,但是如果我这样做了,那么我是首先瞄准父亲还是母亲还是兄弟姐妹(如果有)就没有关系了。但是,如果我还没有执行FamilyStatusCheck,那我就无法做到这一点,因此它属于早期阶段。 一切都很棒... 如果我需要一些其他操作,我只需要添加一个私有方法, 如果该操作在多个阶段都是通用的,那么我可以让它从超类继承, 操作简单且自成体系。任何其他操作都不需要从任何操作中获得任何价值(在不同阶段执行的操作), 线下的对象不需要执行许多测试,因为如果其创建者对象首先没有验证这些条件,它们甚至可能不存在。即,在将插入物放入仪表板,清洁仪表板并验证仪表板时,我不需要验证仪表板是否确实存在。 它便于测试。我可以轻松模拟部分对象并在其上运行任何方法,并且所有操作都是确定性的黑匣子。 ...但... 当我在我的方法对象之一中添加最后一个操作时,就会出现问题,这导致整个模块超过了强制性的复杂性指标(“少于N个私有方法”)。 我已经在楼上解决了这个问题,并建议在这种情况下,私有方法的丰富并不是灾难的故事。复杂性是存在的,但它的存在,因为操作是复杂的,实际上它不是那么复杂-它只是长。 以邪恶的霸王为例,我的问题是邪恶的霸王(又名不容否认的他)要求了所有饮食信息,我的饮食奴才告诉我,我需要查询餐馆,小厨房,街头小贩,无牌街头小贩,温室所有者等,以及邪恶的(sub)Overlord(众所周知的也不应被拒绝的他)抱怨我在GetDietaryInformation阶段执行了太多查询。 注意:我知道从多个角度来看这根本不是问题(忽略可能的性能问题等)。发生的一切是,一个特定的指标不满意,对此有充分的理由。 什么我想我能做到 除了第一个以外,所有这些选择都是可行的,而且我认为是可以辩护的。 我已经证实自己可以偷偷摸摸,并声明一半的方法protected。但是我会利用测试程序中的弱点,除了在被抓住时证明自己是合理的之外,我也不喜欢这样。另外,这是权宜之计。如果所需操作次数加倍怎么办?不太可能,但是那又如何呢? 我可以将此阶段任意拆分为AnnealedObjectAlpha,AnnealedObjectBravo和AnnealedObjectCharlie,并使每个阶段要执行的操作占三分之一。我的印象是,这实际上增加了复杂性(增加了 N-1个类),除了通过测试之外没有任何好处。我当然可以认为,CarWithFrontSeatsInstalled和CarWithAllSeatsInstall在逻辑上是连续的阶段。Alpha后来要求使用Bravo方法的风险很小,如果我打得很好的话,风险甚至会更低。但是还是。 我可以将一个远程相似的不同操作组合在一起。performAllSeatsInstallation()。这只是权宜之计,并且确实增加了单个操作的复杂性。如果我需要以不同的顺序执行操作A和B,并且将它们打包在E =(A + C)和F(B + D)内,则必须解开E和F并重新整理代码。 我可以使用lambda函数数组,并完全避开检查,但是我发现这很笨拙。但是,这是迄今为止最好的选择。它会摆脱反思。我遇到的两个问题是,可能会要求我重写所有方法对象,不仅是假设对象,CarWithEngineInstalled而且这虽然是很好的工作安全性,但实际上并没有那么大的吸引力。并且代码覆盖率检查器存在lambda 问题(可以解决,但仍然存在)。 所以... 您认为哪个是我最好的选择? 有没有我没有考虑过的更好的方法?(也许我最好打扫卫生,直接问一下是什么?) 这种设计是否存在绝望的缺陷,我最好承认失败与否-这种体系结构?这对我的职业生涯不利,但是从长远来看,编写错误的代码会更好吗? 我当前的选择是否真的是“唯一的方式”,我需要努力获得更好的质量指标(和/或仪器)?对于这最后一个选项,我需要参考...我不能只在抱怨的同时对@PHB挥手,这不是您要查找的指标。不管我想要多少

3
模型驱动软件工程(MDSE)到底是什么?
我今天在infoq上遇到了MDSE的缩写,该信息我可以找到非常不清楚的地方,并且描述中充斥着流行语: MDSE旨在使软件工程师能够在抽象级别上工作,在该级别上,需求,体系结构和设计信息将得到最大程度的排序(就信息“熵”而言)。(将其称为“设计工作产品”)。此外,MDSE应该为工程师提供主要根据其“设计工作产品”条款验证和验证其设计的方法。 显然,每个人都在这样做:(再次从文章中) 我们正处在MDSE时代的曙光中。在接下来的5-10年中,我们将看到向MDSE的重大转变,我认为到此阶段结束时,也许有60-80%的软件将使用基于模型的技术进行设计。 我想对MDSE是什么有一个具体的,无术语的描述。是否像在90年代使用Rational Rose那样绘制UML框并用它生成代码? (当时,如果有人有使用这些技术生成的软件示例,我真的很想看到一个具体的示例)。

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.