软件工程

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

3
通过源代码访问来管理内部NuGet软件包
我们有很多内部库,我们希望在公司内部的项目之间共享。这些是一些要求: 库资源存储在与最终项目分开的存储库中 最终项目包括通过NuGet提供的库 在进行最终项目时,必须有可能轻松检查任何给定库的源代码 设置我们的私有NuGet存储库不是问题,但是管理源代码是有问题的。我们试图通过暴露源服务器的来源和它还挺作品,但并不完全:VS下载源在调试外部代码,而不是当你尝试导航到定义/实施。基本上,您只能在调试时使用源代码,这不是我们所需要的。 因此,问题是: 有哪些方法可以提供对内部库源代码的访问权限,而无需将代码放在同一存储库/解决方案中 有没有办法设置Symbol服务器/ NuGet feed组合,以便VS使用符号进行导航,而不仅仅是调试? 选择使用ReSharper /其他加载项。

3
我是否应该使用git stash保存项目的正在进行的更改并将其推送到github以便在其他计算机上访问?
我经常在项目的某些功能上工作,需要休息一下才能使其足够好提交。但是,我每天使用两台不同的计算机进行编码(我的笔记本电脑和我的研究实验室台式机)。例如:我正在家里进行某项功能,然后停下来去实验室。 我不想将云同步(例如Dropbox)与GitHub远程跟踪混合使用。 我只是在(然后推入)代码之前提交了未完成的(和混乱的)代码状态,仅是为了将其拉入另一台计算机以继续工作。我很确定这是一个不好的做法。 不过今天,我git stash在Google搜寻了一下之后遇到了。这似乎是我需要的完美解决方案。 但是,一旦我推送更改,该文档就不会说是否转到github。除此之外,我想知道是否有一种更有效的方式来实现所需的机动性。 提前致谢!
20 git  github  gitflow 

3
如何正确地将UI与Pyqt / Qt应用上的逻辑分离?
过去,我已经阅读了很多有关该主题的文章,并观看了Bob叔叔的有趣的演讲。但是,我始终很难正确地构建桌面应用程序,并区分在UI端和逻辑端应该承担哪些责任。 良好做法的简短摘要就是这样的。您应该设计与UI分离的逻辑,以便无论哪种后端/ UI框架,都可以(理论上)使用库。基本上,这意味着UI应该尽可能地虚设,繁重的处理应该在逻辑端进行。否则,我可以在控制台应用程序,Web应用程序或桌面应用程序上真正使用我的漂亮库。 此外,鲍伯叔叔建议对使用哪种技术会给您带来很多好处(良好的界面)的不同讨论,这种递延概念使您可以将经过良好测试的实体高度去耦,这听起来不错,但仍然很棘手。 因此,我知道这个问题是一个相当广泛的问题,已经在整个互联网上讨论了很多次,还以大量好书进行了讨论。因此,为了从中获得好处,我将发布一个非常小的虚拟示例,尝试在pyqt上使用MCV: import sys import os import random from PyQt5 import QtWidgets from PyQt5 import QtGui from PyQt5 import QtCore random.seed(1) class Model(QtCore.QObject): item_added = QtCore.pyqtSignal(int) item_removed = QtCore.pyqtSignal(int) def __init__(self): super().__init__() self.items = {} def add_item(self): guid = random.randint(0, 10000) new_item = { "pos": [random.randint(50, 100), …
20 design  python  mvc  gui  coupling 

5
与在代码中完成所有工作相比,对软件系统进行建模有什么好处?
我认识的大多数(如果不是全部)IT人员相信,在编码之前使用UML或其他类型的图对软件进行建模是有益的。(我的问题不是专门关于UML的,它可以是软件设计的任何图形或文本描述。) 我不太确定。主要原因是:代码没有说谎。它由编译器或解释器检查。希望它具有自动化测试,并且需要通过静态代码分析。如果一个模块不能与另一个模块正确连接,则在代码中通常很明显,因为会收到一条错误消息。 使用图表和其他文档无法完成所有这些操作。是的,有些工具可以检查UML,但是到目前为止,我所看到的一切都非常有限。因此,这些文档往往不完整,不一致或简单。 即使图本身是一致的,您也不能确定代码是否实际实现了它们。是的,有代码生成器,但是它们从不生成所有代码。 我有时会觉得对建模结果的痴迷是因为这样的假设,即代码不可避免地必须是一些不可理解的混乱,而建筑师,设计师或其他掌握高薪的高薪人士则不必处理这些混乱。否则,它将变得太昂贵。因此,所有设计决策都应远离代码。代码本身应该留给能够写(甚至可以读)但不必处理其他任何东西的专家(代码猴子)。当汇编程序是唯一的选择时,这可能很有意义,但是现代语言允许您以很高的抽象水平进行编码。因此,我真的不再需要建模。 我缺少用于建模软件系统的哪些论据? 顺便说一句,我相信图是一个伟大的方式来记录和沟通软件设计的某些方面,但是,这并不意味着我们应该立足于他们的软件设计。 澄清: 由于不清楚,这个问题被搁置了。因此,让我添加一些解释: 我在问使用将软件建模的(非代码)文档作为有关软件设计的主要事实来源是否有意义。我没有想到从这些文档中自动生成很大一部分代码的情况。如果是这种情况,我会将文档本身视为源代码,而不是模型。 我列出了此过程的一些缺点,这使我想知道为什么有这么多人(以我的经验)认为它是进行软件设计的首选方法。

6
使用TDD时如何删除功能或功能
在有关TDD的文章中,我经常在重构步骤中读到“删除重复项”或“提高可读性”。但是,什么使我删除了未使用的功能? 例如,假设有一个C带有方法a()和的类b()。现在我认为有一个f()被驱动的方法会很不错C。实际上,除定义/描述的单元测试外,f()所有对的调用都将替换。不再需要-测试除外。b()b() 删除b()和使用它的所有测试是否保存?那是“提高可读性”的一部分吗?

4
在功能编程中“记住”值
我已经决定将学习函数式编程的工作推给自己。到目前为止,这是一个爆炸,我已经“看到了光”。不幸的是,我实际上不认识任何可以跳出问题的函数式程序员。介绍堆栈交换。 我正在上网络/软件开发课程,但是我的老师对函数式编程并不熟悉。他对我使用它很好,他只是请我帮助他了解它是如何工作的,以便他可以更好地阅读我的代码。 我认为最好的方法是通过说明一个简单的数学函数,例如将值提高到幂。从理论上讲,我可以使用预先构建的函数轻松地做到这一点,但这会违背示例的目的。 无论如何,我在弄清楚如何保持价值方面有些困难。由于这是函数式编程,因此我无法更改变量。如果我必须对它进行编码,它将看起来像这样: (以下是所有伪代码) f(x,y) { int z = x; for(int i = 0, i < y; i++){ x = x * z; } return x; } 在函数式编程中,我不确定。这是我想出的: f(x,y,z){ if z == 'null', f(x,y,x); else if y > 1, f(x*z,y-1,z); else return x; } 这是正确的吗?z在这两种情况下,我都需要保留一个值,但是我不确定如何在函数编程中执行此操作。从理论上讲,我的工作方式有效,但是我不确定它是否“正确”。有更好的方法吗?

3
在测试和生产代码之间复制常量?
在测试和真实代码之间复制数据是好是坏?例如,假设我有一个Python类FooSaver,该类将具有特定名称的文件保存到给定目录: class FooSaver(object): def __init__(self, out_dir): self.out_dir = out_dir def _save_foo_named(self, type_, name): to_save = None if type_ == FOOTYPE_A: to_save = make_footype_a() elif type == FOOTYPE_B: to_save = make_footype_b() # etc, repeated with open(self.out_dir + name, "w") as f: f.write(str(to_save)) def save_type_a(self): self._save_foo_named(a, "a.foo_file") def save_type_b(self): self._save_foo_named(b, "b.foo_file") 现在,在我的测试中,我想确保所有这些文件均已创建,因此我想说一下这样的话: …

4
使用平面文件与数据库/ API进行前端和后端之间的传输
我有一个应用程序,在几个开发人员之间引起了相当激烈的讨论。 基本上,它分为Web层和后端层。Web层通过一个简单的Web表单收集信息,并将此数据作为JSON文档(字面上是.json文件)存储到后端使用的watch文件夹中。后端每隔几秒钟轮询一次该文件夹,拾取文件并执行其功能。 文件本身非常简单(即所有字符串数据,无嵌套),最大时约为1-2k,系统大部分时间都处于空闲状态(但在任何给定时间突发多达100条消息)。每个邮件的后端处理步骤大约需要10分钟。 当一个开发人员建议使用文件系统作为消息传递层是一个糟糕的解决方案时,这种说法就出现了,而应改为使用诸如关系数据库(MySQL),noSQL数据库(Redis)甚至是普通的REST API调用之类的东西。 应当注意,Redis用于组织中其他地方的队列消息处理。 我听到的论点如下 支持平面文件: 平面文件比任何其他解决方案都更可靠,因为仅在拾取后将文件从“监视”文件夹移至“处理”文件夹,完成后才移至“完成”文件夹。除非存在非常低级的错误,否则消息消失的风险为零,这无论如何都会破坏其他功能。 平面文件需要较少的技术知识来理解-就是cat这样。无需编写查询,也不会意外将消息从队列中弹出并永久消失。 从编程的角度来看,文件管理代码比数据库API更简单,因为它是每种语言的标准库的一部分。这降低了代码库的整体复杂性以及必须引入的第三方代码的数量。 在YAGNI原则规定,平面文件工作得很好,现在,没有表现出需要更换一个更复杂的解决方案,所以离开它。 支持数据库: 扩展数据库比充满文件的目录更容易 平面文件存在有人将“完成”文件复制回“监视”目录的风险。由于此应用程序(虚拟机管理)的性质,这可能会导致灾难性的数据丢失。 要求T / S应用程序具有更高的技术水平,这意味着未受过教育的员工不太可能仅仅通过戳东西来搞砸。 数据库连接代码,尤其是针对Redis之类的数据库连接代码,至少与标准库文件管理功能一样强大。 从开发人员的角度来看,数据库连接代码明显(如果没有功能)更简单,因为它的级别比文件操作更高。 从我的看到,两个开发人员都有很多有效的观点。 因此,在这两个人中,亲文件开发人员或亲数据库开发人员中,哪一个更符合软件工程最佳实践,为什么?

11
应该始终使用编码最佳实践吗?
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 在对软件进行编码时,对于正在构建的应用程序,体系结构应该始终是最佳实践还是实践? 如果我要构建一个两页的Web应用程序,该应用程序可能会使用5年,并且在那5年中有2项改进,那么我应该编写依赖注入,设计模式,带有视图模型的model-view-controller等代码吗?

5
为什么将类型与生成器结合在一起?
我最近在Code Review上删除了我的一个Java答案,它的开始是这样的: private Person(PersonBuilder builder) { 停止。红色标志。一个PersonBuilder将建立一个Person;它知道一个人。Person类应该对PersonBuilder一无所知-这只是一个不可变的类型。您已经在此处创建了圆形耦合,其中A取决于B,而B取决于A。 该人员应仅获取其参数;愿意创建一个人而不创建它的客户应该能够做到这一点。 我被选票打了耳光,并告诉我(引用)红旗,为什么?这里的实现与Joshua Bloch在其“ Effective Java”书(项目2)中演示的形状相同。 因此,看来在Java 中实现构建器模式的一种正确方法是使构建器成为嵌套类型(尽管这不是这个问题),然后制造产品(正在构建的对象的类) )对构建器的依赖,如下所示: private StreetMap(Builder builder) { // Required parameters origin = builder.origin; destination = builder.destination; // Optional parameters waterColor = builder.waterColor; landColor = builder.landColor; highTrafficColor = builder.highTrafficColor; mediumTrafficColor = builder.mediumTrafficColor; lowTrafficColor = builder.lowTrafficColor; } https://zh.wikipedia.org/wiki/Builder_pattern#Java_example 对于相同的Builder模式,相同的Wikipedia页面对于C#具有非常不同的实现(并且更加灵活): //Represents …

3
为什么Java / Linux堆栈无法“实时”运行的原因是什么?
我经常听到开发人员提的是Java的不能“ 做实时 ”,这意味着在Linux上运行的Java应用程序不能满足一个确定性的实时系统的要求,如对RIOT-OS等运行的东西 我试图理解为什么。我的SWAG告诉我,这可能主要是由于Java的Garbage Collector可以在任何时间运行并完全暂停系统。而且,尽管那里有所谓的“无暂停GC”,但我不一定相信他们的广告,也没有每个JVM实例$ 80K的兴趣来支持这个业余项目! 我还阅读了有关在Linux上运行无人机软件的文章。在那篇文章中,作者描述了Linux几乎导致无人机撞车的情况: 在选择在Pi上执行低级控制循环(PID)之后,我学到了很难的一课-为了变得聪明,我决定在循环的中间放置一个日志记录以进行调试-Quad最初运行良好,但随后Linux决定花2秒写一个日志条目,然后四边形几乎撞到了我的车上! 现在,尽管那个作者用C ++编写了无人机软件,但我可以想象,在Linux上运行的Java应用程序可能遭受同样的命运。 根据维基百科: 如果一个操作的总正确性不仅取决于它的逻辑正确性,还取决于它执行的时间,那么该系统就是实时的。 所以对我来说,这意味着“ 如果完全正确需要逻辑上的正确性和及时性,那么您就不会实时。 ” 假设我已经编写了一个Java应用程序以使其具有超强的性能,可以这么说,我已经“挤满了柠檬”,并且不能合理地用Java编写该程序以使其更快。 总而言之,我的问题是:我正在寻找可以向我解释所有/大多数运行Linux的Java应用程序无法成为“实时应用程序”的原因。意思是,什么使Java / Linux堆栈上的所有事物类别阻止了它“及时”,从而使其“ 完全正确 ”?如前所述,GC和Linux日志刷新似乎可以暂停执行,但是我敢肯定Java应用程序本身之外还有更多事情会导致计时/性能下降,并使其难以满足最终期限的要求。这些是什么?
20 java  linux  real-time 

5
具有后备情况的特殊情况是否违反《里斯科夫替代原则》?
假设我有一个FooInterface具有以下签名的接口: interface FooInterface { public function doSomething(SomethingInterface something); } 还有一个ConcreteFoo实现该接口的具体类: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { } } ConcreteFoo::doSomething()如果它传递了一种特殊类型的SomethingInterface对象(例如称为SpecialSomething),我想做一些独特的事情。 如果我加强方法的先决条件或引发新的异常,则绝对是LSP违规,但是如果我SpecialSomething在为通用SomethingInterface对象提供后备时又对特殊情况的对象进行了处理,这是否仍会违反LSP ?就像是: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { if (something instanceof SpecialSomething) { // Do SpecialSomething magic } else { // Do generic …

1
您的代码中处理复数形式的标准是什么?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 当使用其复数和单数都相同的变量时,如何命名它们?有没有什么标准? 例如: Series[] series // Plural Series series // Singular 深入: 具体来说,我的系列集合需要称为系列(由于JSON格式),您是否考虑命名要添加到集合中的系列的单数形式Series s? 如: List<Series> series = new List<Series>(); Series s; while (someBool) { s = new Series(); s.Name = "Name"; while (anotherBool) { s.AddValue(someValue); } series.Add(s); }


1
<和有什么区别?扩展了Foo>和<Foo>
我似乎对&lt;Foo&gt;和之间的区别有误解&lt;? extends Foo&gt;。据我了解,如果我们有 ArrayList&lt;Foo&gt; foos = new ArrayList&lt;&gt;(); 这表明Foo可以将类型的对象添加到此数组列表中。由于的子类Foo也是type Foo,因此也可以添加它们而不会出现错误,如下所示 ArrayList&lt;Foo&gt; foos = new ArrayList&lt;&gt;(); foos.add(new Foo()); foos.add(new Bar()); 在哪里Bar extends Foo。 现在,说我定义foos为 ArrayList&lt;? extends Foo&gt; foos = new ArrayList&lt;&gt;(); 我目前的理解是,这表示some unknown type that extends Foo。我的意思是可以将任何属于其子类的对象Foo添加到此列表中。表示ArrayList&lt;Foo&gt;和之间没有区别ArrayList&lt;? extends Foo&gt;。 为了对此进行测试,我尝试编写以下代码 ArrayList&lt;? extends Foo&gt; subFoos = new ArrayList&lt;&gt;(); subFoos.add(new Foo()); subFoos.add(new Bar()); …
20 java  generics 

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.