精华内容
下载资源
问答
  • 对上下文起着什么作用
    千次阅读
    2020-02-04 17:39:16

           随着微服务的流行,项目工程往往有很多子系统组成,涉及的面也是比较广的。如何根据业务划分系统功能,限界上下文Context,非常重要,而限界上下文之间的关系有哪些呢?俯视,正视,宏观把握系统是非常重要的,掌握每个角色的作用,也非常重要。看下:


           1,合作关系(Partnership):如果两个限界上下文的团队要么一起成功,要门一起失败,此时他们需要建立起一种合作关系。他们需要一起协调开发计划和集成管理。两个团队应该在接口的演化上进行合作以同时满足两个系统的需求。应该为相互关联的软件功能制定好计划表,这样可以确保这些功能在同一个发布中完成。

           2,共享内核(Shared Kernel):对模型和代码的共享将产生一种紧密的依赖性,对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显示的边界,并保持共享内核的小型化。共享内核具有特殊的状态,在没有与另一个团队协商的情况下,这种状态是不能改变的。我们应该引入一种持续集成过程来保证共享内核与通用语言的一致性。

           3,客户方-供应方开发(Customer-Supplier Development):当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。因此,在上游团队的计划中,我们应该顾及到下游团第的需求。

           4,尊奉者(Conformist):在存在上游-下游关系的两个团队中,如果上游团队已经没有动力提供下游团队之所需,下游团队便孤军无助了。出于利他主义,上游团队可能向下游团队做出种种承诺,但是有很大的可能是:这些承诺是无法实现。下游团队只能盲目地使用上游团队的模型。

           5,防腐层(Anticorruption Layer):在集成两个设计良好的限界上下文时,翻译层可能很简单,甚至可以很优雅地实现。 但是,当共享内核、合作关系或客户方-供应方关系无法顺利实现时,此时的翻译将变得复杂。对于下游客户来说,你需要根据自己的领域模型创建一个单独的层,该层作为上游系统的委派向你的系统提供功能。防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无须修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转换。

           6,开放主机服务(Open Host Service):定义一种协议,让你的子系统通过协议来访问你的服务。你需要将该协议公开,这样任何想与你集成的人都可以使用该协议。再有新的集成需求时,你应该对协议进行改进或者扩展。对于一些特殊的需求,你可以采用一次性的翻译予以处理,这样可以保持协议的简单和连贯性。

           7,发布语言(Published Language):在两个限界上下文之间翻译模型需要一种公用哦的语言。此时你应该使用一种发布出来的共享语言来完成集成交流。发布语言通常与开放服务一起使用。

           8,另谋出路(SeparateWay):在确定需求时,我们应该做到坚决彻底。如果两套功能没有显著的关系,那么它们是可以被完全解耦的。集成总是昂贵的,有时带给你的好处也不大。声明两个限界上下文之间不存在任何关系,这样使得开发者去另外寻找简单的、专门的方法来解决问题。

           9,大泥球(Big ball of Mud):当我们检查已有系统时,经常会发现系统中存在混杂在一起的模型,他们之间的边界是非常模糊的。此时你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。在这个边界之内,不要试图使用复杂的建模手段来化解问题。同时,这样的系统有可能会向其他系统蔓延,你应该保持警觉。

             可以多思考这些关系,自己处在什么位置,自己的项目处在什么位置,又怎么更好的去应对这些……

              内容来自于:《实现领域驱动设计》

    更多相关内容
  • DDD—上下文映射图

    千次阅读 2019-11-17 16:34:22
    一个项目的上下文映射图(Context Map)可以用两种方式表示, (1)比较容易的一种是画一个...1、上下文映射图为什么重要 在开始采用DDD时,首先应该为你当前的项目绘制一个上下文映射图,其中应该包含你项目中当...

    一个项目的上下文映射图(Context Map)可以用两种方式表示,
    (1)比较容易的一种是画一个简单的框图来表示两个或多个限界上下文之间的映射关系。该框图表示了不同的限界上下文在解决方案空间中是如何通过集成相互关联的。

    (2)另一种更详细的方式通过限界上下文集成的源代码实现来表示。

    1、上下文映射图为什么重要

    在开始采用DDD时,首先应该为你当前的项目绘制一个上下文映射图,其中应该包含你项目中当前的限界上下文和它们之间的集成关系。下图表示一个抽象的上下文映射图,后文将不断地向里面添加细节内容。

    在这里插入图片描述

    比如,当你为一个大型企业进行限界上下文之间的集成时,你可能需要与大泥球进行交互。大泥球的维护团队才不关心你的项目呢,因为你依赖于他们的API、因此,他们并不会深入到你的上下文映射图中,然而你的映射图依然需要反映出和他们的集成关系,因为这样可以使你了解到映射图的内部,并且可以指明在哪些地方需要与其他团队进行交流。这样对你团队的成功是有帮助的。

    假定你期望大泥球维护团队提供一套新的API。然而,他们并不打算这样做。此时你的团队和大泥球的维护团队的关系便成了客户方-供应方的关系。由于大泥球团队决定维持现状,你的团队不得不陷入一种遵奉者关系中。尽早绘制上下文映射图,这样可以迫使呢仔细思考你的项目和你所依赖项目之间的关系。

    CollabOvation团队应该在建模之初就使用上下文映射图,然而当时他们对于战略建模一无所知。后来,通过经验积累,在之后的ProjectOvation中,尝到了建模的甜头。

    上下文映射图表现的是项目当前的状态,如果项目发生变化,你可以更新上下文映射图。注意上下文映射图不需要画得太正式了,手绘即可。

    2、产品和组织关系

    这一节主要重复下,整个专栏的案例说明,详情见:DDD案例说明。

    SaaSOvation公司正在开发的3个产品:

    1、CollabOvation——一款社交协作软件。该产品允许注册用户发布对业务有价值的内容,发布方式是一些流行的基于Web的工具,比如论坛、共享日历、博客和wiki等。这是SaaSOvation公司的旗舰产品,也是该公司的第一个核心域。开发团队后来从CollabOvation中提取了IdOvation模型。对于CollabOvation来说,IdOvation是一个通用子域,而CollabOvation本身又作为ProjectOvation的支撑子域。

    2、IdOvation——一款可重用的身份和访问管理产品。IdOvation为注册用户提供安全的、基于角色的访问管理。这些功能一开始和CollabOvation混合在一起,这样导致的问题是:实现受到了限制,功能不可重用。SaaSOvation对CollabOvation进行了重构,引入了一个新的、结构清晰的限界上下文。SaaSOvation公司决定支持多个租户,这种功能对于SaaS产品来说是至关重要的。对于消费方来说,IdOvation扮演着通用子域的角色。

    3、ProjectOvation——一个敏捷项目管理产品。这是SaaSOvation公司的核心域。ProjectOvation采用基于Scrum的项目运行框架,用户可以创建项目管理资产,同时对项目资产进行分析和设计,还能跟踪项目进度。和CollabOvation一样,ProjectOvation将IdOvation作为一个通用子域来使用。该产品的一大创新是将CollabOvation引入了敏捷项目管理,这样用户可以围绕Scrum的产品、发布、冲刺和待定项展开讨论。

    这些限界上下文之间的关系如何,不同开发团队之间的关系又如何?让我们看下各种关系之间的定义:

    • 合作关系(partnership):如果两个限界上下文的团队要么一起成功,要么一起失败,此时他们需要建立起一种合作关系。他们需要协调开发计划和集成管理。

    • 共享内核(share kernel):对模型和代码的共享将产生一种紧密的依赖性,对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显式的边界,并保持共享内核的小型化。共享内核具有特殊的状态,在没有与另一个团队协商的情况下,这种状态是不能改变的。我们应该引入一种持续集成过程来保证共享内核与通用语言的一致性。

    • 客户方——供应方开发(Customer-Supplier Development):当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队开发可能会受到影响。因此,在上游团队的计划中,我们应该顾及到下游团队的需求。

    • 遵奉者(conformist):在存在上游-下游关系时,如果上游团队已经没有动力提供下游团队之所需,下游团队便孤军无助了。只能盲目地使用上游团队的模型。

    • 防腐层(Anticorruption layer):在集成两个良好的限界上下文时,翻译层可能很简单,甚至可以很优雅地实现。但是,当共享内核、合作关系或客户方-供应方关系无法顺利实现时,此时的翻译将变得复杂。对于下游客户来说,你需要根据自己的领域模型创建一个单独的层,该层作为上游系统的委派向你的系统提供功能。防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无须修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转化。

    • 开放主机服务(open host service):定义一种协议,让你的子系统通过该协议来访问你的服务。你需要将该协议公开,这样任何与你集成的人都可以使用该协议。在有新的集成需求时,你应该对协议进行改进或者扩展。对于一些特殊的需求,你可以采用一次性的翻译予以处理,这样可以保持协议的简单性和连贯性。

    • 发布语言(published language):在两个限界上下文之间翻译模型需要一种公用的语言。此时你应该使用一种发布出来的共享语言来完成集成交流。发布语言通常与开放主机一起使用。

    • 另谋他路(separateWay):在确定需求时,我们应该做到坚持到底。如果两套功能没有显著的关系,那么它们也可以被完全解耦的。声明两个限界上下文之间不存在任何关系,这样使得开发者去寻找简单的、专门的方法来解决问题。

    • 大泥球(Big Ball of mud):当我们检查已有系统时,经常会发现系统中存在混杂在一起的模型,它们之间的边界是非常模糊的。此时,你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。在这个边界之内,不要试图使用复杂的建模手段来化解问题。同时,这样的系统有可能会向其他系统蔓延,你应该对此保持警觉。

    在与身份与访问上下文集成时,协作上下文和敏捷项目管理上下文均没有采用另谋他路的手法。诚然,在上下文范围之内,另谋他路的手法可以应用在特殊的系统上,同时它也可以用于一些个例。比如,一个团队可能拒绝使用集中式的安全管理系统,但他们依然会与另外类型的安全管理系统集成。

    在集成时,他们将会用到开放主机服务和发布语言,有可能还会用到防腐层。虽然这两者都会在限界上下文之间创建开放的标准,但是它们并不矛盾。通过使用下游上下文中的基本原则,他们依然可以得到由独立翻译所带来的好处,并且不会像与大泥球集成那样复杂。翻译层将变得简单、优雅。

    在上下文映射图中,我们使用以下缩写来表示各种关系:

    • ACL 表示防腐层
    • OHS 表示开放主机服务
    • PL 表示发布语言

    3、映射3个示例限界上下文

    当CollabOvation团队意识到自己已经陷入僵局时,他们研究发现“上下文映射图”的工具非常实用。

    从团队设计的第一张映射图可以看出,他们已经知道应该创建一个名为“协作上下文”的限界上下文。从图中怪异的边界又可以看出,他们可能希望创建第二个限界上下文,但是却不知道如何将这个上下文从核心域中分离出来。
    在这里插入图片描述

    团队成员意识到安全、用户和权限并不属于协作上下文,需要将这些概念从核心域中分离出来,是这些概念只有在得到同意的时候才能进入核心域。

    在对子域进行了分析,或对问题空间进行了评估之后,团队所绘制的上下文映射图如图所示,从一个限界上下文中分离出了两个子域。由于子域和限界上下文最好保持一对一的关系,我们应该将原来的协作上下文分离成两个限界上下文。

    在这里插入图片描述

    对子域和边界的分析要求我们做出决定。当人们需要使用CollabOvation的功能时,他们扮演者时参与者、作者和主持者的身份。有了这样的角色分离,我们便可以绘制一个更高层次的上下文映射图,如图所示。团队使用了分离内核对系统进行重构。

    在这里插入图片描述

    当下一个ProjectOvation项目启动时,团队将使用这个新的核心域——敏捷项目管理上下文来增强已有的上下文映射图,如图所示。

    在这里插入图片描述

    SaaSOvation的开发团队已经对核心的模型分离有了很好的理解。与CollabOvation相似,当ProjectOvation的用户扮演的是产品负责人或团队成员的角色。身份与访问上下文已经从核心域中分离出去了。协作上下文对于ProjectOvation来说只是一个支撑子域。任何时候,这个新的模型都受到了上下文边界的保护,外部概念需要通过翻译才能进入核心域中。

    身份与访问上下文位于最上游,它对协作上下文和敏捷项目管理上下文均会产生影响。同时,协作上下文又是敏捷项目管理上下文的上游,因为后者的模型依赖于前者的模型和服务。

    在限界上下文中我们提到,ProjectOvation将自治地运行,而不会依赖于周边的环境。这并不是说自治服务就可以完全独立于上游模型,而是我们的设计应该尽可能地限制实时依赖性。虽然ProjectOvation是自治的,但是它依然属于其他系统的下游。

    上图中,上游系统的连接框,都标以OHS/PL,分别表示开放主机服务和发布语言。所有下游的连接框都标以ACL,即防腐层。简单地来说,这些集成模式采用以下技术:

    • 开放主机服务:该模式可以通过REST实现。通常来讲,我们可以将开放主机服务看成是远程过程调用(RPC)的API。同时,他也可以通过消息机制实现。

    • 发布语言:发布语言可以通过多种形式实现,但最常见的是使用XML Schema。在使用REST服务时,发布语言用来表示领域概念,此时可以使用XML和JSON。发布语言既可以使用标准的媒体类型进行发布,也可以使用自定义类型。同时,发布语言还可以用于事件驱动架构(Event-Driven Architecture),其中领域事件以消息的形式发送给订阅方。

    • 防腐层:在下游上下文中,我们可以为每个防腐层定义相应的领域服务(Domain Service)。同时,你也可以将防腐层用于资源接口。在使用REST时,客户端的领域服务将访问远程的开放主机服务,远程服务以发布语言的形式返回,下游的防腐层将返回内容翻译成本地上下文的领域对象。比如,协作上下文向身份与访问上下文请求“具有Moderator角色的用户”。所返回的数据可能是XML格式或JSON格式,然后防腐层将这些数据翻译成协作上下文中的Moderator对象,该对象是一个值对象。这个Moderator实例反映的是下游模型中的概念,而不是上游模型。

    由于协作上下文是第一个核心域,让我们把它放大来看看。首先我们将接触到一些简单的集成方式,然后再是更高级的。

    4、协作上下文

    协作上下文作为SaaSOvation公司的第一个核心域。开发团队已经对其有很好的理解了。这里他们使用的集成方式比较简单,但是在可靠性和自治性上还稍逊一筹。要将此上下文映射图进行放大还是相对容易的。

    身份与访问上下文通过REST的方式向外发布服务。作为该上下文的客户,协作上下文通过传统类似于RPC的方式来获取外部资源。协作上下文并不会永久性地记录下从身份与访问上下文中获取来的数据,而是在每次需要数据时重新向系统发出请求。显然,协作上下文高度依赖于远程服务,它不具有自治性。但目前SaaSOvation公司愿意采取这种方式集成,以满足交付计划。由于之后的ProjectOvation项目将使用自治性服务,CollabOvation到时可以借鉴ProjectOvation的做法。

    在这里插入图片描述

    上图是放大后的上下文映射图,下游系统的边界对象采用同步的方式向上游系统获取到资源。当获取到远程数据模型数据之后,边界对象取出所需数据,再将其翻译成适当的值对象实例。

    在这里插入图片描述

    在上图中,翻译图(Translation Map)将所获取数据转化成一个值对象。这里,身份与访问上下文中一个具有Moderator角色的User被翻译成了协作上下文中的Moderator值对象。

    不幸的是,如果由于远程系统不可用而导致同步请求失败,那么本地系统也将跟着失败。虽然REST并不是真正意义上的RPC,但它却具有与RPC相似的特征。彻底的系统失败并不多见,但它却是一个潜在的问题。CollabOvation团队急切地希望解决这个问题。

    5、敏捷项目管理上下文

    为了达到比RPC更高的自治性,敏捷项目管理上下文团队将尽量限制对RPC的使用,此时他们可以选择异步请求,或者事件处理等方式。

    如果系统所依赖的状态已经存在于本地,那么我们将获得更大自治性。有人可能认为这只是对所有依赖对象进行缓存,但这不是DDD的做法。DDD的做法是:在本地创建一些由外部模型翻译而成的领域对象,这些对象保留着本地模型所需的最小的状态集。为了初始化这些对象,我们要有限的RPC调用或REST请求。然而,要与远程模型保持同步,最好的方式是在远程系统中采用面向消息的通知机制。消息通知可以通过服务总线进行发布,也可以采用消息队列或者REST。

    被同步的状态应该是本地模型所需远程模型的最小属性集。这里并不只是限制我们的对数据的需求,还应该对概念进行恰当的建模。

    6、和身份与访问上下文集成

    在这里插入图片描述

    在图中我们看到,对于身份与访问上下文的领域事件,系统将以URI的方式向外发布事件通知。这种功能是通过NotificationResource提供的,它向外发布REST资源。这里的通知资源是一组被发布的领域事件。对于消费方来说,每个事件总是可用的。消费方应该避免对事件的重复消费。

    一个自定义的媒体类型表明客户可以请求两种资源:
    在这里插入图片描述

    通过第一个资源URI,客户可以(使用HTTPGET请求)获取当前的通知日志(一个固定大小的通知集合)。对于自定义的媒体类型:
    在这里插入图片描述

    可以看出,这里的URI是全新的,并且是稳定的,因此它不会改变。无论当前的通知日志中包含了什么样的内容,该URI都会将其发布。

    事实上,ProjectOvation团队并不打算全盘使用REST。比如,他们目前正与CollabOvation团队协商是否可以使用消息机制,例如rabbitMQ。但就目前而言,它们和身份与访问上下文的集成依然是基于REST的。

    现在,让我们忽略技术细节,看看映射图中各个交互对象所扮演的角色。如图表示集成过程的序列图:

    在这里插入图片描述

    • MemberService是一个领域服务,它向本地模型提供ProductOwner和TeamOwner对象,同时作为基本防腐层的接口。maintainService方法用于周期性地检查身份与访问上下文所发出的通知。该方法不由模型的正常用户调用,而是由通知组件周期性地调用,在上图中,MemberSynchronizer表示这样的同步组件,它会把请求委派给MemberService。
    • MemberService进一步把请求委派给IdentityAccessNotificationAdapter,该类在领域服务和远程开放主机服务之间扮演着适配器的角色。该适配器作为远程系统的客户端而存在。与远程系统NotificationResource交互并没有显示在图中。
    • 一旦适配器从远程的开放主机服务获取到了数据,它将调用Member
      Translator的toMember()方法将发布语言中的媒体数据翻译成本地系统中的领域对象Member。如果该对象在本地系统中已经存在,则更新该对象。MemberService的updateMember()方法用于更新一个Member
      对象,此时它把委托操作委派给了自己。Member的子类有ProductOwner和TeamMember,它们反映了本地系统中的上下文概念。

    我们不应该将重点放在技术实现和集成产品上,而应该放在限界上下文之间的分离上,这样我们可以保持每个上下文的纯洁性,同时将一个上下文中的数据用于另一个上下文的概念中。

    让我们看看敏捷管理上下文是如何与协作上下文集成的。同样,我们关注的是系统的自治性,但这给集成带来了更多的困难与挑战。

    ProjectOvation将使用CollabOvation所提供的附加功能,比如论坛和共享日历等。ProjectOvation用户并不直接与CollabOvation交互。对于某租户来说,ProjectOvation必须决定出哪些CollabOvation的功能时该租户可用的。然后,ProjectOvation将协调对CollabOvation资源的创建。

    比如,Forum和Discussion必须在协作上下文进行创建的。在身份与访问上下文中,对象是先前存在的。而对于敏捷项目管理上下文来说,对象是不会预先存在的,直到被请求为止。这对于实现系统自治性来说是一个潜在的障碍,因为我们依赖于协作上下文来远程地创建资源。

    在使用领域事件和事件驱动架构时,我们应该仔细思考最终一致性。本地系统产生的事件通知并不是只能由远程系统消费。在ProjectOvation中,当ProjectInitiated事件产生时,该事件将由本地系统进行处理。本地系统要求Forum和Discussion在远程完成创建。这可以通过RPC或消息机制完成。

    如果项目负责人是图使用一个不存在的Discussion会发生什么问题吗?有时是由于调用失败,有时是由于没有预先付款导致协作功能不可用,这不一定是一个技术原因。对于最终一致性的处理我们应该将其考虑在建模访问之内。

    处理资源不可用的一个好办法便是将其显现出来。考虑以下由标准类型实现的状态和模式。此时的状态是一个值对象。
    在这里插入图片描述
    在该设计中,由DiscussionAvailability定义的状态将对象Discussion其保护作用。当有人是图参加关于一个Product的讨论时,该设计将正确地处理Discussion的状态。如果状态不为READY,参与者将得到以下消息之一:
    (1)要使用团队协作功能,你需要购买附加功能。
    (2)产品负责人还没请求创建产品讨论。
    (3)讨论启动失败,请稍后再试。

    此时,ProjectOvation团队还不清楚采用哪种方式与CollabOvation进行集成。在讨论了客户方-供应方关系后,它们得到了下图:
    在这里插入图片描述

    敏捷项目管理上下文可以使用第二个防腐层来处理与协作上下文之间的集成。事实上CollaborationAdapter并不是单个,此处只是一个占位符,表示有多个适配器。

    敏捷项目上下文在本地有DiscussionService和SchedulingService,它们是领域服务,用于管理协作系统中的讨论和日历条目。

    以上的例子已经展示了上下文映射图的某些细节。

    对于一个非常详细的上下文映射图,我们很有可能无法对其进行实时更新。保持简单性和敏捷性,拒绝繁文缛节,这样我们创建的上下文映射图将对项目起推动作用,而不是阻碍作用。

    展开全文
  • 领域、子域和限界上下文概述

    千次阅读 2019-11-03 17:45:05
    该领域模型将在最优获取上下文中实现,该上下文与最优获取核心域存在一的关系。由于只对应一个子域,同时又拥有优秀的领域模型,这个最优获取上下文将会是业务领域中最好的限界上下文之一。 在上下文映射图...

    1、概述

    1.1 领域

    广义领域:领域(Domain)即是一个组织所做的事情以及其中所包含的一切。每个组织都有它自己的业务范围和做事方式。这个业务范围以及在其中所进行的活动都有它自己的业务范围和做事方式。这个业务范围以及在其中所进行的活动便是领域。当你组织开发软件时,你所面对的便是这个组织的领域。

    领域既可以表示整合业务系统,也可以表示其中的某个核心域或者支撑域。在DDD中,一个领域被分成若干子域,领域模型在限界上下文中完成开发,在开发一个领域模型时,我们关注的通常只是这个业务系统的某个方面。

    1.2 子域

    子域是领域更细粒度的划分,根据重要性与功能将领域分为大致三类的多个子域,分别是核心子域、支撑子域和通用子域。核心域是业务成功的主要促成因素,主要竞争力,支撑子域是支撑核心域的,而通用子域是业务系统的公用部分。支撑子域在领域中是可以有多个的,核心域应该是只有一个为好,当然,除了核心域外,其他子域也可以没有。

    核心域是最重要的,开发核心域的解决方案是一种关键性的业务的投入,应该给予核心域的开发最高的优先级和最优秀的开发团队。如果核心域中的一些功能可以从核心域中分离出来,那我们可以用模块的形式从核心域分离出来,这里说的模块其实就是java中说的包,也可以理解为命名空间,文件夹。

    1.3 限界上下文

    限界上下文包含的是一个系统、一个应用、一种业务服务以及一系列实现业务的复杂组件。

    比如说在一个电子商务服务系统的领域中,加入一个库存系统和一个外部的预测系统,那么这个领域就可以拥有对应的三个限界上下文,一个限界上下文可能被包含在一个子域里,也可能多个子域,比如电子商务系统就包含了发票子域、订单子域等。

    2、工作中的子域和限界上下文

    对于如何使用子域,先看下一个简单的例子:一个零售商在线销售产品的例子。

    要在这个领域中开展业务,该零售商要展示不同类别的产品,支持下单和付款,还需要安排物流。在这个领域中,零售商的领域可以分为4个主要的子域:产品目录(Product Catalog)、订单(Order)、发票(Invoicing)和物流(Shiping),下图是一个含有子域和限界上下文的领域,它的上半部分表示了这个的一个电子商务系统。

    在这里插入图片描述
    这看起来比较简单,一个领域包含四个子域。但是考虑加入一些额外细节,以上这个例子将变得复杂,如果向上述系统加入一个库存(Inventory)系统和外部接入的预测库存系统,如上图下半部分。

    目前,该零售商的领域中只包含了三个物理系统,其中两个是内部系统。这两个系统表示两个限界上下文。这导致了几个子系统承担了太多的业务功能。

    在上面的电子商务系统限界上下文中,可以找出多个隐式的领域模型,这些领域模型被融合成了一个软件模型。随着各个逻辑模型中不断加入新的功能,他们之间的复杂关系对于每个模型都是一个阻碍,这些问题导致的原因通常都是由于软件的关注点没有得到清晰的划分导致。

    通过使用DDD战略设计工具,我们可以按照实际功能将这些交织的模型划分为逻辑上相互分离的子域,从而在一定程度上减少系统的复杂性。逻辑子域的边界如上图中的虚线所示。在不同的逻辑子域之间或者不同的物理限界上下文之间均有划线,这表示它们之间存在集成关系。

    库存问题也是电商系统中的一个重要问题,库存各种货物存多少合适呢?一种好的做法是,根据过去的销售趋势来制定未来的库存计划,从而达到优化库存系统的目的。

    增加一个预测引擎意味着开发一个新的核心域。如果这个新的解决方案是一个核心域,那么开发团队将从周围的逻辑子域以及集团体系中收益。因此,在该核心域的项目启动时,上图已有的集成体系对于掌握项目情况来说起到关键作用。

    子域并不一定做得很大,并且包含很多功能。有时,子域可以简单到只包含一套算法,这套算法可能对于业务系统来说非常重要,但是并不包含在核心域之中。在正确实施DDD的情况下,这种简单的子域可以以模块(module)的形式从核心域中分离出来,而并不需要包含在笨重的子系统组件中。

    在实施DDD的时候,致力于将限界上下文中领域模型所用到的每一个术语都进行上下文限界区分。这种限界主要是语言层面上的上下文边界,也是实现DDD的关键。

    在上图中,哪种类型的限界上下文在语言层面上设计的更好呢?
    在电子商务系统中,当我们谈到四个子域时,可以非常确定的有些术语是存在冲突的。如”顾客“,在浏览产品目录时,”顾客“被放在了先前购买的情况、忠诚度、可买产品、折扣和物流方式这样的上下文中。而在下单时,”顾客“的上下文包括名字、产品寄送地址、订单总价和一些付款术语。在这个电子系统中,”顾客“并没有一个清晰的定义。在一个好的上下文中,每一个术语仅表示一种领域概念。

    然而,我们也不能保证库存系统的模型就是完全清晰的,并且使用了完全非歧义的领域语言。比如”库存件“概念,已经被订购但还无法销售的产品称为延期订单件;保存在仓库中的产品称为积压件。等等。

    从表面上来看,可以得出结论,库存系统比电子商务系统具有更高的DDD健康指数,原因是库存系统的开发团队并没有使用一个库存件来表示所有的概念。虽然也不确定这一定吗,但是可以肯定:库存模型比电子商务系统模型更容易集成。

    一个企业的限界上下文并不是孤立存在的。不同子域之间的实线表示集成关系,这样表明不同的模型时需要协同工作的。集成的方式有很多种,将在上下文映射图中学到不同的集成方案。

    3、将关注点放在核心域上

    下图是一个领域的抽象视图,它可以表示任何一个领域,但是仅仅表示在某个时刻,从某个角度看的业务模型。

    在这里插入图片描述

    核心域:它是整个业务领域的一部分,也是业务成功的主要促成因素。从战略层面上讲,企业应该在核心域上胜人一筹。在实施DDD的过程中,应该主要关注核心域。

    **支撑子域:**有时,我们会创建或者购买某个限界上下文来支撑我们的业务。如果这样的上下文对应着业务的某些重要方面,但却是不核心,那么它便是一个支撑子域。创建支撑子域的原因在于它们专注于业务的某个方面。

    **通用子域:**如果一个系统被用于整个业务系统,那么这个子域便是通用子域。

    并不能说支撑子域和通用子域是不重要的,它们是重要的,只是我们对他们的要求并没有像核心域那么高。

    4、现实世界中领域和子域

    领域中还同时存在问题空间(problem space)和解决方案空间(solution space)。在问题空间中,我们思考的是业务所面临的挑战,而在解决问题空间中,我们思考的是如何实现软件以解决这些业务挑战。

    • 问题空间是领域的一部分,对问题空间的开发将会产生一个新的核心域。对问题空间的评估应该同时考虑已有子域和额外所需子域。因此,问题空间是核心域和其他子域的组合。问题空间中的子域通常随着项目的不同而不同,他们各自关注于当前的业务问题,这使得子域对于问题空间的评估非常有用。子域允许我们快速地浏览领域中的各个方面,这些对于解决特定的问题是必要的。

    • 解决方案空间包括一个或多个限界上下文,即一组特定的软件模型。这是限界上下文中即是一个特定的解决方案,它通过软件的方式来实现解决方案。

    为了澄清问题空间和解决方案空间的区别,来看个例子。

    例如大型的ERP系统,我们可以将一个ERP系统想象成一个单一的限界上下文。由于ERP系统提供许多模块化的业务服务,将不同的模块看成不同的领域是有好处的,比如,可将库存模块和采购模块拆分成不同的逻辑子域,分别命名为库存子域和采购子域。

    在这里插入图片描述

    上图表示的是一个ERP系统的领域,也是上述抽象领域模板的一个实例。该企业计划开发一个特定的领域模型来降低成本,该模型可以为采购人员提供决策工具,这个新的核心域可以提高该企业的竞争优势。

    在实施某个解决方案之前,我们需要对问题空间和解决方案空间进行评估。为了项目朝着正确的方向进行,需要先回答以下问题:

    • 这个战略核心域的名字是什么,它的目标是什么?
    • 这个战略核心域中包含哪些概念?
    • 这个核心域的支撑子域和通用子域是什么?
    • 如何安排项目人员?
    • 你能组建一支合适的团队吗?

    在理解问题空间之后,来看看解决方案空间。对于问题空间的评估也是有益于理解解决方案空间的。解决方案空间在很大程度上受到现有系统和技术的影响。这里,我们应该根据分离的限界上下文仔细地思考,考虑以下问题:

    • 有哪些软件资产是已经存在的,它们可以重用吗?
    • 哪些资产是需要创建的,或者从别处获得?
    • 这些资产是如何集成在一起的?
    • 还需要什么样的集成?
    • 假如已经有了现有资产和那些需要被创建的资产,我们还需要做什么?
    • 核心域和那些支撑项目的成功率如何?会不会由于其中一个失败而导致整个项目失败的可能性?
    • 在哪些地方我们使用了完全不同的术语?
    • 限界上下文之间在哪些地方存在概念重叠?
    • 这些重叠的概念在不同的限界上下文之间是如何映射和翻译的?
    • 哪些限界上下文包含了核心域的概念,其中使用了哪些战术模式?

    在上图中,用于捕获决策工具和算法的采购模型表示了核心域的解决方案。该领域模型将在最优获取上下文中实现,该上下文与最优获取核心域存在着一对一的关系。由于只对应一个子域,同时又拥有优秀的领域模型,这个最优获取上下文将会是业务领域中最好的限界上下文之一。

    在上下文映射图中,将主要介绍通过集成上下文的方式来完成不同通用语言之间的映射。

    5、理解限界上下文

    限界上下文是一个显式的边界,领域模型便存在这个边界之内。领域模型把通用语言表达成软件模型。创建边界的原因在于,每一个模型概念,包括它的属性和操作,在边界之内都具有特殊的含义,且每个概念的含义便是确定的。因此,限界上下文主要是一个语义上的边界,我们应该通过这一点来衡量对一个限界上下文的使用正确与否。

    限界上下文并不旨在创建单一的项目资产,让我们来看下一个账户(Account)模型在银行上下文(Blanking Context)和文学上下文(Literary Context)中的不同,如下表:

    在这里插入图片描述

    在图中,光凭名字我们根本无法区分两个账户的意思。只有通过它们所在的限界上下文我们才能看出他们之间的区别。

    在这里插入图片描述

    这两个限界上下文可能不属于同一个领域,这里说明:上下文才是王道。

    • 限界上下文不仅仅只包含模型

    一个限界上下文并不是只包含领域模型,诚然,模型是限界上下文的主要“公民”。但是,限界上下文并不只局限于容纳模型,它通常标定了一个系统、一个应用程序或者一种业务服务。有时,限界上下文所包含的内容可能比较少,比如,一个通用子域便可以只包含领域模型。

    当模型驱动着数据库Schema的设计时,此时的数据库scheme也应该位于该模所处的上下文边界之内。

    限界上下文主要用来封装通用语言和领域对象,但同时它也包含了那些为领域模型提供交互手段和辅助功能的内容。需要注意的是,对于架构中的每个组件,我们都应该将其放在适当的地方。

    • 限界上下文的大小
      限界上下文可以包含多少领域模型中的基础部件呢,比如,模块、聚合、领域事件和领域服务等。限界上下文应该足够大,以能够表达它所对应的整套通用语言。但不要将核心域之外的概念不应该包含在限界上下文中。如果有一个概念不属于你的通用语言,那么一开始你就不应该将其引入到模型中。

    • 与技术组件保持一致
      将限界上下文想成是技术组件并无大碍,只是需要注意:技术组件并不能定义限界上下文。来看一些构成和部署限界上下文的常见做法。

    当使用IDEA时,一个限界上下文通常就是一个工程项目。在使用Java时,顶层包名通常表示限界上下文中顶层模块的名称。对于上文中提到的例子,我们可以采用以下方式来定义包名:

    com.chunsoft.optimalpurchasing
    

    限界上下文的源代码结构可以根据职责做进一步分解。下面是一些二级包名:

    com.chunsoft.optimalpurchasing.presentation
    com.chunsoft.optimalpurchasing.application
    com.chunsoft.optimalpurchasing.domain.model
    

    请注意,即便存在这种模块化的拆分,团队依然应该只工作在一个限界上下文中。

    展开全文
  • 一篇了解 JS的上下文(context)

    千次阅读 多人点赞 2021-04-13 21:34:37
    先说以下简单的概念: 我们都知道每个函数执行时,都会有个this,这个this的执行便是上下文的一种 ...dist_request_id=&d

    查阅了大量文章文献,终于把js的执行顺序搞通了,我发觉这里面难搞的原因在于,很多文章只写了某一块知识点,或者某块知识点还没讲透彻导致有点懵,现在我总算是搞懂了,所以我想从头到尾彻彻底底的讲一遍。

    1.JS的执行顺序

    先简单讲下整个执行顺序

    1.我们所写的js代码在执行阶段前,会有个预加载过程,目的是建立当前js代码的执行环境,而这个执行环境就是上下文(context)。
    2.这个上下文包含了VO(Variable Object变量声明对象),AO(Active Object动态变量对象),scopeChain(作用域链)。
    3.建立好上下文后,才会开始执行我们写的js代码。

    1.1上下文(Execution Context)

    通过上面我们可以直到,上下文就是每段代码的执行环境。

    它分为三种类型:
    1.全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境。
    2.函数级别的代码 - 当执行一个函数时,运行函数体中的代码。
    3.Eval的代码 - 在Eval函数内运行的代码。

    先讲函数级别的上下文(执行环境)。

    上下文建立的阶段:
    1.建立VO(Variable Object)
    2.建立AO(Active Object)
    3.建立 scopeChain
    在这里插入图片描述

    1.1.1 静态变量声明(Variable Object)

    我们看下面的代码:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以看到foot在声明前打印会显示“undefind”,但ball在声明前打印会报错显示 “ball is not defined”。两者的区别在于,后面foot被声明了,而ball至始都没有声明过。

    那么,就抛出一个问题了,既然代码是从上到下执行,按道理来说两者都应该是“is not defined”,为什么前者会是undefind并且无报错执行。

    答案就是在js代码执行前有个预加载阶段用来建立代码的执行环境(上下文),而建立上下文的第一个阶段就是建立当前环境声明过的变量Variable Object。

    我们来看下面代码所生成的上下文对象

    function fn(){
            var foot = '脚';
            var head = function(){
                return '头';
            }
            function hand(){
                return '手';
            }
        }
    

    Variable Object :
    // VO创建

    fnExecutionContext  = {//fn函数的上下文对象
      VO: {
        arguments: { .... },
        hand:hand函数的引用地址,//函数声明
        head: undefined, // 变量函数声明
        foot: undefined, // 变量声明
        this:Window,//this指向
      },
      scopeChain: {} //作用域链
    }
    

    我们可以看出,就跟我们刚才打印的一样,声明过的参数全部都被记录在了这个VO对象中,只不过var声明的参数值都为undefined。
    也因此我们为什么刚才的打印会undefined了。

    那么会有个疑问,为什么function声明的函数就有值呢,这个简称变量提升:

    所谓的变量提升,就是在建立上下文是会把function声明的函数都提升到上面来,这样即时你把function写到下面,他依然会比你var声明的值更快获得实际的值。
    那么什么时候var声明的变量才能有值呢,这个就是AO的原因了。

    1.1.2 动态变量声明(Active Object)

    所谓AO就是Active Object的简写,那么什么是AO呢,他其实就是VO,只不过在初步建立完VO后,就会开始执行我们的js代码。
    js代码从上到下执行的过程中,如果遇到赋值的情况,那么就会更新VO变成了AO。我们来看看AO对象。

    fnExecutionContext  = {//fn函数的上下文对象
      AO: {
        arguments: { .... },
        hand:hand函数的引用地址,//函数声明
        head: head函数的引用地址, // 变量函数声明
        foot: '脚', // 变量声明
      },
      scopeChain: {} //作用域
    }
    

    是不是一下子就懂了。

    接下来我们看VOAO的arguments参数

    1.1.3 Variable Object的arguments属性

    每个函数的调用,都必然存在arguments对象,它存在于Variable对象当中,接下来我们来看看arguments对象里面到底有些什么东西。

    function showargs() {
    	console.log( arguments );
    }
    
    showargs(1,2,3,4,5);
    

    打印结果如下:
    在这里插入图片描述
    从上图可以明白,其实就是把调用这个函数时所传入的参数,通过一个类数组对象接收了。

    类数组对象是什么意思呢,就是类似数组的对象,他没有数组的一些方法,但是他却是以{“0”:‘您好’,“1”:我好,“2”:大家好}
    这种很像数组的方式存在。

    除了传入的参数,我们通过arguments.callee还能获得当前函数的代码

    function showcallee() {
        var a = '这里是代码';
        var b = '这是另一段代码';
        var c = a + b;
        
        console.log(arguments.callee);
        
        return c;
    }
    showcallee();
    

    在这里插入图片描述
    到此,arguments对象我们就了解完毕了,他在上下文中起着,记录调用此函数时所传入的参数的作用。

    1.1.4 scopeChain作用域链

    在上下文对象中,我们看到了一个scopeChain作用域链,那么这个作用域链有什么用呢。
    我们看如下代码:

    function fn(){
            var foot = '脚';
            function footBall(){
                var footBall = '足球';
                console.log(footBall+ '需要:' +foot);
            }
            footBall();
        }
        打印结果如下:足球需要脚
    

    从上面代码看出,函数footBall可以使用到函数fn所声明的变量foot。
    如果没有scopeChain,这是做不到的,scopeChain就是充当这一角色。

    JS权威指南指出”JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.”

    ECMA262中所述 任何执行上下文时刻的作用域, 都是由作用域链(scope chain)来实现.在一个函数被定义的时候, 会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性.

    作用域链其实就是所有内部上下文的变量对象的列表。用于变量查询。比如,在上述例子中,“footBall”上下文的作用域链包含了VO(footBall),VO(foot)和VO(global)。

    看完上面的概念,我们可能会有点懵,接下来我们看下这个footBall的上下文对象。

    footBallExecutionContext = {
    	  VO: {
    	    arguments: { .... },
    	    footBall : undefined, // 变量声明
    	    this: fn,
      		scopeChain: {
    			VO(footBall函数的VO),
    			VO1(fn函数的VO),
    			VOGlobal(全局的VO)
    		} //作用域链
    	  }
    	  .....
    	}
    

    可以看出来footBall的VO对象是没有foot的变量声明,那为什么执行下来不会报错,而且还有值呢。
    这就是scopeChain的意义了,如果在当前VO找不到相关的定义,便会通过scopeChain对象找父级的VO,找不到就再往上找,直到全局的VO。所以当footBall的VO对象里没有foot的定义时,便会去找父级的VO也就是fn函数的VO,在fn函数里有foot的定义。

    如此下来,整个上下文就讲完啦。简单来说就是一个执行代码的环境,但细讲会发觉他有好多的属性,这都是为了在执行每一段js代码时都能有序,无误的执行。不得不赞叹,语言类的开发者真的要顾全很多的东西。

    总结:

    一个js的代码的执行顺序简单来讲是两步

    1.建立当前所要执行的js代码的执行环境,简称上下文。
    2.从上到下一次执行代码。

    而这篇文章主要讲的是建立环境的过程和顺序
    下一篇我们会讲我们所写的代码的执行顺序,这里我们

    参考文献:https://blog.51cto.com/enjoyjava/1124940
    参考文献:https://www.tensweets.com/article/5ba71b42f0cb0c04f86b23dd
    js代码的执行顺序参考文献:https://www.jb51.net/article/127025.htm

    拓展

    我们都知道,在es6多了let这个声明方式,虽然用是用的很多,也知道他的作用,但其实他和var的区别还是蛮大的。特别是在上下文环境建立的过程中。

    比如最简单的:
    console.log(k);//undifined
    var k=2;

    比如最简单的:
    console.log(k);//报错
    let k=2;

    这里其实说的就是你定义了let的时候,在预编译阶段let定义的时候就会分配一个内存空间给这个变量,但分配后并不像var定义的那样,一旦分配内存空间,立刻定义值为undefined;用let定义的分配了内存,但这个内存并没有被分配任何值,为uninitialized状态。

    executionContextObj={
    ‘scopeChain’: {VO},
    ‘variableObject’: {
    k:uninitialized //uninitialized
    },
    ‘this’: {window}
    }

    2.执行代码阶段(AO的建立阶段 VO=>AO)

    执行第一行代码后,executionContextObj对象中的variableObject中的name:修改为jackiewillen.继续执行第二行,修改subName为kevin;这个时候你可能会有这样的疑问,如果这个subName只被let定义,而一直都未被赋值,那么值一直是uninitialized吗?
    来看下面这样一段代码:

    let k;
    console.log(k);//the result is undefined;

    那么为什么这里打印出了undefined呢,却没有报错呢,因为之前的console.log是放在let定义之前的,那个时候k的值是uninintialized;但过了预编译进入执行阶段程序运行到let k;时发现其未赋值,只是定义了这个变量,这个时候编译器才决定给k赋值为undefined。这个可以参见es6标准。
    这也就是为什么let没有变量提升的原因。

    进入到for循环,我们知道在es6中增加了块级作用域。也就是只要有{}都是一个块,在块外访问不到块内部的内容。
    let声明的变量,事实上会另外开辟一个空间,叫词法环境,专门存储let声明的变量,只有在这个块中,才能使用。下面的代码blockObject就是所谓的此法环境。

    如if(true){ let a=4;}
    console.log(a);
    这样就是访问不到这个a的值的。

    接下来执行当for循环中的i值为1的时候,executionContextObj如下所示:

    	var name = 'name';	
    	var myName = 'yin';
    	for(let i = 0; i<2;i++){
    		let yourName = 'herry'
    		console.log(i);
    	}
    	iftrue){
    		let subName = 'kevin'
    	}
    
    executionContextObj={
    	'scopeChain': {},
    	'variableObject': {
    		name:jackiewillen,
    		myName:yin, //因为对于var定义的变量,不存在块作用域
    		anonymous1:reference to function(){console.log(i)};
    	},/* function arguments / parameters, inner variable and function declarations */
    	'blockObject':{
    		subName:kevin
    	},
    	'blockObject':{
    		i:1,
    		yourName:herry //为什么这里在block中呢,而不像subName那样在variableObject中呢,因为用let定义的都在它所待的块定中
    	},
    	'this': {window}
    }
    

    注:scopeChain每次生成时都会检查有没有闭包Closure存在,然后再检查有没有Block的然后把上一个variableObject拿过来(除去其中已经是闭包的元素,和block的元素。其样式如同scopeChain={closure+vo+bo+vo+bo…} ,还有,只有在函数被激活也就是调用的那一刻,其内部声明的变量vo和bo才会加到scopeChain中去。打算再写一篇文章专门去写这个scopeChain
    注:此时的blockObject是一个全新的blockObject因为前一个已经被销毁,当一对花括号运行过后,相应的block也就销毁了。

    1.第一步,看看有没有闭包,发现没有。

     'scopeChain': {}
    

    2.第二步,看看有没有引用block块元素。发现引用了一个executionObject中的blockObject中的i,所以scopeChain为:

    'scopeChain': {
    		blockObject:{
    			i:1
    		}
    	}
    

    3.第三步,把区块链上的vo和bo都拿过来。

     'scopeChain': { blockObject:{ i:1 }}'variableObject': { 			
      		name:jackiewillen, 
      		myName:yin, //因为对于var定义的变量,不存在块作用域
     		anonymous1:reference to function(){console.log(i)}; }, 
    		'blockObject':{
    			subName:kevin
    		}, 
     }
    

    这个就是匿名函数anynmous1中的scopeChain

    当for当中的i运行到2的时候,executionObject如下所示:

    executionContextObj={
    	'scopeChain': {},
    	'variableObject': {
    		name:jackiewillen,
    		myName:yin, //因为对于var定义的变量,不存在块作用域
    		anonymous1:reference to function(){console.log(i)};
    		anonymous2:reference to function(){console.log(i)};
    	},/* function arguments / parameters, inner variable and function declarations */
    	'blockObject':{
    		subName:kevin
    	},
    	'blockObject':{
    		i:2,
    		yourName:herry, //为什么这里在block中呢,而不像subName那样在		variableObject中呢,因为用let定义的都在它所待的块定中
    	},
    	'this': {window}
    }
    

    通过以上实验,我们知道let声明的变量会存放在一个单独开辟的词法环境当中,这个环境在这个{}花括号运行中才能拿到,直到这个花括号结束后,这个词法环境也会被销毁。

    展开全文
  • 在分布式链路跟踪系统中,同一条请求处理链路要用...利用 Mtrace(公司内部统一的分布式会话跟踪系统)的服务间传递上下文特性,在原有传输上下文的基础上,添加了测试标识的属性,以保证传输中始终带测试标识。
  • Canvas——2D上下文

    千次阅读 2018-09-13 20:32:55
    Canvas——2D上下文 一、基本概念 使用2D绘图上下文提供的方法,可以绘制简单的2D图形,比如矩形、弧线和路径 2D上下文的坐标开始于&amp;amp;amp;amp;amp;amp;amp;amp;lt;canvas&amp;amp;amp;...
  • CSS基础:CSS的上下文之BFC

    万次阅读 2021-02-24 14:34:36
    看到这个名词,可能会有些陌生,但其实 上下文 = 区域,如果这么理解的话就会有行级上下文、块级上下文、flex上下文等等有一定排列规则的区域,我们今天只聊一聊 块级格式化上下文(BFC) 一、什么是BFC? BFC全称...
  • 线程上下文切换

    千次阅读 2018-08-29 10:05:04
    一、为什么要减少线程上下文切换  当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行。这种切换称为...
  • 什么是:CPU寄存器 CPU上下文切换? 进程上下文切换 线程上下文切换 中断上下文切换 Go程序内核线程能有多少个? Linux创建的线程是用户级还是内核级线程? 什么是:CPU寄存器 CPU上下文切换? CPU寄存器,是...
  • 安全上下文

    千次阅读 2015-04-21 21:05:23
    (一)、类型强制策略的安全上下文 所有的操作系统访问控制都是基于与主体和客体相关的访问控制属性的。在SELinux中,访问控制属性杯称作安全上下文。所有的客体(文件,进程间通信,通信管道,套接字,网络主机等...
  • Android之所以不同于java,源于java工程简单,随便一个main方法便可运行起来,而android工程需要依赖一些特定的android环境,在此环境中需要衔接好各组件的正常运作,context起着至关重要的作用。 获取上下文有三种...
  • 基本功:线程上下文切换

    万次阅读 多人点赞 2019-05-31 22:06:42
    更多的线程意味线程创建销毁开销加大、上下文非常频繁,你的程序反而不能支持更高的TPS。可以看另一篇《Java从线程安全到synchronized和Lock探索》 时间片 多任务系统往往需要同时执行多道作业。作业数往往大于...
  • 形状上下文(shape context)算法完全解读

    千次阅读 多人点赞 2020-04-11 00:12:08
    形状上下文(Shape Context)算法完全解读前言一. 轮廓提取(Canny Edge Detection)和轮廓点采样(Jitendra's Sampling) 前言 一般来说,在计算机视觉任务中,形状匹配可以分为 基于特征(Feature-based): 基于傅里叶...
  • 一、获取正确的上下文 ZeroMQ应用程序总是从创建一个上下文开始,然后使用它来创建套接字 上下文是指:在单个进程中所有套接字的容器,并充当inproc套接字的传输工具,这是在一个进程中连接线程的最快办法 单个...
  • 探讨Linux CPU的上下文切换原由

    千次阅读 2022-05-25 18:42:58
    CPU 上下文(CPU Context) 在每个任务运行之前,CPU 需要知道在哪里加载和启动任务。这意味系统需要提前帮助设置 CPU 寄存器和程序计数器。 CPU 寄存器是内置于 CPU 中的小型但速度极快的内存。程序计数器用于...
  • Flask——请求上下文和应用上下文

    千次阅读 2019-08-09 10:06:14
    在flask框架中,引入了上下文的概念,为了能够让大家真实的感受到上下文在flask框架中所到的作用,所以下面我就用一个具体的需求实例来给大家进行说明,首先在我不使用上下文思路的情况下来解决这一需求,然后再...
  • 上下文切换技术

    千次阅读 2016-10-10 18:50:46
    简述 在进一步之前,让我们先回顾一下各种上下文切换技术。...当我们说“上下文切换”的时候,表达的是一种从一个上下文切换到另一个上下文执行的技术。而“调度”指的是决定哪个上下文可以获得接下去的CPU时
  • 一、中断上下文 当执行一个中断处理程序时,内核处于中断上下文(interrput context) 中 让我们先回忆一下进程上下文。进程上下文是一种内核所处的操作模式,此时内核代表进程执行——例如, 执行系统调用或运行...
  • windbg中所谓的上下文

    千次阅读 2017-06-17 23:34:30
    为了深入了解背后的含义,我翻开windbg帮助文档,发现其进程/寄存器上下文的解释最为晦涩。只能通过实际的练习,趟石子过河,最后记录下自己的总结。  windbg中与进程上下文相关的命令是.process,与寄存器...
  • windows设备上下文的概念

    千次阅读 2016-08-06 22:57:03
    关于设备场景,叫法颇多,有些书说为设备环境、显示场景,更常见的叫做设备描述表或设备...而实质,widnows下的所有绘图都是 通过设备场景进行的,而不是直接窗口和设备本身进行。为了说明设备场景,很多书都拿
  • Qt学习—qt上下文菜单显示

    千次阅读 2015-12-30 10:17:04
    Qt学习—qt上下文菜单显示   Qwidget类及其子类都具有右键菜单响应功能,QWidget类提供了以下两个与右键菜单有关的函数: 1、 Qt::ContextMenuPolicy contextMenuPolicy()const 该函数用来获取控件上下文菜单项的...
  • 上下文切换详解

    千次阅读 2018-10-12 23:10:08
    ...   原文地址,译文地址,译者: 董明鑫,...上下文切换(有时也称做进程切换或任务切换)是指 CPU 从一个进程或线程切换到另一个进程或线程。 进程(有时候也称做任务)是指一个程序运行的实例。在 Linux ...
  • linux进程-线程-协程上下文环境的切换与实现

    万次阅读 多人点赞 2018-05-30 17:46:38
    进程调度,切换进程上下文,包括分配的内存,包括数据段,附加段,堆栈段,代码段,以及一些表格。线程调度,切换线程上下文,主要切换堆栈,以及各寄存器,因为同一个进程里的线程除了堆栈不同。协程又称为轻量级...
  • 点击上方“AI算法修炼营”,选择“星标”公众号精选作品,第一时间送达这篇文章收录于ECCV2020,主要是有关语义分割算法中的上下文信息重建方法,本文中同时考虑了通道维和空间维,可以看作...
  • 深入理解Linux的CPU上下文切换

    千次阅读 2018-12-14 11:10:11
    如何理解Linux的上下文切换 Linux 是一个多任务操作系统,它支持同时运行的任务数量远大于 CPU 个数。其实这些任务没有真正的同时运行,是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉...
  • Linux进程上下文切换过程context_switch详解 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度 前面我们了解了linux进程调度器的...
  • 介绍了多线程的概念、优点,以及线程上下文切换时的性能损耗问题
  • 一文让你明白CPU上下文切换

    千次阅读 2018-12-20 13:07:37
    我们都知道,Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU...什么是 CPU 上下文 CPU 寄存器和程序计数器就是...
  • 上下文无关文法、上下文有关文法

    千次阅读 多人点赞 2014-01-17 02:24:59
    一直被这两个绕,现在...(任何产生规则的左手端和右手端都可以被终结符和非终结符的上下文所围绕,乔姆斯基描述自然语言的一种方式介入的,在自然语言中一个单词是否可以出现在特定的位置要依赖于上下文。)  
  • 在当前 CPU 数量远远不止一个的情况下,操作系统将 CPU 轮流分配给线程任务,此时的上下文切换就变得更加频繁了,并且存在跨 CPU 上下文切换,比单核上下文切换,跨核切换更加昂贵。 多线程上下文切换诱因 在操作...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 155,290
精华内容 62,116
热门标签
关键字:

对上下文起着什么作用