¿Cuáles son algunas formas de mantener las bases de código escritas en dos idiomas que implementan la misma lógica?


10

Tengo un algoritmo lógico intensivo que necesito codificar en dos idiomas (en realidad lo terminé satisfactoriamente en un idioma y estoy a punto de comenzar a codificar en el otro idioma). Por lógica intensiva quiero decir que el algoritmo no es trivial, necesita una comprensión cuidadosa y, lo que es más importante, podría tener errores (debido a la complejidad y el descuido, ya sabes) que tendrían que repararse en el futuro.

Además, quiero asegurarme de que cuando este código cambie de manos, eventualmente, no debe abrumar a los nuevos programadores.

Dado este escenario, ¿cuáles son algunas formas que ayudarían a mantener las bases de código y mantenerlas sincronizadas? Por maneras me refiero a herramientas de software, mejores prácticas, etc.

Para su información, los dos lenguajes son C ++ y Java. C ++ para Windows / Linux y Java para "todo lo demás", incluido Android.


3
¿Realmente tienes que volver a implementarlo en otro idioma? ¿Por qué no usar solo Java?
Oleksi

@Oleksi El código es mejor cuando se ejecuta de forma nativa, por lo que Java fue solo un compromiso donde C ++ no se puede usar.
vin

13
Solo asegúrate absolutamente de que necesitas ese rendimiento. Mantener dos versiones de un programa (especialmente uno de este complejo) es un gran esfuerzo. Asegúrese de que absolutamente necesita hacer esto en C ++, ya que va a pagar un costo enorme en tiempo y esfuerzo para hacerlo en dos idiomas.
Oleksi

99
Como dijo @Oleksi: si se ejecuta de manera aceptable en Java en un Driod, no puedo imaginar que, dado que la PC necesita las mejoras (probablemente marginales) que dará C ++. Como no ha declarado que ha realizado pruebas de rendimiento, supongo que no, en cuyo caso esto apesta a una optimización prematura. Escriba en Java, ejecute pruebas de rendimiento, optimice Java. Solo entonces considere una reescritura de C ++: el tiempo ahorrado manteniendo una base de código, puesto en lugar de optimización en su lugar, casi seguramente superará el mantenimiento de dos bases de código, dos conjuntos de todo (excepto los requisitos).
mattnz

@thePrivateProject define ejecuta mejor , en cualquier caso (C ++ o Java) el código bien escrito debe ser portátil .

Respuestas:


16

Respuesta corta: no hagas esto a menos que sea absolutamente forzado.

Si tiene que usar C ++, entonces podría considerar usar el NDK para construir su algoritmo para Android en C ++ y luego agregar un envoltorio Java delgado para la IU. Tenga en cuenta que el uso del NDK significa que su código es mucho menos portátil para diferentes tipos de hardware. Definitivamente, esto no es preferible a usar Java en todas partes, pero es mejor que tener dos bases de código.

Si absolutamente no puede hacer esto, y tiene que tener dos bases de código, aquí hay tres sugerencias:

1) Busque una herramienta como Unity orientada al software portátil.

2) Intente extraer los bits complejos del código en los datos o en algún lenguaje de secuencias de comandos. Si puede escribir un código bastante genérico para lidiar con el lenguaje de secuencias de comandos, es más fácil probarlo y acertar dos veces. (Especialmente si es un lenguaje estándar creado por otra persona). Entonces puede tener una base de código para los bits complejos. (Puede probar Lua, que está orientado a la capacidad de inserción).

3) Como dice la otra respuesta, cree un conjunto de pruebas para validar ambos conjuntos de códigos. Tenga en cuenta que esto es realmente difícil de entender. Habiendo hecho exactamente esto, puedo decirle que genera muchos debates sobre qué versión es "correcta", especialmente en casos de error.

(2) y (3) se pueden usar juntos.


44
Buenos puntos. Otra cosa para pensar es escribir un conjunto de pruebas de regresión y probar ambas implementaciones con él (por ejemplo, a través de SWIG).
James Youngman

15

Cree un único conjunto de pruebas externas que pueda garantizar que ambas bases de código se comporten de la misma manera. Pongo énfasis adicional en la palabra "single" porque de lo contrario tendrá que mantener dos conjuntos de pruebas que pueden diferir en sus afirmaciones. No tengo ninguna sugerencia sobre cómo hacer esto, pero parece una forma de mantener su cordura (y la de los futuros desarrolladores) al trabajar en este tipo de código base.


4

puede usar un lenguaje que pueda compilarse en código de máquina y código de bytes java, ya sea transformando primero en java y C ++ o directamente. La última vez que verifiqué que LLVM tiene back-end para ambos

editar: un poco de navegación en la wiki me llevó a GCJ, que puede compilar Java al código de máquina


4

En mi opinión, la regla más importante para un programador es "No te repitas". Lo que sugiere es una clara violación de esta regla.

Sugeriría seriamente que encuentre una manera de implementar el algoritmo solo una vez. Actualmente puedo pensar en dos enfoques diferentes.

  • Use un lenguaje específico de dominio. Quizás el algoritmo pueda expresarse mejor en un lenguaje diferente, por ejemplo, un lenguaje de script, para el cual podría existir un analizador en todas las plataformas en las que espera ejecutar la aplicación, o podría generar código C ++ / Java basado en el código DSL.

  • Escribe todo en C ++. C ++ se puede compilar a prácticamente cualquier plataforma. Si en algunas plataformas necesita que la aplicación principal esté escrita en Java, supongo que es posible llamar a una biblioteca nativa (no tengo mucho conocimiento en Java, pero supongo que se puede hacer).

Mantener el mismo algoritmo en dos plataformas diferentes solo puede generar dolor y errores.


Supongo que por su opinión no debería haber un sistema operativo, en traje de productividad de oficina, un paquete de software de vídeo reproductor ........
mattnz

1
@mattnz - Has entendido mal mi punto. Me refiero al principio de programación de "DRY". Ese principio de ninguna manera sugiere que debería haber un solo sistema operativo, suite ofimática, etc. Puede producir fácilmente un producto para múltiples plataformas mientras se apega a DRY.
Pete

2

Además de los excelentes consejos para usar un conjunto de pruebas externo común, es posible que desee considerar la programación alfabetizada . Las herramientas de programación literarias le brindan la capacidad de producir múltiples archivos a partir de un solo archivo fuente.

El uso tradicional de LP es permitirle entrelazar documentación con código de una manera que le permita mantener la documentación muy cerca del código fuente. Un solo archivo noweb (por ejemplo) podría usarse para generar un archivo de documentación que podría compilarse en un documento más grande usando (digamos) LaTex, y producir un archivo .cppy .hque podría compilarse en su aplicación.

En su caso, podría permitirle mantener juntas las bases de código y la documentación, produciendo un .javaarchivo también.

Mantener la documentación y las diferentes versiones de código juntas en un solo archivo, dividido en secciones lógicamente equivalentes, debería hacer que sea mucho más fácil mantenerlos sincronizados entre sí.


2

Este es un buen ejemplo de dónde las pruebas pueden ser útiles.

Yo sugeriría que tiene un único conjunto de pruebas de que tanto su base de código ejecuta contra. ¡Entonces sabrá que sus bases de código se ajustan a la misma especificación!

(¡y tenga una buena cobertura de prueba!)


1

Considere la posibilidad de generar código en C ++ y Java desde otro lenguaje


0

Descargo de responsabilidad

Como se mencionó en publicaciones anteriores, si realmente no tienes otra opción, entonces.

Responder

Varias sugerencias prácticas, en lugar de una sola respuesta:

(1) Use estructuras comunes, incluso, si las mismas cosas se pueden hacer de manera diferente.

Ejemplo: tenía que tener el mismo código en "Object Pascal" y "C ++", donde la oración "if" existe en ambos, el paréntesis en "C ++" es obligatorio, pero no en "object Pascal".

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

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

Cambiado a:

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

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

Paréntesis agregado a ambos idiomas. Otro caso será espacios de nombres opcionales versus espacios de nombres requeridos ("paquetes").

(3) Mantener nombres de identificadores, mayúsculas y minúsculas, especialmente tipos, similares, usar alias, subclases, envoltura:

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

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

// C++
// 
include <iostream>

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

Dentro:

// 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");

...

Resumen

Normalmente tengo que trabajar con varios lenguajes de programación, y hay algunas bibliotecas "básicas" personalizadas que guardo en varios lenguajes de programación.

Buena suerte.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.