Questions tagged «architecture»

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

11
被多线程错误困扰
在我管理的新团队中,我们的大部分代码是平台,TCP套接字和http网络代码。所有C ++。其中大多数来自离开团队的其他开发人员。团队中目前的开发人员非常聪明,但从经验来看大多是初级的。 我们最大的问题:多线程并发错误。我们的大多数类库都通过使用某些线程池类而被编写为异步的。类库中的方法通常将长时间运行的任务从一个线程排队到线程池中,然后在另一个线程上调用该类的回调方法。结果,我们有很多涉及错误线程假设的边缘错误。这导致了一些细微的错误,这些错误不仅仅具有关键部分和锁以防止并发问题。 使这些问题更难解决的是,修复尝试通常是不正确的。我发现团队在尝试(或在遗留代码本身中)尝试犯的一些错误包括以下内容: 常见错误#1-通过仅对共享数据进行锁定来解决并发问题,但是忘记了当方法未按预期顺序调用时会发生什么情况。这是一个非常简单的示例: void Foo::OnHttpRequestComplete(statuscode status) { m_pBar->DoSomethingImportant(status); } void Foo::Shutdown() { m_pBar->Cleanup(); delete m_pBar; m_pBar=nullptr; } 因此,现在有了一个错误,其中在OnHttpNetworkRequestComplete发生时可以调用Shutdown。测试人员找到错误,捕获故障转储,并将错误分配给开发人员。他反过来修复了这样的错误。 void Foo::OnHttpRequestComplete(statuscode status) { AutoLock lock(m_cs); m_pBar->DoSomethingImportant(status); } void Foo::Shutdown() { AutoLock lock(m_cs); m_pBar->Cleanup(); delete m_pBar; m_pBar=nullptr; } 除非您意识到还有一个更微妙的边缘情况,否则上面的修补程序看起来不错。如果在调用OnHttpRequestComplete 之前调用Shutdown,会发生什么情况?我的团队拥有的真实示例更加复杂,并且在代码审查过程中很难发现边缘情况。 常见错误#2-通过盲目退出锁来解决死锁问题,等待另一个线程完成,然后重新进入锁-但是没有处理对象只是被另一个线程更新的情况! 常见错误#3-即使对象是引用计数,关闭序列也会“释放”它的指针。但是忘记等待仍在运行的线程释放它的实例。这样,组件将完全关闭,然后在不希望再有任何调用的状态下在对象上调用伪造或较晚的回调。 还有其他边缘情况,但最重要的是: 即使对于聪明人,多线程编程也很难。 当我发现这些错误时,我会花时间与每个开发人员讨论这些错误,以开发更合适的修复程序。但是我怀疑,由于“正确的”解决方案涉及到大量遗留代码,因此他们常常对如何解决每个问题感到困惑。 我们将很快发货,并且我确定我们正在应用的补丁将在即将发布的版本中保留。之后,我们将有一些时间来改善代码库并在需要时进行重构。我们将没有时间重新编写所有内容。而且大多数代码还不错。但是我希望重构代码,以便可以完全避免线程问题。 我正在考虑的一种方法是这种方法。对于每个重要的平台功能,请使用专用的单线程,将所有事件和网络回调整理到其中。与Windows中使用消息循环的COM公寓线程相似。长阻塞操作仍然可以分派到工作池线程,但是完成回调在组件的线程上调用。组件甚至可能共享同一线程。然后,可以在单个线程世界的假设下编写线程中运行的所有类库。 在走这条路之前,如果还有其他标准技术或设计模式来处理多线程问题,我也非常感兴趣。我必须强调-除了描述互斥量和信号量基础知识的书以外的内容。你怎么看? 我也对其他用于重构过程的方法感兴趣。包括以下任何一项: 有关线程周围设计模式的文献或论文。除了互斥量和信号量介绍之外,还有其他内容。我们也不需要大规模的并行性,只需设计对象模型以正确处理来自其他线程的异步事件的方法即可。 …

4
微服务和数据存储
我正在考虑将整体式REST API移至微服务体系结构,并且对数据存储有些困惑。如我所见,微服务的一些好处是: 水平可伸缩-我可以运行微服务的多个冗余副本以应对负载和/或服务器故障。 松散耦合-我可以更改微服务的内部实现而不必更改其他服务,并且我可以独立部署和更改它们等。 我的问题是数据存储。在我看来,有几种选择: 所有微服务共享一个数据库服务-这似乎完全消除了松耦合的任何好处。 每个微服务上的本地安装的数据库实例-我看不到横向扩展此方法的方法,因此我认为这不是一个选择。 每个微服务都有自己的数据库服务-这似乎是最有前途的,因为它保留了松散耦合和水平扩展的优势(使用冗余数据库副本和/或跨多个分片) 在我看来,第三种选择似乎是唯一的选择,但是对我来说,这似乎是难以置信的沉重负担,并且是一种过度设计的解决方案。如果我理解正确,那么对于具有4-5个微服务的简单应用程序,我将必须运行16-20台服务器-每个微服务两个实际的微服务实例(以防服务器故障,并且在不停机的情况下进行部署),以及每个微服务有两个数据库服务实例(如果发生服务器故障等)。 坦率地说,这似乎有些荒谬。要记住,一个现实的项目可能会提供4-5个以上的服务,而16-20个服务器运行一个简单的API,该不该?我是否缺少一些基本的概念来解释这一点? 回答时可能会有所帮助的一些事情: 我是该项目的唯一开发人员,并将在可预见的将来。 我正在使用Node.js和MongoDB,但是我对与语言无关的答案很感兴趣-一个答案甚至可能是我使用了错误的技术!

2
如果不是“所有非第三方代码”,“业务逻辑”实际上意味着什么?
我听说人们经常在工作中和在线上谈论业务逻辑,并且我已经在此站点上阅读了一些有关它的问题,但是这个词对我来说仍然没有多大意义。例如,以下是我经常看到的一些(释义)语句: “业务逻辑是程序中编码实际业务规则的部分。” 我读过的大多数定义都是这样的循环定义。 “业务逻辑是您的特定应用程序所独有的一切。” 我不认为这与“您的特定应用程序不过是业务逻辑”有什么不同,除非我们不小心重新发明了一些轮子,可以使用现有的第三方软件。因此,问题标题。 “在数据访问层上方和GUI层下方应该有一个业务逻辑层。” 在我编写的代码中,数据库访问者必须知道他们应该访问什么数据,UI代码必须知道很多关于其显示内容的信息才能正确显示,这之间没有任何实际要做的事情。除了在客户端和服务器之间传递数据Blob之外,还有这两个地方。那么,实际上应该放入业务逻辑层的内容是什么? “业务逻辑应与表示逻辑分开。” 我们收到的大多数功能请求都是出于业务原因更改展示逻辑。如果业务规则之一是默认情况下以32位符号显示美国政府债券价格(同时还为用户提供配置UI的功能),则表示逻辑至少需要知道该规则存在(如果未完全实现)。而且,UX设计的主要部分似乎是帮助用户了解我们的软件试图实现的业务规则。 我是否有可能实际上只在一个只包含业务逻辑的团队中工作,而所有非业务逻辑都由其他团队来完成?还是“业务逻辑”作为一个单独实体的整个概念仅适用于某些应用程序或体系结构? 为了使答案更具体:假设您必须重新实现Domino的Pizza应用程序。什么是业务逻辑,该应用程序的非业务逻辑是什么?以及如何在不将大多数披萨信息渗入数据访问和表示层的情况下,将披萨订购业务逻辑放入其自己的代码“层”中? 更新:我得出的结论是,我的团队可能正在执行90%的UI代码,并且您所称的大多数(但不是全部)业务逻辑都来自其他团队或公司。基本上,我们的应用程序是用于监视财务数据以及几乎所有功能都是用户自定义其所见以及所见方式的方式。没有进行买卖(尽管我们与公司的其他应用程序进行了一些集成),并且实际数据由大量外部资源提供。但是我们确实允许用户执行诸如将其“监视器”的副本发送给其他用户之类的事情,因此我们处理方式的详细信息可能符合业务逻辑。实际上,目前有一个移动应用程序正在与我们的一些后端代码进行对话,并且我确切地知道我希望在理想的世界中与我们的UI共享前端代码的哪一部分(基本上是准MVC中的M),因此我猜这就是我们的BLL。 我接受user61852的回答,因为它使我对“业务逻辑”指的是和不指的有更具体的了解。

7
解决主键不属于您的业务领域的事实
在几乎所有情况下,主键都不是您的业务领域的一部分。当然,您可能会拥有一些具有唯一索引的重要的面向用户的对象(UserName针对用户或OrderNumber订单),但是在大多数情况下,除了单个或多个值外,无需通过单个值或一组值公开标识域对象。管理用户。即使在那些特殊情况下,尤其是在使用全局唯一标识符(GUID)的情况下,您也会希望或希望使用备用键而不是公开主键本身。 因此,如果我对域驱动设计的理解是准确的,则不需要主键,因此也不必公开主键,这是很好的方法。他们很丑,使我的风格狭窄。但是,如果我们选择在域模型中不包括主键,则会产生以下结果: 天真的,仅从域模型组合中得出的数据传输对象(DTO)将没有主键 传入的DTO将没有主键 因此,可以肯定地说,如果您真的要保持纯洁并在域模型中消除主键,那么您应该准备能够根据该主键上的唯一索引来处理每个请求吗? 换句话说,在删除领域模型中的PK之后,下列哪种解决方案是处理识别特定对象的正确方法? 能够通过其他属性识别需要处理的对象 在DTO中获取主键;即,从持久性映射到域时消除PK,然后从域映射到DTO时重新组合PK? 编辑:让我们具体化。 说我的域模型VoIPProvider,其中包括像场Name,Description,URL,以及引用喜欢ProviderType,PhysicalAddress和Transactions。 现在让我们说我想构建一个允许特权用户管理VoIPProvider的Web服务。 在这种情况下,用户友好的ID可能没有用;毕竟,VoIP提供商是出于商业原因其名称在计算机意义上趋于不同甚至在人性意义上趋于不同的公司。因此,可以说一个唯一VoIPProvider性完全由决定(Name, URL)。因此,现在让我们说我需要一种方法,PUT api/providers/voip以便特权用户可以更新VoIP提供程序。他们发送一个VoIPProviderDTO,其中包括的很多但不是全部字段VoIPProvider,包括可能会展平的字段。但是,我看不懂他们的想法,他们仍然需要告诉我我们正在谈论的提供商。 看来我有2个(也许3个)选项: 在我的域模型中包含主键或备用键,并将其发送给DTO,反之亦然 通过唯一索引确定我们关注的提供商,例如 (Name, Url) 引入某种总是可以在持久层,域和DTO之间映射的中间对象,而不会暴露有关持久层的实现细节-例如,在从域到DTO并返回时引入内存中的临时标识符,

7
HTML5,本机和混合移动应用程序方法的优缺点是什么?
我想开发一个移动应用程序。我最近在Telerik论坛上阅读了一篇文章,该文章比较了三种类型的移动应用程序,但我不知道应该选择哪种类型。这是一张描述不同移动设计选择的利弊的图像 为了在这些设计选择之间做出决定,我想更好地理解图中列出的每种体系结构选择的利弊。每种架构方法的优缺点是什么?

3
多线程应用程序的UML图
对于单线程应用程序,我喜欢使用类图来概述该应用程序的体系结构。但是,在尝试了解大量的多线程/并发应用程序时,这种类型的图并不是很有用,例如,因为类的不同实例在不同的线程上“处于活动状态”(意味着访问一个实例仅从一个实例中保存)线程继续存在)。因此,类之间的关联并不一定意味着我可以在那些对象上调用方法,而是必须在目标对象的线程上进行该调用。 我在该主题上挖掘过的大多数文献 ,例如Hassan Gomaa的UML设计并发,分布式和实时应用程序,都有一些不错的主意,例如将线程边界绘制到对象图中,但总体而言似乎有点学术性和冗长性真的很有用。 我不想将这些图用作问题域的高级视图,而只是作为我的类/对象,它们之间的相互作用以及我上面提到的线程边界所造成的限制的详细描述。 因此,我想知道: 您发现哪种类型的图对理解多线程应用程序最有帮助? 对经典UML的扩展是否考虑了多线程应用程序的特殊性,例如通过说明 有些对象可能生活在某个线程中,而另一些对象则没有线程亲和性; 对象的某些字段可以从任何线程读取,但只能从一个线程写入。 有些方法是同步的并返回结果,而另一些方法则是异步的,这些方法使请求排队,并例如通过不同线程上的回调返回结果。

4
在MVC中,模型应处理验证吗?
我正在尝试重新构造为使用MVC模式开发的Web应用程序,但是我不确定是否应在模型中处理验证。例如,我正在建立一个这样的模型: class AM_Products extends AM_Object { public function save( $new_data = array() ) { // Save code } } 第一个问题:所以我想知道我的save方法是否应该在$ new_data上调用验证函数,或者假设数据已经被验证? 另外,如果要提供验证,我在想一些定义数据类型的模型代码看起来像这样: class AM_Products extends AM_Object { protected function init() // Called by __construct in AM_Object { // This would match up to the database column `age` register_property( 'age', 'Age', …
25 architecture  mvc 

8
可以使用什么软件来创建架构图?[关闭]
关闭。这个问题是题外话。它当前不接受答案。 想改善这个问题吗? 更新问题,使它成为软件工程堆栈交换的主题。 6年前关闭。 已锁定。该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 当我需要能够将图保存在某处并稍后进行编辑时,我将MS Visio用于大部分设计/架构工作。我不是Visio的最大粉丝,但是它可以完成工作(而且工作是免费的)。 我想知道你们是否曾经使用过并且感到满意的相当昂贵的Visio软件的替代品,甚至更好的东西。我当然希望在我的工具箱中有该程序!

6
为什么LMAX的团队为什么要使用Java并设计架构以避免不惜一切代价避免GC?
为什么LMAX的团队为什么要用Java 设计LMAX Disruptor,但所有设计都着眼于最大限度地减少GC使用?如果不想运行GC,那么为什么要使用垃圾回收语言? 他们的优化,硬件知识水平和他们的想法都很棒,但是为什么要使用Java? 我不反对Java或其他任何东西,但是为什么要使用GC语言?为什么不使用不带GC的D之类的语言或其他语言却允许高效的代码呢?是团队最熟悉Java还是Java拥有我没有看到的某些独特优势? 假设他们使用带有手动内存管理功能的D进行开发,会有什么区别?他们将不得不考虑低级(他们已经是),但是他们可以从系统本身中榨取最佳性能。

2
我们有一个大型的Ruby on Rails应用程序(每月有2500万用户),我们的管理层决定在Node.js中重写,我疯了吗?
请告诉我是否: Node.js将使我们的网站更快! Node.js将消耗更少的服务器资源,我们可以节省金钱! Node.js将使我们的生产力更高! Node.js意味着我们可以共享客户端和服务器端JavaScript代码。 为了澄清起见,我们正在重写前端服务器,该前端服务器将作为API与我们现有的Ruby on Rails应用程序通信。同时,我们将Ruby on Rails应用程序重构为服务。 现有架构的更多详细信息: Memcached用于HTML部分缓存 Redis用于会话和一些结构化数据缓存 MySQL单主机,多从机 有一张大桌子可以接受大量写操作(想象一个民意测验) 否则大多读。 MongoDB中的一些元数据 Ruby on Rails 3.0 Nginx和独角兽


2
Web开发的替代模式?(非MVC)[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 4年前关闭。 最近,我一直在阅读有关MVC及其与网络不兼容的博客文章。我了解了RMR体系结构之类的替代模式。 我很好奇,除了MVC,人们还在网上使用其他哪些模式?另外,如果有实现该模式的框架,请发布其链接。

3
授权在分层体系结构中适合什么地方?
通常,我将授权决策放置在服务器端控制器中。这些最近是RESTful端点,但我认为MVC类型架构也是如此。为了争论起见,假设它是基于角色的授权。将对受保护的方法进行注释,或者进行检查并在必要时返回403s。 现在,考虑到授权实际上是一条业务规则-例如,“只有管理员可以列出X”,我认为应该将它们推到下一层。当控制器要求业务层执行操作时,服务或业务层会通知控制器未经授权。 这是合理的方法吗?这有缺点吗? 我不愿意拥有一个AuthorizationService,该服务本质上包含一堆静态过程编码规则来执行此操作,但是将所有访问逻辑都放在一个地方也许很有意义。是否应该将跨领域关注点分开? 因此,我想问是否有人做到这一点,以及他们如何以一种干净的方式实现它,或者是否有我可以阅读的好资源。我正在使用Java fwiw,但这是一个与语言无关的问题。 我已经在这里检查了相关的问题,它们在地面和答案上都很薄。例如:域模型中的验证和授权,并将其通过服务层传送到MVC 我正在阅读Spring安全文档,这些文档将其作为一个跨领域的关注点,因此提出了很好的论据,但是我担心这只是“春天的方式”,并且希望有更广阔的视野。它还将您的应用程序绑定到特定框架。

5
封装ORM逻辑的存储库模式的替代方案?
我只需要切换一个ORM,这是一个相对艰巨的任务,因为查询逻辑到处都有泄漏。如果我不得不开发一个新的应用程序,我个人的喜好是封装所有查询逻辑(使用ORM)以对它进行将来的更改。存储库模式很难编码和维护,因此我想知道是否还有其他模式可以解决问题? 我可以预见到有关在实际需要时不增加额外复杂性,敏捷性等方面的帖子,但是我只对以更简单的方式解决类似问题的现有模式感兴趣。 我的第一个想法是拥有一个通用类型存储库,通过扩展方法,我可以根据需要向特定类型存储库类添加方法,但是对静态方法进行单元测试非常痛苦。IE浏览器: public static class PersonExtensions { public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep) { // logic } }

6
我是否在这种体系结构上打破了面向对象的实践?
我有一个Web应用程序。我不认为这项技术很重要。该结构是一个N层应用程序,如左图所示。共3层。 UI(MVC模式),业务逻辑层(BLL)和数据访问层(DAL) 我的问题是我的BLL非常庞大,因为它具有通过应用程序事件调用的逻辑和路径。 通过应用程序的典型流程可能是: 在UI中触发的事件遍历BLL中的方法,执行逻辑(可能在BLL的多个部分中),最终执行DAL,返回到BLL(可能还有更多逻辑),然后向UI返回一些值。 此示例中的BLL非常繁忙,我正在考虑如何将其拆分。我也有自己不喜欢的逻辑和对象。 右边的版本是我的努力。 逻辑仍然是应用程序的UI和DAL之间的流动,但也有可能没有属性...只有方法(在这一层中的大多数类可能可能是静态的,因为他们不存储任何状态)。Poco层是存在具有属性的类的地方(例如Person类,其中会有名称,年龄,身高等)。这些与应用程序的流程无关,它们仅存储状态。 流可以是: 甚至从UI触发,并将一些数据传递到UI层控制器(MVC)。这将转换原始数据并将其转换为poco模型。然后将poco模型传递到逻辑层(即BLL),最后传递到命令查询层,可能会在途中被操纵。Command查询层将POCO转换为数据库对象(几乎是同一件事,但是一个是为持久性而设计的,另一个是为前端设计的)。存储该项目,并将数据库对象返回到“命令查询”层。然后将其转换为POCO,在其中返回到逻辑层,可能进行进一步处理,然后最终返回到UI 共享逻辑和接口是我们可能拥有持久数据的地方,例如MaxNumberOf_X和TotalAllowed_X以及所有接口。 共享逻辑/接口和DAL都是体系结构的“基础”。这些人对外界一无所知。 除了共享的逻辑/接口和DAL,其他一切都与poco有关。 流程仍然与第一个示例非常相似,但是它使每一层都对一件事情负责(无论是状态,流程还是其他)……但是我是否用这种方法打破了OOP? 演示Logic和Poco的示例可能是: public class LogicClass { private ICommandQueryObject cmdQuery; public PocoA Method1(PocoB pocoB) { return cmdQuery.Save(pocoB); } /*This has no state objects, only ways to communicate with other layers such as the cmdQuery. Everything else is just …

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.