软件工程

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

1
Guice中@ImplementedBy批注背后的动机是什么?
我最近阅读了有关Google Guice中@ImplementedBy可用的注释的信息。它允许程序员指定接口与其实现之间的绑定,以供将来在依赖关系注入中使用。这是即时绑定的示例。 我已经习惯于使用以下语法在模块中定义显式绑定: bind(SomeInterface.class).to(SomeInterfaceImplementation.class); 根据文档,这等效于@ImplementedBy注释的以下用法: @ImplementedBy(SomeInterfaceImplementation.class) public interface SomeInterface { //method declarations } 我在这里看到的唯一好处是代码短了一点。同时,这种方法也有一个缺点,由相同的文档正确指出: @ImplementedBy小心使用;它从接口到其实现添加了编译时依赖性。 在许多情况下,这种依赖关系可能不是问题,但我个人认为这是代码的味道。 什么用例使@ImplementedBy注释值得使用? 一种可能的方法似乎是在库或框架的代码中使用它。如文档中所述,注释可以提供默认绑定,很容易被显式绑定覆盖。 如果一个类型同时在一个bind()语句(作为第一个参数)中并且具有@ImplementedBy注释,bind()则使用该语句。批注建议可使用绑定覆盖的默认实现。 这样,作为库的开发人员,我可以为用户提供现成的绑定,可以在客户端代码中的某个位置进行自定义。 这是注释存在的唯一原因吗?还是我想念的东西?我可以通过在只使用某些业务逻辑的应用程序而不是要扩展的库/框架的代码中使用它来获得任何收益吗?

3
成员:使用唯一ID与域对象
在关于是否应将域对象或唯一ID作为方法/函数参数(此处将标识符与域对象用作方法参数)使用几个有用的答案之后,我有一个类似的问题:成员(先前的讨论没有设法解决)盖上这个)。使用唯一ID作为成员与使用对象作为成员的优缺点是什么。我要问的是强类型语言,例如Scala / C#/ Java。我应该有(1) User( id: Int, CurrentlyReadingBooksId: List[Int]) Book( id: Int, LoanedToId: Int ) 或(2),而不是(1)经历之后:是否应该为所有内容定义类型? User( id: UserId, CurrentlyReadingBooksId: List[ BookId] ) Book( id: BookId, LoanedToId: UserId ) 或(3) User( id: Int, CurrentlyReadingBooks: List[Book]) Book( id: Int, LoanedTo: User) 虽然我没有想到拥有对象(3)的好处,但是拥有ID(2)和(1)的好处之一是,当我从数据库创建User对象时,不必创建Book对象,可能反过来取决于User对象本身,从而创建了一个无尽的链。对于RDBMS和No-SQL(如果它们不同)是否有通用的解决方案? 根据到目前为止的一些答案,改写我的问题:(使用ID应该是包装类型的ID)1)始终使用ID?2)总是使用对象?3)在序列化和反序列化存在递归风险时使用ID,否则使用对象吗?4)还有什么? 编辑:如果您回答应始终使用对象或在某些情况下使用对象,请确保回答其他回答者已发布的最大问题=>如何从数据库获取数据

1
社交网络通知系统
背景 我正在为包含一些社交网络功能的客户端开发应用程序。我原本是在开发移动前端,但当时的情况也让我负责开发后端。 作为一般背景,我们的系统允许用户关注其他用户,并收到有关他们关注的人的通知,这是您期望从社交网络获得的。需要注意的是,只有一小部分用户(最多几百个)是可追踪的,并期望大多数用户群将关注这些个人中的至少一个。 在用户界面侧,我们将有一个带有数字的通知按钮,单击该按钮将带您进入通知屏幕。 问题 我一直在研究实现通知的策略,发现的大多数资源都指向在数据库中创建一个或多个通知表。(我喜欢的一个示例是此处接受的答案:https : //stackoverflow.com/questions/9735578/building-a-notification-system)。 让我烦恼的是,大多数数据库驱动的通知策略都要求为每个关注者的每个通知插入一行。因此,如果有一千人在关注​​Sally,我们将在相应表中插入一千行。那可扩展吗?如果我们到了成千上万的用户关注Sally并且她每天发表数十条帖子的情况,会发生什么? 我最初的想法是处理查询的所有问题:通知按钮上的数字将通过请求比上次访问通知屏幕最近发布的内容的行计数来获得,而单个通知将通过更详细的查询生成当您访问通知屏幕时。这种方法不需要写入或额外的存储空间,但是不灵活,可能会严重影响服务器。 设定 后端(由先前的开发人员建立)使用CodeIgniter和MySQL数据库。它目前在糟糕的GoDaddy共享托管帐户上运行,但我认为(希望吗?)在我们投入生产之前,将对其进行升级,并且托管软件包将随着用户的增长而扩展。 目前,我们唯一的前端是移动应用程序,但我们计划稍后再建立一个网站。我现在不关心从服务器获取有关通知的实时推送更新。 附录 我不专门研究后端,而我在那个部门负责。客户知道这一点,并且我已尽力解释这种性质的项目的范围,但是他们已经明确表示,在这一点上,他们将不信任任何其他人来从事该项目。在开始添加测试人员之前,我们可能还要再做一个月的工作,我才能获得任何类型的性能指标。我真的无法估计未来5年我们将拥有多少用户,或者我们将使用什么硬件,但是我认为客户希望有成千上万的用户或更多。 我希望这个问题足够具体,可以在此处发布。如果需要,我可以对其进行优化。请询问您是否有任何疑问,或者我省略了重要的详细信息。 tl; dr 当所有用户都只跟随数百人时,数据库驱动的通知系统是否会对长期可扩展性产生负面影响? 有没有一种方法可以使通知由数据库驱动,而无需为每个关注者的每个通知单独的通知行? 完全由查询驱动的通知系统是否具有可伸缩性,或者除了不向数据库写入任何数据以外,还具有其他优点? 我想得太早了吗?我是否应该仅构建一个目前可以使用的产品,并且由于客户预算有限并且我们不知道最终产品是否会流行,如果问题出现,我们可以担心对其进行优化吗?

2
维持状态而不分配
我正在学习函数式编程,无法理解如何在不使用分配的情况下实现某些特定方案。以下简单的问题几乎使我感到困惑。 编写一个程序,该程序接收有关给定数据结构更改的事件,并在此数据结构达到特定状态时发出事件。 所以我有一个我要维护的数据结构的副本 datastructure_copy::DataStructure 当事件发生变化时,我会触发事件流: datastructure_changes::Stream Change 我有一个将更改应用于数据结构并返回新副本的函数: apply_change::Change -> DataStructure -> DataStructure 而且我有一个谓词,用于检查数据状态是否已达到所需状态。 is_ready::DataStructure ->Boolean 换句话说,我需要在流上工作的“ reduce”之类的东西。 我知道实现此目标的一种方法是在每次更改到达时重新计算状态,但这似乎不切实际。我在State monad玩了一点,但在我看来,这似乎是为了解决另一个问题。 那么还有另一种方法吗? 请注意,我的问题纯粹是概念性的,对Haskell并不很熟悉。

1
一流的延续在现代的面向对象的编程语言中有用吗?
连续在功能性编程语言(例如ContHaskell中的monad)中非常有用,因为它们允许对命令式代码进行简单且规则的表示。它们在某些较旧的命令式语言中也很有用,因为它们可用于实现缺少的语言功能(例如,异常,协程,绿色线程)。但对于内置支持这些功能流行的面向对象的语言,什么样的参数会有的还加入了一流的延续支持(无论是更现代的风格定界reset和shift或方案类call-with-current-continuation)? 除了性能和实现的复杂性之外,是否还有反对增加支持的论点?

3
在其他开源程序中使用封闭源模块限制集群大小
我在高度依赖高性能计算的学术研究机构工作。在过去的十年中,我们已经开发了自己的Fortran代码,该代码非常受关注并且可以在非常大的群集上运行。为了使更大的研究社区从该代码中受益,我们正在考虑将其开源。但是,由于我们的资金高度依赖于我们可以使用该代码执行的研究,因此,我们可能会全力以赴。 想法之一是限制代码可以运行的CPU数量,例如,最多1000个CPU,而不是我们使用的100,000。这样,全球研究界可以从代码中受益,但是我们将在可以解决的问题规模方面拥有优势。 从概念上讲这种功能是否可行?以及如何实现这种功能?本质上,我们想开源完整的代码,但是将并行化(使用MPI)限制为固定数量的MPI线程,例如使用(封闭源)模块。

2
HTTP请求/响应对象应该是不可变的吗?
我认为可以肯定地说,大多数Web应用程序都基于请求/响应范例。PHP从未对这些对象进行正式的抽象。一个小组正在尝试改变这一点:https : //github.com/php-fig/fig-standards/blob/master/proposed/http-message.md 但是,他们在不变性问题上有些偏颇。一方面,请求/响应对象通常在其生命周期内几乎不需要更改。另一方面,响应对象尤其经常需要添加HTTP标头。 此外,不变性从未真正在PHP领域流行。 人们在使用不可变的请求/响应对象时会看到哪些优势? 假设您要返回一个json对象。 $response = new JsonResponse($item); 漂亮又简单。但是事实证明,该请求是跨域资源共享(CORS)请求。生成响应的代码无关紧要,但是下游的某个过程将添加必要的Access-Control标头。保留原始响应并使用其他标题创建新响应有什么好处?还是严格来说是编程风格的问题。 请求对象更加有趣。它从相同的地方开始: $request = new Request('incoming request information including uri and headers'); 初始信息不需要更改。但是,随着请求的传递,通常需要添加其他处理信息。例如,您可能有一个URL匹配器,该匹配器决定应为给定请求执行什么操作。 $request->setAttribute('action',function() {}); 实际执行操作是下游流程的责任。您可能有一个可变的RequestAttributesCollection,它包装了不可变的请求,但在实践中往往有些尴尬。除了属性集合之外,您还可能有一个不变的请求。异常也往往很尴尬。处理此类要求有经验吗?

1
什么时候应该在Python中继承异常?
在我的代码中,大约有七个地方会引发异常。所有这些异常的处理方式相同:将错误输出到日志文件,将软件状态恢复为默认状态并退出。 在代码审查期间,我非常重视的高级工程师说,我应该将所有这些异常归为一类。他的论点是,将来我们可能希望以不同的方式处理异常,这将更加容易。 我的观点是当前它只会使我们的代码混乱,并且由于我们不知道我们是否会以不同的方式处理异常,因此我们应该将代码保持简洁,并且如果时间到了,那么我们应该将其子类型化。 我想听听每种情况的论点。

4
为什么python生成器和函数共享“ def”关键字?
考虑以下: def some_function(): return 1 def some_generator(): yield 1 在上面的代码中,some_function是一个函数,some_generator而是一个生成器。他们看起来很相似。 我在阅读代码时遇到的问题是,我需要在“函数”的每一行中进行扫描以寻找yield关键字,然后才能确定它实际上是函数还是生成器! 在我看来,为生成器使用其他关键字会更有意义,例如: gen some_generator(): yield 1 def对生成器和函数使用关键字有什么好处?为什么未将新关键字引入单独的函数和生成器?

1
如何避免健谈的界面
背景: 我正在设计一个服务器应用程序,并为不同的子系统创建单独的dll。为简化起见,假设我有两个子系统:1)Users2)Projects 用户的公共界面具有如下方法: IEnumerable<User> GetUser(int id); 而且Projects的公共接口具有如下方法: IEnumerable<User> GetProjectUsers(int projectId); 因此,例如,当我们需要显示某个项目的用户时,我们可以调用GetProjectUsers,这将为对象提供足够的信息以显示在数据网格或类似物中。 问题: 理想情况下,Projects子系统不应同时存储用户信息,而应仅存储参与项目的用户的ID。为了服务的GetProjectUsers,它需要调用GetUser的的Users系统存储在自己的数据库中的每个用户ID。但是,这需要大量单独的GetUser调用,从而在User子系统内部引起大量单独的sql查询。我还没有真正测试过,但是具有这种健谈的设计会影响系统的可伸缩性。 如果不考虑子系统的分离,我可以将所有信息存储在两个系统Projects都可以访问的单个模式中,并且可以简单地执行a操作,JOIN以在单个查询中获取所有项目用户。Projects还需要知道如何User从查询结果中生成对象。但这打破了具有许多优点的分离。 问题: 有人可以建议一种在避免所有这些单独GetUser通话的同时保持分隔的方法GetProjectUsers吗? 例如,我曾想过让用户为外部系统提供使用标签值对“标记”用户并请求具有特定值的用户的能力,例如: void AddUserTag(int userId, string tag, string value); IEnumerable<User> GetUsersByTag(string tag, string value); 然后,Projects系统可以在将每个用户添加到项目中时对其进行标记: AddUserTag(userId,"project id", myProjectId.ToString()); 在GetProjectUsers期间,它可以在一次调用中请求所有项目用户: var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString()); 我对此不确定的部分是:是的,用户与项目无关,但实际上有关项目成员资格的信息存储在用户系统中,而不是项目中。我只是感觉不自然,所以我试图确定我是否缺少一个很大的劣势。

3
数据库中的专有弧是什么?为什么它是邪恶的?
我正在阅读开发人员对Stackoverflow进行问答时最常见的数据库设计错误。最初的答案是关于专有弧的短语: 如果用两个或多个外键创建一个表,并且其中一个只能为非空,则独占弧是一个常见错误。大错。一方面,维护数据完整性变得更加困难。毕竟,即使具有参照完整性,也无法阻止设置两个或多个这些外键(尽管有复杂的检查约束)。 我真的不明白为什么排斥弧是邪恶的。可能我不了解它的基本知识。排他弧线有什么好的解释吗?

1
依赖性提升策略:孤立还是精心策划?
我们有很多相互依赖的应用程序和Web服务(一些面向公众的产品,一些内部和私有“后端”的一部分)。这些组件中的每一个都有4个环境(用于特定目的的服务器/节点集群): 非生产 DEV-CI建立推动变更的集成开发环境;有助于工程师解决在本地无法复制的难以发现的错误 QA -隔离的质量检查/测试环境 DEMO -为业务利益相关者提供稳定的UAT环境 生产 LIVE -我们的现场/制作环境 代码升级是:(LOCAL开发人员的机器)=> DEV=> QA=> DEMO=> LIVE。 假设我们有一个名为的应用程序myapp,该应用程序由RESTful Web服务支持,该服务myws本身由一个名为的数据库支持mydb。 目前,我们拥有我所说的“ 策划 ”推广这些依赖关系之中:在myapp-dev指向myws-dev它使用mydb-dev。同样,myapp-qa指向myws-qa使用mydb-qa。与DEMO和相同LIVE。 问题是,无论何时我进行更改,例如myapp,这都需要我也对myws和进行更改mydb。但是因为每个DEV环境都指向其依赖项的DEV环境,所以这意味着我必须同时计划和部署这些更改。此外,如果一个构建变得不稳定/损坏,它通常会使其他上游组件崩溃;例如,如果开发人员在更改时破坏了某些内容mydb-dev,则myws-dev和myapp-dev群集通常也会变得不稳定。 为了解决这个问题,我针对我所谓的“ 孤立的 ”促销策略提出了一个建议:所有组件间的依赖关系都遵循以下准则: 上游的依赖关系取决于DEMO对它们的下游依赖环境,对于所有其非生产环境的(DEV,QA和DEMO); 和 上游依赖项依赖于LIVE环境,生产环境依赖于下游依赖项 使用此约定,实际myapp-dev将指向myws-demo,而将使用mydb-demo。同样,myapp-qa也将指向myws-demo和mydb-demo。 我在这里可以找到的优势是构建稳定:DEMO特定组件的环境变得不稳定的可能性要小得多,因为DEMO没有在DEV和上进行严格的测试,代码就无法实现QA。 我可以发现这种方法的唯一缺点是,如果DEMO某个特定组件发生故障,则所有上游依赖项的所有非生产环境都将突然中断。但是我要反驳说,由于在DEV和上进行的测试,这种情况极少发生QA。 这已经得到了成为一个问题,很多开发者(比我更聪明,经验丰富)已经解决了,如果这个问题,其解决方案已经有名字给他们我不会感到惊讶(除了什么我打电话策划/孤立)。所以我问:孤立的促销策略的优点是否胜过任何缺点,在这里我可能忽略哪些缺点?

2
为什么Scala编译器不能为未密封的类/特征给出模式匹配警告?
如果我使用未密封的trait或abstract class在Scala中使用模式匹配,我想知道,编译器是否不知道在编译时针对该特定模式匹配,可以使用此特性/类的哪些可能的实现?所以,如果这样做,会不给模式匹配的警告,即使是在trait/ abstract class不密封,因为他知道哪些类型可以被使用,通过检查所有可能的依赖性/进口? 例如,如果我有一个,Option[A]并且我只为Some[A]但不为进行模式匹配None,则编译器会抱怨,因为Option是密封的。 如果编译器无法知道/解决该问题,那为什么不呢?如果编译器(理论上)可以做到这一点,那么在Scala中不使用它的原因是什么?还有其他支持这种行为的语言吗?

1
用于微控制器的RTOS的消息队列
我目前正在为微控制器编写RTOS。整个过程都是用C ++ 11编写的-如果有人感兴趣,则指向存储库的链接在底部。 当前,我正在编写一个类,该类是一个简单的数据队列,用于在线程之间(或在中断处理程序和线程之间或中断处理程序和其他中断处理程序之间)传递对象。通常,我尝试遵循在其他项目上找到的一些常见API,但是我没有找到具有emplace()功能并支持超时的并发队列的任何示例。 我一般的“问题”是我无法在这两个接口之间做出决定: (std::chrono::duration<Rep, Period>是模板化类型,为清晰起见,我省略了模板样板) 第一版: template<typename T> class FifoQueue { public: ... template<typename... Args> int tryEmplaceFor(std::chrono::duration<Rep, Period>, Args&&... args); int tryPopFor(T&, std::chrono::duration<Rep, Period>); int tryPushFor(const T&, std::chrono::duration<Rep, Period>); int tryPushFor(T&&, std::chrono::duration<Rep, Period>); ... } 第二版: template<typename T> class FifoQueue { public: ... template<typename... Args> int tryEmplaceFor(std::chrono::duration<Rep, Period>, …

2
单元测试和集成测试的代码覆盖率报告是分开的,还是两者都有一个报告?
应该为单元测试和集成测试提供单独的代码覆盖率报告,还是为两者提供一个代码覆盖率报告? 其背后的想法是,代码覆盖率使我们能够确保我们的代码已被尽可能多的测试所覆盖(无论如何,现在无论如何机器)。 拥有单独的报告更方便我们了解单元测试未涵盖的内容以及集成测试未涵盖的内容。但是这样一来,我们看不到总覆盖率。

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.