软件工程

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

5
您应该在哪里放置常数,为什么?
在大多数大型应用程序中,通常只有几个“常量”位置: 一类用于GUI和内部内容的内容(制表页标题,组框标题,计算因子,枚举) 一类用于数据库表和列(此部分是生成的代码)以及它们的可读名称(手动分配) 一类应用程序消息(日志,消息框等) 在这些类中,常量通常分为不同的结构。在我们的C ++应用程序中,仅在.h文件中定义常量,而在.cpp文件中分配值。 优点之一是,所有琴弦等都放在一个中央位置,每个人都知道在必须更改某些内容时可以在哪里找到它们。 这尤其是项目经理在人们来来往往时喜欢的东西,这样每个人都可以更改这些琐碎的事情,而不必深入研究应用程序的结构。 另外,您可以轻松地一次更改相似的“组框” /“选项卡页”等的标题。另一个方面是,您可以仅打印该类并将其交给非程序员,该非程序员可以检查字幕是否直观,向用户发送的消息是否太详细或太混乱等。 但是,我看到了某些缺点: 每个类都与常量类紧密耦合 添加/删除/重命名/移动常量需要重新编译至少90%的应用程序(注意:至少在C ++中,不需要更改值)。在我们的一个带有1500个类的C ++项目中,这意味着大约7分钟的编译时间(使用预编译的标头;如果没有它们,则大约为50分钟),再加上大约10分钟的链接到某些静态库。 通过Visual Studio编译器构建速度优化的发行版最多需要3个小时。我不知道是否大量的类关系是源,但也有可能。 您会被迫将临时硬编码的字符串直接转化为代码,因为您想非常快速地测试某项内容,并且不想仅等待15分钟来进行该测试(并且可能以后每次测试)。每个人都知道“以后我会解决”的想法。 在另一个项目中重用一个类并不总是那么容易(主要是由于其他紧密的耦合,但是常量处理并没有使它更容易。) 您将在哪里存储这样的常量?为了使您的项目经理相信还有更好的概念也符合上面列出的优点,您还会提出什么论点? 随意给出特定于C ++或独立的答案。 PS:我知道这个问题是主观的,但是老实说,我不知道有比这个网站更好的地方。 有关此项目的更新 关于编译时间,我有个新闻: 在Caleb和gbjbaanb的帖子中,有空时,我将常量文件拆分为其他几个文件。我最终还将我的项目分成几个库,现在可以轻松得多。在发布模式下进行编译显示,包含数据库定义(表,列名等-超过8000个符号)并建立了某些哈希值的自动生成的文件在发布模式下造成了巨大的编译时间。 现在,通过停用包含DB常量的库的MSVC优化器,我们可以将发布模式下的项目(几个应用程序)的总编译时间从最多8小时减少到不到一小时! 我们还没有找到为什么MSVC很难优化这些文件,但是现在,由于我们不再只依赖夜间构建,因此此更改减轻了很多压力。 这个事实以及其他好处,例如紧密耦合少,可重用性更好等,也表明花时间拆分“常量”并不是一个坏主意;-) 更新2 由于这个问题仍然受到关注: 这是过去几年中我一直在做的事情: 将每个常量,变量等完全放在与其相关的范围内:如果仅在单个方法中使用常量,则可以在该方法中定义它。如果单个类对此感兴趣,请将其保留为该类的私有实现细节。这同样适用于名称空间,模块,项目,公司范围。我还将相同的模式用于助手功能等。(如果您开发一个公共框架,这可能不会100%适用。) 这样做可以提高可重用性,可测试性和可维护性,使您不仅花费更少的时间(至少在C ++中),而且花费在错误修复上的时间也更少,这使您有更多的时间实际开发新功能。同时,开发这些功能的速度会更快,因为您可以更轻松地重用更多代码。这在一定程度上胜过中央常量文件可能具有的任何优势。 如果您想了解更多,请特别看一下接口隔离原则和单一职责原则。 如果您同意,请支持Caleb的回答,因为此更新基本上是他所说的更一般的看法。

3
为实现未决但未计划抽象的方法引发NotImplementedError是常规的吗?
我喜欢为NotImplementedError我想实现的任何方法提出一个,但是我还没有去做。我可能已经有了部分实现,但是raise NotImplementedError()由于我还不喜欢它而在它前面加上了它。另一方面,我也喜欢遵守约定,因为这将使其他人更容易维护我的代码,并且约定可能存在是有充分理由的。 但是,NotImplementedError的Python文档指出: 此异常派生自RuntimeError。在用户定义的基类中,抽象方法要求派生类重写该方法时,应引发此异常。 这是比我描述的更为具体的正式用例。提出一个NotImplementedError简单的方法来简单地指出API的这一部分是否还在进行中,这是一种很好的传统样式吗?如果不是,是否有另一种标准化的方式表明这一点?

12
公司使用盗版软件[关闭]
几个月前,我开始在一家公司工作,担任工程师。这是一家小公司,他们基本上要做的是通过电话接听服务。现在,他们正在从普通电话切换到IP电话,以便计算机在工作中占据更重要的位置。 但是,工人使用的所有计算机都配备了盗版软件,包括其操作系统。而且,他们甚至没有购买任何许可证来复制其他计算机。换句话说,他们没有花任何钱在办公室购买软件。我并不是说复制许可的文件是合法的,但情况太多了。 有一个人安装了盗版软件。当我问他时,他没有内feel感,甚至没有道理。他甚至都不是专家。他只是在互联网上搜索以安装盗版软件。我们的老板对计算机没有任何了解,所以他采取了更便宜的方式。 你怎么看待这件事?由于我还是该公司的新手,所以我不对那些破裂的计算机进行维护。但是我必须每天使用那些软件。稍后,我将提供支持和帮助台工作。我真的不想承担操作盗版软件的责任。从开发人员和工程师的角度来看,盗版软件无法获得法律支持,并且可能无法正常工作。所以,我正在考虑换工作。 我在想太多吗?我应该等到我对老板有了更多信誉后,再尝试改变他的政策吗?到目前为止,老板没有对我说任何话。欢迎任何意见。谢谢
33 ethics 

7
如果没有库就可以执行任务吗?[关闭]
我处于可以使用开源JavaScript插件完成任务的情况。但是,当我尝试使用它时,我发现自己不得不重新设计已经完成的很多工作,以我的拙见,这给项目增加了一定的复杂性。尽管我可以用干净的代码完成相同的任务,但我可以自己制作,而无需更改到目前为止的工作。 在这种情况下,您是否仍应选择一个库(例如,为了获得更好的质量代码?)

6
块中的附加行与清理代码中的附加参数
语境 在第35页的“ 清理代码”中,它说 这意味着if语句,else语句,while语句等中的块应为一行。该行可能是函数调用。这不仅使封闭函数较小,而且还增加了文档价值,因为在块中调用的函数可以具有很好的描述性名称。 我完全同意,这很有意义。 稍后,在第40页上,它介绍了有关函数参数的信息 函数的理想参数个数为零(尼拉度)。接下来是一个(单声道),紧接着是两个(双声道)。在可能的情况下,应避免使用三个参数(三重性)。超过三个(多义词)需要非常特殊的理由-因此无论如何都不应使用。争论很难。他们具有很大的概念力。 我完全同意,这很有意义。 问题 但是,通常我会发现自己从另一个列表创建了一个列表,而我将不得不忍受两个弊端之一。 我在代码块中使用了两行,一行用于创建事物,一行用于将其添加到结果中: public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms) { List<Flurp> flurps = new List<Flurp>(); foreach (BadaBoom badaBoom in badaBooms) { Flurp flurp = CreateFlurp(badaBoom); flurps.Add(flurp); } return flurps; } 或者,我在要向其中添加事物的列表的函数中添加了一个参数,从而使其“变差了一个参数”。 public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms) { List<Flurp> flurps = new List<Flurp>(); foreach (BadaBoom badaBoom …
33 clean-code  solid 

4
Scrum-冲刺期间团队成员忙什么
因此,Scrum冲刺是一个固定的时间段,在此期间应实现一组特定的功能。Scrum团队由致力于提供这些功能的所有人员组成,其中大多数通常是开发人员和测试人员。 建立了这些规则后,您可能会想知道如何在整个冲刺期间让所有这些人都忙。在sprint的开始阶段,没有什么要测试,而在sprint的末尾,通常没有什么东西可以开发/修复。 我已经看到了两种方法可以解决此问题,但是它们似乎都无法正确解决问题。 1)让团队成员决定在任务结束时应该做什么。 缺点: 如果他们的工作没有得到充分的计划(例如,重大的重构,改用新的测试框架),那么他们的工作可能会变得毫无用处,或者被困在中间 另一方面,计划这样的工作可能要花费大量时间,并且客户可能会失望地看到团队浪费时间在无法带来即时价值的事情上 通常无法对这些任务进行彻底的估算,因此,无原则的工作人员很容易花时间看YouTube猫,而不会在Scrum板或其他任何地方反映出来 2)在sprint中留出仅用于开发的空间,并在sprint完成后开始测试(当开发人员开始处理下一个sprint的功能时) 缺点: 在为当前sprint开发功能时,开发人员会通过修正前一个bug来分心,而他们可能无法执行估计在当前sprint期间完成的工作量 需要两个Scrum板:一个用于当前的sprint功能,一个用于以前的sprint错误 所以我的问题是:如何在开发人员和测试人员之间的冲刺期间正确分配工作,以使任何人都不会负担过多的工作,或者在任何时候都没有任务而最终失败?有什么方法可以改善上述方法?还是有更好的方法?
33 agile  scrum  sprint 

5
为什么删除通常比在许多数据结构中插入要难得多?
您能想到任何特定的原因,为什么对于许多(大多数)数据结构而言,删除通常比插入要难得多吗? 快速示例:链接列表。插入是微不足道的,但是删除有一些特殊情况,使插入变得非常困难。自平衡二进制搜索树(例如AVL和Red-black)是痛苦的删除实现的经典示例。 我想说这与大多数人的想法有关:对于我们而言,以结构性方式定义事物更容易,这很容易导致插入。

9
如何为昂贵的程序员辩护?
在我们公司中,我们需要做许多看似并不复杂的事情,例如开发Mobile UI。 假设经验丰富的程序员花费我们的费用是初学者的4倍。 两者基本上都可以在相同的时间内完成看似简单的事情。 不同之处在于,经验丰富的程序员产生的bug更少,代码更稳定等。初学者程序员浪费了很多其他人(PM,客户端等)的时间。但是它们便宜得多。 counter参数是,有经验的初学者用相同的时间来制作HTML表。因此,聘请有经验的程序员来做是奢侈的,初学者也可以做到。 考虑到我们领域经验丰富的程序员与新程序员之间的差异可能是4倍,我们应该投资更多,更好的程序员,还是更多,更好的PM。

5
如何创建和执行例外合同?
我试图说服我的团队领导者允许在C ++中使用异常,而不是返回isSuccessful带有错误代码的布尔值或枚举。但是,我不能反驳他的批评。 考虑这个库: class OpenFileException() : public std::runtime_error { } void B(); void C(); /** Does blah and blah. */ void B() { // The developer of B() either forgot to handle C()'s exception or // chooses not to handle it and let it go up the stack. C(); }; …
33 c++  exceptions 

6
在开发人员的便携式计算机上存储关键数据库的良好安全实践是什么?
我们有一些建议: 开发人员需要在其机器上复制生产数据库。 开发人员在App.config文件中具有所述数据库的密码。 我们不想破坏所说数据库中的数据。 一些建议的解决方案及其缺点: 全盘加密。这样可以解决所有问题,但会降低笔记本电脑的性能,而且我们是一家初创企业,因此没有钱购买动力强劲的产品。 使用加密的硬盘创建虚拟机,并将数据库存储在该虚拟机上。它运行良好,但并没有太大帮助,因为Web.Config中有一个密码。 解决方案2 +要求开发人员在每次运行任何操作时都要键入数据库密码。它解决了所有问题,但是对于开发人员而言,有时一分钟多次启动应用程序确实很麻烦。另外,我们有多个连接到同一数据库的应用程序,并且每个密码屏幕的实现都必须有所不同。 因此,我的问题是,是否有针对此类问题的通用解决方案,或有关如何使上述解决方案可行的建议?

5
我应该通过参数还是通过返回值初始化C结构?[关闭]
我工作的公司正在通过初始化函数来初始化所有数据结构,如下所示: //the structure typedef struct{ int a,b,c; } Foo; //the initialize function InitializeFoo(Foo* const foo){ foo->a = x; //derived here based on other data foo->b = y; //derived here based on other data foo->c = z; //derived here based on other data } //initializing the structure Foo foo; InitializeFoo(&foo); 我遇到了一些尝试初始化我的结构的问题: …

8
如果C允许,为什么Java完全不允许数字条件,如if(5){…}?
我有两个小程序: C #include <stdio.h> int main() { if (5) { printf("true\n"); } else { printf("false\n"); } return 0; } 爪哇 class type_system { public static void main(String args[]) { if (5) { System.out.println("true"); } else { System.out.println("false"); } } } 报告错误消息: type_system.java:4: error: incompatible types: int cannot be converted to …
33 java  c  type-systems 

9
质量检查人员如何测试他们看不到的缓存逻辑?
我刚刚在Web应用程序中实现了一个缓存层,现在我想知道QA应该如何测试它,因为缓存对用户是透明的。 我的一个想法是将登录记录在调用填充缓存的代码的方法中,并记录何时从缓存中提取对象以及何时需要从数据库中重新创建对象,然后测试人员可以查看日志以查看是否,例如,每隔10分钟就会从数据库中重新加载某个对象,而不是每一次页面浏览。 但是有人可以针对这种情况提出一些更好的做法吗?
33 testing  caching 

1
raw,weak_ptr,unique_ptr,shared_ptr等…如何明智地选择它们?
C ++中有很多指针,但是老实说,在5年左右的C ++编程中(特别是Qt Framework),我仅使用旧的原始指针: SomeKindOfObject *someKindOfObject = new SomeKindOfObject(); 我知道还有很多其他“智能”指针: // shared pointer: shared_ptr<SomeKindofObject> Object; // unique pointer: unique_ptr<SomeKindofObject> Object; // weak pointer: weak_ptr<SomeKindofObject> Object; 但是我对如何处理它们以及在原始指针比较中它们可以为我提供什么一无所知。 例如,我有这个类头: #ifndef LIBRARY #define LIBRARY class LIBRARY { public: // Permanent list that will be updated from time to time where // each items …

6
如何在事件驱动的体系结构中处理初始状态?
在事件驱动的体系结构中,每个组件仅在事件通过系统发送时起作用。 假设有一辆带有刹车踏板和刹车灯的假想汽车。 刹车灯在接收到刹车启动事件时亮起,并在接收到刹车关闭事件时熄灭。 制动踏板发送brake_on当它被按下事件和brake_off当它被释放事件。 这是一切都很好,直到你有其中汽车已开启,制动踏板的情况已经按下。由于刹车灯从未收到过刹车事件,因此它将保持熄灭状态-显然是不希望的情况。默认情况下,打开刹车灯只会扭转这种情况。 如何解决此“初始状态问题”? 编辑:谢谢您的所有答复。我的问题不是关于一辆真正的汽车。在汽车中,他们通过不断发送状态来解决此问题-因此在该域中没有启动问题。在我的软件领域,该解决方案将使用许多不必要的CPU周期。 编辑2:除了@gbjbaanb的答案外,我还将使用以下系统: 假设的制动踏板在初始化后会发送一个事件及其状态,并且 假设的制动灯在初始化后发送一个事件,要求从制动踏板发出状态事件。 使用此解决方案,组件之间没有依赖关系,没有竞争条件,没有消息队列过时,也没有“主”组件。

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.