软件工程

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

9
为什么构造函数中的while(true)循环实际上不好?
尽管是一个普遍的问题,但我的范围是C#,因为我知道像C ++这样的语言在构造函数执行,内存管理,未定义的行为等方面具有不同的语义。 有人问我一个有趣的问题,对我来说不容易回答。 为什么(或者根本不?)让类的构造函数开始永无止境的循环(即游戏循环)被认为是不好的设计? 有一些与此有关的概念: 像最小惊讶原则一样,用户并不希望构造函数具有这种行为。 单元测试比较困难,因为您无法创建此类或将其注入,因为它永远不会退出循环。 从概念上讲,循环的结束(游戏结束)是构造函数完成的时间,这也是奇怪的。 从技术上讲,此类除了构造函数外没有其他公共成员,这使它很难理解(尤其是对于没有可用实现的语言) 然后是技术问题: 构造函数实际上从未完成,所以GC在这里发生了什么?这个对象已经在Gen 0中了吗? 由于基本构造函数从不返回,因此无法或至少非常复杂地从此类派生 这样的方法是否存在更明显的弊端或弊端?
47 c#  architecture 

8
为什么在函数名称中对参数名称进行编码不是更常见?[关闭]
在Clean Code中,作者举了一个例子 assertExpectedEqualsActual(expected, actual) 与 assertEquals(expected, actual) 前者声称更为清晰,因为它消除了记住论据去向以及由此引起的潜在滥用的必要性。但是,我从未在任何代码中看到前者命名方案的示例,并且一直都在看到后者。正如作者所断言的,为什么编码人员不采用前者,如果后者比后者更清晰?
47 clean-code 

9
确定元素的交货日期是否是“敏捷”的工作方式?
我们一直被告知,我们将由高级管理层以敏捷的方式开展新项目。他们设置了站立式,冲刺计划,回顾展等。但是,他们现在想出了一个计划,详细说明了他们希望我们针对每个要素提供的所有工作,并再次展示了日期,并在每个要素中进行了演示。一。该计划将于2017年第二季度发布。 在我看来,这似乎是最糟糕的瀑布,一个没有技术团队投入的计划已经草拟,其中计划中的某些故事还不清楚,开发团队也没有估计。 但是,我知道他们的论点是“高级利益相关者必须有日期并且必须有计划,我们不能仅仅从积压的工作中进行。” 在我看来,似乎高级利益相关者还没有购买敏捷,因此我们注定无法在较低的水平上实施它。 这是公平的判断还是我对这个计划反应过度了?

12
避免使用“ goto”伏都教?
我有一个switch可以处理几种情况的结构。对进行switch操作会enum通过组合值引起重复代码的问题: // All possible combinations of One - Eight. public enum ExampleEnum { One, Two, TwoOne, Three, ThreeOne, ThreeTwo, ThreeOneTwo, Four, FourOne, FourTwo, FourThree, FourOneTwo, FourOneThree, FourTwoThree, FourOneTwoThree // ETC. } 当前,该switch结构分别处理每个值: // All possible combinations of One - Eight. switch (enumValue) { case One: DrawOne; break; case Two: DrawTwo; …

4
HTTP状态代码,用于“静态处理”
我正在构建一个RESTful API,该API支持对长时间运行的任务进行排队以进行最终处理。 该API的典型工作流程为: 用户填写表格 客户端将数据发布到API API返回202已接受 客户将用户重定向到该请求的唯一URL(/results/{request_id}) 〜最终〜 客户再次访问URL,并在该页面上看到结果。 我的麻烦在于步骤6。每当用户访问该页面时,我都会向我的API(GET /api/results/{request_id})发出请求。理想情况下,该任务将在此时完成,并且我将与他们的任务结果一起返回200 OK。 但是用户很吃力,我希望在结果尚未完成处理时会进行许多过度的刷新。 我最好的状态代码指示是什么: 该请求存在, 还没有完成 但它也没有失败。 我不希望有一个代码可以传达所有这些信息,但是我希望可以让我传递元数据而不是让客户期望内容。 返回202可能是有意义的,因为在这里没有别的意思:这是一个GET请求,因此可能没有任何东西被“接受”。那是一个合理的选择吗? 所有这些的明显替代方案-起作用,但违反了状态码的一个目的-将始终包括元数据: 200 OK { status: "complete", data: { foo: "123" } } ...要么... 200 OK { status: "pending" } 然后客户端,我会(叹息)switch上response.data.status,以确定该请求是否已完成。 这是我应该做的吗?还是有更好的选择?Web 1.0对我而言是如此。
47 rest  http 

7
一致的代码样式的实际价值是什么
我是顾问团队的成员,该团队为客户实施新的解决方案。我负责客户端代码库(React和javascript)上的大多数代码审查。 我注意到一些团队成员使用独特的编码模式,以至于我可以从一个样式中随机选择一个文件,以告诉谁是作者。 示例1(一次性内联函数) React.createClass({ render: function () { var someFunc = function () { ... return someValue; }; return <div>{someFunc()}</div> } }); 作者认为,通过为someFunc分配有意义的名称,代码将更易于阅读。我相信,通过内联函数并添加注释,可以达到相同的效果。 示例2(未绑定函数) function renderSomePart(props, state) { return ( <div> <p>{props.myProp}</p> <p>{state.myState}</p> </div> ); } React.createClass({ render: function () { return <div>{renderSomePart(this.props, this.state)}</div>; } }); 这是我们通常的做法(避免通过状态和道具): React.createClass({ renderSomePart: function …


7
我如何令人信服地反对复制数据库列?
我已经开始在一个新组织中工作,我在数据库中看到的一种模式是复制字段,以使业务分析师更容易编写查询。我们正在使用Django及其ORM。 在一种情况下,我们保留一个MedicalRecordNumber对象,该对象带有在特定上下文中标识患者的唯一字符串。我们有登记其追踪病人和有关联的对象MedicalRecordNumbers,但不是使用外键关系,他们复制的字符串,使他们能够避免写一个连接(不是由于性能原因)。这种模式在整个数据库中很常见。 对我来说,干净的数据模型的重要性只是为了让我能好好考虑一下。不必要的复杂性浪费了我有限的认知处理时间。这是一个系统的问题。编写连接不舒服是一个可纠正的技能问题。我不一定要提倡返回并更改模式,但我希望能够令人信服地阐明此类重复问题。

4
为什么方法不应该引发多种类型的检查异常?
我们使用SonarQube分析我们的Java代码,它具有以下规则(设置为关键): 公共方法最多应引发一个检查异常 使用检查的异常会强制方法调用者通过传播错误或通过处理错误来处理错误。这使得这些异常完全成为方法API的一部分。 为了使调用者的复杂度保持合理,方法不应抛出一种以上的检查异常。” 声纳的另一点是这样的: 公共方法最多应引发一个检查异常 使用检查的异常会强制方法调用者通过传播错误或通过处理错误来处理错误。这使得这些异常完全成为方法API的一部分。 为了使调用者的复杂度保持合理,方法不应引发超过一种检查异常。 如下代码: public void delete() throws IOException, SQLException { // Non-Compliant /* ... */ } 应该重构为: public void delete() throws SomeApplicationLevelException { // Compliant /* ... */ } 覆盖方法不受此规则检查,并允许引发多个检查的异常。 在阅读有关异常处理的文章时,我从没有遇到过这个规则/建议,也没有尝试找到有关该主题的一些标准,讨论等。我从CodeRach中发现的唯一东西是:一个方法最多应抛出多少个异常? 这是一个公认的标准吗?

4
如何精确创建抽象语法树?
我想我了解AST的目标,并且之前我已经构建了几个树结构,但从未构建过AST。由于节点是文本而不是数字,所以我很困惑,因此在解析某些代码时,我想不出一种输入令牌/字符串的好方法。 例如,当我查看AST的图表时,变量及其值是等号的叶节点。这对我来说很有意义,但是我将如何实施呢?我想我可以视情况而定,以便当我偶然遇到“ =”时,我将其用作节点,并将在“ =”之前解析的值添加为叶子。这似乎是错误的,因为根据语法的不同,我可能不得不为成千上万的东西辩护。 然后我遇到了另一个问题,那棵树是如何横穿的?我会一直下降到最低点吗,当我到达最低点时又返回一个节点,并对它的邻居也这样做吗? 我已经看到了大量关于AST的图表,但是我找不到一个简单的代码示例,这可能会有所帮助。

3
为什么C#允许接口中的属性?
在C#中,以下代码有效 interface I{ int property{get;set;} } 这对我来说毫无意义。这似乎打破了接口最重要的原则之一:缺少状态(换句话说,没有字段)。该属性是否不会创建隐式私有字段?这对接口真的不好吗?

9
一般来说,是让所有功能部件先使UI工作-还是两者兼而有之更好?
一般来说,是让所有功能部件先使UI工作-还是两者兼而有之更好? 假设您正在做的事情比较大,通常是在所有UI之前使所有功能数据收集Blob工作,或者一次使所有UI一起工作,还是在中间进行工作,这是公认的惯例吗? 我们都知道将工作分解为可管理的部分,但问题是最终我是否应该将UI包含在可管理的部分中。 对于该示例,请考虑一个GUI应用程序,该应用程序具有一个根窗口,但在各个扩展坞中有12个以上的选项卡用于分隔不同的数据组件。从功能单元的角度来看,每个单独的选项卡后面都有一组相对复杂的运动部件。 此特定问题的示例应用程序在此处带有随附的博客和原始商业产品。

8
为什么要设计一种没有异常处理机制的现代语言?
许多现代语言提供了丰富的异常处理功能,但是Apple的Swift编程语言没有提供异常处理机制。 像我一样,我陷入了异常,无法理解这意味着什么。Swift有断言,当然还有返回值。但是我很难想象我基于异常的思维方式如何映射到一个没有例外的世界(就此而言,为什么这样的世界是可取的)。有像Swift这样的语言我无法做的事情我可以做例外吗?通过丢掉异常我能获得一些收益吗? 例如,我如何最好地表达这样的话 try: operation_that_can_throw_ioerror() except IOError: handle_the_exception_somehow() else: # we don't want to catch the IOError if it's raised another_operation_that_can_throw_ioerror() finally: something_we_always_need_to_do() 缺少异常处理的语言(例如,Swift)?

1
go-langs goroutine池只是绿色线程吗?
在这里评论员提供绿色线程的批评如下: 最初,我是在N:M模型上出售的,这是一种使事件驱动的程序不带回调地狱的方法。您可以编写看起来像是古老的过程代码的代码,但是在其中有一种神奇之处是,只要有东西阻塞,它就会使用用户空间任务切换。听起来不错。问题在于,我们最终要用更多的复杂性来解决复杂性。swapcontext()和family相当困难,其复杂性来自其他意外地方。 突然之间,您被迫编写了一个用户空间调度程序,并猜测编写一个调度程序确实很难做,而要使Linux的调度程序投入大量的精力,这将做得更好。现在,您希望您的日程表将N个绿色线程分配给M个物理线程,因此您不必担心同步。同步带来了性能问题,因此现在就开始您的工作吧,您将遇到一个新的无锁兔子洞。构建正确的高度并发调度程序绝非易事。 另一个批评是在这里: 伪造多个线程的单个进程存在很多问题。其中之一是,所有伪造的线程都会在任何页面错误时停止运行。 我的问题是- 是去浪的够程(用于默认池)只是绿色的线?如果是这样,他们是否解决了上述批评?

2
生成唯一且安全的标识符以供“有时离线” Web应用程序使用的策略
我有一个基于Web的项目,允许用户联机和脱机工作,我正在寻找一种为客户端记录生成唯一ID的方法。我想要一种方法,该方法在用户脱机时(即无法与服务器对话)有效,并且保证是唯一的并且是安全的。通过“安全”,我特别担心客户端(恶意或以其他方式)提交重复的ID,从而严重破坏数据完整性。 我一直在做一些谷歌搜索,希望这已经解决了。我还没有找到任何非常确定的东西,尤其是在生产系统中使用的方法方面。我发现了一些系统的示例,在这些系统中,用户将仅访问他们创建的数据(例如,在多个设备上访问的Todo列表,但仅由创建它的用户访问)。不幸的是,我需要一些更复杂的东西。我确实在这里找到了一些非常好的想法,这些想法与我一直认为事情可能有效的方式是一致的。 以下是我建议的解决方案。 一些要求 ID应该是全局唯一的(或至少在系统中唯一) 在客户端上生成(即通过浏览器中的javascript) 安全(如上所述和其他方面) 数据可以由多个用户查看/编辑,包括未编写数据的用户 不会对后端数据库(例如MongoDB或CouchDB)造成严重的性能问题 拟议的解决方案 当用户创建帐户时,将为他们提供一个uuid,该uuid由服务器生成,并且在系统内是唯一的。此ID不得与用户身份验证令牌相同。我们将此ID称为用户的“ ID令牌”。 当用户创建新记录时,他们会在javascript中生成新的uuid(如果可用,则使用window.crypto生成。请参见此处的示例)。该ID与用户创建帐户时收到的“ ID令牌”并置。现在,此新的复合ID(服务器端ID令牌+客户端uuid)是记录的唯一标识符。当用户在线并将此新记录提交到后端服务器时,该服务器将: 将其标识为“插入”操作(即不是更新或删除) 验证组合键的两个部分都是有效的uuid 验证所提供的复合ID的“ ID令牌”部分对于当前用户是否正确(即,它与服务器在创建用户时分配给该用户的ID令牌相匹配) 如果一切copasetic,插入数据到数据库(小心做插入,而不是一个“更新插入”,这样如果ID 确实已经存在,它不会更新错误现有记录) 查询,更新和删除不需要任何特殊逻辑。他们将简单地以与传统应用程序相同的方式将id用于记录。 这种方法的优点是什么? 客户端代码可以在脱机时创建新数据,并立即知道该记录的ID。我考虑了替代方法,即在客户端上生成一个临时ID,然后在系统联机时将其替换为“最终” ID。但是,这感觉很脆弱。特别是当您开始考虑使用外键创建子数据时,也需要对其进行更新。更不用说处理ID更改后会更改的网址。 通过将ID组合为客户端生成的值和服务器生成的值,每个用户都可以在沙箱中有效地创建ID。这旨在限制恶意/流氓客户端可能造成的损害。同样,任何id冲突都是基于每个用户的,而不是整个系统的全局冲突。 由于用户ID令牌与他们的帐户相关联,因此ID仅可以由经过身份验证的客户端(即用户成功登录的地方)在用户沙箱中生成。这旨在防止恶意客户端为用户创建错误的ID。当然,如果用户的身份验证令牌被恶意客户端窃取,他们可能会做坏事。但是,一旦身份验证令牌被盗,该帐户便会受到威胁。如果确实发生了这种情况,那么所造成的损害将仅限于被盗用的帐户(而不是整个系统)。 顾虑 这是我对这种方法的一些担忧 这样会为大型应用程序生成足够唯一的ID吗?有没有理由认为这会导致id冲突?javascript可以生成足够随机的uuid使其正常工作吗?看起来window.crypto 相当广泛,该项目已经需要相当现代的浏览器。(此问题现在有一个单独的SO问题) 我是否缺少任何漏洞,这些漏洞可能允许恶意用户破坏系统? 查询由2个uuid组成的组合键时,是否有理由担心数据库性能。应该如何存储此ID以获得最佳性能?两个单独的字段还是一个对象字段?Mongo和Couch会有不同的“最佳”方法吗?我知道在执行插入操作时,使用非顺序主键会导致明显的性能问题。为主键自动生成一个值并将该ID存储为单独的字段会更聪明吗?(此问题现在有一个单独的SO问题) 使用这种策略,可以很容易地确定一组特定记录是由同一用户创建的(因为它们都共享相同的公共可见id令牌)。虽然我看不到有任何立即出现的问题,但最好不要泄露比内部需求更多的信息。另一种可能性是对复合键进行哈希处理,但这似乎比其价值更大。 如果用户发生ID冲突,则没有简单的恢复方法。我想客户端可以生成一个新的id,但这似乎确实是不应该发生的。我打算解决这个问题。 只有经过身份验证的用户才能查看和/或编辑数据。这是我的系统可接受的限制。 结论 以上是合理的计划吗?我意识到其中一些归结为基于对相关应用程序的更全面了解的判断调用。

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.