写点什么

Jezz Santos 谈软件工厂和 DSL

  • 2007-06-17
  • 本文字数:8373 字

    阅读完需:约 27 分钟

InfoQ 的 Hartmut Wilms 有幸采访了 Jezz Santos ——Microsoft 咨询服务部( Microsoft Consulting Services )资深产品研发顾问,主要研究方向是企业产品研发(Enterprise Product Development)、自动化任务引导(Guidance Automation)和软件工厂(Software Factory)等。

从上世纪 90 年代中期开始,Jezz 就积极投身于产品研发领域,他曾在各种研究机构、独立软件开发商( ISV )和全球系统集成商( GSI )中从事研发工作。Jezz 担任 Microsoft 专业顾问已逾 6 年,成绩斐然,他探索出了一系列实现和组织可重用部件与知识、自动化任务引导的手段和方法,帮助用户实现自己的定制诉求——将这些手段和方法归纳起来,就是软件工厂。

我们就 Microsoft 软件工厂计划( Microsoft Software Factory Initiative )向 WSSF( Web Service Software Factory )领域的权威和世界上首批软件工厂( EFx Factory 。它为我们展示了 Microsoft 下一代软件工厂中一些高级特性)实现者之一——Jezz Santos——提出了如下问题:

InfoQ:Microsoft 软件工厂计划的主要内容是什么?在软件工厂和领域专用语言(Domain-Specific Language)方面,你承担什么研究任务?

Jezz Santos (JES):我个人认为,软件工厂计划的全部目标,就是推动软件产业向生产力更高、成本更低和质量更好的方向发展。而且我们必须达到这个目标,因为对于终端用户来说,目前的软件解决方案的开发和维护成本过高。我们还生活在一个软件质量不能满足市场要求的时代。

要想达到这个目标,我们必须从实际出发,集中精力办好几件事情。第一,也是最重要的,是要将软件需求的主体部分标准化,并让用户定制需求成为在此基础上的非规范化补充。定制需求的确会导致研发成本大幅攀升,但在任何一个行业中,客户定制需求都是客观存在的。第二,软件解决方案应该主要通过对满足标准需求的标准的、可重用的部件组装得到。标准部件的研发和打包,必须以可重用、易于集成和配置为前提。因此,我们需要专家开发用户配置工具,帮助我们将这些部件有效组织到既有架构中去。配置工具应该使用专用语言,达到简洁描述问题的目的,以便方案的实现过程能专注于满足用户需求。

软件工厂,就是这样的用户配置和编辑工具,它具有将不同可配置部件装配入特定类型软件产品的能力。当然,软件工厂并非是适合所有类型的软件研发目标的万能方案;它要求的前提是——问题的目标领域明确,并且软件工厂的建造者的人在该领域内拥有丰富经验和专家级求解域(Solution Domain)技能。

软件工厂的真正价值,是可用工具(即工厂)实现部件的有效组织。简单来说,工厂提供的解决方案,能以问题所属领域的通用语言,告诉你应该使用哪些部件、部件间的装配原理,以及如何、何时使用它们。

这么说吧,工厂掌握了它正在装配的产品的架构,以及架构中使用的各类组件,另外它使用了针对问题领域的高级语言,因此工厂可以准确告诉你如何在特定需求基础上构造解决方案,以及完成此方案所需的部件和活动。作为工厂的使用者,你只需要理解工厂用以表述其架构和部件,以及部件如何装配以满足你特定需求的语言。

InfoQ:严格来说,软件工厂应该如何定义呢?

JES:实际上,软件工厂主要有三个组成部分:标准部件本身,部件如何表述、配置和协作,以及软件工厂如何装配部件。对绝大多数软件开发组织,特别是有产品线经验的人来说,标准部件并非什么新鲜玩意。构建工厂的过程,就是取得部件,对部件施行抽象和自动化,最后将它们集成到一个工具。

InfoQ:这样啊,那么如果利用这些部件构造软件工厂呢?

JES:那就讲个故事吧。假设你现在需要为客户定制软件解决方案。我们来看看如何利用标准化部件建造软件工厂。注意,我会逐步介绍有关软件工厂的术语。

我假设某用户希望从你这购买一台有特殊要求的摩托车。这台摩托车不能从商店直接买到,因为它不是工厂模式的(抱歉,这个词可能引起误会,我的意思是非标准模式),而是用户定制型的——不过又不是从零开始完全定制的那种——而类似于在一种标准型摩托车(比如“巡洋舰”)上稍加改造。

现在清楚了,客户希望你能帮他办成这件事情,因为:(a)从商店中直接买不到,商店出售的都是标准型的;(b)不想整车定制,很有名的“巡洋舰”摩托车满足其基本要求;(c)他想对这台摩托车做点个性化改造;(d)很明显,他宁愿付点钱找人帮忙,因为自己非专业人士,操作存在风险。

那么,你一个摩托车厂商,无非如下几个选择:

  • 整车从零生产——风险大,且成本高、回报低。
  • 付钱找其他厂家帮你完成——成本高、回报低。
  • 购买“巡洋舰”摩托车的零件包,你自己为客户改装——成本低、回报高。

其实,你的目标就是一台略加改造的“巡洋舰”摩托车。零件包里有预先加工好的零部件(如发动机、汽化器、汽缸和轮胎等),还有一些原材料(如布料、钢管、金属片和塑料等)和专业工具。再按照组装说明,正确使用零部件、材料和工具,步步为营,最终必然能装配一辆摩托车。至于细节上真正存在高难度的部分,如化油过程、动能传送和燃料供应等,早就已经解决并包含在零部件中了。你唯一需要做的就是将这些零部件挂到一个可乘放你屁股的架子上去。

InfoQ:那么,这和我们目前的软件开发过程有何不同呢?

JES:对于大多数成功的解决方案提供商来说,构造软件系统的过程和上面是一样的。但如果你只能从原材料(如电镀板、钢管,使用扳手、螺丝钉、焊枪和钻机)级别着手,只有草图,仅仅大概知道如何将这些东西拼起来,那就是另外一回事了。经过努力,你最终按照客户的特殊需求完成了一台高质量、单件化的摩托车。当然不是说这样做就不行,很多人都是这么干的;但到最后,只有少数人能真正成功,其中一些就成为了该领域的专家(我好像在哪个电视片中看到过有人在摩托车个性化定制方面就干的很不错)。

对于终端用户来说,单件定制的成本是很高的,这个市场目前的购买力尚不旺盛,很少消费者有能力投资在仅仅外观漂亮、可将他们时髦地从这运到那的奢侈品上。而软件工厂故事的揭幕,则是因为有些人希望进入解决方案的重点不是满足定制需求,客户更关心软件功能、愿意为高质量产品投资的庞大市场。

客户来找你帮忙,是因为你拥有实现用户需求的能力——你是领域专家。你能将成本控制在合理范围内;你以前可能完成过这类产品,今后也还能再做——因为你拥有行业经验和领域知识。就像你曾经实践过摩托车装配方案的全部工作,那么对于其中各种细节和诀窍(拿软件业行话说就是实践、模式等),更重要的是各个零部件彼此如何装配,才能满足更高要求,如行车安全性、性能、功耗、噪声控制和舒适性等(这些都是行业专有的质量指标),你都了如指掌。总之,你就是一位行业专家。你以前可能自己开发了一些工具,或总结归纳了某些过程和架构——它们在历次工作中都是一样的。不用怀疑,在构建这类方案的过程中,你可能已用同样方法完成了很多单件化的摩托车;其中有些可能失败了,但这能让你学会(尽管十分艰难)如何做的更好、更高效、满足更多质量指标要求。一句话,你已经成为了生产该类交通工具、能提供专业品质保证的行业专家。

InfoQ:嗯,明白了。那么接下来应该做什么呢?

JES:你现在知道,花费一点工作量,你就能使用同样的设计方法、原材料和工具制造任何类型的摩托车。每辆车可能在局部有所不同,比如挡泥板、颜色、把手长度、发动机和轮胎大小等。但所有车子的心脏(结构)都是一样的。那么,如果你能确定市场上存在一个群体(终端用户),他们对这种设计形式(产品线)的摩托车(产品)很感兴趣,就可以召集一组人专门生产这种产品。你一个人满足不了市场需求,而只要为你的团队提供专业指导和工具,生产力就会大增。

因此,你必须归纳总结出摩托车的设计模型,并以一般性术语(工件)定义其核心部件,并说明如何组装这些部件(逻辑装配结构)。当然,你也应该找到各个逻辑部件实现一定程度差异化的办法,这样才能满足不同终端用户的需要(可变性)。最后就是实现这些部件的可重用性。

接下来,就是对部件的描述,必须尽可能避开细节,使用任何人(如摩托车迷和普通用户)都能理解的简单用户语言。描述应该只包括部件的重要方面,而隐藏其他内容(即要进行提取和抽象)。它定义了在新产品线上生产其他各类摩托车的方法(体现了可变性)。而用户语言是意见和需求交流的工具(用领域专用语言)。至于对摩托车的全貌描述,则需要从各个彼此可独立而又有关联的方面(视角)入手,比如:电路图、燃油和润滑系统、冷却系统示意图、物理结构框架图(包含了整车所有视角的抽象模型)。

最后,你必须说明各零部件组合为完整摩托车的装配关系——这才能成为一个真正的解决方案。这部分具体包括零部件的获取、组装和配置步骤(活动)。当然,你也需要说明需使用何种原材料(人工加工)和工具(资源),以及工具的使用方法。

如你所见(如果你将上述过程和软件设计过程做了类比),绝大多数解决方案提供商(它们反复面对不同的用户需求,但实际上解决的是相同的问题)的工作方法和上述是类似的。

如果你也希望自己能在下次工作中节省力气的话,那么上述过程应该显得相当自然且富于逻辑性。这就是我有关产品线的想法。

InfoQ:那么,软件工厂如何完成产品的装配?

JES:现在,我们不得不谈到软件工厂的核心问题了——通常而言,以我们今天的实践看,领域知识和经验都存在于人们的脑子和他们构造的解决方案中。几乎没有办法将这些资源(智力的或物理的)真正转化为可重用形态,以供其他人在下一个项目中使用——甚至重用任何一点东西都显得难以办到。使用说明和开发语言通常实现了文本化管理,但物理资源则基本以最低级的非文档二进制格式保存。而且这些资源的质量和清晰度差异也很大。因此,利用这些资源所需成本往往大于其本身价值,最终,我们就看到“not-built-here”(译者注:可参看 http://timstall.dotnetdevelopersjournal.com/why_the_notbuilthere_mentality.htm )综合症这样的结果。

创新能力,本是推动软件重用的重要力量,却被严重低估。

为了实现这些资源的高可重用、可配置和可定制化,我们需要主动采取一些特殊措施。在我们目前的软件开发过程中,活动常常未加评估,因此项目结束时,往往无法为下一个项目留下任何资源。

软件工厂将此断链问题的解决推到桌前,那就是系统化捕获上述价值和资源,并将它们转化为自动化的、可供他人重用的形态。在此基础上,使用者就无须深入掌握领域专业知识,他们只要能使用软件工厂,就可快速、准确定义和装配各种部件。

软件工厂的建造过程,就是获取资源、定义其可配置的抽象手段(比如从各个方面描述摩托车),然后利用自动化方法将这些抽象转化为有形解决方案。

InfoQ:软件工厂的用户是谁,使用体验如何?

JES:软件工厂的主要用户是构造解决方案的软件专家。还是拿上面的例子来说,软件工厂向用户展示各种抽象形式(如模型、设计器、工具窗口等),并使用用户熟悉的领域内语言描述摩托车的各项特性,并多视角呈现你构造形式。可能开发小组的各工厂用户感兴趣的视角各不相同;各个小组拥有不同的技术资源;电路、发动、安全和焊接专家只关心摩托车的特定方面。而软件工厂,能为所有用户提供恰当的工具和认知角度。

工厂为用户提供的说明类似一个任务列表,包含了用户使用各种抽象模型构造每个部件的所有步骤。它能实时反映产品状态,不断为用户指出能继续进行或已完成的任务。当然在每一阶段,工厂还为用户提供准确实现部件装配的工具(且预先做好了设置);用户只需“操作几个旋钮和开关”,并给定和优化各任务中部件实现特定要求所需的配置。

InfoQ:对于用户来说,软件工厂的价值是什么?

JES:以上面的例子来说,这个价值就是:摩托车软件工厂,将确保任何摩托车爱好者和发烧友(也包括其他对技术知识,如发动机内部工作原理、更上层结构和以及制铅业更少关心的人)都能按照自己的意愿装配完成自己心目中的摩托车。

工厂构造商为用户提供了可按自己需要选择的各种部件,用户利用设计器(用来描述摩托车,用户可根据需要自行调整)就能将这些部件指定到正确位置。软件工厂根据用户指令,实现摩托车自动化装配,最终输出几乎完整的产品。当然,有兴趣的人还可在输出结果基础上继续调整和修改。

软件工厂的价值是不言而喻的,因为使用者可以从中学到很多东西。可以这么说,工厂会在过程中教给你领域知识,而不是让你一开始就向某个人学习实践知识和经验细节。

InfoQ:你在上面说“最终输出几乎完整的产品”,请解释一下。

JES:因为即使到了今天,能为终端用户提供完全满足你要求的软件解决方案厂商几乎还不存在。要做到这一点,整个模型将非常复杂,必须预置用户所有可能的设定。在早期工厂中,模型相对简单(抽象层次更高)。但随着时间的推移,它们为适应更为复杂的可变性,满足更为精细的要求,愈加庞大。一般来说,我们今天建造的大多数工厂将产品自动化完成目标定位在 60-80%,剩下的部分还需要用户自己完成。当然,目前的自动化缺口在未来会慢慢收缩,因为专业工厂一直在反复优化,一般工厂的建造过程、工具和技术也在持续发展。

InfoQ:软件工厂使用的架构是否必须是固定的?如果我想根据架构要求修改一些部件,该如何做?软件工厂的灵活性和可装配性如何?

JES:当然,软件工厂必须定义产品架构,这是工厂施行操作的基础。我们将这个架构称为“工厂模式”(Factory Schema),它为我们提供构造什么、用什么和怎么构造等信息,也是工厂构造者解决方案模型说明书的一个组成部分。而工厂构造者如何定义其产品架构的可变性,则恰是此工厂的品质之一。一些工厂会有意识将架构固化,而另一些可能允许扩展(架构本身就是体现可变性的一个方面)。

理想状态下,不应该限制产品架构的适用范围。我们平常谈及工厂时,潜意识里都假设工厂能构造出无所不包的解决方案,但在实际中,对绝大多数工厂来说,都不是这么回事。特定工厂可能仅能构造方案的一个部件,这个部件可提交给另一个工厂,再组装为更大的部件,以此类推。所以,我们可以通过若干次类似操作达成最终目标;另外,你也可以利用包含多种组件工厂(及其产品)的大型工厂管理各级部件的组装。无论哪种方式,可装配性能都是工厂的一个重要目标。在第二种情况下,需要工厂构建者共享和扩展工厂模式的部分组件。像我们演示过的 EFx Factory,以及下个版本的 WSSF(Web Service Software Factory),它们都可为其他工厂的组件、产品和架构提供插件式“扩展点”。

这也是构造所谓“横向型工厂”的一大要求,当然这样的工厂也可以朝特定行业或技术方向做垂直再造。比如,你可以自定义 WSSF,并构造一个金融支付 WebService(FPSSF)。在这种“垂直型工厂”基础上,还可以固化或扩展产品架构的某些方面,如约束部件可变性;或为某个专门领域做深入研究,如 FPSSF 可依靠行业标准固定或限制被交换消息的数据契约(Data Contract)。在前种情况下,FPSSF 将有效固化数据契约的可变性,避免用户完全自配置;而后种情况里,则实现了可变性的扩展,仅仅允许用户选择行业标准内的数据契约规范。

InfoQ:严格来说,何谓“工厂模式”?

JES:软件工厂的核心就是工厂模式(以领域专用语言为描述工具)。它告诉我们上述有关工厂正在构造的解决方案(即产品)的架构的全部信息,以及产品的逻辑可变部件有哪些么(即工件),它们彼此之间如何发生关系,如何观察这些部件(即不同视角),它们如何构造(即活动),以及使用什么工具和材料(即资源)实现构造。

产品装配活动,会在各阶段包括与之关联的工件和管理工具,以可行事件清单的方式呈现给用户。活动的进行顺序是以产品当前状态为前提的,取决于工厂用户已完成和剩下工作情况。以前面的例子来说,在气缸活塞和汽化器到位前,将发动机装配到摩托车架是没有意义的。不过你可以在其他人装配发动机的同时做摩托车外壳喷漆。也就是说,工厂中的活动只有在它具备实际意义时才会出现。这完全有别于将需做事项以 A 到 Z 的无关联清单列举的组织形式,活动只会在你(或者其他人)完成其前置活动时变成可能状态。因此,团队利用工厂工作更为容易,并能得到前后一致的自动化指导,比如现在该做什么,不该做什么(以及为什么)。

审查工厂产品的方法有很多(视角)。比如前面说过的电路图、冷却和润滑系统等。工件、资源和活动就通过不同视角组织起来。通常,特定人群只关心特定视角,而每个视角需关注的资源和活动也各不相同。如果你负责外壳喷涂,那么你就不需要了解“装配燃料道”这样活动,也不会用到扳手。同样,如果发动机归你装配,也不会需要喷雾器,并被告知现在该“为外壳打底漆”了。视角与活动及其相关资源是紧密关联的。如果你仅负责喷涂,自然无须拥有专业技工的技能和专业工具。

InfoQ:你谈到过 DSL,并介绍了它在软件工厂计划中的用途。有些读者可能对这个概念不甚了解,能否举个例子?

JES:你可以将 DSL 理解为采用专门术语实现想法和概念交流的工具。不应该强迫大家遵照某种严格的结构或过程描述问题。一般性的建模语言,比如 UML 的问题在于,你必须将自己的想法套入某些苛刻的术语和结构(比如类、操作和属性等)中。依照这种想法,你可以需要花费大量时间才能搞明白各种描述方法和符号的含义,而最终表述可能已经让你的观点丢失了原有的真实与独特性。

而 DSL,就像是给你一块巨大的白板,告诉你“把你的想法画出来,标明各个部件,并描述其属性,让我们明白它们之间的关系!”无论你使用哪种语言、什么词汇,只要将问题描述清楚就万事大吉了。至于使用文本型语言,还是常见的图表式,都没有关系。

可见,DSL 的好处在于,它赋予你用自己的语言表述事物的能力,没有粒度更细、更关注细节的苛刻语法体系。

如果你已习惯于用代码描述系统,那么需要阐明所有编程接口和对象模型。显然,这种方法对细节的涉及太深,并且要表述你的全部想法(编程语言必须)很耗费时间(特别是做修改和优化时)。类图真的是向客户描述软件的最好方式么?

DSL 的抽象层次比一般语言更高,因此它更容易把握并与之交互。这在软件工程学里,这是非常有用的,因为在同领域内协作的人(比如开发小组、管理层、客户和市场人员等)更容易理解我们研发的软件。

以开发多层应用和服务为例,使用专注于部件的语言,描述架构、架构内的组件及其交互关系会更为容易。

而 DSL 就是这样一种专门语言。

InfoQ:和普通用途的语言相比,领域专用语言的优缺点分别有哪些?

JES:像我这样的具备丰富经验的专业开发人员,从过去的实践看,很显然,完成同样的任务(如定义 SOAP 消息、用户接口或数据库查询行为),一般用途语言(如 C#/VB/C++/Java)比专用语言(如 SQL、XAML 和 SOAP)更难使用。我当然会首先想到利用像 SQL 这样的专用语言,实现与数据库的交互,而不是编写 C#/C++ 代码去实现。我相信数据库也更希望你使用受限语言完成这类工作!因为一般用途语言(如 C#)不能告知你它的使用方法,用什么描述特定问题,缺乏对边界的定义,因为它可描述问题的范围实在是太宽广了。那么在特定领域应用时,这就成了它的致命伤(译者注:原文为“Achilles Heel”,请参看 http://learning.sohu.com/20010206/file/0115,134,100005.html )。一般语言过于灵活,,以致于你可以用任何方式描述任何你想要描述的东西,这就意味着使用它难于验证你最终是否达成了开始时确立的问题目标。

比如,你在开发一个智能客户端应用(Smart Client Application)时,需要确认是否照顾到了智能客户端涉及的所有问题(比如离线处理、连通性、自动更新等)。如果使用 C#,你能对我的开发结果做核实么?而如果我使用 SQL,那么你就可能直接告诉我某处数据库查询表述是否错了。

领域专用语言将问题压缩到有限范围内,你的选择是有限的,因此使用更为容易和方便。使用者无须是经验丰富的程序员,因为语言本身及其使用的符号,对于此领域的人来说,都是非常熟悉的。

专用语言简化了对问题的描述,这本身也是一种抽象行为。它仅为你展示问题中变化的方面,而隐藏不变和复杂的内容。当然它也会告诉你可变部分的配置方法。

如果你想描述或建模的对象与已有领域模型存在差异,那么原有模型可能就帮不上什么忙了,除非它是现有问题的推广或特化模型。事物就是这样,本质上越特殊,自然就越难泛化。因此从这个角度说,领域专用语言一般不具备用于描述其他领域问题的灵活性。例如,专用于描述智能客户端应用的语言,对于描述 Web 客户端可能就束手无策了。而更一般的建模语言如 UML,对二者都可以实现描述。

InfoQ:非常感谢您抽出时间接受我的采访!

查看英文原文: Interview: Jezz Santos about Software Factories - - - - - -

译者简介:罗小平,上海某大型公司互联网中心技术总监, CSDN 大版主,网络 ID 为 lxpbuaa(桂枝香在故国晚秋),曾著有《Delphi 精要》一书。个人博客为 http://blog.csdn.net/lxpbuaa ,现在 CSDN 主持翻译国外专家 Herb Sutter 的中文博客。他的 Email 和 MSN 为 lxpbuaa AT 263.net

2007-06-17 22:271412
用户头像

发布了 26 篇内容, 共 79808 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

云小课|云小课带您快速了解LTS可视化查看

华为云开发者联盟

云计算 后端 华为云

高并发下丢失更新的解决方案

京东科技开发者

幻读 脏读 不可重复读 更新丢失

PCB layout有DRC,为什么还要用CAM和DFM检查?

华秋PCB

PCB PCB设计 PCB工具

桌面端软件的开发框架如何选型

Onegun

macos windows 桌面端 桌面应用

大数据分析如何进行?瓴羊Quick BI成为了很重要的工具

小偏执o

【Linux】之【CPU】相关的命令及解析[lscpu、mpstat]

A-刘晨阳

Linux 运维 cpu 命令 11月月更

聊聊Mybatis的数据源之PooledDataSource

急需上岸的小谢

11月月更

炎凰数据完成超亿元 A1 和 A1+ 轮融资,推出异构数据即时分析平台

晨山资本

大数据 大数据处理 大数据分析

室内高清led电子显示屏的定义

Dylan

LED显示屏 全彩LED显示屏 led显示屏厂家

百度架构师手写万字Spring Security实战笔记,一篇就搞懂

小小怪下士

Java spring springsecurity

react源码中的生命周期和事件系统

flyzz177

React

你可见过如此细致的延时任务详解

骑牛上青山

Java redis kafka 延时队列

与时俱进「风险系统保障质量之路」非同寻常

京东科技开发者

自动化 风险识别 风险控制 预警监控 风险系统

算法基础:区间合并算法及模板应用

timerring

11月月更 区间合并 算法学习

Karmada跨集群优雅故障迁移特性解析

华为云开发者联盟

云原生 后端 华为云

动手实践丨基于ModelAtrs使用A2C算法制作登月器着陆小游戏

华为云开发者联盟

人工智能 华为云 A2C算法

安卓??传奇!!探寻世界最大操作系统的崛起之路

博文视点Broadview

5种典型 API 攻击及预防建议

SEAL安全

API API安全

Centos7安装Mysql5.7(超详细版)

A-刘晨阳

MySQL Linux 运维 11月月更

centos安装python3/pip3项目所需的第三方模块(在线安装&&离线安装)

A-刘晨阳

Linux 运维 Python3 11月月更 pip3

SAP ERP系统里的那些核心主数据

SAP虾客

那些适用于跨境电商的ERP系统

SAP虾客

混合开发Hybrid App的优劣

Onegun

ios 混合应用开发 移动端 andiod 混合开发

学会二阶思维,你就能像巴菲特一样思考了

华为云开发者联盟

软件开发 开发 华为云 二阶思维

聊聊Mybatis的数据源之工厂模式

急需上岸的小谢

11月月更

react源码分析:babel如何解析jsx

flyzz177

React

ERP系统能给企业带来的那些好处

SAP虾客

主流BI软件,哪一个软件使用效果更好?

夏日星河

react源码分析:实现react时间分片

flyzz177

React

开源共建 | 中国移动冯江涛:ChunJun(原FlinkX)在数据入湖中的应用

袋鼠云数栈

flink 开源

ERP 实施,甲方公司前期应该准备什么?

SAP虾客

Jezz Santos谈软件工厂和DSL_.NET_Hartmut Wilms_InfoQ精选文章