Questions tagged «architecture»

软件系统的高级设计和描述。架构设计提取了实现,算法和数据表示的细节,以专注于“黑匣子”组件的交互。

11
是否可以编写不需要不断修改的软件?
我已经用许多不同的语言编写了许多软件,并且还“编写”了与使用Verilog和VHDL的FPGA一起使用的硬件。 我倾向于更喜欢编写硬件而不是编写软件,我认为主要原因之一是可以编写“完成”并且不需要修改的硬件:定义接口和功能,编写测试平台,实施硬件模块,然后使用模拟器测试其功能。然后,您可以依靠该硬件模块作为构建块来创建更大更好的产品:如果需要向该模块添加功能,则可以创建第二个模块并在其中添加功能。您永远不会丢掉原始模块,因为它可以正常工作并且仍然有用。 我对软件的主要不满之一是它永远不会“完成”。总有另一个功能要添加。通常,添加功能时会在以前正常工作的其他地方引入错误。只要不违反接口,在硬件中就不会发生这种情况。 明确地说,我并不是在建议使用某些功能列表来构建某个版本,而仅此而已:永远是这样:我赞成随着时间的推移进行迭代和发行多个版本以添加新功能。我只是不想在左侧戳代码而在右侧找到错误,而这似乎是在添加新功能之后发生的。 是否可以通过类似于“编写”硬件的方式来编写软件?有没有一种好的软件开发方法,可以始终取得向前的进展,并允许添加新功能而无需重写现有代码和引入新的错误?

4
如何显着提高Java性能?
LMAX团队进行了有关如何在不到1毫秒的延迟时间内完成100k TPS的演示。他们通过博客,技术论文(PDF)和源代码本身来备份该演示文稿。 最近,马丁·福勒(Martin Fowler)发表了一篇有关LMAX架构的出色论文,并提到他们现在每秒能够处理600万个订单,并着重介绍了该团队为提高性能而采取的一些步骤。 到目前为止,我已经解释了业务逻辑处理器速度的关键是在内存中按顺序进行所有操作。这样做(并没有真正愚蠢的事情)允许开发人员编写可处理10K TPS的代码。 然后,他们发现专注于良好代码的简单元素可以将其带入100K TPS范围。这只需要精心构造的代码和小的方法-本质上,这使Hotspot可以更好地进行优化,并使CPU在运行代码时更高效地缓存代码。 提升另一个数量级需要更多的技巧。LMAX团队发现有几件有助于实现目标的方法。一种是编写Java集合的自定义实现,这些实现被设计为对缓存友好并且谨慎处理垃圾。 达到最高性能水平的另一种技术是将注意力放在性能测试上。长期以来,我一直注意到人们在谈论提高性能的技术,但是真正起作用的一件事就是对其进行测试 福勒提到发现了几件事情,但他只提到了几件。 是否还有其他架构,库,技术或“事物”有助于达到这样的性能水平?

1
拆分一个大项目以创建一个多模块Maven项目
我正在开发一个Spring-MVC应用程序,其中我们使用Maven进行依赖项管理。由于项目规模很大,我们正在考虑将项目分为几个部分。我有一些疑问,希望能在这里得到答案。 当前,我们正在ROOT.war服务器上的Apache tomcat上部署单个WAR文件。由于项目规模很大,因此Web应用程序中包括通知和电子邮件,第三方服务,PUSH(Cometd),REST API等组件。目前,它们都是相互依存的,相互依赖。例如,Notification对象也取决于Person对象,因为通知是为用户量身定制的。 拆分大项目的主要目的是能够在单个模块上工作,进行错误修复,添加功能,进行测试等。如果满意,则只能在服务器上替换此模块,而不是整个应用程序。这可能吗? 如前所述,对象之间存在依赖关系和映射。如何在不同的子模块之间进行管理,或者只是将import语句更改为包括其他项目? 如我所说,其目的是在单个模块上工作并能够部署它们(最好是热的)。目前,我们只有一个WAR文件,如ROOT.war。拆分会创建多个war文件,然后将其称为URL domain-name.com/module_name/some_mapping吗? 我目前正在检查文档,但这是我们要使用Maven提供的多模块要实现的主要目标,并且想知道这是否可行。如果需要更多信息,请告诉我。 目前,我正在使用Spring的父POM,如下所示: <parent> <groupId>io.spring.platform</groupId> <artifactId>platform-bom</artifactId> <version>1.1.3.RELEASE</version> <relativePath /> </parent>

5
Bob Martin的“ Clean Architecture”是所有架构的经验法则还是只是其中之一?
我非常喜欢Bob Martin叔叔的视频“清洁建筑的原理”中的概念。但是我觉得这种模式就像是抽象工厂和生成器模式的组合核心。 这是编写好的程序的一种方法,但不是唯一的方法。 Rails和reactjs是想到的两个框架,它们不会促进这种干净的体系结构。Rails希望您的业务逻辑出现在模型中(FatModels和SkinnyControllers),并在组件内部做出反应。两种方法都将业务逻辑和框架代码紧密结合在一起。 我没有发现这3种方式中的任何错误。这是一个选择任何人的判断电话。 但是在视频中,我觉得他建议干净的架构应该在业务逻辑和框架之间有明确的界限。框架(网页,Android等)应该是插件,插件中的业务逻辑。他甚至在视频中巧妙地嘲弄了轨道。 那么,鲍勃·马丁(Bob Martin)的“清洁架构”是否是所有架构的经验法则,还是只是其中一种选择?

4
动态和静态语言之间的架构差异
在设计将基于静态语言(例如C#或Java)和动态语言(例如Ruby或Python)构建的应用程序时,在体系结构上是否存在重大差异? 哪一种设计可能对某一种类型是好的选择而对另一种却是不好的呢?一种类型可以实现任何其他类型都不能实现的有用功能(当然在设计和体系结构上)? 另外,是否有任何动态特定的设计模式?

3
什么时候应该将类或模块放在单独的Assembly / DLL中?
是否有任何准则来决定何时将一个类放在其自己的程序集中/ DLL中?我经常看到两种思想流派: 1)每个类的“分组”都属于其自己的DLL,例如存储库,服务,DTO,基础结构等。 2)一切都应在单个DLL中,但应通过名称空间/文件夹分开,例如,具有“ Core” DLL以及其他名称空间,例如Core.Repositories,Core.Services,Core.DTO等。 在工作中,我们将所有组件都集中在一个称为“业务”的程序集中。有一些文件夹,但没有真正的分离-业务对象(带有逻辑,其中一些甚至不应该是类)被放在“ BusinessObjects”文件夹中而不用管。多个类中使用的内容位于“ Core”文件夹中。实用程序位于“实用程序”文件夹中,数据访问基础结构位于“数据”文件夹中-您就明白了。 对于我正在使用的新模块,我希望/需要一个单独的数据访问层(认为是基本的存储库实现),但我不想将其与其他160个一起放到“ BusinessObjects”文件夹下!在那里上课。同时,我担心创建一个新的类库,因为每个人都习惯于将一个类填充到单个库中。文件夹/命名空间可以工作。


3
API与前端与后端之间的区别
我正在尝试编写一个“标准”商业网站。所谓“标准”,是指该站点在前端,后端(用于处理内容)运行常规的HTML5,CSS和Javascript,并在数据库中运行MySQL。这是一个基本的CRUD网站:前端几乎可以存储数据库中存储的所有内容;不论用户输入什么,后端都会将其写入数据库并进行一些处理。就像大多数网站一样。 创建我的Github存储库以开始编码时,我意识到我不了解前端后端和API之间的区别。解决我的问题的另一种方式是:API进入这张图片的位置是什么? 我将列出更多详细信息,然后列出我要提出的问题-希望这会使你们对我的实际问题有更好的了解,因为我很困惑,以至于我不知道要问的具体问题。 一些更多的细节: 我想尝试Model-View-Controller模式。我不知道这是否会改变问题/答案。 该API将是RESTful 我希望后端使用自己的API,而不是允许后端作弊并调用特殊查询。我认为这种风格更加一致。 我的问题: 前端是否调用调用API的后端?还是前端只是调用API而不是调用后端? 后端是否仅执行API,并且该API将控制权返回给后端(其中后端充当最终的控制器,委派任务)? 建议使用详尽详尽的答案来解释API与前端后端的作用。如果答案取决于编程模型(除Model-View-Controller模式以外的模型),请描述API的这些其他思考方式。谢谢。我很困惑

3
在C#中这种明显的自引用的目的是什么?
我正在评估一个名为Piranha(http://piranhacms.org/)的开源CMS ,以便在我的一个项目中使用。至少对于我来说,我发现以下代码有趣且有点混乱。可以帮助我理解为什么类从相同类型的基类继承吗? public abstract class BasePage<T> : Page<T> where T : BasePage<T> { /// <summary> /// Gets/sets the page heading. /// </summary> [Region(SortOrder = 0)] public Regions.PageHeading Heading { get; set; } } 如果BasePage<T>要定义的类,为什么要继承Page<T> where T: BasePage<T>?它有什么具体目的?
21 c#  architecture  .net  cms 

4
有什么方法可以避免域类和SQL查询之间的逻辑重复?
下面的示例完全是人为的,其唯一目的是使我理解我的观点。 假设我有一个SQL表: CREATE TABLE rectangles ( width int, height int ); 域类: public class Rectangle { private int width; private int height; /* My business logic */ public int area() { return width * height; } } 现在假设我有一个要求向用户显示数据库中所有矩形的总面积。我可以通过获取表的所有行,将它们变成对象并对其进行迭代来做到这一点。但这看起来很愚蠢,因为我的桌子上有很多矩形。 所以我这样做: SELECT sum(r.width * r.height) FROM rectangles r 这很容易,快速并且利用了数据库的优势。但是,它引入了重复的逻辑,因为我的域类中的计算也相同。 当然,对于这个例子,逻辑的重复根本不是致命的。但是,我的其他域类也面临同样的问题,它们更为复杂。

9
在敏捷开发中,我应该在数据库之前尝试在平面文件中进行持久化吗?
有人向我解释说,由于在敏捷开发中,策略和应用程序逻辑应该比持久性方法之类的细节更为重要,因此持久性决策应该在最后做出。因此,从简单的持久性(例如平面文件)开始可能是一个好主意,直​​到我们意识到该方法的弱点显而易见,然后才更改持久性(例如,使用关系数据库)。 这是真的吗?还是我误解了这个概念?这是敏捷团队通常如何构建应用程序吗?有什么理由?何时不应该采用这种方法?

4
以函数为参数的函数是否还应该以那些函数的参数为​​参数?
我经常发现自己编写的函数看起来像这样,因为它们使我可以轻松地模拟数据访问,并且仍然提供一个接受参数的签名来确定要访问的数据。 public static string GetFormattedRate( Func<string, RateType>> getRate, string rateKey) { var rate = getRate(rateKey); var formattedRate = rate.DollarsPerMonth.ToString("C0"); return formattedRate; } 要么 public static string GetFormattedRate( Func<RateType, string> formatRate, Func<string, RateType>> getRate, string rateKey) { var rate = getRate(rateKey); var formattedRate = formatRate(rate); return formattedRate; } 然后我用它像这样: using FormatterModule; …

5
与在代码中完成所有工作相比,对软件系统进行建模有什么好处?
我认识的大多数(如果不是全部)IT人员相信,在编码之前使用UML或其他类型的图对软件进行建模是有益的。(我的问题不是专门关于UML的,它可以是软件设计的任何图形或文本描述。) 我不太确定。主要原因是:代码没有说谎。它由编译器或解释器检查。希望它具有自动化测试,并且需要通过静态代码分析。如果一个模块不能与另一个模块正确连接,则在代码中通常很明显,因为会收到一条错误消息。 使用图表和其他文档无法完成所有这些操作。是的,有些工具可以检查UML,但是到目前为止,我所看到的一切都非常有限。因此,这些文档往往不完整,不一致或简单。 即使图本身是一致的,您也不能确定代码是否实际实现了它们。是的,有代码生成器,但是它们从不生成所有代码。 我有时会觉得对建模结果的痴迷是因为这样的假设,即代码不可避免地必须是一些不可理解的混乱,而建筑师,设计师或其他掌握高薪的高薪人士则不必处理这些混乱。否则,它将变得太昂贵。因此,所有设计决策都应远离代码。代码本身应该留给能够写(甚至可以读)但不必处理其他任何东西的专家(代码猴子)。当汇编程序是唯一的选择时,这可能很有意义,但是现代语言允许您以很高的抽象水平进行编码。因此,我真的不再需要建模。 我缺少用于建模软件系统的哪些论据? 顺便说一句,我相信图是一个伟大的方式来记录和沟通软件设计的某些方面,但是,这并不意味着我们应该立足于他们的软件设计。 澄清: 由于不清楚,这个问题被搁置了。因此,让我添加一些解释: 我在问使用将软件建模的(非代码)文档作为有关软件设计的主要事实来源是否有意义。我没有想到从这些文档中自动生成很大一部分代码的情况。如果是这种情况,我会将文档本身视为源代码,而不是模型。 我列出了此过程的一些缺点,这使我想知道为什么有这么多人(以我的经验)认为它是进行软件设计的首选方法。

11
应该始终使用编码最佳实践吗?
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 在对软件进行编码时,对于正在构建的应用程序,体系结构应该始终是最佳实践还是实践? 如果我要构建一个两页的Web应用程序,该应用程序可能会使用5年,并且在那5年中有2项改进,那么我应该编写依赖注入,设计模式,带有视图模型的model-view-controller等代码吗?

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块临时替换“默认类”属性,然后将其还原。使用类引用变量执行此操作要简单得多,而不是使用泛型即可完成。

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.