软件工程

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

1
通过微前端向下发送冗余代码
我对微前端的理解是,他们解决的关键问题是帮助企业拥有多个可能组成不同的团队,研究将用于组成大型Web应用程序的单个组件/小型应用程序。 这里要解决的关键问题是多个团队独立工作的能力,并且仍然能够构建大型复合材料。问题不在于为最终用户提供精简的发行包。这种理解正确吗? 的确,如果我们有多个用于组成大型Web应用程序的小型应用程序,则有可能会有多个小型应用程序将相同的Javascript库(例如Lodash)作为最终用户的一部分传送给最终用户的浏览器。各个供应商捆绑包是否导致一定数量的重复/冗余代码被发送给用户? 在设计前端应用程序时,这不是我们应该担心的问题吗?

4
具有无意义默认值的结构
在我的系统经常与机场代码(操作"YYZ","LAX","SFO"等),他们总是在完全一样的格式(3封信,表示为大写)。系统通常每个API请求处理这些代码中的25-50个(不同),总共分配了上千个代码,它们在我们应用程序的许多层中传递,并且经常比较它们的相等性。 我们从传递字符串开始就可以了,但仍然可以正常工作,但很快就发现了很多编程错误,因为在期望3位代码的地方传递了错误的代码。我们还遇到了一些问题,我们应该进行不区分大小写的比较,而没有这样做,从而导致错误。 由此,我决定停止传递字符串并创建一个Airport类,该类具有一个采用并验证机场代码的构造函数。 public sealed class Airport { public Airport(string code) { if (code == null) { throw new ArgumentNullException(nameof(code)); } if (code.Length != 3 || !char.IsLetter(code[0]) || !char.IsLetter(code[1]) || !char.IsLetter(code[2])) { throw new ArgumentException( "Must be a 3 letter airport code.", nameof(code)); } Code = code.ToUpperInvariant(); } public string …

5
如果我已经有一个抽象类,定义一个接口是否有意义?
我有一类带有一些默认/共享功能的类。我用abstract class它: public interface ITypeNameMapper { string Map(TypeDefinition typeDefinition); } public abstract class TypeNameMapper : ITypeNameMapper { public virtual string Map(TypeDefinition typeDefinition) { if (typeDefinition is ClassDefinition classDefinition) { return Map(classDefinition); } ... throw new ArgumentOutOfRangeException(nameof(typeDefinition)); } protected abstract string Map(ClassDefinition classDefinition); } 如您所见,我也有接口ITypeNameMapper。如果我已经有一个抽象类,TypeNameMapper或者abstract class已经足够,定义这个接口是否有意义? TypeDefinition 在这个最小的例子中也是抽象的。


5
在什么条件下(如果有),查询两个服务器并且仅消耗最快的响应是一种好习惯吗?
我问过什么是SO上现在被社区删除的问题,为什么有人会使用javascript的问题Promise.race,而一个高级用户则对此发表了评论: 如果您有两个计算某个值的服务,则可以并行查询它们,并使用第一个返回的值,而不是查询一个,等待失败,然后查询第二个。 我已经在冗余和这种用例上进行了全面的搜索,但是我什么也找不到,而且从我的POV中来看,如果不打算使用响应,只向服务器/服务添加工作负载绝不是一个好主意。

1
有什么方法可以制作Windows和Mac的.Net库,并具有依赖于平台的引用?
我们正在尝试使用C#开发用于台式机(Windows和Mac)的跨平台应用程序。该应用程序包含大量与平台相关的内容,我们的团队负责人希望我们用C#编写所有这些代码。做到这一点的简单方法是用C ++编写包装程序,然后只引用C#代码中的库,然后让C ++库处理平台方面的东西……可惜,事实并非如此。 我正在尝试使用Visual Studio for Mac建立一个库。我希望能够在单个库中提供单个接口,以将对本机文本的访问权限授予当前平台上的语音库-最好不进行两个程序集。Mac上不提供Windows版C#中的文本到语音库,因此我们除了提供自己的桥梁之外,没有其他选择。 我很高兴让该库执行操作系统查找以确定它运行在哪个操作系统上和/或尝试加载一堆本机库并仅使用将加载的库。 如果必须的话,必须有一个可以让我编写两个实现的项目。我还没有找到在Visual Studio for Mac中创建库项目的方法,但是允许我这样做。唯一允许多种实现的项目类型似乎要求这些实现是针对iOS还是针对Android。

2
当应用的某些部分用不同的语言编写时,如何避免数据结构重复?
例如,假设您正在用Java编写应用程序。 您的应用程序与使用Python编写的API服务器进行通信。 Python服务器与SQL数据库进行通信。 您还拥有一个用JavaScript编写的应用程序网站。 使用4种不同的语言,很容易以4次不同的时间重复基本相同的数据结构。 例如,User类型可能看起来像这样(伪代码): type User { integer id; string name; timestamp birthday; } 项目的每个部分都需要某种形式的表示User。Java和Python部分将需要两个不同的class声明。数据库将需要一个User表声明。前端站点也需要代表一个站点User。 重复此类型4次确实违反了“ 请勿重复自己”原则。还有一个问题是,如果User更改了类型,则需要在项目的每个不同部分中重复这些更改。 我知道Google的protobuf库为该问题提供了一种解决方案,您可以使用特殊的语法编写数据结构,然后该库以多种不同的编程语言为您生成结构声明。但这仍然没有解决必须为您的类型重复验证逻辑的问题。 是否有人对此有任何建议或链接到书籍/博客文章?

4
类应如何向用户传达其实现的方法子集?
情境 Web应用程序IUserBackend使用以下方法定义用户后端接口 getUser(uid) createUser(uid) deleteUser(uid) setPassword(uid,密码) ... 不同的用户后端(例如LDAP,SQL等)实现此接口,但并非每个后端都能做所有事情。例如,一个具体的LDAP服务器不允许该Web应用程序删除用户。因此LdapUserBackend实现的类IUserBackend将不会实现deleteUser(uid)。 具体的类需要向Web应用程序传达允许Web应用程序与后端用户进行的操作。 已知解决方案 我已经看到了一个解决方案,其中IUserInterface具有一种implementedActions方法,该方法返回一个整数,该整数是操作按位与所请求的操作进行“与”运算的结果: function implementedActions(requestedActions) { return (bool)( ACTION_GET_USER | ACTION_CREATE_USER | ACTION_DELTE_USER | ACTION_SET_PASSWORD ) & requestedActions) } 哪里 ACTION_GET_USER = 1 ACTION_CREATE_USER = 2 ACTION_DELETE_USER = 4 ACTION_SET_PASSWORD = 8 .... = 16 .... = 32 等等 因此,Web应用程序根据需要设置位掩码,并implementedActions()使用布尔值回答是否支持它们。 意见 在我看来,这些位操作看起来像C时代的遗物,就干净的代码而言,不一定易于理解。 …

3
新的C项目何时应针对非常老的C标准(> 20年,即C89)?
偶尔我会看到针对较旧的C标准(通常是C89)的大型,相对较新的开源C项目。有一个例子。这些项目由聪明的人掌舵,因此他们可能对这个我不知道的决定有很好的理由。除了疑问的好处之外,似乎基本原理是“较老和标准化总是更具可移植性和更好性”,这是荒谬的,因为逻辑结论是FORTRAN优于C,COBOL甚至比FORTRAN更好。 什么时候以及为什么有理由要求新的C项目针对非常老的C标准? 我无法想象用户系统绝对不能更新其C编译器而可以自由安装新软件的情况。例如,Debian的LTS版本具有gcc 4.6软件包,该软件包支持C99和某些C11。我猜想肯定会存在奇怪的情况,而像systemd这样的程序正是针对这些用户的。 我能想到的最合理的用例是,预期用户将具有异国情调的体系结构,在该体系结构上只有 C89编译器可用,但他们完全愿意安装新软件。鉴于指令集体系结构多样性的下降,这似乎是一个过度假设的场景,但我不确定。
12 c  standards 

2
当用户编辑行时,是否应该将行锁定在云数据库中?
我正在创建一个桌面应用程序,将数据持久存储在云中。我关心的一个问题是开始在应用程序中编辑项目,并将其保留一段时间会导致数据过时。如果两个人同时尝试编辑同一项目,则显然也会发生这种情况。当他们完成编辑并要保存数据时,我要么需要覆盖数据库中当前存在的内容,要么检查他们在上一次更改之后是否开始编辑,或者迫使他们放弃更改,或者给他们选择冒险的选择覆盖他人的更改。 我想增加一个字段is_locked和lock_timestampdb表。当用户开始编辑项目时,该行将is_locked变为true并将锁定时间戳记设置为当前时间。然后,我将拥有一段时间的锁定时间(例如5分钟)。如果其他任何人尝试编辑该项目,他们将收到一条消息,指出该项目已被锁定,并且锁定自动失效。如果用户在编辑时走开,则锁会在相对较短的时间后自动过期,一旦这样做,将警告用户锁已过期,并在刷新数据后被迫重新开始编辑。 这是防止覆盖陈旧数据的好方法吗?是不是太过分了(我不希望单个帐户同时使用多个应用程序)。 (我还要担心的是,有2个人为同一物品锁上了锁,但是我认为这是我可以接受的比赛条件。)

5
微型重构代码以提高质量是否有用,还是只是“移动代码”而没有太多好处?
例 我遇到了在一个地方完成所有工作的整体代码-从数据库加载数据,显示HTML标记,充当路由器/控制器/动作。我开始应用SRP将数据库代码移动到其自己的文件中,从而为事物提供了更好的命名,而且看起来都不错,但是随后我开始怀疑为什么要这样做。 为什么要重构?什么目的?它没用吗?有什么好处?请注意,我基本上保留了整体文件,但只重构了与需要进行某些工作的区域相关的较小部分。 原始代码: 举一个具体的例子,我遇到了以下代码片段-它通过已知的产品ID或用户选择的版本ID加载产品规格: if ($verid) $sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid); else $sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ; $result1 = query($sql1); $row1 = fetch_array($result1); /* html markup follows */ 重构: 由于我正在做一些工作,要求我在代码的此特定部分中进行更改,因此我将其更改为使用存储库模式,并将其升级为使用面向对象的MySQL工具: //some implementation details omitted …


5
禁止在外部代码中调用任意函数/类
我曾遇到过一些案例,其中有必要限制外部库和框架的API的访问,以防止对系统造成负面影响。 例如,在SharePoint应用程序中,调用spList.Items.GetItemById以获取列表项似乎很自然,即使是在循环中,也可能没有意识到这会导致巨大的性能问题。 也可能是我们需要禁止使用SmtpClient,以迫使每个人都使用我们自己的类来发送电子邮件,以确保我们可以在测试环境中正确代理和模拟所有电子邮件。 除了在我们自己的代码中的某些特定位置之外,是否有任何可靠且合理直接的方法来实现对外部代码的这些约束?不必绝对在每种情况下都禁止访问这些方法/类,例如通过反射或仅通过某种禁用来禁止访问,而应该严格警告不要使用它们。优选地,如果可能/需要,迫使程序员积极采取措施来克服这些约束。

1
“语法醋”是什么意思
我正在阅读《Groovy in Action,第二版》,并在一个脚注中找到了以下内容: Java将“语法醋”浇在这样的结构上,以阻止程序员使用它。 该术语syntax vinegar在这里意味着什么? 我之前从未听说过这个词,并在DuckDuckGo和Google上进行了搜索,但找不到含义。但是它已在多个地方使用。如果有人可以澄清该术语的含义以及它在编程语言中的应用,那就太好了。希望这构成一个有效的问题。找不到其他我可以问这个的stackexchange网站。
12 java  syntax  groovy 

1
为什么将信号量称为信号量?
在我看来,铁路信号灯比任何其他通用信号对象(例如旗帜或交通信号灯)对信号灯的描述都更好。甚至像钥匙圈之类的东西(人们将钥匙从环上取下来以访问锁定的资源,然后在完成后返回它们)更具描述性。那么为什么一个信号量被称为信号量呢?
12 semaphore 

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.