繁体   English   中英

如何跨不同的编程语言分享业务概念?

[英]How to share business concepts across different programming languages?

我们开发了一个分布式系统,该系统是用不同编程语言(C ++,C#和Python)实现的组件构建的,并通过网络相互通信。 系统中的所有组件都以相同的业务概念运行,并且在这些概念方面也相互通信。

结果,我们在以下两个挑战中奋力拼搏:

  1. 保持我们的业务概念在这三种语言中的表现同步
  2. 跨这些语言对我们的业务概念进行序列化/反序列化

这个问题的一个天真的解决方案就是定义相同的数据结构(和序列化代码)三次(对于C ++,C#和Python)。

不幸的是,这种解决方案有严重的缺点:

  • 它创造了很多“代码重复”
  • 它需要大量的跨语言集成测试才能使所有内容保持同步

我们考虑的另一个解决方案是基于ProtoBufs或Thrift等框架。 这些框架具有内部语言,其中定义了业务概念,然后这些框架自动生成C ++,C#和Python(以及序列化逻辑)中这些概念的表示。

虽然此解决方案没有上述问题,但它还有另一个缺点:这些框架生成的代码将表示底层业务概念的数据结构和序列化/反序列化这些数据结构所需的代码耦合在一起。

我们认为这污染了我们的代码库 - 我们系统中使用这些自动生成的类的任何代码现在都“熟悉”这种序列化/反序列化逻辑(严重的抽象泄漏)。

我们可以通过我们的类/接口包装自动生成的代码来解决它,但这使我们回到了天真解决方案的缺点。

任何人都可以推荐解决所述问题的解决方案吗?

列夫,你可能想看看ICE 它提供面向对象的IDL,并映射到您使用的所有语言(C ++,Python,.NET(据我所知,所有.NET语言,而不仅仅是C#))。 虽然ICE是一个中间件框架,但您不必遵循其所有策略。

特别是在您的情况下,您可能希望在ICE IDL中定义组件的接口,并将它们作为代码的一部分进行维护。 然后,您可以生成代码作为构建例程的一部分并从那里开始工作。 或者你可以使用ICE给你的更多力量。

ICE支持C ++ STL数据结构并且它支持继承,因此它应该为您提供足够强大的形式,以便随着时间的推移逐步构建您的系统,并具有良好的可维护性。

好吧,曾几何时MS试图用IDL来解决这个问题。 好吧,实际上它试图解决的问题不仅仅是定义数据结构,但是,无论如何,这一切都在过去,因为现在没有一个心智正常的人会去COM路线。

要看的一个选项是SWIG ,它应该能够移植数据结构以及跨语言的实际调用。 我自己没有这样做,但有可能它不会像序列一样紧密地将序列化和数据结构耦合在一起。

但是,你应该考虑上述耦合是否是一件坏事。 什么是理想的解决方案? 据说它可以做两件事:它根据一个定义生成跨多种语言的兼容数据结构,它还提供序列化代码将它们拼接在一起 - 但是在一个单独的抽象层中。 我们的想法是,如果有一天您决定使用不同的序列化方法,您可以切换出该层,而无需重新定义所有数据结构。 所以考虑一下 - 实际上有多么真实地期望有一天只切换序列化代码而根本不接触接口? 在大多数情况下,序列化格式是最永久的设计选择,因为您通常会遇到向后兼容等问题 - 所以您愿意立即支付多少开发成本,以便能够在理论上将其拉出来。未来?

现在让我们假设存在这样一种工具,它将数据结构生成与序列化分开。 让我们说,2年后你决定需要一个完全不同的序列化方法。 除非此工具还支持可插入的序列化格式,否则无论如何都需要开发该层,以便将现有结构与新的序列化解决方案相结合 - 这与完全选择新的包一样多。 因此,满足您需求的唯一真正可行的解决方案不仅支持所有语言的数据类型定义和代码生成,而且不仅与序列化无关,而且还可以实现您希望的未来序列化格式的实现切换到 - 因为如果它只对序列化格式不可知,那意味着你仍然需要自己实现它 - 在所有语言中 - 这比重新定义一些数据结构要少得多。

所以我的观点是,序列化和数据类型定义经常合在一起是有原因的 - 它只是最常见的用例。 我会仔细研究一下你希望能够使用你需要的抽象级别实现什么,想想开发这样一个解决方案需要做多少工作以及它是否值得。 我确信这些工具可以做到这一点,顺便说一句 - 可能是昂贵的专有类,每个许可证的成本为1万美元 - 我认为同样的论点也适用于此 - 它可能只是过度工程化。

我同意Tristan Reid(包含业务逻辑)。 实际上,几个月前我遇到了同样的问题,然后偶然发现了“Unix编程的艺术”一书(可在网上免费获得)。 引起我注意的是将策略与机制分离的理念(即来自引擎的接口)。 现代编程环境(如.NET平台)尝试将所有内容集成到单个域下。 在那些日子里,我被要求开发一个必须满足以下要求的WEB应用程序:

  1. 它必须能够轻松适应用户界面的未来趋势,而无需更改核心算法。

  2. 它必须通过不同的接口访问:web,命令行和桌面GUI。

  3. 它必须在Windows和Linux上运行。

我打赌用C / C ++完全开发机制(引擎)并使用本机OS库(POSIX或WinAPI)和良好的开源库(postgresql,xml等......)。 我开发了引擎模块作为命令行程序,我最终实现了2个接口:web(使用PHP + JQuery框架)和桌面(.NET框架)。 这两个接口都与机制无关:它们只是通过调用Windows中的CreateProcess()或UNIX中的fork()等函数来启动核心模块可执行文件,并使用管道来监视它们的进程。

我不是说UNIX编程哲学对所有目的都有好处,但我从那时起应用它并取得了良好的效果,也许它对你也有用。 选择实现机制的语言,然后使用另一种使界面设计变得容易的语言。

系统中的所有组件都以相同的业务概念运行,并且在这些概念方面也相互通信。

当我找到你的时候,你已经将你的系统分成不同的部分,通过定义良好的接口进行通信。 但是你的接口共享你称之为“业务概念”的数据结构(很难理解而没有看到一个例子),并且由于这些接口必须为所有三种语言构建,因此在保持它们“同步”时会遇到问题。

保持接口同步会出现问题,那么很明显您的接口过于宽泛。 使用不同的解决方案有不同的可能原因。

可能的原因1 - 您过度概括了您的界面概念。 如果是这种情况,请在此重新设计:在板上进行泛化并创建只有它们必须广泛的接口。

可能的原因2:用不同语言编写的部分不处理单独的业务案例,它们之间可能有“水平”分区,但不是垂直分区。 如果是这种情况,则无法避免接口的广泛性。

如果原因2是您的问题,代码生成可能是正确的方法。 如果现有的代码生成器不满足您的需求,为什么不编写自己的代码生成器呢? 在C#中定义接口,例如作为类,引入一些元属性,并在代码生成器中使用反射,在生成相应的C ++,Python以及“实际使用的”C#代码时再次提取信息。 如果您需要使用或不使用序列化的不同变体,也可以生成它们。 一台工作的发电机应该比几天更省力(YMMV取决于您的要求)。

您可以将业务逻辑包装为Web服务,并使用所有三种语言调用它 - 只需一个实现。

您可以使用UML建模器之类的工具对这些数据结构进行建模(因为它可以为所有人生成代码,因此可以想到Enterprise Architect),然后直接从模型生成每种语言的代码。

虽然我会仔细研究之前关于使用XSD的评论。

我会通过使用某种关于域实体的元信息(XML或DSL,取决于复杂性)来实现这一点,然后为每种语言进行代码生成。 这将减少(手动)代码重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM