软件工程

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

10
代码正确性证明会成为主流吗?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 除了最琐碎的程序外,所有程序中都充满了错误,因此承诺删除它们的任何事情都非常诱人。目前,正确性证明是非常深奥的代码,主要是由于学习起来很困难,以及证明程序正确所付出的额外努力。您认为代码验证会成功吗?

12
类型和作用域前缀是否值得命名约定?
最近开始担任软件开发人员的第一份工作时,有人被告知我不必在代码中遵循任何命名约定。由从事其他较大项目的小组编写的代码遵循命名约定,但是由于我被邀请编写一个新的独立应用程序,因此感觉并不重要。这是我最后的担心,所以我只是采用了现有的惯例并予以遵守。 int nTickCount bool bConnected object[] m_aItems fSum += fWeight * fValue class cManager enum etSystemStates etSystemStates eState cManager.cs 但这真的值得吗?我发现很难判断遵循这种命名约定对理解和检测错误的最终效果,但是,从视觉上看,它看起来很丑陋。另外,在项目中拥有名为cSomething的每个类和文件似乎很精明。 与具有明显不同的事物(例如您所采用的算法和体系结构)相比,我并不觉得这有什么大不了的。但是任何影响我编写的每一行代码的约定似乎都应该正确。 如果完全需要使用一种命名惯例,您会发现什么是最优雅,最有效的命名惯例?它表示类型和/或范围吗?

6
纯功能vs告诉,不要问?
“函数的理想参数个数为零”是完全错误的。理想的参数数目恰好是使函数不受副作用影响所需的数目。少于这个数目,您不必要地导致您的功能不纯净,从而迫使您远离成功之路,攀登痛苦的梯度。有时“鲍勃叔叔”会在他的建议下出现。有时他错得很厉害。他的零论点建议就是后者的一个例子 (来源:@David Arno在此站点上的另一个问题下的评论) 该评论获得了133个投票的惊人成绩,这就是为什么我想更加关注它的优点。 据我所知,编程有两种不同的方式:纯函数式编程(此评论令人鼓舞)和告诉,不要问(不时建议在本网站上推荐)。AFAIK这两个原则从根本上是不兼容的,彼此之间几乎是相反的:纯函数可以概括为“仅返回值,没有副作用”,而告诉,不问可以概括为“不返回任何东西,只有副作用”。另外,我有点困惑,因为我认为告诉,不要问,它被视为OO范式的核心,而纯函数则被视为功能范式的核心-现在,我看到了OO中推荐的纯函数! 我想开发人员应该选择这些范例之一并坚持下去吗?好吧,我必须承认,我永远也无法跟随自己。通常,返回值对我来说似乎很方便,而且我真的看不到如何仅凭副作用实现我想达到的目标。通常,对我来说副作用很方便,而且我真的看不到如何仅通过返回值就能达到我想要达到的目的。而且,有时(我想这太可怕了),我有两种方法都能做到。 但是,从这133个投票中,我认为当前纯函数式编程正在“取胜”,因为它已成为一种共识,说出来更好,不要问。它是否正确? 因此,在这个反模式化游戏的示例中,我尝试制作:如果我想使其符合纯功能范式-怎么办?! 对我来说,拥有战斗状态似乎是合理的。由于这是基于回合的游戏,因此我将战斗状态保留在字典中(多人游戏-可能有许多玩家同时进行许多战斗)。每当玩家回合时,我都会在战斗状态上调用适当的方法,该方法会(a)相应地修改状态,然后(b)向玩家返回更新,这些更新会序列化为JSON,并且基本上只是告诉他们发生了什么板。我想,这是在公然违反两项原则的同时。 好的-如果我确实想,我可以制定一个方法返回战斗状态,而不是就地修改它。但!然后,我是否将不得不复制战斗状态中的所有内容,只是为了返回一个全新的状态,而不是就地进行修改? 现在,如果此举是一种攻击,那么我可以返回一个更新了HP的角色?问题是,这不是那么简单:游戏规则,一举一动不仅会消除一部分玩家的生命值,而且往往会产生更多的影响。例如,它可能会增加字符之间的距离,应用特殊效果等。 对我来说,只需修改适当的状态并返回更新就简单得多了。 但是,经验丰富的工程师将如何解决这个问题?

3
阻碍广泛采用正式方法的障碍是什么?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 2年前关闭。 形式化方法可用于指定,证明和生成应用程序的代码。这不太容易出错-因此通常用于安全/关键程序中。 为什么我们不经常在日常编程或Web应用程序等中使用它? 参考文献: 形式方法 B法 霍尔逻辑

3
通过DRY和OOD引入代码耦合
我正在寻找有关DRY与代码耦合的指南。我不喜欢复制代码,也不喜欢无关模块之间的代码耦合。因此,如果在引入重复项一年后发现完全相同的重复代码,我将重构重复代码。但是,我越来越多地体验到现实世界中更加难以预测的情况,并且在重构代码之后,出现了一些情况,需要再次分叉代码。 例如,如果我有处理汽油车,汽油SUV,电动汽车和电动SUV的代码,可以说我将重复的代码重构为“汽油”层次结构和“电动”层次结构,它们均从“车辆”层次结构中衍生而来。到目前为止,一切都很好。然后,我的公司推出了混合动力汽车和混合动力汽车Semi-需要对我的原始等级本身进行核心更改。可能需要在汽油和电气层次之间进行“组合”。 显然,代码重复是不好的,因为它增加了实现上述所有产品共有的更改所花费的时间。但是重构通用代码使引入产品特定的变体同样困难,并且当人们不得不找到代码行来修复错误时,会导致很多“类跳转”-上级父类中的一项更改可以触发所有后代之间的回归错误。 如何在DRY与有害代码耦合之间达到最佳平衡?
14 design  dry  coupling 

3
穷人的依赖注入是将可测试性引入旧版应用程序的好方法吗?
在过去的一年中,我使用依赖注入和IOC容器创建了一个新系统。这教会了我很多关于DI的知识! 但是,即使在学习了概念和正确的模式之后,我仍然认为将代码解耦并将IOC容器引入旧版应用程序是一个挑战。该应用程序足够大,以至于真正的实现将是压倒性的。即使理解了价值并准予了时间。谁有时间抽出这样的东西? 当然,目标是将单元测试引入业务逻辑! 与防止测试的数据库调用交织在一起的业务逻辑。 我已经阅读了这些文章,并且了解了这篇Los Techies文章中描述的穷人依赖注入的危险。我了解它并没有真正分离任何东西。 我知道它可能涉及很多系统范围的重构,因为实现需要新的依赖项。我不会考虑在任何大小的新项目中使用它。 问题:可以使用穷人的DI 将可测试性引入旧版应用程序并开始滚动吗? 另外,使用穷人的DI作为真正依赖注入的基层方法是否是教育该原理的需求和收益的有价值的方法? 您是否可以重构具有数据库调用依赖关系的方法,并将该调用抽象到接口后面?简单地拥有这种抽象将使该方法可测试,因为可以通过构造函数重载传递模拟实现。 将来,一旦获得支持者的支持,就可以对该项目进行更新以实现IOC容器,并且构造函数将在那里使用抽象。

3
从“快照”投影而不是事件存储中补水聚合
因此,尽管我从未有机会在实际项目中应用这些模式,但我一直在调动Event Sourcing和CQRS一段时间。 我了解将读取和写入问题分开的好处,并且感谢事件搜寻如何使将状态更改轻松地投影到与事件存储区不同的“读取模型”数据库中变得容易。 我不清楚的是,为什么您会从Event Store自身中重新添加聚合。 如果将更改投影到“读取”数据库很容易,为什么不总是将更改投影到其架构与您的域模型完全匹配的“写入”数据库呢?这实际上将是快照数据库。 我想这在野外的ES + CQRS应用程序中一定很常见。 在这种情况下,事件存储仅在由于架构更改而重建“写”数据库时有用吗?还是我想念更大的东西?

1
为什么有人会使用multipart / form-data进行混合数据和文件传输?
我正在使用C#,正在编写的2个应用程序之间进行一些通信。我开始喜欢Web API和JSON。现在,我正在编写例程以在两个服务器之间发送包含一些文本数据和文件的记录。 根据互联网,我应该使用multipart / form-data请求,如下所示: SO问题“来自C#客户端的多部分表单” 基本上,您手动编写一个遵循如下格式的请求: Content-type: multipart/form-data, boundary=AaB03x --AaB03x content-disposition: form-data; name="field1" Joe Blow --AaB03x content-disposition: form-data; name="pics"; filename="file1.txt" Content-Type: text/plain ... contents of file1.txt ... --AaB03x-- 从RFC 1867复制-HTML中基于表单的文件上传 这种格式对于习惯于使用JSON数据的人来说非常令人不快。因此,很明显,解决方案是创建一个JSON请求,并对文件进行Base64编码,并最终得到如下请求: { "field1":"Joe Blow", "fileImage":"JVBERi0xLjUKJe..." } 我们可以在任何需要的地方使用JSON序列化和反序列化。最重要的是,发送此数据的代码非常简单。您只需为JSON序列化创建类,然后设置属性即可。文件字符串属性的设置很简单: using (FileStream fs = File.Open(file_path, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] file_bytes = …

3
CSS为什么不允许单行注释?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 我了解CSS仅支持像这样的多行注释 /* foobar */ 为什么不支持单行注释。 // foobar 它们在编程中同样常见,并且对于像CSS这样的语言(每个规则都在一行上)特别有用。 如果此决定没有特殊的历史原因,是什么阻止了浏览器转向支持该决定?
14 css  css3 

2
如马丁的《清洁法》所指,输出自变量是什么?
在Robert C. Martin的“清洁代码:敏捷软件技巧手册”的第45页上,Martin写道,应避免使用输出参数。我在理解“输出参数”的含义以及为什么应避免使用它们时遇到了麻烦。 马丁的输出参数示例appendFooter(s);调用了function public void appendFooter(StringBuffer report)。他对代码的改进是report.appendFooter(); 也许是由于缺少代码上下文所致,但是我看不出如何使用输出参数被认为是较差的编码。有人可以解释这个概念或提供其他示例代码来理解这一点吗? 根据上述原理,以下功能是否也可以视为不洁代码的示例? int[] numberArray = {3, 5, 7, 1}; sortArray(numberArray); 如果以上内容违反了马丁不使用输出参数的原则,那么最好让一个对象具有一个数组作为字段和一个可以调用以对数组进行排序的函数? ObjectWithArrayField numberArray = new ObjectWithArrayField(3, 5, 7, 1); numberArray.sort();
14 java  clean-code 

2
创建新的List来修改每个循环中的集合是设计缺陷吗?
我最近Collection was modified在C#中遇到了这个常见的无效操作,尽管我完全理解它,但这似乎是一个常见的问题(谷歌,大约30万个结果!)。但这在您浏览列表时修改列表似乎是合乎逻辑且直接的事情。 List<Book> myBooks = new List<Book>(); public void RemoveAllBooks(){ foreach(Book book in myBooks){ RemoveBook(book); } } RemoveBook(Book book){ if(myBooks.Contains(book)){ myBooks.Remove(book); if(OnBookEvent != null) OnBookEvent(this, new EventArgs("Removed")); } } 有些人会创建另一个列表进行迭代,但这只是在躲避问题。真正的解决方案是什么,或者这里的实际设计问题是什么?我们大家似乎都想这样做,但这是否表明存在设计缺陷?
14 c# 


3
允许不同版本的软件之间的文件向后兼容的最佳设计是什么?
有什么好的设计可以允许文件类型在不同版本的软件之间向后兼容? 例如,Microsoft如何将Word 2007、2010和2013等信息获取到所有打开的docx文件,但是不同版本可以保存更多/更少的数据,并以略有不同的方式保存数据,所有数据都保存到相同的文件类型,并且保存在一个版本中的文件可以在另一个版本中打开,但是文件的某些元素可能在较早版本中不可用? 我的意思是,最明显的方法是 private string openfile(string filename) { File.Open(filename) ... some logic that gets a header from the file that will never change switch (fileversion) case 2007: ..... case 2010 ..... case 2013 ..... } 但这似乎是令人难以置信的整体,不是很可扩展,并且可能导致大量复制/粘贴代码。 因此,我正在考虑对所有版本使用基本接口,该接口定义文件中需要存在的不变结构(例如标头)和需要用于序列化/反序列化的方法,然后进行多次继承,以便每个实现该接口的新版本的类继承了旧版本,并且仅覆盖已更改的内容,因为该文件在大多数情况下都是相同的。 我并没有真正为文件的结构而烦恼,因为它已经决定我们将使用XML,并且基本上已经确定了初始模式。但是,毫无疑问,将来会对其进行更改,我只希望能够以一种易于适应这些更改的方式来设计代码。

3
功能编程和文字冒险
这主要是关于FP的理论问题,但是我将以文字冒险(例如老式的Zork)来说明我的观点。我想知道您对如何使用FP建模有状态模拟的意见。 文字冒险似乎真的需要OOP。例如,所有“房间”都是一个Room类的实例,您可以拥有一个基本的Item类和接口,例如Item<Pickable>可以携带的东西等等。 FP中的世界建模的工作原理有所不同,特别是如果您要在一个必须随着游戏的进行而不断变化的世界(对象移动,敌人被击败,得分提高,玩家改变其位置)中实施不变性的情况下。我想象一个World拥有全部的大对象:您可以探索哪些房间,它们如何链接,玩家所携带的东西,触发了哪些杠杆。 我认为一种纯粹的方法是基本上将这个大对象传递给任何函数,然后由它们返回(可以修改)。例如,我有一个moveToRoom获取World并返回World.player.location到新房间的函数,World.rooms[new_room].visited = True依此类推。 即使这是更“正确”的方法,它也似乎在强制执行纯净。根据编程语言的不同,World来回传递可能非常大的对象可能很昂贵。同样,每个功能可能都需要访问任何World对象。例如,一个房间可能是可进入的还是不可进入的,这取决于另一个房间中触发的杠杆,因为它可能被淹没了,但是如果玩家携带救生衣,它仍然可以进入。怪物是否具有侵略性,取决于玩家是否在其他房间杀死了他的堂兄。这意味着该roomCanBeEntered功能需要访问World.player.invetory和World.rooms,describeMonster需要访问World.monsters等等,(基本上,您必须传递整个负载)。在我看来,这确实需要全局变量,即使这只是良好的编程风格,尤其是在FP中。 您将如何解决这个问题?

9
为什么不能有任何隐式转换?
据我了解,隐式转换会导致错误。 但这是没有道理的-那么正常转换是否还会导致错误? 为什么没有 len(100) 通过将语言解释(或编译)为 len(str(100)) 尤其是因为(这是我知道的)唯一可行的方法。语言知道错误是什么,为什么不解决呢? 对于这个示例,我使用了Python,尽管我觉得对于这么小的东西它基本上是通用的。

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.