软件工程

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

3
.NET中记录和跟踪的最佳实践
我已经阅读了很多有关跟踪和日志记录的内容,试图为该问题的最佳实践找到一些黄金法则,但是没有任何东西。人们说好的程序员会产生良好的跟踪,但是要这样说,它必须来自经验。 我也在这里和通过互联网阅读了类似的问题,它们并不是我要问的一样,或者我的回答不令人满意,也许是因为这些问题缺乏细节。 因此,人们说,在无法附加调试器的情况下,跟踪应可以复制调试应用程序的经验。它应该提供足够的上下文,以便您可以看到应用程序中每个控制点采用的路径。 更深入地讲,您甚至可以区分跟踪和事件日志记录,因为“事件日志记录与跟踪的不同之处在于它捕获主要状态而不是详细的控制流”。 现在,说我想仅使用标准.NET类(System.Diagnostics名称空间中的类)进行跟踪和记录。我认为TraceSource类比静态Trace类更适合这项工作,因为我想在跟踪级别之间进行区分,并且使用TraceSource类可以传递用于通知事件类型的参数,而在使用Trace类时我必须使用Trace.WriteLineIf然后验证类似SourceSwitch.TraceInformation和的东西SourceSwitch.TraceErrors,它甚至没有类似TraceVerbose或的属性TraceStart。 考虑到所有这些,您是否可以考虑按以下方式进行操作: 开始方法时,跟踪“开始”事件,该事件应表示单个逻辑操作或管道,以及传递给方法的参数值的字符串表示。 将项目插入数据库时​​,跟踪“信息”事件。 在重要的if / else语句中采用一条路径或另一条路径时,跟踪“信息”事件。 在catch块中跟踪“严重”或“错误”,具体取决于它是否是可恢复的错误。 完成该方法的执行时,跟踪“停止”事件。 另外,请说明何时最好跟踪“详细”和“警告”事件类型。如果您的示例代码具有良好的跟踪/记录功能并且愿意共享,那将是极好的选择。 注意:我在这里找到了一些很好的信息,但仍然不是我想要的信息:http : //msdn.microsoft.com/zh-cn/magazine/ff714589.aspx
53 .net  logging 

5
“ Nightly Builds”是什么意思?
我使用开放源代码项目已有一段时间,并且一直在开发开放源代码应用程序,每隔一段时间我会碰到“ Nightly Build”一词,而我一直对它的真正含义感到好奇。从字面上看,这是否意味着这些项目纯粹是作为副项目完成的(通常是在每个人完成日常工作后的晚上),并且没有真正的贡献者/专门的开发团队,还是比这更复杂?


14
TDD是否真的适用于复杂项目?
我问这个问题,关于我在TDD项目期间遇到的问题。在创建单元测试时,我注意到了以下挑战。 生成和维护模拟数据 维护大型模拟数据既困难又不切实际。当数据库结构发生变化时,这甚至变得更加困难。 测试GUI 即使具有MVVM和测试GUI的能力,也需要大量代码来重现GUI场景。 测试业务 我的经验是,如果将TDD限于简单的业务逻辑,则它会很好地工作。但是,由于测试组合(测试空间)的数量非常大,因此很难测试复杂的业务逻辑。 需求矛盾 实际上,很难捕获正在分析和设计中的所有需求。由于项目很复杂,很多情况下一个便笺的要求会导致矛盾。在实施阶段的后期发现了矛盾。TDD要求要求100%正确。在这种情况下,可以期望在创建测试期间会捕获到相互矛盾的需求。但是问题在于,在复杂的场景中情况并非如此。 我已经读过这个问题:TDD为什么起作用? TDD是否真正适用于复杂的企业项目,或者实际上是对项目类型的限制?
53 tdd 

10
如何测试测试?
我们测试代码以使其更正确(实际上,不正确的可能性较小)。但是,测试也是代码-它们也可能包含错误。而且,如果您的测试有错误,则很难使您的代码变得更好。 我可以想到测试中三种可能的错误类型: 逻辑错误,当程序员误解了手头的任务,并且测试按照他认为应该做的事情进行时,这是错误的; 基础测试框架中的错误(例如,泄漏的模拟抽象); 测试中的错误:测试的执行与程序员认为的稍有不同。 类型(1)错误似乎无法防止(除非程序员只是……变得更聪明)。但是,(2)和(3)可能很容易处理。您如何处理这些类型的错误?您有什么特殊策略可以避免它们吗?例如,您是否编写了一些特殊的“空”测试,仅检查测试作者的预设?此外,您如何调试已损坏的测试用例?

27
您看到的最浪费金钱的事情是什么,您对此做了什么?[关闭]
作为程序员,我们经常会看到大型组织在ated肿,效率低下的问题解决方案上浪费大量金钱。这让我非常痛苦,因为我希望组织从最佳解决方案中受益。但是,在影响关键决策者方面,我作为程序员的能力是有限的,而且通常我的观点仅限于我自己的小技术领域。 所以,我的问题是这个。在确实使您的山羊陷入困境的某些软件和/或硬件上浪费了巨额资金之后,您如何处理以使其得到修复?或者您注定要永远硬着头皮咕m咕m呢?我很想听听您的整体经验,尤其是您从中学到的经验教训,以了解将来如何解决此类问题。不要说名字了,解决问题的经验比实际的冒犯产品更为重要。

4
如果合并到开发中的功能被管理层推迟,该怎么办?
最近,我们遇到了一个问题,管理层推迟了webapp(自动注册)的功能,因为他们觉得开始太“冷”了,但是他们希望我们一直在努力的所有其他功能都可以上线。 问题在于该功能在完成时已与我们期望在下一个版本中发布的所有其他功能一起合并到开发中,因此我们不能像往常一样将dev-> test-> master合并。 我们如何避免这个问题?

1
Swift协议命名约定
来自主要是C#的背景,我习惯于使用术语“接口”来描述对象,而该对象没有定义行为的实现。在c#中,惯例是在接口名称前加上“ I”,如IEnumerable等等。 当然,该概念在不同的语言中具有不同的名称。在Swift中,相同的概念称为“协议”。在开发协议时,我经常为协议和实现它的类有非常相似的名称。到目前为止,我一直在将“ protocol”一词附加到这些对象上,就像在c#中使用“ I”一样,在EnumerableProtocol等等中。 对快速命名协议的约定有何想法?

5
我应该传递要打开的文件名还是打开文件?
假设我有一个处理文本文件的函数-例如,读取文本文件并删除单词“ a”。我可以将其传递给文件名并处理函数中的打开/关闭,也可以将其传递给打开的文件并期望有人调用它可以处理关闭它的问题。 第一种方法似乎是一种更好的方法,可以确保没有文件保持打开状态,但是会阻止我使用StringIO对象之类的东西 第二种方法可能有点危险-无法知道文件是否将关闭,但是我可以使用类似文件的对象 def ver_1(filename): with open(filename, 'r') as f: return do_stuff(f) def ver_2(open_file): return do_stuff(open_file) print ver_1('my_file.txt') with open('my_file.txt', 'r') as f: print ver_2(f) 这些通常是其中之一吗?通常是否期望某个函数以这两种方式之一运行?还是应该对其进行详细记录,以便程序员可以适当地使用该函数?

6
Java最佳实践中是否会尽可能使用Lambda表达式?
我最近掌握了Java 8中引入的Lambda表达式。我发现,每当我使用功能接口时,我总是总是使用Lambda表达式,而不是创建实现该功能接口的类。 这被认为是好的做法吗?还是他们的情况不适合将Lambda用于功能接口?
52 java  lambda 

9
为什么Java有`void`方法?
/为什么Java需要有void方法?参考: 任何声明为void的方法都不会返回值。 就我所能想到的,void通过返回状态标志,被调用的对象或,将更好地服务于的每次使用null。 这将使每个调用成为可分配的语句,并有助于构建器模式和方法链接。仅出于效果而调用的方法通常会返回布尔值或泛型Success类型,或者在失败时引发异常。

4
Unix管道的确切知识是什么
我听说过道格拉斯·麦克罗伊(Douglas Mcllroy)如何提出这个概念以及肯·汤普森(Ken Thompson)如何在一夜之间实现这个故事。 据我了解,管道是一个系统调用,它在两个进程之间共享一块内存,一个进程在其中写入数据,其他进程从中读取数据。 作为不熟悉OS内部或概念的人,我想知道故事中的“天才”到底是什么?这是两个进程共享内存的想法吗?还是执行?或两者? PS:我知道管道的用途或如何在外壳中使用它。问题是关于|

8
C ++中的垃圾会发生什么?
Java有一个自动GC,它偶尔会停止世界,但会处理堆上的垃圾。现在C / C ++应用程序没有这些STW冻结,它们的内存使用也不会无限增长。如何实现这种行为?如何处理死物?

9
引发异常或让代码失败
我想知道是否有反对这种风格的利弊: private void LoadMaterial(string name) { if (_Materials.ContainsKey(name)) { throw new ArgumentException("The material named " + name + " has already been loaded."); } _Materials.Add( name, Resources.Load(string.Format("Materials/{0}", name)) as Material ); } 对于每个方法,该方法name只能运行一次。_Materials.Add()如果同一对象将被多次调用,将抛出异常name。结果是我的后卫完全多余了,还是有一些不太明显的好处? 如果有人感兴趣,那就是C#,Unity。
52 exceptions 

11
如何避免级联重构?
我有一个项目。在此项目中,我希望对其进行重构以添加功能,并且对项目进行重构以添加功能。 问题是,当我完成后,原来我需要做一个小的接口更改以适应它。所以我做了改变。然后,就新类而言,无法使用其当前接口来实现消费类,因此它也需要一个新接口。现在已经三个月了,我不得不解决了几乎不相关的无数问题,而且我正在寻找解决从现在开始经过一年规划的问题,或者只是因为困难而列为无法解决的问题,然后再进行编译再次。 将来如何避免这种级联重构?这仅仅是我以前的课程互相依赖的一种征兆吗? 简要编辑:在这种情况下,重构就是功能,因为重构增加了特定代码的可扩展性并减少了一些耦合。这意味着外部开发人员可以做更多的事情,而这正是我想要提供的功能。因此,原始重构本身不应该是功能上的更改。 我五天前承诺的更大修改: 在开始重构之前,我有一个带有接口的系统,但是在实现中,我只是简单地dynamic_cast通过了所有可能的实现。显然,这意味着您不能一方面从接口继承,其次,对于没有实现访问权即可实现此接口的任何人,这都是不可能的。因此,我决定要解决此问题并开放供公众使用的界面,以便任何人都可以实施,而实施该界面是整个合同所必需的-显然是一项改进。 当我发现并用火杀死所有地方时,我发现一个地方被证明是一个特殊的问题。它取决于所有各种派生类的实现细节以及已经实现但在其他地方更好的重复功能。它可以代替公共接口来实现,而可以重新使用该功能的现有实现。我发现它需要特定的上下文才能正常运行。粗略地说,调用先前的实现看起来像 for(auto&& a : as) { f(a); } 但是,要获得此上下文,我需要将其更改为更类似的内容 std::vector<Context> contexts; for(auto&& a : as) contexts.push_back(g(a)); do_thing_now_we_have_contexts(); for(auto&& con : contexts) f(con); 这意味着对于以前曾经是其中一部分的所有操作f,其中一些操作需要成为g无需上下文的新功能的一部分,而其中某些操作则需要由现在延迟的一部分组成f。但是,并非所有方法都f调用需要或需要此上下文-其中一些需要通过单独的方式获得的独特上下文。因此,对于f最终调用的所有内容(大致来说,几乎所有内容),我必须确定他们需要的上下文(如果有的话),应该从哪里获取以及如何将它们从旧f分为新f与新g。 这就是我最终所处位置的方式。我一直坚持下去的唯一原因是因为无论如何我都需要这种重构。

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.