软件工程

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

2
通过事务将业务逻辑与数据库逻辑分开
我们的应用程序包含三层。服务层提供外部API。BO层用于我们的业务逻辑,而DAO层用于我们的数据库连接。 假设每次更新文件时,我们还希望更改文件夹中的某些内容,例如“上次修改日期”。这需要在事务中完成。要么成功,要么文件和文件夹都被编辑。否则发生故障,事务将回滚,因此两个对象都处于先前状态。 “编辑文件时编辑文件夹”操作纯粹是业务逻辑。因此,这将意味着它属于BO层。但是,我们将Objectify用于数据库,因此要启动事务,我们需要调用ofy()。transact(...)。如果在BO层中调用此函数,则会破坏我们的设计,因为在业务层中将有数据库特定的调用(Objectify)。 什么是解决此问题的干净方法?

6
命名:您是否应该为了简洁而牺牲简洁性?
例如,以下函数循环遍历包含输入字段名称和错误的数组。它通过检查验证字段的名称,然后将错误信息推送到无效的字段数组来完成此操作。 简短点说并写成更好: addInvalidField (field, message) { const foundField = this.invalidFields.find(value => { return value.name === field.name }) const errors = foundField.errors if (!errors.some(error => error.name === message)) { errors.push({ name: message, message }) } }, 还是更具体地这样? addInvalidField (validatingField, message) { const foundField = this.invalidFields.find(invalidField => { return validatingField.name === invalidField.name …

5
单个故障是否会使批量操作失败?
我正在使用的API中有一个批量删除操作,该操作接受ID数组: ["1000", ..., "2000"] 我可以按照自己的意愿随意执行删除操作,因此我决定使整个事务具有事务性:也就是说,如果单个ID无效,则整个请求将失败。我将其称为严格模式。 try{ savepoint = conn.setSavepoint(); for(id : IDs) if( !deleteItem(id) ){ conn.rollback(savepoint); sendHttp400AndBeDoneWithIt(); return; } conn.commit(); } 备选方案(在软件套件中的其他位置实现)是尽我们所能在后端进行操作,并报告阵列中的故障。该软件的这一部分处理的请求较少,因此从理论上讲,响应不会成为一个巨大的数组。 资源贫乏的服务器中最近发生的一个错误使我再次查看代码,现在我在质疑最初的决定-但是这次,我更多地是出于业务需求而不是最佳实践的动力。例如,如果我未能通过整个请求,则用户将不得不重试,而如果删除了许多项目,则用户可以完成操作,然后要求管理员执行其余操作(在我修复错误的同时) !)。这将是许可模式。 我尝试在网上寻找有关此事的一些指导,但我空手而归。所以我来找你:这种性质的批量操作最期望什么?我应该坚持更严格,还是应该更宽容?

3
实体框架和避免贫血领域模型
在我们的业务逻辑中,我们有时会定义一些类似于以下内容的方法: User.ResetCourse(Course courseToReset) 问题在于用户和课程都是实体框架代理对象。这意味着当我们在“用户”或“课程”上命中导航属性时,可能会严重打击数据库,因为这些对象不可查询,因此可以正常地遍历它们。 为了解决这个问题,我们将签名更改为: User.ResetCourse(MyDBContext db, Course courseToReset) 这意味着我们可以直接查询数据库以有效地进行所需的更改,但是将Database上下文传递给业务对象似乎太错误了。 后来我们向用户迁移了服务层,这意味着我们拥有以下内容: CourseService.ResetForUser(Course courseToReset, User forUser) 该服务引用了创建时注入的DBContext,但是现在我们的业务对象只是没有行为的数据包(例如,Anemic Domain Model)。 我们如何避免这种情况?

5
有什么好的设计习惯可以避免询问子类类型?
我已经读到,当您的程序需要知道对象是什么类时,通常表明存在设计缺陷,因此我想知道什么是处理此问题的好方法。我正在实现一个Shape类,该类具有从其继承的不同子类,例如Circle,Polygon或Rectangle,并且我有不同的算法来确定Circle是否与Polygon或Rectangle碰撞。然后假设我们有两个Shape实例,并且想知道一个是否与另一个碰撞,在这种方法中,我必须推断正在碰撞的对象是哪种子类类型,以便知道应该调用哪种算法,但这是一个设计或实践不当?这就是我解决的方法。 abstract class Shape { ShapeType getType(); bool collide(Shape other); } class Circle : Shape { getType() { return Type.Circle; } bool collide(Shape other) { if(other.getType() == Type.Rect) { collideCircleRect(this, (Rect) other); } else if(other.getType() == Type.Polygon) { collideCirclePolygon(this, (Polygon) other); } } } 这是一种不良的设计模式吗?如何解决这个问题而不必推断子类类型?

2
我应该如何在一个宁静的服务中设计一个有序列表资源?
我一遍又一遍地遇到了同样的问题,但我还没有找到我真正认为是最佳的解决方案。 在应用中说,您有一个有序列表,然后让用户通过拖放等方式更改该顺序。您希望顺序中的更改得以保留。您如何建模? 如何设计有序列表资源的静态服务? 特别是,我应该如何设计list和item宁静的资源的模型?我见过的最常见的设计是item具有order或position属性的实体。我听到的另一种方法是在商品上使用双链表。 什么是一种方法,它不会向数据库写入太多内容,并且通常可以为客户端快速更新和读取?端点应该如何暴露?

2
如果我对C ++使用线性代数包,是否认为它是懒惰的?
首先,在实际陈述问题之前,让我提供一些背景知识。我学习物理学,所有编程课程都使用MATLAB等简单的编程语言。简单来说,我的意思是该语言为您完成了很多思考。在接下来的几年中,我将学习计算机科学课程,并且我正在考虑从事编程职业。 考虑到很多大学课程都是用C ++编写的,使用具有类似于MATLAB语法的线性代数包(Armadillo)是否被认为是懒惰的? 我现在正在编写一种遗传算法,尽管它在MATLAB中运行很快,但在没有这些软件包的帮助下,在C ++中花费了大量时间。 它在现实生活中如何运作?您可以使用哪些套餐? 例如,我不想使用armadillo构建我的C ++知识,并且不了解其他更广泛使用的软件包,例如“ vector.h”,“算法”,“列表”等。
11 c++  experience 

1
顺序图:演员对象?
最可能的答案是“否”,但我对此表示怀疑。演员可以当班吗? 我知道actor会触发事件并且可以有提示,但是如果有一个模拟actor的类(例如用户类),我们可以在它们之上调用方法吗?还是这完全是对演员角色的误解,演员角色与代表阶级混在一起? 假设是正确的: 怀疑是否正确:

9
Scrum团队应该输入什么?
我们的Scrum团队由通常的Scrum角色组成。我们没有UI / UX设计器,开发人员与产品所有者一起使用UI / UX。这是一个问题。每次我们要创建积压订单时,我们都没有在sprint开始之前定义确切的UI / UX设计,我们最终在sprint中花费太多时间试图确定UI / UX设计。 对于功能的分析和架构,这是完全正确的。您是否认为应该在sprint开始之前将有关功能的所有可能的细节都提供给开发人员,或者这应该是功能内的任务?我们已经对此进行了体验,它导致了一些没有任何标准的未定义功能。
11 agile  scrum 

3
是否可以在不使用%运算符的情况下实现分布良好的哈希表?
我希望在C#中实现一个快速,分布均匀的哈希表。我在选择需要任意哈希码并“约束”它的哈希约束函数时遇到麻烦,因此可以将其用于索引存储桶。到目前为止,有两种选择: 一方面,您可以确保存储桶中始终有素数个元素,而要限制哈希,您只需对存储桶数进行模运算即可。实际上,这就是.NET词典所做的。这种方法的问题在于,与其他操作相比,使用%的速度非常慢。如果您查看Agner Fog指令表,idiv(这是为%生成的汇编代码)对于较新的Intel处理器,其指令等待时间约为25个周期。与此相比,大约3 mul或1逐位OPS像and,or或xor。 另一方面,您可以使存储桶的数量始终为2的幂。您仍将必须计算哈希的模数,因此您不必尝试在数组外部进行索引,但这一次的开销较小。由于对于2的幂% N是& (N - 1),约束被减少到仅需要1-2个周期的屏蔽操作。这是由Google的sparsehashash完成的。缺点是我们指望用户提供良好的哈希值;屏蔽哈希基本上会切断一部分哈希,因此我们不再考虑哈希的所有位。如果用户的哈希值分布不均匀,例如仅填充了较高的位或较低的位始终相同,则此方法的冲突率就会高得多。 我正在寻找一种我可以使用的兼具两全其美的算法:它考虑了哈希的所有位,并且比使用%还要快。它不一定必须是模数,而是一定要保证在一定范围内0..N-1(其中N是铲斗的长度)并且在所有插槽中具有均匀的分布。是否存在这样的算法? 感谢您的帮助。

3
github策略,用于保持文件的一个版本私有
我是一位为学生编写编码问题的讲师。我要做的是给学生提供样板代码,并带有占位符以表示学生要完成的功能。我将为学生提供访问私人github存储库的权限,以克隆它。 但是,我还想要一个版本的代码库,以及示例解决方案。显然,我不希望学生可以使用该解决方案(直到作业结束)。 我已经考虑过分支机构,但是AFAIK,我不能将一个分支机构设为私有。 也许我可以将项目分叉到另一个私有仓库中,但是不确定如何将项目保留在snyc中(除了包含解决方案的文件之外)。 有针对这种情况的工作流程吗?
11 git  github 

5
如何防止两个用户同时使用相同的用户名注册?
我们无法序列化注册,因为有数百万人同时注册。需要并行注册。 假设数据库不包含用户名“ user1”。当两个用户尝试同时使用“ user1”注册时,它将接受它。但是以后会引起问题。这不应该发生。 我正在寻找一个合理的解决方案。没有什么特别的。解决这个问题的一个想法。

7
用OO语言实现对象状态?
我已经看过一些Java代码,它可以模拟赛车,其中包括基本状态机的实现。这不是经典的计算机科学状态机,而仅仅是一个可以具有多个状态并且可以基于一系列计算在其状态之间进行切换的对象。 为了描述问题,我有一个Car类,它带有一个嵌套的枚举类,该类为汽车的状态定义了一些常量(例如OFF,IDLE,DRIVE,REVERSE等)。在同一个Car类中,我有一个update函数,该函数基本上由一个大的switch语句组成,该语句打开汽车的当前状态,进行一些计算,然后更改汽车的状态。 据我所知,Cars状态仅在其自己的类中使用。 我的问题是,这是处理上述性质的状态机的最佳方法吗?听起来确实是最明显的解决方案,但过去我一直听说“ switch语句不好”。 我在这里看到的主要问题是,随着我们添加更多状态(如果认为必要),switch语句可能会变得非常大,并且代码可能变得笨拙且难以维护。 有什么更好的解决方案?

2
软件开发中的日常工作量及其对估算的影响
我坚信,软件开发中的日常工作量(即使应该忽略不计)相对较小,而且应该相对较小,这是软件估算的基本问题。 让我描述一下我如何得出这个结论,并告诉我该论证是否存在严重缺陷: 可以高精度估计的只是例行工作,这意味着以前已经做过。涉及研究和创造力的所有其他类型的工作都无法真正估计,至少不能以+/- 20%的准确度估算。 软件开发就是要避免重复的任务。它的基本原则之一是干燥(不要重复自己)。每当程序员发现自己在做重复的工作时,就该找到避免这种重复的抽象了。这些抽象可能很简单,例如将重复的代码提取到函数中或放入循环中。它们也可能更复杂,例如创建特定领域的语言。无论如何,实施它们都将涉及研究(以前有人做过吗?)或创造力。 从这两点我得出以上结论。 实际上,我已经想了好一阵子了,为什么在其他所有有关软件评估的讨论,博客文章或文章中都没有提到这种关系。太理论了吗?我的假设错了吗?还是太琐碎了-但是,为什么我所知道的大多数开发人员都相信他们可以以+/- 20%或更高的精度进行估算?

3
XML优于S-expressions(-ish)表示法的优点是什么?
我想问一个关于XML和S-expressions(-ish)表示法的问题。S表达式很老。他们也很简单。我们可以考虑两种含义相同但语法不同的形式: (来自波兰维基百科的 xml代码) <?xml version="1.0" encoding="UTF-8"?> <ksiazka-telefoniczna kategoria="bohaterowie książek"> <!-- komentarz --> <osoba charakter="dobry"> <imie>Ambroży</imie> <nazwisko>Kleks</nazwisko> <telefon>123-456-789</telefon> </osoba> <osoba charakter="zły"> <imie>Alojzy</imie> <nazwisko>Bąbel</nazwisko> <telefon/> </osoba> </ksiazka-telefoniczna> S-Expression(-ish)版本: (:version "1.0" :encoding "utf-8") (ksiazka-telefoniczna :category "bohaterowie książek" ; komentarz(a comment) (osoba :charakter "dobry" (imie Ambroży) (nazwisko Kleks) (telefon 123-456-789)) (osoba :charakter "zły" (imie …
11 xml 

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.