软件工程

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

9
'<'与'!='作为'for'循环中的条件?
假设您有以下for循环*: for (int i = 0; i &lt; 10; ++i) { // ... } 通常也可以写成: for (int i = 0; i != 10; ++i) { // ... } 最终结果是相同的,因此是否有真正的论据来使用一个?我个人使用前者,以防万一i由于某种原因而陷入混乱,并跳过了值10。 *对不起幻数的用法,但这只是一个例子。
31 syntax 

4
何时不应该对提交进行版本标记?
上下文:我最近发现了语义版本控制,并且正在尝试确定如何在我自己的项目中最佳地实际使用它。 鉴于semver需要对主要更改,次要更改和补丁进行版本控制,何时不应使用更​​新的版本标记提交?在我看来,每项更改都将属于这些类别之一,因此,应对每项更改进行版本控制,但是当我查看GitHub上的各种流行项目时,这似乎并不是事情的完成方式(只是看一下实际上,大型项目只有数以百计的标签才有成千上万次提交。

6
何时应更新依赖项?
我们有两个与依赖关系有关的主要危机,它们具有两个不同的代码库(Android和一个Node.js Web应用程序)。Android存储库需要从Flurry迁移到Firebase,这需要将Google Play服务库更新为四个主要版本。我们在Heroku托管的Node应用程序中发生了类似的事情,在该应用程序中,我们的生产堆栈(cedar)已被弃用,需要升级到cedar-14。我们的PostgreSQL数据库也需要从9.2更新到9.6。 这些应用程序的每个依赖项都已经存在了将近两年的时间,而当其中的一些应用程序被弃用并且我们进入“日落”时期时,更新或替换它们一直是头疼的大问题。在过去的一个月中,我花了30多个小时来慢慢解决所有冲突和代码损坏。 显然,让事情搁置两年已经太久了。技术发展日新月异,特别是当您使用Heroku等平台提供商时。假设我们有一个完善的测试套件,以及一个像Travis CI这样的CI流程,它不需要进行很多更新工作。例如,如果某个功能在升级后被删除,而您正在使用它,则测试将失败。 应该多长时间更新一次依赖关系,或者何时应该更新依赖关系?我们进行了更新,因为我们被迫这样做,但似乎某种先发制人的方法会更好。发行次要版本时,我们应该更新吗?主要版本?每个月是否有更新?我想不惜一切代价避免发生我刚刚经历的情况。 PS-对于我的一个个人Rails项目,我使用了一项名为Gemnasium的服务,该服务可以跟踪您的依赖关系,以便可以将安全漏洞通知给您。这是一项很棒的服务,但是我们必须手动检查我提到的项目的依赖关系。

5
为什么区分联合与函数式编程相关联?
在多年的OO编程中,我了解了区别工会是什么,但我从未真正错过过他们。我最近一直在用C#进行一些函数式编程,现在我一直希望自己拥有它们。这让我感到困惑,因为从表面上看,区别工会的概念似乎与功能/ OO二分法完全无关。 函数式编程中是否有固有的功能,使有区别的联合比在OO中更有用,或者是通过强迫自己以“更好”的方式分析问题,我只是提高了标准,现在要求更好模型?


6
成千上万的错误!
我最近被分配到一个新项目。好吧,实际上是一个用经典ASP编写的旧项目。现在,该应用程序的新版本正在最新的ASP.NET中编写,但预计不会在一段时间内成为RTM(估计发布日期为2017年1月),因此我必须对旧应用程序执行一些维护,直到可以丢弃。 另外,我有一种感觉,不是所有客户都会立即切换到新程序,因此该版本可能会出现一段时间。 问题是,它充满了错误。它的一部分可以追溯到上个世纪,当时还没有Web标准,而且我不太介意Quirks模式,width并且height属性而不是CSS,用于布局的表格,框架集等,但是哦,所有这些错误!width="20px"在所有onchange="javascript:..."使用css的地方,style="width:20"并且style="width=20px"很常见。更不用说有矛盾width和style属性的地方。等等。 因此,Web应用程序仅在IE下运行,并且仅在兼容模式下运行。显然,开发人员从来没有考虑过代码有效性,只有结果看起来像他们所想的那样。 而且我不知道该如何处理。在查找代码中的其他错误时,我发现无法对那些错误闭目。 我当然可以进行全局查找和替换,以解决大部分问题,但这意味着我的第一次提交将包含成千上万个已更改的.asp文件。我可以那样做吗?

2
C预处理程序的起源是什么?
C预处理程序已附加到C,但是它的语法与主要语言完全不同: 语法上显着的空格(行尾终止一条语句,宏确定替换列表的开始后的间隔) 基于关键字的块而不是支撑块,elif而不是else if 关键字主导的定义,而不是声明反射的使用,=对于值定义,否 其他字符串语法的提示(#include &lt;&gt;vs #include "") 惰性求值(显然是C的;但是6.10.3.1可以理解为也暗示着宏扩展的特定顺序,在一些重要的地方) 真的看起来根本不像C!从技术上讲,它是它自己的语言,但是它一直被用作C的几乎不可或缺的部分,并且它在语法上不与它集成似乎很奇怪。 维基百科没有谈论它的历史。波特兰模式存储库给了它一个提及,但没有详细介绍它是由其他人(而不是C的其他人)设计的。具有C历史的Dennis Ritchie的网站可能有答案,但不幸的是没有不再可用。 宏引擎,它显然已经从运行系统语言,这可以解释非常不同的语义一些差异,但不是视觉设计方面(这也不清楚现代眼光是否本来是打算作为能够在中样的的乐趣,其替代系统是否允许,或者它是否仅仅是在功能强大的优化程序之前的一种内联函数的便捷方式)。如果实际上像C一样的语义已经成为起点,那感觉似乎更接近最终成为C ++模板的东西向宏的逻辑发展。但是,没有比语法更具体的证据了。 我们是否有任何记录说明为何采用这种方式设计,或者创作者的影响是什么?
30 c  history  macros 

7
在循环中设置标记以供以后使用是否有代码味道?
我有一段代码在其中迭代地图,直到某个条件为真,然后再使用该条件做更多的事情。 例: Map&lt;BigInteger, List&lt;String&gt;&gt; map = handler.getMap(); if(map != null &amp;&amp; !map.isEmpty()) { for (Map.Entry&lt;BigInteger, List&lt;String&gt;&gt; entry : map.entrySet()) { fillUpList(); if(list.size() &gt; limit) { limitFlag = true; break; } } } else { logger.info("\n&gt;&gt;&gt;&gt;&gt; \n\t 6.1 NO entries to iterate over (for given FC and target) \n"); } if(!limitFlag) …


5
如果数字太大,会溢出到下一个存储位置吗?
我一直在审查C编程,但有几件事困扰着我。 让我们以以下代码为例: int myArray[5] = {1, 2, 2147483648, 4, 5}; int* ptr = myArray; int i; for(i=0; i&lt;5; i++, ptr++) printf("\n Element %d holds %d at address %p", i, myArray[i], ptr); 我知道一个int可以容纳正数2,147,483,647的最大值。因此,通过遍历它,是否“溢出”到下一个内存地址,从而导致元素2在该地址处显示为“ -2147483648”?但这并没有真正的意义,因为在输出中它仍然说下一个地址保持值为4,然后是5。如果该数字已溢出到下一个地址,则不会改变存储在该地址的值? 我隐约记得在MIPS Assembly中进行编程时,看着地址在程序执行过程中逐步改变了值,分配给这些地址的值会改变。 除非我没有记错,否则这是另一个问题:如果分配给特定地址的数字大于类型(如myArray [2]中的类型),那么它是否不影响存储在后续地址中的值? 示例:我们在地址0x10010000处有int myNum = 40亿。当然,myNum不能存储40亿,因此它在该地址显示为负数。尽管不能存储这么大的数字,但它对存储在后续地址0x10010004上的值没有影响。正确? 内存地址仅具有足够的空间来容纳某些大小的数字/字符,如果大小超出限制,则其表示方式将有所不同(例如尝试将40亿存储到int中,但它将显示为负数),并且因此,它不会影响下一个地址中存储的数字/字符。 对不起,如果我过分。从那以后,我整天都在闹大闹鬼。

5
记录产品设计决策依据的有效方法是什么?
在我们公司,我们不使用任何产品设计文件。我们共有三名员工,因此所有产品设计讨论都当面或在Slack上进行。(我们还在基本的Slack软件包上,该软件包仅允许查看最新消息。) 我们的产品仍处于早期阶段,我们经常重新访问几个月前确定的设计元素。 我们经常痛苦地面临的一个问题是忘记了为什么要做出产品设计决策。这导致浪费了数小时来重读相同的地面。 我们如何有效记录设计决策背后的基本原理? 我们的工作流程基于Pivotal Tracker。我想到的一种解决方案是,将所有相关设计决策的依据记录为对用户故事本身的评论,但这似乎并不可靠。 要100%清楚:我不是在谈论代码的设计。我说的是由代码实现的产品设计。换句话说,我不是在谈论诸如“我们应该使用合成而不是多重继承来构造这个类吗?”之类的决策。我正在谈论诸如“我们应该要求用户在登录之前确认用户的电子邮件地址吗?”之类的决定。 该文档的目的是允许企业查看做出决策的原因的记录,以帮助做出有关同一主题的进一步决策。

9
设计一个类以将整个类作为参数而不是单个属性
举例来说,假设您有一个应用程序,该应用程序具有广泛共享的类,称为User。此类公开有关用户,其ID,名称,对每个模块的访问级别,时区等所有信息。 用户数据显然在整个系统中得到了广泛的引用,但是无论出于何种原因,都对系统进行了设置,因此,我们不是在将用户对象传递到依赖于该对象的类中,而是从其中传递了各个属性。 需要用户ID的类仅需要GUID userId作为参数,有时我们可能还需要用户名,因此将其作为单独的参数传递。在某些情况下,这将传递给各个方法,因此这些值根本不会保存在类级别。 每当我需要从User类访问不同的信息时,我都必须通过添加参数进行更改,而在不适合添加新的重载的地方,我也必须更改对方法或类构造函数的每个引用。 用户只是一个例子。这在我们的代码中得到了广泛的实践。 我认为这违反了开放/封闭原则,对吗?不仅是更改现有类的行为,而且是首先设置它们,以便将来很有可能需要进行广泛的更改吗? 如果我们只是传入User对象,则可以对正在使用的类进行一些小的更改。如果必须添加参数,则可能不得不对类的引用进行数十次更改。 这种做法是否违反了其他任何原则?依赖倒置也许?尽管我们没有引用抽象,但是只有一种类型的用户,因此并没有真正需要User界面的需求。 是否还有其他违反非Solid的原则,例如基本的防御性编程原则? 我的构造函数应如下所示: MyConstructor(GUID userid, String username) 或这个: MyConstructor(User theUser) 发表编辑: 已经建议在“密码或对象?”中回答问题。这并未回答以下问题的问题:无论哪种方式的决定都会如何影响遵循SOLID原则的尝试,而SOLID原则是此问题的核心。
30 java  c#  design  solid 

4
为什么我不需要功能语言如Scala的ORM?
我想知道是否可以在Spring + Hibernate项目中从Java切换到Scala,以利用一些Scala功能,例如模式匹配,Option以及对我来说似乎更简洁的语法。我一直在Scala生态系统中寻找默认的ORM,并且发现了类似Activate的想法(但大多数情况下,我尝试查找Hibernate是否可以与Scala一起使用)。搜索此内容,我已经在有关JPA + Scala 的Play文档中阅读了此内容。 但是最重​​要的一点是:如果您拥有功能语言的强大功能,您是否真的需要一个“关系到对象”映射器? 可能不会。JPA是一种抽象的Java数据转换能力不足的便捷方法,但是当您从Scala开始使用它时,确实感觉不对。 我对如何使用函数式编程来创建完整的应用程序没有深入的了解(这就是为什么我打算使用Scala以便使我能够逐步理解这一点,因为它结合了OO + Functional),所以我不知道为什么我不需要功能语言的ORM,以及解决领域模型持久性的功能方法是什么? 对于Scala,用于业务逻辑的DDD方法仍然有意义,不是吗?

8
测试驱动开发(通常是敏捷)的这种局限性在实际上是否相关?
在测试驱动开发(TDD)中,您从次优解决方案开始,然后通过添加测试用例和重构来迭代地产生更好的解决方案。该步骤应该很小,这意味着每个新解决方案都将以某种方式位于前一个解决方案的附近。 这类似于数学上的局部优化方法,例如梯度下降或局部搜索。这种方法的一个众所周知的局限性是它们不能保证找到全局最优值,甚至不能保证找到可接受的局部最优值。如果您的起点与所有可接受的解决方案之间有很大范围的不良解决方案,则无法到达此目标,该方法将失败。 更具体地说:我正在考虑一个场景,在该场景中,您已经实现了多个测试用例,然后发现下一个测试用例将需要一种完全不同的方法。您将不得不放弃以前的工作,然后重新开始。 这种想法实际上可以应用于所有以小步骤进行的敏捷方法,而不仅仅是TDD。TDD与局部优化之间的拟议类比是否存在严重缺陷?

3
为什么XML类型安全?
他们为什么说XML提供类型安全性,以及它如何在XML本身中表达? 与JSON(例如,据我所知)不是类型安全的JSON有何不同?
30 xml  type-safety 

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.