软件工程

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

2
哪些数据应存储为“声明”?
在ASP.Net Core中,我发现Claims授权不是很具体的方法。我们可以添加任何东西作为ClaimType和ClaimValue配对;组,名字,姓氏,生日,canAccessThisURI,isEditor等。但是,这种方法(存储可以存储为声明的任何内容)将构成一个巨大的声明表,其中包含50%的应用程序数据。 我想知道,作为一种好的做法,应将哪些常见数据存储为索赔?

1
模式不是构建块–因此,我不应该在MVC / MVP模式上构建应用程序吗?
我读过这个页面设计模式,并编写代码时,你应该如何对待他们。据我了解,链接标题如下: 模式不是构件。 如果我理解正确,这意味着在有意义之前不要使用设计模式,对吗?不要一开始就说要使用策略模式,请等到编写一些代码为止,如果使用策略模式对您的设计有意义,那么就使用它。 创建GUI应用程序时,是否以相同方式对待MCV / MVP模式?从各自的链接,它说这是一种建筑模式。 假设如果我创建一个GUI应用程序并且不使用MCV / MVP模式,但是我的代码是干净,可读且可维护的,那么我是否仍未使用MCV / MVP模式仍然是代码异味/不良设计? ?

4
拥有诸如yield这样的生成器语言设施是一个好主意吗?
PHP,C#,Python和可能的其他几种语言都有yield用于创建生成器函数的关键字。 在PHP中:http://php.net/manual/en/language.generators.syntax.php 在Python中:https://www.pythoncentral.io/python-generators-and-yield-keyword/ 在C#中:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/yield 我担心作为一种语言功能yield会破坏一些约定。其中之一就是我所说的“确定性”。该方法每次调用都会返回不同的结果。使用常规的非生成器函数,您可以调用它,并且如果给定相同的输入,它将返回相同的输出。使用yield时,它会根据其内部状态返回不同的输出。因此,如果您在不知道生成函数的先前状态的情况下随机调用生成函数,则不能指望它返回某个结果。 这样的功能如何适应语言范式?它实际上违反了任何约定吗?拥有并使用此功能是个好主意吗?(举例说明什么是好事,什么是坏事,goto这曾经是许多语言的功能,现在仍然是,但是它被认为是有害的,因此已经从某些语言(例如Java)中消除了)。编程语言的编译器/解释器是否必须突破任何约定才能实现此功能,例如,语言是否必须实现多线程才能使此功能正常工作,或者可以不使用线程技术来完成?

7
规避巫师和战士中的规则
在这一系列博客文章中,Eric Lippert使用向导和战士作为示例描述了面向对象设计中的问题,其中: abstract class Weapon { } sealed class Staff : Weapon { } sealed class Sword : Weapon { } abstract class Player { public Weapon Weapon { get; set; } } sealed class Wizard : Player { } sealed class Warrior : Player { } 然后添加一些规则: 战士只能使用剑。 向导只能使用人员。 …

7
我是否使我的课程过于细腻?单一责任原则应如何应用?
我编写了许多涉及三个基本步骤的代码。 从某处获取数据。 转换数据。 将该数据放在某处。 我通常最终使用三种类型的类-受它们各自的设计模式的启发。 工厂-从某些资源构建对象。 调解员-要使用工厂,执行转换,然后使用指挥官。 指挥官-将数据放在其他地方。 我的班级往往很小,通常是一个(公共)方法,例如获取数据,转换数据,执行工作,保存数据。这导致类的激增,但总体上效果很好。 我在进行测试时遇到的困难是,我最终会紧密耦合测试。例如; 工厂-从磁盘读取文件。 指挥官-将文件写入磁盘。 没有其他人,我无法测试。我可以编写其他“测试”代码来进行磁盘读/写操作,但是随后我要重复一遍。 看看.Net,File类采用了不同的方法,它将(我的)工厂和指挥官的职责结合在一起。它具有“创建”,“删除”,“存在”和“全部读取”功能。 我是否应该遵循.Net的示例并将我的类结合在一起(尤其是在处理外部资源时)?它仍然耦合了代码,但是它更具故意性-它发生在原始实现中,而不是在测试中。 我在这里是否过于狂热地应用了“单一责任原则”?我有负责读和写的单独的类。当我可以拥有一个负责处理特定资源(例如系统磁盘)的组合类时。

3
C#模式可以清晰地处理“自由功能”,避免使用Helper风格的“实用程序包”静态类
我最近正在查看一些浮动的Helper风格的“实用程序包”静态类,这些静态类围绕我使用的一些大型C#代码库进行浮动,基本上类似于以下非常简短的代码段: // Helpers.cs public static class Helpers { public static void DoSomething() {} public static void DoSomethingElse() {} } 我审查过的具体方法是 彼此之间几乎没有关系 没有明确的状态在调用之间持续存在, 小,和 每一种都由各种不相关的类型消耗。 编辑:上面的内容并非旨在列出所指控的问题。这是我正在审查的特定方法的共同特征的列表。帮助答案提供更多相关解决方案的上下文。 仅针对此问题,我将把这种方法称为GLUM(通用轻量级实用程序方法)。部分地意在“消极”的负面含义。抱歉,这是愚蠢的双关语。 即使撇开我自己对GLUM的默认怀疑态度,我也不喜欢以下内容: 静态类仅用作命名空间。 静态类标识符基本上是没有意义的。 添加新的GLUM时,要么(a)毫无理由地触摸此“ bag”类,要么(b)创建一个新的“ bag”类(这本身通常不成问题;糟糕的是,新的静态类通常只会重复不相关性问题,但方法更少。 元的命名无疑也是可怕的,非标准的,通常内部不一致,无论是Helpers,Utilities或什么的。 什么是重构的合理好简单的模式,最好解决上述问题,并且最好轻触一下? 我可能应该强调:我正在处理的所有方法都是成对的彼此无关。似乎没有一种合理的方法可以将它们分解为更细粒度但仍为多成员的静态类方法包。

6
单元测试应仅涵盖“功能性”软件
我们正在一个新的软件开发项目中使用StructureMap。团队成员之一已实现了一个单元测试,该单元测试基本上测试了StructureMap容器配置。它通过执行以下操作来做到这一点; 计算为应用程序名称空间中的类配置的程序集的实例数。 在类级别定义期望的实例 断言预期实例与找到的实例总数匹配。 断言预期实例与测试中定义的实例匹配 一个例子是; var repositories = container.GetAllInstances<IEnvironmentRepository>(); Assert.AreEqual(1, repositories .Count()); foundInstances = foundInstances + repositories .Count(); 我们还为下一节课提供“单元测试”; public MyClass(IEnvironmentRepository environmentRepository) { } 在这些测试中,我们模拟了IEnvironmentRepository,因此不会像在实时系统中那样从容器中注入它。 一位同事忽略了对结构图配置的单元测试,并带有“单元测试仅测试它自己的配置”的注释。这显然是测试的目的,我认为这是完全正确的。我要求忽略测试的人删除结构映射配置IEnvironmentRepository(仍然忽略测试)并运行完整的单元测试套件,它们都通过了。然后,我们运行了该应用程序,由于容器配置现在无效,因此该应用程序崩溃了。我认为,这证明了测试的价值,我的同事仍然不同意。他只是简单地说我们不应该测试配置,但是我认为这完全可以进行单元测试。 有很多问题; 这是有效的单元测试吗?-我们正在测试容器的配置,而不是结构图起作用(但我可以看到重叠的部分) 如果不是,您如何在不测试的情况下验证配置。您如何阻止某人意外删除所需的代码行并将其检入? MyClass单元测试是否应该IEnvironmentRepository从容器中解析出实例并传递给它?

3
在文件的开头写一些您仅在结尾知道的内容
背景:我正在编写微控制器C代码来编写EBML文件。EBML就像是带有嵌套元素的二进制XML,但是不是开始和结束标签,而是一个开始ID,长度和数据。我将其写入低功耗应用程序的外部Flash中,因此我希望将Flash的访问量降至最低。内存也很有限,因为没有一件事情容易。 当我可以将整个EBML元素保留在内存中时,生成它很容易,因为在知道长度之后,我可以返回并填写每个元素的长度。问题是当我无法将整个元素保存在内存中时该怎么办。我看到的选项是: 写出我所知道的内容,然后返回并添加长度(最简单,但是添加的闪存访问量比我想要的更多) 在开始编写每个元素之前,先计算它们的长度(相对容易,但是需要很多处理器时间) 一旦我的内存填满,就切换模式,这样我就可以继续浏览数据,但是仅是为了计算已经在内存中保留的元素的长度。然后写出内存中的内容,然后返回并继续从上次中断的地方处理数据。(到目前为止,我最喜欢的选项) 在需要编写元素且最终长度未知时,为它们提供最大或最坏情况的长度。(比上面更容易,但可能适得其反并浪费空间) 问题:看来这应该是人们思考过的相对普遍的问题。我知道在形成一些数据包时也会发生这种情况。我在这里缺少更好/更常见/更容易接受的技术吗?还是我可以搜索的一些术语?

4
在复杂的以域为中心的应用程序中,用于基本CRUD操作的DDD方法
我的公司正在从头开始重写我们的Web应用程序。它是大型企业级应用程序,在金融行业中具有复杂的领域。 我们使用ORM(实体框架)进行持久化。 本质上,我们的应用程序的一半集中在从用户那里收集原始数据,进行存储,然后包含大部分实际域逻辑的应用程序的另一半使用原始数据来创建我们的域图片,该域图片与原始数据有很大的不同原始输入,并将其传递到calc引擎,运行calcs,并吐出结果,然后将结果显示给用户。 在使用层的DDD方法中,CRUD操作似乎遍历域层。但至少在我们看来,这似乎没有道理。 例如,当用户转到编辑屏幕以更改投资帐户时,屏幕上的字段是存储在数据库中的确切字段,而不是以后用于计算的域表示形式。那么,当编辑屏幕需要数据库表示形式(原始输入)时,为什么要加载投资帐户的域表示形式呢? 在用户单击投资帐户屏幕上的“完成”,并对控制器执行POST之后,控制器现在几乎具有需要保存的投资帐户的确切数据库表示形式。但是出于某种原因,我应该加载域表示以进行修改,而不是仅将控制器模型直接映射到数据库模型(实体框架模型)? 因此,从本质上讲,我是将数据模型映射到域模型,以便可以将其映射回数据模型以持久化。这有什么意义?

3
当自然语言模棱两可时,行为驱动开发如何提高清晰度?
我目前正在探索诸如黄瓜之类的BDD测试框架,当有人说时我感到很好奇 由于功能文件使用简单的自然语言,因此可以提高清晰度并提供清晰的视野 但是,自然语言难道不是我们在软件工程中遇到的大多数麻烦的原因吗? 自然语言是模棱两可的,这就是许多软件项目由于对客户需求和开发人员的理解的错误理解而失败的原因。我没有在这里的利基。 是的,将测试分解为微小的简单可行的操作是有意义的,并且可以提供一定程度的清晰度,但这是否可以整体上提高生产率? PS:我不是专家,在这里也没有发表意见。我很好奇理解这个概念。
9 bdd  cucumber 


1
如何管理项目中的非单元测试?
我在我的项目中亲自调用tests了一些不是单元测试的代码。它们旨在运行,并且结果必须由人工评估。我这样做是因为我正在制造物理引擎,并且在开发过程中,我需要查看自己在做什么。所以我simulation在测试模块中做了一个包装。从技术上讲,这是单元测试,因为模拟使用的是单元测试库,但我并不是要像实际的单元测试一样运行它们。 我想做的是将那些特殊测试与单元测试区分开来,因为我想轻松地运行所有单元测试。我认为这有点像功能测试。您是否遇到过必须为功能测试准备应用程序的情况?功能测试准备(基本上是我的模拟测试)应该放在项目中的什么位置,以及如何将它们与单元测试区分开来? 我在Java中,因此我可以将所有方法签名从更改为@Test public void myNamedTest(),public static void main(String[] args)但是使用仿真对我来说既费力又不实用。 我junit在一个gradle项目中使用。gradle欢迎使用创建特殊测试文件夹的任何解决方案。

6
我们应该开始进行敏捷测试的哪个阶段(SCRUM)?
我的一些背景知识-在敏捷环境中,我使用SCRUM(1-2周冲刺)是手动测试人员将近2年。因此,我想在使用Selenium WebDriver(带有Java)的工作中引入自动化测试。 我的问题是在什么时候应该手动测试功能以及什么时候应该转换它们以进行自动化测试? 我一直在阅读并获得不同的方法,例如: 当开始新的Sprint时,将用户故事转换为上一个Sprint的自动化脚本,或者; 在相同的Sprint中转换用户故事。 任何建议将不胜感激。先感谢您。

5
是否可以使表示计算的长代码更易于阅读?
长方法通常被认为是不好的,但是在我的代码中,我有一些难以理解的长方法(超过50行)。我很难使这些方法更容易阅读,因为里面的一条语句已经超过了50行,而且难以理解的一条语句是使用ORM建立数据库查询来完成某些特定的工作在方法名称上明确指出。该语句之所以这么长是因为它在多个列上联接,应用多个wheres并选择多个不同的列以形成所需的文档化输出格式。 这样难读的代码是否被视为错误代码?同样,如果我为复杂的算法编写代码,导致难以理解的代码包装在一个清晰命名的方法中,那么该代码是否是错误代码?

2
我应该在服务和存储库之间使用一个层来构建干净的架构-Spring
我正在架构中,它将为Web客户端和移动应用程序提供rest api。我正在使用Spring(spring mvc,spring data jpa,... etc)。域模型使用JPA规范编码。 我正在尝试应用干净架构的一些概念(https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html)。并非全部,因为我将保留jpa域模型。 通过各层的实际流量是这样的: 前端 <-> API服务 -> 服务 -> 存储库 -> 数据库 前端:Web客户端,移动应用 API服务:Rest控制器,在这里我使用转换器和dto并调用服务 服务:与实现的接口,并且包含业务逻辑 存储库:具有自动实现的存储库接口(由spring data jpa完成),它包含CRUD操作以及一些sql查询 我的疑问:我应该在服务和存储库之间使用额外的一层吗? 我正在计划这个新流程: 前端 <-> API服务 -> 服务 -> 持久性 -> 存储库 -> 数据库 为什么要使用这个持久层?正如它在干净的体系结构文章中所说的,我希望有一个访问不可知的持久层的服务实现(业务逻辑或用例)。如果我决定使用其他“数据访问”模式,例如,如果我决定停止使用存储库,则不需要更改。 class ProductServiceImpl implements ProductService { ProductRepository productRepository; void save(Product product) { // do …

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.