软件工程

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

9
如何传达插入顺序在地图中的重要性?
我正在从数据库中获取一组元组,并将其放入地图中。数据库查询成本很高。 映射中的元素没有明显的自然顺序,但是插入顺序仍然很重要。对地图进行排序将是一项繁重的操作,因此鉴于查询结果已经按照我想要的方式进行了排序,因此我想避免这样做。因此,我只是将查询结果存储到中LinkedHashMap,然后从DAO方法返回地图: public LinkedHashMap<Key, Value> fetchData() 我有一种方法processData应该在地图上进行一些处理-修改一些值,添加一些新的键/值。定义为 public void processData(LinkedHashMap<Key, Value> data) {...} 但是,一些短毛猫(Sonar等)抱怨说,“数据”的类型应该是诸如“地图”之类的接口,而不是实现“ LinkedHashMap”(squid S1319)。 所以基本上说我应该有 public void processData(Map<Key, Value> data) {...} 但是我希望方法签名说映射顺序很重要 -这对算法很重要processData-这样我的方法就不会仅传递任何随机映射。 我不想使用SortedMap,因为它(来自的javadocjava.util.SortedMap)“是根据其键的自然顺序来排序的,或者是由通常在排序的地图创建时提供的Comparator来排序的。” 我的键没有自然的顺序,创建比较器不执行任何操作似乎很冗长。 而且我仍然希望它是一个地图,以利用它put来避免重复的键等。如果没有,则data可能是一个List<Map.Entry<Key, Value>>。 那么我怎么说我的方法想要一个已经排序的地图?可悲的是,没有java.util.LinkedMap接口,否则我会使用它。
24 java  code-quality  map 

6
什么时候可以接受对父指针的循环引用?
这个堆栈溢出问题是关于一个孩子通过指针对其父对象的引用。 最初,评论对于设计是一个可怕的想法至关重要。 我了解这通常不是最好的主意。从一般的经验来看,似乎很公平地说:“不要这样做!” 但是,我想知道在什么样的条件下您将需要执行以下操作。这里的问题和相关的答案/注释甚至建议图不要做这样的事情。
24 design 

5
在Java中,私有助手应该放在公共方法之上还是之下?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 我注意到一个同事和我在Java类中对方法的排序有相反的做法。我们中的一个人开始使用主要的公共方法上课,然后再放置所有私人帮手。我们中的另一个人确保公共方法在最后。 显然,这只是样式问题,没有正确的答案。但是,在我们决定这件事只是Yooks vs Zooks的另一场争执而只是任意选择一个之前,我想知道是否存在标准的Java风格指南推荐,或者某种可行的理由,为什么一种方法比另一种更好。

3
在单元测试中挣扎于循环依赖
我正在尝试通过使用TDD开发类似于Bit Vector的简单方法来练习TDD。我碰巧正在使用Swift,但这是一个与语言无关的问题。 My BitVector是一个struct存储单个的UInt64,并在其上方提供一个API,可让您将其视为集合。细节无关紧要,但是很简单。高57位是存储位,低6位是“计数”位,它告诉您实际上有多少个存储位存储一个包含的值。 到目前为止,我有一些非常简单的功能: 构造空位向量的初始化程序 count类型的属性Int isEmpty类型的属性Bool 等于运算符(==)。注意:这是类似于Object.equals()Java 的值相等运算符,而不是像==Java中的引用相等运算符。 我遇到了一堆周期性依赖关系: 测试我的初始化程序的单元测试需要验证新构造的BitVector。它可以通过以下三种方式之一进行操作: 校验 bv.count == 0 校验 bv.isEmpty == true 检查一下 bv == knownEmptyBitVector 方法1依赖count,方法2依赖isEmpty(它本身依赖count,因此没有用处),方法3依赖==。无论如何,我不能孤立地测试初始化​​程序。 测试是否count需要对某些东西进行操作,这不可避免地会测试我的初始值设定项 实施isEmpty依赖count 执行==依赖count。 我能够通过引入一个私有API来部分解决此问题,该API BitVector从现有的位模式(作为UInt64)构造一个。这使我可以在不测试任何其他初始化程序的情况下初始化值,以便可以向上“引导”。 为了使我的单元测试真正成为单元测试,我发现自己做了很多黑客操作,这使我的产品和测试代码大大复杂化。 您如何解决这些问题?

4
如何在请求请求中处理TODO?
该问题是从软件质量保证和测试堆栈交换迁移而来的,因为可以在软件工程堆栈交换中回答。 去年迁移 。 当我查看请求请求中的更改时,有时会偶然发现带有“ TODO”注释的注释,该注释可能有不同的原因,在我们的情况下,主要是因为: 用于解决问题的解决方案可以改进,但需要大量的时间投入。作者选择了一种更快的解决方案,但评论说可能有更好的选择 有一个临时代码可以解决现有的错误,应尽快修复 知道TODOs通常会在代码库的整个生命周期内停留在代码库中,那么我应该如何在请求请求中对它们做出反应?我如何礼貌地避免使用它,或者如果它确实是合理的,我如何确保PR的作者在以后的晚些时候进行跟进?

8
每天执行一次用户操作:24小时重置与午夜重置[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 12个月前关闭。 当用户每天只能执行一次动作(例如,获得比赛的免费门票)时,我会遇到两种可能性。 1)24小时重置 如果他在第1天的晚上11:45执行动作,则只能在第2天的11:45或之后再次执行动作。他将无法在第二天的11:44做到这一点。 2)午夜重置(或任何固定时间) 无论用户在第1天什么时候执行该操作,只要它变成午夜且第2天开始,他都将能够再次执行该操作。 两者都限制了用户每天仅执行一项操作,但是我经常遇到方法1,我认为这样做很不方便,原因有两个: 首先,我必须等待时间 在很长一段时间内,我执行动作的时间戳会变得越来越迟,因为我将无法在每天的那个时间戳上准确地执行动作,而只能在几秒钟或几分钟后执行。 有什么技术上的原因,尽管我认为对于事先说明的用户来说,重要的缺点是它会首选方法1? 编辑,以指定:我特别是在谈论一个示例,其中显然不需要24小时的实际时间间隔,例如在当前的Theory11自由旋转事件中,您每24小时可获得1次自由旋转以获得机会在获奖中。

1
Java中的模块需求与依赖注入
这些天来,我脑海中浮现出一个问题: 我们的Javascript方法是否与传统软件开发中被认为是好的做法的几乎所有东西背道而驰? 我有一系列与此陈述有关的问题/意见,但是为了遵守StackExchange的格式,将它们分成不同的问题会更好。 模块要求 如今的标准Javascript代码如下所示: const someModule = require('./someModule') module.exports = function doSomethingWithRequest() { // do stuff someModule.someFunc() // do other stuff } 好处 封装:模块独立工作,并且知道执行其功能所需的一切。 作为一种颜色,客户可以更轻松地使用该模块。 缺点 可测试性差:在不使用DI时这是标准配置,但在动态语言(例如Javscript)中,可以通过* mockery或模块来规避* rewire。 它确实违反了DIP-请勿与依赖注入混淆。-因为我只能导入具体模块。 它可能违反了OCP-例如,假设我有一个日志模块(通过fs模块)写入文件系统。如果我想扩展此日志模块以将其发送到网络,那将非常困难。 *这可能与CommonJS甚至AMD模块一起使用,因为它们大部分是在用户领域实现的。但是,我不确定使用ES6 import语法怎么可能。 依赖注入 使用依赖注入,它将更像是: module.exports = function doSomethingWithRequest(someModule) { // do stuff someModule.someFunc() // do other stuff } …

7
在大型应用中应避免使用STL吗?
这听起来像是一个很奇怪的问题,但是在我的部门中,我们遇到以下问题: 我们正在开发一个服务器应用程序,该应用程序正在变得越来越大,即使是在考虑将其拆分为不同部分(DLL文件)时,也可以在需要时动态加载,然后再卸载,以便能够处理性能问题。 但是:我们正在使用的函数将输入和输出参数作为STL对象传递,并且正如Stack Overflow答案中所述,这是一个非常糟糕的主意。(该帖子包含一些解决方案和技巧,但看起来并不十分牢固。) 显然,我们可以用标准C ++类型替换输入/输出参数,并从函数内部的那些对象创建STL对象,但这可能会导致性能下降。 是否可以得出结论,如果您正在考虑构建一个可能会增长到一台PC无法再处理的应用程序,您绝对不能将STL用作一项技术吗? 有关此问题的更多背景:该问题 似乎有一些误解:问题如下: 我的应用程序正在使用大量性能(CPU,内存)以完成其工作,我想分拆此工作分解为不同的部分(由于程序已经被拆分为多个功能),从我的应用程序中创建一些DLL并将某些功能放入这些DLL的导出表并不难。这将导致以下情况: +-----------+-----------+---- | Machine1 | Machine2 | ... | App_Inst1 | App_Inst2 | ... | | | | DLL1.1 | DLL2.1 | ... | DLL1.2 | DLL2.2 | ... | DLL1.x | DLL2.x | ... +-----------+-----------+---- App_Inst1是安装在Machine1上的应用程序的实例,而App_Inst2是安装在Machine2上的同一应用程序的实例。 DLL1.x是安装在Machine1上的DLL,而DLL2.x是安装在Machine2上的DLL。 DLLx.1涵盖了导出的function1。 DLLx.2涵盖了导出的function2。 现在在Machine1上,我想执行function1和function2。我知道这会使Machine1重载,所以我想向App_Inst2发送一条消息,要求该应用程序实例执行function2。 …
24 c++  stl 

7
九十九规则在实践中
代码的前90%占开发时间的前90%。其余10%的代码占了开发时间的90%。 —贝尔实验室的汤姆·卡吉尔 实际上这是什么意思?程序员需要做大量工作,他们付出了180%的努力吗?

4
功能样式异常处理
有人告诉我,在函数式编程中,不应抛出和/或观察异常。取而代之的是,应将错误的计算结果视为底值。在Python(或其他不完全鼓励函数式编程的语言)中,只要出现“保持纯净”的错误,就可以返回None(或另一种替代方法,尽管None它严格地不符合定义)。所以必须首先观察到错误,即 def fn(*args): try: ... do something except SomeException: return None 这违反纯洁吗?如果是这样,是否意味着不可能仅用Python处理错误? 更新资料 埃里克·利珀特(Eric Lippert)在他的评论中使我想起了FP中处理异常的另一种方法。尽管我从未在实践中看到过用Python完成的工作,但一年前我学习FP时我还是玩过它。在这里,任何optional装饰函数返回的Optional值对于正常输出以及指定的异常列表都可以为空(未指定的异常仍可以终止执行)。Carry创建一个延迟的评估,其中每个步骤(延迟的函数调用)要么Optional从上一步获取非空输出,然后继续传递,要么通过一个new评估自身Optional。最后,最终值是normal或Empty。此处,该try/except块隐藏在装饰器后面,因此可以将指定的异常视为返回类型签名的一部分。 class Empty: def __repr__(self): return "Empty" class Optional: def __init__(self, value=Empty): self._value = value @property def value(self): return Empty if self.isempty else self._value @property def isempty(self): return isinstance(self._value, BaseException) or self._value is Empty def __bool__(self): …

6
您为什么要“等待”一个方法,然后立即查询它的返回值?
在本文中,提供了以下示例代码(为简便起见,对其进行了略作编辑): public async Task<ActionResult> Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Department department = await db.Departments.FindAsync(id); if (department == null) { return HttpNotFound(); } return View(department); } 该FindAsync方法Department通过其ID 检索对象,并返回Task<Department>。然后立即检查部门以查看其是否为空。据我了解,以这种方式要求Task的值将阻止代码执行,直到返回了来自waited方法的值,从而有效地使它成为同步调用。 你为什么要这样做?Find(id)如果您要立即阻止,仅调用sync方法不是更简单吗?
24 c#  .net  asp.net-mvc  async 

6
可读性是在(参考)参数中不使用const的正当理由吗?
在编写一些函数时,我在这样的参数中找到了const关键字: void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){ } 通常会导致在IDE或vim中将一行分成两行,因此我想删除参数中的所有const关键字: void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){ } 这是不使用const的正当理由吗?手动保持参数对象不变是否可以维护?

10
控制是否引发异常或返回null的参数-好的做法?
我经常遇到带有附加布尔参数的方法/函数,该参数控制是否在失败时引发异常或返回null。 已经讨论了在哪种情况下哪种选择是更好的选择,因此在这里我们不要专注于此。参见例如返回魔术值,抛出异常或在失败时返回false? 相反,让我们假设我们有一个很好的理由要支持这两种方式。 我个人认为这样的方法应该分为两种:一种在失败时引发异常,另一种在失败时返回null。 那么,哪个更好? 答:一种带$exception_on_failure参数的方法。 /** * @param int $id * @param bool $exception_on_failure * * @return Item|null * The item, or null if not found and $exception_on_failure is false. * @throws NoSuchItemException * Thrown if item not found, and $exception_on_failure is true. */ function loadItem(int $id, bool $exception_on_failure): …
24 exceptions 

10
如果一个类属性创建并返回一个新的类实例,它是一种反模式吗?
我有一个叫做Heading一些事情的类,但它也应该能够返回当前标题值的反面,最后必须通过创建Heading类本身的新实例来使用它。 我可以使用一个简单的属性reciprocal来返回当前值的相反标题,然后手动创建Heading类的新实例,或者我可以创建一种方法createReciprocalHeading()来自动创建Heading类的新实例并将其返回给用户。 但是,我的一位同事建议我只创建一个名为的类属性reciprocal,该属性通过其getter方法返回该类本身的新实例。 我的问题是:类属性的行为不是一种反模式吗? 我特别觉得这不太直观,因为: 在我看来,类的属性不应返回类的新实例,并且 如果reciprocal没有从IDE获得帮助或检查getter签名,该属性的名称为,将无法帮助开发人员完全理解其行为。 我是否对类属性应该做的事情过于严格?还是真正的顾虑?我一直试图通过类的字段和属性来管理类的状态,并通过其方法来管理类的行为,而我却看不出它如何适合于类属性的定义。

5
如何在C#中的不可变对象之间建立循环引用?
在下面的代码示例中,我们有一个表示房间的不可变对象的类。北,南,东和西代表进入其他房间的出口。 public sealed class Room { public Room(string name, Room northExit, Room southExit, Room eastExit, Room westExit) { this.Name = name; this.North = northExit; this.South = southExit; this.East = eastExit; this.West = westExit; } public string Name { get; } public Room North { get; } public Room South { …

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.