维护用两种语言编写的实现相同逻辑的代码库有哪些方法?


10

我有一个逻辑密集型算法,需要用两种语言进行编码(实际上,我已经令人满意地用一种语言完成了编码,并且即将开始用另一种语言进行编码)。逻辑密集型是指算法不平凡,需要仔细理解,并且重要的是,可能存在将来必须修补的错误(由于复杂和粗心,您知道)。

另外,我想确保当这些代码易手时,它一定不会使新的程序员不知所措。

在这种情况下,有哪些方法可以帮助维护代码库并使它们保持同步?我的意思是软件工具,最佳做法等。

仅供参考,两种语言是C ++和Java。适用于Windows / Linux的C ++和适用于“其他所有东西”的Java(包括Android)。


3
您真的需要用另一种语言重新实现它吗?为什么不只使用Java?
奥列克西(Oleksi)2012年

@Oleksi该代码在本机运行时是最佳的,因此Java只是无法使用C ++的妥协。
Vin

13
只要绝对确保您需要该性能即可。维护一个程序的两个版本(尤其是一个复杂的版本)是一项巨大的工作。确保绝对需要使用C ++来执行此操作,因为您将花费大量时间和精力来使用两种语言来执行此操作。
Oleksi 2012年

9
正如@Oleksi所说-如果它可以在Java上的Driod上可接受地运行,我无法想象PC会需要C ++会带来的(可能是微不足道的)改进。如您所言,您尚未进行性能测试,所以我认为没有,在这种情况下,这会过早优化。用Java编写,运行性能测试,优化Java。只有这样,才考虑进行C ++重写-节省维护一个代码库的时间,改为进行优化,几乎可以肯定会执行维护两个代码库,两组所有内容的需求(需求除外)。
马滕兹

@thePrivateProject define 最好运行,无论哪种情况(C ++或Java),编写良好的代码都应该是可移植的

Answers:


16

简短的答案:除非绝对强制,否则请勿这样做。

如果必须使用C ++,则可以考虑使用NDK在C ++中为Android构建算法,然后为UI添加一个瘦Java包装器。请注意,使用NDK意味着您的代码对于各种硬件的可移植性要差很多。绝对不是在所有地方都使用Java,而是比拥有两个代码库更好。

如果您绝对不能做到这一点,并且必须有两个代码库,那么这里有三个建议:

1)寻找像Unity这样的针对便携式软件的工具。

2)尝试将代码的复杂部分提取到数据或某些脚本语言中。如果您可以编写相当通用的代码来处理脚本语言,那么测试两次就容易了。(特别是如果它是其他人创建的标准语言。)然后,您可以为复杂位使用一个代码库。(您可以尝试适用于嵌入式性的Lua。)

3)作为其他答案,请创建一个测试套件以验证两个代码集。请注意,这确实很难解决。恰好做到了这一点,我可以告诉您,它引起了关于哪个版本“正确”的大量争论,尤其是在错误情况下。

(2)和(3)可以一起使用。


4
好点。要考虑的另一件事是编写一组回归测试,并使用它测试两个实现(例如,通过SWIG)。
James Youngman

15

构建单个外部测试套件,以确保两个代码库的行为相同。我特别强调“单”一词,因为否则您将必须维护两个测试套件,它们的断言可能不同。对于如何执行此操作,我没有任何建议,但在处理此类代码库时,这似乎是保持您(以及将来的开发人员)理智的一种方法。


4

您可以使用可以先转换为Java和C ++或直接转换为机器代码和Java字节码的语言。最后我检查了LLVM是否都具有后端

编辑:Wiki浏览让我进入了GCJ,它可以将Java编译为机器代码


4

我认为,对于程序员来说,最重要的规则是“不要重复自己”。您的建议明显违反了该规则。

我会认真建议您找到一种只执行一次算法的方法。我目前可以想到两种不同的方法。

  • 使用特定领域的语言。也许可以用另一种语言(例如脚本语言)更好地表达该算法,对于这种语言,解析器可以存在于您希望在其上运行应用程序的所有平台上,或者可以基于DSL代码生成C ++ / Java代码。

  • 用C ++编写所有内容。C ++几乎可以编译到任何平台。如果在某些平台上需要将主应用程序用Java编写,则我猜可以调用一个本机库(我不太懂Java,但是我认为可以做到)。

在两个不同的平台上维护相同的算法只会导致痛苦和错误。


我想根据您的意见,应该有一个操作系统,一套办公室办公软件,一个视频播放器软件包……
..

1
@mattnz-您完全误解了我的观点。我指的是“ DRY”的编程原理。该原则绝不意味着应该只有一个操作系统,办公套件等。在坚持使用DRY的同时,您可以轻松地为多个平台生产产品。
皮特

2

除了使用通用外部测试套件的出色建议之外,您可能还希望研究有素的编程。精巧的编程工具使您能够从单个源文件生成多个文件。

LP的传统用法是允许您以一种使文档与源代码非常接近的方式来使文档与代码交织。单个noweb文件(例如)可用于生成文档文件,该文档可使用(例如)LaTex编译成更大的文档,并生成.cppand .h文件,可将其编译到您的应用程序中。

就您而言,它可以使您将代码库和文档保持在一起,并生成.java文件。

在一个文件中保持文件和不同的代码版本一起,分成逻辑上相当的部分,应该让太多容易保持他们都在相互同步。


2

这是一个测试有用的好例子。

我建议您使用一个单独的测试套件,您的两个代码库都将针对该套件。然后,您知道您的代码库都符合相同的规范!

(并且,具有良好的测试覆盖率!)



0

免责声明

如前所述,如果您真的没有其他选择,那么。

回答

一些实用的建议,而不是一个单独的答案:

(1)即使相同的东西可以做的不同,也要使用通用的结构。

示例:我必须在“ Object Pascal”和“ C ++”中具有相同的代码,其中“ if”语句都存在,则必须在“ C ++”中加上括号,但在“ Object Pascal”中则不需要。

// Object Pascal
...
if MyBollExpression
begin
  ...
end;
...

// C++
...
if (MyBollExpression)
{
  ...
}
...

变成:

// Object Pascal
...
if (MyBollExpression)
begin
  ...
end;
...

// C++
...
if (MyBollExpression)
{
  ...
}
...

在两种语言中都添加了括号。另一种情况是可选名称空间与必需名称空间(“包”)。

(3)保留标识符名称,区分大小写,特殊类型,相似,使用别名,子类化,包装:

// Java
// 
import java.io.*;

...
System.out("Hello World\n");
...

// C++
// 
include <iostream>

...
cout << "Hello World\n";
...

进入:

// Java
// 
import java.io.*;

static class ConsoleOut
{
   void Out(string Msg)
   {
     System.out("Hello World\n");
   }
}

...
ConsoleOut MyConsole = new ConsoleOut();
...
MyConsole.out("Hello World\n");
...

// C++
// 
include <iostream>

public class ConsoleOut
{
   void Out(string Msg)
   {
     cout << "Hello World\n";
   }
}

...
ConsoleOut MyConsole = new ConsoleOut();
...
MyConsole.out("Hello World\n");

...

摘要

我通常必须使用几种编程语言,并且有一些定制的“核心”库,我使用几种编程语言。

祝好运。

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.