软件工程

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

6
如何记录我的代码以进行最短时间检查?[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 去年关闭。 我想记录我的代码,以使几个月后再次阅读和浏览代码的需求降至最低。 我知道有不同类型的文档(在源代码中和外部,序列图等中)。 我只想知道什么是记录我的代码的有效方法,所以几个月后我想看我的代码时,我花更少的时间在阅读代码和理解代码流上。

2
如何准确地验证CQRS命令并将其转换为域对象?
我一直在修改穷人的CQRS 1,因为我喜欢它的灵活性,可以在一个数据存储中存储细粒度的数据,这为分析提供了极大的可能性,从而增加了商业价值,并且在需要时还提供了另一种包含非规范化数据的读取以提高性能。 。 但是不幸的是,从一开始,我就一直在为应该在这种架构中放置业务逻辑的问题而苦苦挣扎。 据我了解,命令是传达意图的手段,它本身与域没有关系。它们基本上是数据(哑巴,如果需要的话)传输对象。这是为了使命令可以在不同技术之间轻松转移。对于成功完成的事件的响应,同样适用于事件。 在典型的DDD应用程序中,业务逻辑驻留在实体,值对象,集合根中,它们既包含数据又包含行为。但是命令不是域对象,因此命令不应仅限于数据的域表示形式,因为这会对它们造成很大的压力。 因此,真正的问题是:逻辑到底在哪里? 我发现我在尝试构建一个非常复杂的集合(该集合为它的值的组合设置一些规则)时往往最容易遇到这种斗争。另外,在对域对象建模时,我喜欢遵循快速失败范例,知道对象何时到达处于有效状态的方法。 假设聚合Car使用两个组件: Transmission, Engine。 两个Transmission和Engine值对象被表示为超级类型和具有根据子类型,Automatic和Manual传输,或Petrol与Electric分别引擎。 在此域中,完全依靠成功创建的Transmission,,Automatic或Manual或任意一种类型来生存Engine。但是Car聚合引入了一些新规则,这些规则仅在Transmission和Engine对象在同一上下文中使用时才适用。即: 当汽车使用Electric发动机时,唯一允许的变速箱类型是Automatic。 当汽车使用Petrol发动机时,可能有两种类型的发动机Transmission。 我可以在创建命令的级别上捕获这种违反组件组合的行为,但是正如我之前所说,据我所知,不应这样做,因为命令将包含业务逻辑,而业务逻辑应限于域层。 一种选择是将这种业务逻辑验证移至命令验证器本身,但这似乎也不对。感觉就像我将解构该命令,检查使用getter检索的属性,并在验证器中比较它们并检查结果。这让我尖叫得像是违反了得墨meter耳的法律。 放弃提到的验证选项,因为它似乎不可行,似乎应该使用该命令并从中构造聚合。但是这种逻辑应该在哪里存在?是否应该在负责处理具体命令的命令处理程序中?还是应该在命令验证器中(我也不喜欢这种方法)? 我当前正在使用命令,并在负责的命令处理程序中从中创建一个聚合。但是,当我执行此操作时,如果我有一个命令验证器,它将根本不包含任何内容,因为如果该CreateCar命令存在,则它将包含我知道在单独的情况下有效的组件,但集合可能表示不同。 让我们想象一个混合了不同验证过程的场景-使用CreateUser命令创建一个新用户。 该命令包含Id将要创建的一个用户及其Email。 系统为用户的电子邮件地址规定以下规则: 必须是唯一的 不能为空, 最多包含100个字符(数据库列的最大长度)。 在这种情况下,即使有一个唯一的电子邮件是一条业务规则,但对其进行汇总检查几乎没有任何意义,因为我需要将系统中的全部当前电子邮件加载到内存中,并在命令中检查该电子邮件(Eeeek!某物,某物,性能)。因此,我将此检查移至命令验证程序,该程序将UserRepository作为依赖项,并使用存储库来检查是否存在使用命令中存在电子邮件的用户。 当涉及到这一点时,突然将其他两个电子邮件规则也放入命令验证器中是有意义的。但是我觉得规则应该确实存在于User聚合中,并且命令验证程序应该只检查唯一性,如果验证成功,我应该继续在中创建User聚合CreateUserCommandHandler并将其传递到要保存的存储库中。 我之所以这样,是因为存储库的save方法很可能会接受一个聚合,该聚合可确保一旦传递了聚合,所有不变量都将得到满足。当逻辑(例如,非空性)仅出现在命令验证本身中时,另一位程序员可以完全跳过此验证,并直接UserRepository使用User对象调用对象中的save方法,这可能导致致命的数据库错误,因为电子邮件可能包含太久了。 您个人如何处理这些复杂的验证和转换?我大多对自己的解决方案感到满意,但是我觉得我需要肯定的是,我对自己的选择并不满意,但我的想法和方法并不完全愚蠢。我完全接受完全不同的方法。如果您有自己尝试过的东西并且为您做得很好,我很乐意看到您的解决方案。 1作为负责创建RESTful系统的PHP开发人员,我对CQRS的解释与标准的异步命令处理方法略有不同,例如有时由于需要同步处理命令而从命令返回结果。

5
微服务:处理最终一致性
假设我们有一个更新用户密码的功能。 单击“更新密码”按钮后,会将UpdatePasswordEvent发送到预订了3个其他服务的主题: 实际更新用户密码的服务 一种更新用户密码历史记录的服务 发出电子邮件通知用户其密码已更改的服务。 根据我对最终一致性的了解,所有这些服务(消费者)将同时接收事件并分别处理它们,在良好的情况下,这将导致数据保持一致。 但是,如果服务无法处理事件怎么办?例如突然断开连接,数据库错误等...处理这些事务失败的好的模式/做法是什么? 我当时正在考虑创建一个RollbackTopic,如果任何事件都无法处理,将在一个主题中创建一个RollbackEvent,其中“ rollback services”将完成其工作并将数据还原

3
为什么要编写控制器的单元测试?
对我来说,这是完全不相关的单元测试,我不明白为什么有人会花时间编写它,因为从中获得的价值很小。如果此控制器通过在浏览器中执行该方法返回所需的类型,我会非常清楚。确实,您认为需要为此进行测试吗?为什么? public class ConstituencyControllerTests { private ConstituencyController _constituencyController; private Mock<IConstituencyService> _IConstituencyServiceMock; public ConstituencyControllerTests() { _IConstituencyServiceMock = new Mock<IConstituencyService>(); } [Test] public async Task I_Check_For_Return_Type_And_Result() { _constituencyController = new ConstituencyController( _IConstituencyServiceMock.Object ); var result = await _constituencyController.Get(); var content = ( (dynamic)result ).Content; Assert.IsEmpty( content ); Assert.IsInstanceOf( typeof( System.Web.Http.Results.OkNegotiatedContentResult<IEnumerable<ListOfConstituencies>> ), result …

8
什么时候原始的迷恋不是代码的味道?
最近,我读了很多文章,将原始的痴迷描述为一种代码气味。 避免原始痴迷有两个好处: 它使域模型更加明确。例如,我可以与业务分析师讨论邮政编码,而不是包含邮政编码的字符串。 所有验证都放在一个地方,而不是整个应用程序。 那里有很多文章描述什么是代码气味。例如,我可以看到为这样的邮政编码除去原始的困扰的好处: public class Address { public ZipCode ZipCode { get; set; } } 这是ZipCode的构造函数: public ZipCode(string value) { // Perform regex matching to verify XXXXX or XXXXX-XXXX format _value = value; } 您将打破DRY原则,将验证逻辑放在所有使用邮政编码的地方。 但是,以下对象呢? 出生日期:检查是否大于预期且小于今天。 薪金:检查是否大于或等于零。 您将创建DateOfBirth对象和Salary对象吗?好处是您可以在描述域模型时谈论它们。但是,这是过度工程的一种情况,因为没有太多的验证。是否有一条规则描述了何时以及何时不消除原始的困扰,或者如果可能的话,您应该始终这样做吗? 我想我可以创建一个类型别名而不是一个类,这将有助于上面的第一点。

1
Hindley-Milner推理可以为Go语言工作吗?
我读过Hindley-Milner不适用于具有子类的类型系统,并且还有其他类型系统功能也不能很好地使用它。Go当前在:=运算符中只有非常有限的类型推断。但是Go并没有传统意义上的子类,只有看起来与Haskell的类型类非常相似的接口,可以很好地与Hindley-Milner推理配合使用。 那么,Hindley-Milner推理在原理上是否可以像对Haskell一样进行推论?还是Go具有其他打破它的功能?(另一方面,Haskell还具有某些与Hindly-Milner不兼容的功能,如果要使用这些功能,则必须手动键入程序的那些部分。)

9
在编码和维护期间写下笔记,思想,算法,决策是否正常/可以接受?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 有些人有这个问题,他们一言不发。写下他们的想法和决定是最有效的方法。 那么-在编码过程中在一些Notepad ++文件中写下我的想法和决定是否正常并且可以接受? 有时应该是可以接受的,例如在重新创建技术文档或对更复杂的算法进行推理时,但是有时可能很奇怪,例如当我在考虑设计选项并试图做出判断时。 这种做法对生产率的影响尚不清楚。从一方面来看,使用内在单词的推理可能比使用书面单词的推理更快。另一方面,更复杂的问题需要编写。此外,如果人们坚持使用更多的设计选项,那么在撰写决策时感觉会更好,因此鼓舞士气。

5
成功时返回true / false与void的函数,失败时抛出异常
我正在构建一个API,一个上传文件的函数。如果文件上传正确,此函数将不返回任何内容/无效,并且在出现问题时将引发异常。 为什么要例外而不是错误?因为在异常中,我可以指定失败的原因(无连接,文件名丢失,密码错误,文件描述丢失等)。我想构建一个自定义异常(带有一些枚举来帮助API用户处理所有错误)。 这是一个好习惯还是返回一个对象(内部包含布尔值,可选错误消息和错误枚举)更好?


7
在数据库中使用位掩码的优缺点
不久前,我与同事交谈,他绝对反对使用位掩码,因为很难理解存储在数据库中的所有值。我认为使用它们(例如确定当前用户的角色)并不总是一个坏主意。否则,您需要将其存储在单独的表中,这将导致另一个JOIN。如果我错了,你能告诉我吗?使用位掩码还有其他副作用,优点/缺点吗?

1
“ exit(-1)”来自哪里?
我看到在建议使用在互联网上有很多传统的软件和坏的教程exit(-1),return -1或类似的表示“异常终止”。问题是,至少在POSIX中,该问题-1从未存在过,并且不是有效的状态码。man 3 exit说明了exit()将的值返回status & 0377给父对象,即-1变为255。在非POSIX系统上,EXIT_FAILURE建议可移植。但是我从没看到“ -1表示异常终止”和“ EXIT_FAILURE可能不是1”,这表明他们清楚地相信“ -1”即使在非POSIX系统上也是常规的。 这是一个StackOverflow问题的例子,这个问题可以永久存在。软件“ unrealircd”也是exit(-1)用于终止程序的程序示例。实际上,这使与的交互变得困难systemd。 这种反模式是从哪里来的?在某些情况下有效吗?

5
我们应该在线托管代码吗?
我们正在我的工作场所中寻找良好的源代码控制和项目管理解决方案,我建议创建一个GitHub组织和私有存储库。我之所以喜欢GitHub有很多原因,但这并不是关于GitHub的事实(事实上,我的同事们会提出支持竞争平台的观点),而是关于在线存储我们的私有代码。 我试图了解这是否是一个好主意。这显然是有优势的,因为它消除了服务器成本(至少直接),并且使代码搜索(所有内容都在线)更加容易。 但是我们的团队还没有定论,这使我想到我的问题,为了做出这个决定,我们应该考虑什么?

7
结对编程可能有哪些缺点?[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 3年前关闭。 结对编程在当今非常有名。 它具有以下优点: 错误较少的程序。 后期制作维护成本要少得多。 既定的做法受到挑战,导致出现新的想法。 程序员可以互相学习。 程序员发展软技能。 但是结对编程的缺点是什么?

7
“ Set”是否应具有Get方法?
让我们拥有这个C#类(在Java中几乎相同) public class MyClass { public string A {get; set;} public string B {get; set;} public override bool Equals(object obj) { var item = obj as MyClass; if (item == null || this.A == null || item.A == null) { return false; } return this.A.equals(item.A); } public override int GetHashCode() …

7
在.NET中实现DI的“正确”方法是什么?
我希望在相对较大的应用程序中实现依赖注入,但是对此没有经验。我研究了概念和可用的IoC和依赖注入程序的一些实现,例如Unity和Ninject。但是,有一件事让我难以理解。如何在应用程序中组织实例创建? 我正在考虑的是,我可以创建一些特定的工厂,其中将包含为某些特定的类类型创建对象的逻辑。基本上是一个静态类,带有一个调用此类中静态内核实例的Ninject Get()方法的方法。 它是在我的应用程序中实现依赖注入的正确方法还是我应该根据其他原则实现它?

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.