软件工程

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

1
重构在GitFlow分支命名模型中属于什么地方?
我最近开始使用由bitbucket实现的GitFlow模型。我有一件事还不完全清楚。 我们试图通过积压,计划和实施重构任务来定期解决我们的技术债务。这样的重构分支以合并到中的拉取请求结束develop。我的问题是重构分支在哪里属于GitFlow? 使用feature前缀似乎是最合乎逻辑的方法,但是感觉并不完全正确,因为重构不会添加任何新功能。 但是,使用bugfix前缀似乎并不正确,因为没有实际的错误重构修复程序。 另一方面,如果不过度设计,则创建自定义前缀看起来很复杂。 你有这种情况吗?您使用哪种做法解决此问题?请解释原因。


2
是否可以创建独立于原始解释程序的“自举”解释程序?
根据Wikipedia的说法,在编写编译器的上下文中,“引导”一词的含义是: 在计算机科学中,引导程序是使用要编译的源编程语言编写编译器(或汇编器)的过程。应用此技术将导致自托管编译器。 我可以理解这将如何工作。但是,对于口译员来说,故事似乎有些不同。现在,当然可以编写自托管解释器了。那不是我要的 我实际上要问的是:是否可以使自托管翻译器独立于原始的第一翻译器。为了解释我的意思,请考虑以下示例: 你写在你的语言翻译的第一版本X和解释是为正在创建一个新的语言,称为ÿ。首先,您使用X语言的编译器来创建可执行文件。现在,您可以使用以语言X编写的解释器来解释以您的新语言Y编写的文件。 现在,据我所知,要能够“引导”您使用语言X编写的解释器,您需要使用语言Y重写该解释器。但这很重要:即使您确实使用语言Y重写了整个解释器,仍然需要使用语言X编写的原始解释器。因为要使用语言Y运行解释器,所以您将不得不解释源文件。但是,究竟该如何解释源文件呢?好吧,当然不能没有什么,所以您被迫仍然使用第一个解释器。 不管您用语言Y编写了多少新的解释器,您始终将必须使用用X编写的第一个解释器来解释后续的解释器。仅仅由于口译员的性质,这似乎是一个问题。 但是,另一方面,这篇关于口译员的Wikipedia文章实际上讨论的是自托管口译员。这是一个相关的小摘录: 自解释器是用一种可以解释自身的编程语言编写的编程语言解释器;一个例子是用BASIC编写的BASIC解释器。自解释器与自托管编译器有关。 如果不存在用于要解释的语言的编译器,则创建自解释器需要使用宿主语言(可以是另一种编程语言或汇编程序)来实现该语言。通过拥有这样的第一个解释器,系统将被引导,并且可以使用语言本身开发新版本的解释器 不过,对于我来说仍然不清楚如何完成此操作。看来,无论如何,您总是被迫使用以宿主语言编写的解释器的第一个版本。 现在,上面提到的文章链接到另一篇文章,其中Wikipedia提供了一些假定的自我托管解释器的示例。经过仔细检查,似乎许多这些自托管解释器(尤其是一些较常见的解释器,例如PyPy或Rubinius)的主要“解释”部分实际上是用其他语言编写的,例如C ++或C。 那我上面描述的可能吗?自托管口译员可以独立于其原始主机吗?如果是这样,将如何精确地做到这一点?

3
在C#中这种明显的自引用的目的是什么?
我正在评估一个名为Piranha(http://piranhacms.org/)的开源CMS ,以便在我的一个项目中使用。至少对于我来说,我发现以下代码有趣且有点混乱。可以帮助我理解为什么类从相同类型的基类继承吗? public abstract class BasePage<T> : Page<T> where T : BasePage<T> { /// <summary> /// Gets/sets the page heading. /// </summary> [Region(SortOrder = 0)] public Regions.PageHeading Heading { get; set; } } 如果BasePage<T>要定义的类,为什么要继承Page<T> where T: BasePage<T>?它有什么具体目的?
21 c#  architecture  .net  cms 

5
测试列表…针对每种情况都在同一测试中还是在一项测试中?
我正在测试某个功能是否可以实现列表中的预期功能。所以我要测试 f(null) -> null f(empty) -> empty f(list with one element) -> list with one element f(list with 2+ elements) -> list with the same number of elements, doing what expected 为此,最好的方法是什么? 在同一(方法)测试中测试所有案例,名称为“ WorksAsExpected” 针对每种情况进行一次测试,因此 “ WorksAsExpectedWhenNull” “ WorksAsExpectedWhenEmpty” “ WorksAsExpectedWhenSingleElement” “ WorksAsExpectedWhenMoreElements” 我没有想到的另一种选择:-)
21 unit-testing  tdd 

4
用C#7编写“ Try”方法的最优雅方法是什么?
我正在编写一种类型为Queue的实现,该实现的TryDequeue方法使用与各种.NET TryParse方法类似的模式,如果操作成功,我将在其中返回一个布尔值,并使用一个out参数来返回实际出列的值。 public bool TryDequeue(out Message message) => _innerQueue.TryDequeue(out message); 现在,我想尽可能避免使用outparams。C#7为我们提供了变量代用,以使使用它们变得更容易,但是我仍然认为,参数比起有用的工具更多的是必要的弊端。 我想要此方法的行为如下: 如果有要出队的物品,请将其退回。 如果没有要出队的项目(队列为空),请向调用者提供足够的信息以使其正确执行操作。 如果没有剩余的项目,不要只是返回一个空项目。 如果尝试从空队列中出队,请不要抛出异常。 现在,此方法的调用者几乎总是使用如下模式(使用C#7 out变量语法): if (myMessageQueue.TryDequeue(out Message dequeued)) MyMessagingClass.SendMessage(dequeued) else Console.WriteLine("No messages!"); // do other stuff 总而言之,这还不是最糟糕的。但是我不禁感到可能有更好的方法可以做到这一点(我完全愿意承认可能没有)。我讨厌调用者如何只需要在有条件的情况下获得一个值就可以有条件地打破它的流程。 还有哪些其他模式可以完成相同的“尝试”行为? 就上下文而言,此方法可能会在VB项目中调用,因此在这两种方法中都可以很好地使用的方法可获得加分。不过,这个事实应该没有太大的意义。
21 c# 

4
使用C#中的抽象类作为定义
作为一名C ++开发人员,我已经习惯了C ++头文件,并发现在代码中包含某种强制性的“文档”很有用。通常,在这种情况下,我不得不读一些C#代码时会很糟糕:我没有正在使用的类的思维导图。 假设作为软件工程师,我正在设计程序的框架。将每个类都定义为抽象的未实现类是否太疯狂了,就像我们对C ++标头所做的那样,让开发人员实现它呢? 我猜可能有人可能会因为某些原因而认为这是一个糟糕的解决方案,但我不确定为什么。这样的解决方案必须考虑什么?

3
完全分离后端和前端Web应用程序并允许它们与(JSON)REST API通信是正常的设计吗?
我正在创建新的业务Web应用程序,并且想要实现: 使用各自领域的最佳技术。我想要具有可靠ORM的可靠后端框架。我想要最先进的SPA(单页应用程序)框架,并为前端应用程序使用最新的HTML和Javascript功能 公开后端实体和业务服务以供不同类型的应用程序使用,例如,Web应用程序,移动(Android)以及可能的其他类型(智能设备等) 因此,为了满足这两个要求,我倾向于将我的应用程序完全隔离在后端和前端应用程序中,并使用REST API(JSON)来组织它们之间的通信。这是合理的方法吗? 这种分离并不是显而易见的设计解决方案,因为许多Web应用程序技术都集成了视图层,其中服务器端应用程序或多或少地控制视图的生成并部分处理视图的响应(例如,带有视图层的SpringMVC,带有视图的PHP Yii Java JSF / Facelets层将其组件的状态完全保存在服务器上)。因此-周围有许多技术提出了更强的耦合性,并有望缩短开发时间和提供更标准的路径。所以-在开始以未广泛使用的方式使用技术时,我必须谨慎。 据我了解,完全分离的SPA前端通常是由使用第三方API引起的。但是,当后端和前端都由一家公司开发时,这种去耦声音设计是否有效? 我目前选择的技术是Java / Spring后端和Angular2 / Web组件/聚合物前端-如果允许我这么说的话。但这与这个问题无关,因为这个问题是关于一般设计而不是具体技术的选择?

5
非平凡的条件语句是否应移至循环的初始化部分?
我从stackoverflow.com上的这个问题中得到了这个主意 以下是常见的模式: final x = 10;//whatever constant value for(int i = 0; i < Math.floor(Math.sqrt(x)) + 1; i++) { //...do something } 我要说明的一点是条件语句有些复杂,不会改变。 这样,是否最好在循环的初始化部分中声明它? final x = 10;//whatever constant value for(int i = 0, j = Math.floor(Math.sqrt(x)) + 1; i < j; i++) { //...do something } 这更清楚吗? 如果条件表达式很简单怎么办 final …

6
为什么注释掉代码然后逐渐将其删除以跟踪我已经完成的工作和尚待完成的工作是错误的?
每当我发现需要更改我的代码的很大一部分时,要么是因为它不正确,要么是因为需要将其修改为由于其他原因而需要进行的主要体系结构更改,这通常是我要做的: 我注释掉了我怀疑可能需要更改的所有代码。我将注释掉的代码视为我的TODO列表。 我逐步查看注释掉的代码并取消注释该代码的部分,或者将它们复制粘贴到其他位置,然后根据需要对其进行编辑,或者从头开始重写此代码的部分,查看注释掉的代码以供参考。每当我认为对部分注释掉的代码完成处理后,便将其删除。 我继续进行此操作,直到看不到更多注释掉的代码为止。 我应该注意,我主要是在自己开发的个人项目上进行此操作。 但是,有人告诉我,我应该停止这样做。有人告诉我,我应该开始使用git,指代旧的提交以查看旧的代码,而不是留下注释掉的代码。有人告诉我: 注释掉代码是一个坏习惯,应该清除掉。您缺乏经验,因此无法理解。如果几年后您看到另一个喜欢注释代码的人的代码,您将开始对这个人发誓。每当我看到注释掉的代码时,我都将其完整删除,甚至根本不看它,因为通常这样的代码是完全不值钱的。您肯定不会看到在一个人的小型项目中注释掉代码的弊端。但是,如果您找到工作并保持这种习惯,那将是一种耻辱。 我想问一下我现在看不到的正在做的事情有哪些弊端吗? 我必须说我不太热衷于仅使用git查看过去的代码。如我所说,我将注释掉的代码视为待办事项列表。虽然git会向我展示代码的外观,但无法清楚地告诉我哪些代码部分仍需要检查以及哪些部分已经完成。我担心我可能会错过一部分代码并引入错误。 为了完整起见,我想补充一点,我要引用的人是一位经验丰富的开发人员,并且是Bob叔叔的“ Clean Code”的拥护者-Bob叔叔确实批评了他的书中严厉地注释掉了代码。

5
编写实现后如何纠正测试中的错误
如果正确实施逻辑后,测试仍然失败(因为测试中有错误),则TDD中的最佳措施是什么? 例如,假设您要开发以下功能: int add(int a, int b) { return a + b; } 假设我们按照以下步骤进行开发: 编写测试(尚无功能): // test1 Assert.assertEquals(5, add(2, 3)); 导致编译错误。 编写一个虚拟函数实现: int add(int a, int b) { return 5; } 结果:test1通过。 添加另一个测试用例: // test2 -- notice the wrong expected value (should be 11)! Assert.assertEquals(12, add(5, 6)); 结果:test2失败,test1仍然通过。 编写实际的实现: int …
21 tdd  mistakes 

3
如何处理C ++类构造函数中的失败案例?
我有一个CPP类,其构造函数执行一些操作。其中一些操作可能会失败。我知道构造函数不会返回任何东西。 我的问题是 除了初始化构造函数中的成员之外,是否可以执行其他操作? 是否可以告诉调用函数构造函数中的某些操作已失败? new ClassName()如果构造函数中发生某些错误,我可以使返回NULL吗?

3
词法分析器返回其解析器的令牌的数据类型应该是什么?
如标题中所述,词法分析器应返回/提供解析器哪种数据类型?在阅读Wikipedia 的词法分析文章时,它指出: 在计算机科学中,词法分析是将一系列字符(例如在计算机程序或网页中)转换为一系列标记(具有已标识“含义”的字符串)的过程。 但是,与上述说法完全矛盾的是,当我在另一个站点上问过另一个问题(“代码审查”,如果您很好奇)得到回答时,回答者表示: 词法分析器通常读取字符串,并将其转换为词位流。词素只需要是一串数字。 他给了这个视觉效果: nl_output => 256 output => 257 <string> => 258 稍后,在他提到的文章中Flex,他已经存在一个词法分析器,并说用它编写“规则”比手工编写词法分析器更简单。他继续给我这个例子: Space [ \r\n\t] QuotedString "[^"]*" %% nl_output {return 256;} output {return 257;} {QuotedString} {return 258;} {Space} {/* Ignore */} . {error("Unmatched character");} %% 为了进一步了解并获得更多信息,我阅读了有关Flex的Wikipedia文章。Flex文章显示,您可以通过以下方式使用令牌定义一组语法规则: digit [0-9] letter [a-zA-Z] %% "+" { return PLUS; } …
21 data-types  lexer  flex 

2
优化包含大型二进制文件的git repo
我们的项目约为11GB,其中10个是二进制数据(.png图像)。因此,git diff或git status运算要花费一分钟以上的时间。幸运的是,所有数据文件都以一个漂亮的名称分隔到一个文件夹中data。任务是“避免对二进制文件进行压缩,扩散和其他昂贵的操作”。 考虑将项目分为两个回购。然后data将是一个外部回购,由主源代码回购签出。已决定,使存储库保持同步的开销会太大,尤其是对于处理数据文件的艺术家而言。 明确地告诉git这些文件是二进制文件,不考虑从diffs文件,但是这些文件似乎只是该问题的部分解决方案。 我觉得git属性是解决方案,但是怎么办?还是有比整体仓库更好的体系结构?
21 git  binary 

4
是否存在专门为依赖注入设计的编程语言?
许多通用编程语言都足够灵活,可以允许您支持依赖项注入。即使没有库或框架支持。但是,即使某种语言的图灵能力足以解决任何编程问题,该语言也会做出会影响其中易事和难事的选择。 是否有专门设计用来简化依赖注入的语言,反之,使得创建隐藏的依赖变得困难? 澄清: 由于某些语言(看着您的Java)的限制,许多人将连接和构造方面的帮助作为依赖项注入的一部分。在这里,我只打算为DI设计一种语言,以表示依赖关系不容易隐藏在副作用中。在配置系统上也有约定,只会增加一些影响。 我不是在寻找语言建议。这是一个历史问题。是否有任何语言作者明确提出要这样做?

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.