软件工程

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

3
如何在关系数据库中存储订购的信息
我正在尝试了解如何在关系数据库中正确存储有序信息。 一个例子: 假设我有一个由歌曲组成的播放列表。在我的关系数据库中,我有一个的表Playlists,其中包含一些元数据(名称,创建者等)。我还有一个名为的表Songs,其中包含playlist_id和特定于歌曲的信息(名称,艺术家,时长等)。 默认情况下,将新歌曲添加到播放列表时,它将添加到末尾。按Song-ID(升序)订购时,该顺序将为添加顺序。但是,如果用户应该能够对播放列表中的歌曲重新排序,该怎么办? 我提出了一些想法,每个想法都有其优点和缺点: 称为的列order,它是整数。移动歌曲时,所有歌曲在其旧位置和新位置之间的顺序都会更改,以反映更改。这样做的缺点是,每次移动歌曲时都需要进行很多查询,并且移动算法不像其他选项那样琐碎。 称为的列order,它是一个十进制(NUMERIC)。移动歌曲时,会为其分配两个相邻数字之间的浮点值。缺点:十进制字段会占用更多空间,并且可能会精度不够,除非在每次更改后都注意重新分配范围。 另一种方法是使用previous和next字段引用其他歌曲。(或者,如果现在是播放列表中的第一首和最后一首歌曲,则为NULL;基本上,您将创建一个链表)。缺点:诸如“在列表中找到第X首歌曲”之类的查询不再是固定时间,而是线性时间。 在实践中最常使用以下哪个程序?在大中型数据库上,以下哪个过程最快?还有其他方法可以存档吗? 编辑:为简单起见,在此示例中,一首歌曲仅属于一个播放列表(多对一关系)。当然,也可以使用Junction Table,因此song⟷playlist是一个多对多关系(并在该表上应用上述策略之一)。

2
为什么Swift不需要分号?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 我通常使用c#或Objective-C进行编码,最近我开始学习Apple的新编程语言-Swift。 我注意到的第一件事是,您不需要在Swift中添加分号来结束一行,但是如果您这样做了-至少从我的测试中可以看出,它不会干扰编译器。 当我写: int someNumber = 0; 在Objective-C中,分号告诉程序该行结束并且不会掉线到下一行。 使用Swift我可以用 var someNumber:Int = 5 而不添加分号,系统便知道这是行的结尾。 是什么让某些语言可以这样做而其他语言则不能呢?为什么不保持统一的系统,在末尾添加分号?

3
泛型与通用接口?
我不记得上次写泛型类的时间。每次经过思考后我都认为不需要时,我认为不需要它。 这个问题的第二个答案让我要求澄清(因为我还不能发表评论,所以我提出了一个新问题)。 因此,让我们以给定的代码为例,说明需要泛型的情况: public class Repository<T> where T : class, IBusinessOBject { T Get(int id) void Save(T obj); void Delete(T obj); } 它具有类型约束: IBusinessObject 我通常的想法是:该类只能使用IBusinessObject,使用该类的也是如此Repository。存储库存储这些对象IBusinessObject,最有可能的客户端Repository将希望通过IBusinessObject接口获取和使用对象。那为什么不只是为了 public class Repository { IBusinessOBject Get(int id) void Save(IBusinessOBject obj); void Delete(IBusinessOBject obj); } 那个例子不好,因为它只是另一种类型的集合,而通用集合是经典的。在这种情况下,类型约束看起来也很奇怪。 实际上,该示例class Repository<T> where T : class, IBusinessbBject与class BusinessObjectRepository我非常相似。泛型是要修复的东西。 重点是:泛型除了集合之外,是否对其他任何东西都有用,并且类型约束不会使泛型成为专用对象,就像使用类约束而不是在类内部使用泛型类型参数一样?

5
在几乎每个人都需要访问公共数据结构的情况下,依赖项注入有什么好处?
在OOP中,为什么全局变量是邪恶的有很多原因。 如果需要共享的对象的数量或大小太大而无法在函数参数中有效传递,通常每个人都建议使用依赖注入而不是全局对象。 但是,在几乎每个人都需要了解某种数据结构的情况下,为什么依赖注入比全局对象更好? 示例(一个简化的示例,以大体上说明这一点,而无需在特定应用程序中深入研究) 许多虚拟车辆具有大量的属性和状态,包括类型,名称,颜色,速度,位置等。许多用户可以对其进行远程控制,并且发生大量事件(用户都可以已启动和自动)可以更改其许多状态或属性。 天真的解决方案是仅将它们制成一个全局容器,例如 vector<Vehicle> vehicles; 可以从任何地方访问。 更加面向OOP的解决方案是让容器成为处理主事件循环的类的成员,并在其构造函数中实例化。每个需要它并且是主线程成员的类都将通过其构造函数中的指针被授予对容器的访问权限。例如,如果外部消息是通过网络连接传入的,则负责解析的类(每个连接一个)将接管,解析器将可以通过指针或引用访问容器。现在,如果解析后的消息导致容器元素发生更改,或者需要容器中的某些数据来执行操作,则无需通过信号和插槽来扔掉成千上万个变量(或更糟的是,将它们存储在解析器中,稍后由调用解析器的人检索)。当然,所有通过依赖注入接收对容器的访问的类都是同一线程的一部分。不同的线程不会直接访问它,但是会执行其工作,然后将信号发送到主线程,并且主线程中的插槽将更新容器。 但是,如果大多数类都可以访问该容器,那么到底它与全局容器有什么不同呢?如果这么多的类需要容器中的数据,那么“依赖注入方式”是否只是伪装的全局变量? 一个答案将是线程安全性:即使我注意不要滥用全局容器,也许将来另一个开发人员在紧迫的最后期限的压力下,仍会在另一个线程中使用全局容器,而不会照顾所有人碰撞情况。但是,即使在依赖注入的情况下,也可能会向在另一个线程中运行的某个人提供指针,从而导致相同的问题。


1
Haskell构建和工件环境类似于Maven
我曾经是Java开发人员很长一段时间,但是最近我加入了Haskell团队。在Java世界中,如果您有一个大型项目,并且有多个团队在工作,那么一种常见的方法是使用工件服务器(例如Maven)来简化和加速开发。许多构建工具(例如Ant,Maven,Gradle)都可以构建项目并将jar文件上传到工件服务器,团队其他成员可以轻松使用。因此,通过将项目拆分为较小的子项目,还可以大大减少构建时间。 在Haskell方面,我们正在使用cabal该项目。我们的项目大约需要10-15分钟才能完成构建,而无需进行优化。如果打开编译器优化,则需要几个小时,这很痛苦。 我想知道,如何才能像在Java中一样做同样的事情。有没有一种简单的方法可以编译软件包(库)的二进制文件并将其上传到工件服务器,并在构建时使用预构建的二进制文件?我知道,因为Haskell生成机器代码(而不是Java中的字节码),所以可能存在兼容性问题,但是对于存储在工件服务器上的不同体系结构/操作系统,我们可能具有不同的二进制文件。

1
API网关和ESB之间的区别?[关闭]
关闭。这个问题是题外话。它当前不接受答案。 想改善这个问题吗? 更新问题,使它成为软件工程堆栈交换的主题。 5年前关闭。 我工作的公司正在评估一些中间件解决方案,以解决网络服务的治理,计量和安全问题。当前,我们正在为此目的使用企业服务总线(ESB),但是管理层中的一些帅哥决定他们将部署一些API管理中间件。 我对这些API管理(又称API网关)解决方案进行了一些研究,但找不到它们与实际ESB之间的区别。我评估了Mule,WSO2,Oracle等的一些白皮书,但是两种产品提供的功能似乎几乎相同。问题是,ESB无法做到的API管理能做什么,反之亦然?通过替换API网关的ESB,可以为IT基础架构增加什么价值?

7
给带有“ Info”后缀的类命名的想法是什么,例如:“ SomeClass”和“ SomeClassInfo”?
我正在一个处理物理设备的项目中工作,而在如何正确命名该项目中的某些类方面一直感到困惑。 考虑到实际的设备(传感器和接收器)是一回事,而它们在软件中的表示是另一回事,我正在考虑使用“ Info”后缀名称模式命名某些类。 例如,虽然a Sensor是代表实际传感器的类(当它实际上连接到某个工作设备时),但SensorInfo将仅用于代表此类传感器的特性。例如,保存文件后,我将序列化为SensorInfo文件头,而不是序列化Sensor,这甚至都没有道理。 但是现在我很困惑,因为在对象生命周期中存在一个中间立场,我无法决定是否应该使用一种或另一种,或者如何从另一种中获取一种,甚至不能将这两种变体实际上只折叠为一个类。 而且,太普遍的示例Employee类显然只是真实人物的表示,但EmployeeInfo据我所知,没有人会建议为该类命名。 我使用的语言是.NET,这种命名模式在整个框架中似乎很常见,例如这些类: Directory和DirectoryInfo班级; File和FileInfo班级; ConnectionInfo班级(无对应Connection班级); DeviceInfo班级(无对应Device班级); 所以我的问题是:使用这种命名模式是否有共同的理由?在某些情况下,具有成对的名称(Thing和ThingInfo)是否有意义,而在其他情况下,仅应存在ThingInfo该类,或者Thing该类没有对应物?

1
为什么.NET框架没有将类定义为一流类型的概念?
熟悉历史的人都知道,C#和.NET框架最初是由Delphi的首席开发人员Anders Hejlsberg设计的,“ Delphi被重写为Java感觉”。从那时起,事情发生了很大的分歧,但是在早期的相似性是如此明显,以至于甚至有人认真地猜测.NET实际上最初是Borland的产品。 但是最近我一直在看一些.NET东西,而Delphi最有趣,最有用的功能之一似乎完全消失了:类作为一流数据类型的概念。对于不熟悉它的人,类型TClass代表对类的引用,类似于Type.NET中的类型。但是,在.NET Type用于反射的地方,Delphi将其TClass用作语言的非常重要的内置部分。它允许各种有用的习惯用法,如果没有它,它们就不会存在,也不会存在,例如类子类型变量和虚拟类方法。 每种OO语言都有虚拟方法,其中不同的类以不同的方式实现方法的相同基本概念,然后根据运行时所调用对象实例的实际类型在运行时调用正确的方法。Delphi将此概念扩展到了类:如果您将TClass引用定义为特定的类子类型(即class of TMyClass,该变量可以接受继承自的任何类引用TMyClass,但不能继承继承体系中的任何内容),且该类引用附加了类范围虚拟方法通过使用类的实际类型,可以在没有实例的情况下调用它们。例如,将此模式应用于构造函数会使Factory实现变得很简单。 .NET中似乎没有任何等效的东西。与类引用一样有用(尤其是虚拟构造函数和其他虚拟类方法!),有没有人说过为什么将它们遗漏? 具体例子 形式反序列化 Delphi VCL DFM以DSL格式保存表格,以描述组件层次结构。表单阅读器解析DFM数据时,它跨如下所述的对象运行: object Name: ClassName property = value property = value ... object SubObjectName: ClassName ... end end 有趣的是这里的ClassName部分。每个组件类都会及时TClass在组件流式系统中注册initialization(请考虑静态构造函数,只有一点点不同,保证在启动时立即发生。)这会将每个类注册在string-> TClass哈希图中,且类名称为键。 每个组件都来自TComponent,它具有一个虚拟构造函数,该构造函数采用单个参数Owner: TComponent。任何组件都可以重写此构造函数以提供自己的初始化。当DFM阅读器读取类名称时,它会在上述哈希图中查找该名称并检索相应的类引用(如果不存在则引发异常),然后在其上调用虚拟TComponent构造函数,这被认为是很好的因为注册函数采用了从TComponent继承的类引用,所以您最终得到了正确类型的对象。 缺少这一点,WinForms等效项...坦白地说,这是一个很大的混乱,需要任何新的.NET语言来完全重新实现其自身的格式(反序列化)。当您考虑时,这有点令人震惊。因为拥有CLR的全部目的是让多种语言使用相同的基本基础结构,所以DFM风格的系统将具有完美的意义。 可扩展性 如果您尝试检索不在集合中但在数据源中可用的名称,那么我编写的图像管理器类可以提供数据源(例如图像文件的路径),然后自动加载新的图像对象。它具有一个类变量,该类变量的类型为class of基本图像类,表示要创建的任何新对象的类。它具有默认值,但是在出于特殊目的创建新图像时,有一些要点应以不同方式设置图像。(在没有Alpha通道的情况下创建它,从PNG文件中检索特殊的元数据以指定图片大小,等等。) 这可以通过编写大量的配置代码并将特殊选项传递给所有可能最终创建新对象的方法来完成...或者您可以仅使基本图像类的子类覆盖虚拟方法,已配置有关方面,然后根据需要使用try / finally块临时替换“默认类”属性,然后将其还原。使用类引用变量执行此操作要简单得多,而不是使用泛型即可完成。

2
是否应该仅通过查看代码就总是知道API在做什么?
最近,我一直在开发自己的API,随着对API设计的投入,我一直对如何改善API设计非常感兴趣。 出现了几个方面(不是我的API用户使用,而是在我对该主题的观察讨论中):一个人应该只通过查看调用API的代码来知道它在做什么。 例如,请参见GitHub上有关此讨论的讨论,例如: foo.update_pinned(true, true); 仅仅通过查看代码(不知道参数名称,文档等),就无法猜测它会做什么-第二个参数是什么意思?建议的改进措施如下: foo.pin() foo.unpin() foo.pin_globally() 这就清除了一切(我猜第二个参数是是否全局固定foo),在这种情况下,我同意后者肯定会有所改进。 但是我相信,在某些情况下,设置不同但与逻辑相关的状态的方法最好作为一个方法调用而不是单独的方法公开,即使您仅通过查看代码也不知道它在做什么。(因此,您必须求助于参数名称和文档以查明-如果我不熟悉API,我个人将始终这样做)。 例如,我SetVisibility(bool, string, bool)在FalconPeer上公开了一种方法,并且我承认只看了一下这一行: falconPeer.SetVisibility(true, "aerw3", true); 您将不知道它在做什么。它设置了3个不同的值来控制falconPeer逻辑上的“可见性” :仅接受接受密码的加入请求,然后回复发现请求。将其分为3个方法调用可能会导致API的用户设置“可见性”的一个方面而忘记设置其他设置,而我仅通过公开一种方法来设置“可见性”的所有方面而迫使他们考虑。此外,当用户想要更改一个方面时,他们几乎总是会想要更改另一个方面,现在可以在一个呼叫中进行更改。

2
是否可以在Haskell中“将维度转换为类型”?
假设我想编写一个处理向量和矩阵的库。是否可以将维度烘焙为类型,以使不兼容的维度的操作在编译时产生错误? 例如,我希望点积的签名类似于 dotprod :: Num a, VecDim d => Vector a d -> Vector a d -> a 其中d类型包含单个整数值(代表这些Vector的维)。 我想可以通过为每个整数定义一个单独的类型并将其分组为一个名为的类型类来实现VecDim。是否有某种机制可以“生成”此类类型? 还是一些更好/更简单的方法来实现同一目标?

6
“撤消”整数环绕
几年前,我遇到了一个有趣的理论问题。我从未找到解决方案,当我睡觉时,它仍然困扰着我。 假设您有一个(C#)应用程序,该应用程序在一个称为x的int中保存一些数字。(x的值不固定)。运行该程序时,x乘以33,然后写入文件。 基本的源代码如下所示: int x = getSomeInt(); x = x * 33; file.WriteLine(x); // Writes x to the file in decimal format 几年后,您发现需要X的原始值。一些计算很简单:只需将文件中的数字除以33。但是,在其他情况下,X足够大,以至于乘法运算导致整数溢出。根据文档,C#将截断高阶位,直到数字小于int.MaxValue。在这种情况下,是否可以: 恢复X本身或 恢复X的可能值的列表? 在我看来(尽管我的逻辑肯定有缺陷)应该可行,其中之一或两者都可行,因为加法的简单情况有效(本质上,如果您将X加10并自动换行,则可以减去10再用X结束),而乘法就是重复的加法运算。我相信,在所有情况下X都乘以相同的值(常数33)也是有帮助的(我相信)。 多年来,这一直在我的头颅周围跳舞。它会发生在我身上,我将花一些时间尝试思考它,然后我会忘记几个月。我已经厌倦了追逐这个问题!谁能提供见识? (旁注:我真的不知道如何标记这一标记。欢迎提出建议。) 编辑:让我澄清一下,如果我可以获得X的可能值的列表,则可以做其他测试来帮助我将其范围缩小到原始值。
20 c# 

7
除了一连串的if语句或switch之外,还有其他更智能的方法吗?
我正在实现一个接收消息的IRC机器人,并且正在检查该消息以确定要调用的函数。有更聪明的方法吗?在我掌握了20条命令之后,它似乎很快就变得一发不可收拾。 也许有一种更好的抽象方法? public void onMessage(String channel, String sender, String login, String hostname, String message){ if (message.equalsIgnoreCase(".np")){ // TODO: Use Last.fm API to find the now playing } else if (message.toLowerCase().startsWith(".register")) { cmd.registerLastNick(channel, sender, message); } else if (message.toLowerCase().startsWith("give us a countdown")) { cmd.countdown(channel, message); } else if (message.toLowerCase().startsWith("remember am routine")) …

7
从VBA到C#的团队成员质疑
背景 去年,我被要求为大约10个用户创建一个用于业务计划的工具。这项工作是由另一个IT团队代表完成的,该团队将工作“分包”给我,并且由于项目期限在他们这边有些计划外,我不得不匆忙实施。 当时,我们决定最快的方法是使用VBA创建Excel工作簿,然后让用户从Intranet下载此VBA增强的工作簿以在其PC上使用。在这种情况下,Excel是一个约束,因为我们使用的计划系统(即数据库)只能通过Excel加载项进行交互,该加载项必须在打开计划工作簿的同时加载。但是,当时VBA并不是一个约束。 我创建了约4,000行VBA代码的工作簿,虽然我尝试分离数据层和表示层,但由于项目截止日期,所以在所有情况下都无法做到。老实说,虽然我为创建此工作簿感到自豪,但同时我感到有些失望,因为它在编码和部署到用户方面都可以做得更好。 今天 回到今天,IT团队再次来找我,要求提供类似的工作簿(这样我就可以重用上面其他工作簿的部分内容),但这一次它变得更加复杂,将被更多的用户使用( 200左右)。 但是,这次的计划要好一些,我可以看到我们有更多的时间来计划事情。基于此,我考虑了该解决方案和基础架构,因为针对100个用户的编程比对10个用户的编程影响更大。因此,我向团队建议,也许我们应该考虑将现有代码迁移到C#解决方案,以便我们可以以更精细的方式管理代码。我仍将其视为使用VSTO / Excel-DNA编写的加载项,然后可以将其部署到用户。 两周前,我与IT团队讨论了这一问题,一切似乎都很好,直到昨天,我收到一个团队(不了解VBA或C#)的邮件,询问我们为什么应该在C#中启动这个新项目,而不是使用与以前相同的方法。他们的一些担忧是: 这是一个非常重要的项目,因此它必须能够工作-C#解决方案不能像现有的基于VBA的解决方案那样稳定或有效。 我们将不得不舍弃[I]在VBA解决方案中所做的事情,并在C#中从头开始重新创建它。 有人必须支持两种单独的解决方案,一种在VBA中,一种在C#中。[实际上,他们目前没有任何人支持,我通常会介入]。 现在,我可以在某种程度上理解他们的一些担忧,但是我需要决定下一步的工作以及如何处理这些问题。就个人而言,我想用C#实施,因为我认为它更适合于构建这样的“企业”解决方案。此外,我想借此机会提高我的C#技能,因为我目前不像VBA那样胜任C#的能力,并且我希望通过这样的项目将我带入“下一个级别”。 我准备了一些要点,可以用来说服他们说C#解决方案更适合该项目,这是我到目前为止的目标: 单元测试。 源代码控制。 代码文档-用于将知识转移给其他支持人员。 更好的编码约定-可以使用ReSharper之类的东西来加强更好的命名和结构。 更好的IDE-减少由于错误突出显示而导致的错误。 通过组件实现更高的模块化-可以促进将来工具的重用。 托管部署-可以控制使用此工具的人员。 问题:我还能说些什么来说服他们?还是我想尽全力去完成这个项目?我应该保持安静,还是在VBA中这样做吗? 我知道,仅因为新语言的“较新”或被视为“较凉爽”而改用新语言就不应作为决策的基础,因此我拒绝将其作为决策要点-这是关于事实的。 另外,我不要求在C#和VBA作为语言之间进行字面比较,因为在SO上有很多比较。

3
为有状态系统设计单元测试
背景 在我完成学业后,测试驱动开发得到了普及。我正在尝试学习它,但是一些主要的事情仍然无法解决。TDD的支持者说了很多类似的东西(以下称为“单一声明原则”或SAP): 一段时间以来,我一直在思考TDD测试如何尽可能简单,富有表现力和优雅。本文探讨了使测试尽可能简单和可分解的感觉:针对每个测试中的单个断言。 来源:http://www.artima.com/weblogs/viewpost.jsp? thread = 35578 他们还说这样的话(以下称为“私有方法原理”或PMP): 通常,您不直接对私有方法进行单元测试。由于它们是私有的,因此请考虑将其作为实现细节。没有人会打电话给他们中的一个,并期望它以特定的方式工作。 相反,您应该测试您的公共接口。如果调用您的私有方法的方法按预期工作,则可以假定您的私有方法正常工作。 资料来源:您如何对私有方法进行单元测试? 情况 我正在尝试测试有状态的数据处理系统。给定接收数据之前的状态,系统可以对完全相同的数据执行不同的操作。考虑一个简单的测试,该测试建立系统中的状态,然后测试给定方法要测试的行为。 SAP建议我不要测试“状态构建过程”,我应该假设状态是我希望从构建代码中得到的状态,然后测试我要测试的一个状态更改 PMP建议我不能跳过此“状态建立”步骤,而只能测试独立控制该功能的方法。 我实际代码中的结果是测试膨胀,复杂,冗长且难以编写。而且,如果状态转换发生变化,则必须更改测试……这对于小型,高效的测试是可以的,但对于这些冗长的测试却非常耗时且令人困惑。通常如何做?

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.