Quali sono alcuni modi per mantenere basi di codice scritte in due lingue che implementano la stessa logica?


10

Ho un algoritmo ad alta intensità di logica che devo codificare in due lingue (in realtà l'ho finito in una lingua in modo soddisfacente e sto per iniziare a programmare in un'altra lingua). Per logica intensiva intendo che l'algoritmo non è banale, ha bisogno di un'attenta comprensione e, soprattutto, potrebbe avere dei bug (a causa di complessità e disattenzione, sai) che dovrebbero essere corretti in futuro.

Inoltre, voglio assicurarmi che quando questo codice cambia di mano, alla fine, non deve sopraffare i nuovi programmatori.

Dato questo scenario, quali sono alcuni modi che potrebbero aiutare a mantenere le codebase e mantenerle sincronizzate? Per mezzi intendo strumenti software, migliori pratiche ecc.

Cordiali saluti, le due lingue sono C ++ e Java. C ++ per Windows / Linux e Java per "tutto il resto" incluso Android.


3
Devi davvero implementarlo nuovamente in un'altra lingua? Perché non usare solo Java?
Oleksi,

@Oleksi Il codice è migliore quando viene eseguito in modo nativo, quindi Java era solo un compromesso in cui C ++ non può essere utilizzato.
vin

13
Assicurati solo di aver bisogno di quella performance. Mantenere due versioni di un programma (in particolare una così complessa) è uno sforzo colossale. Assicurati di aver assolutamente bisogno di farlo in C ++, perché pagherai un costo enorme in termini di tempo e sforzi per farlo in due lingue.
Oleksi,

9
Come ha detto @Oleksi - se funziona in modo accettabile in Java su un Driod, non posso immaginare che dato che il PC ha bisogno dei miglioramenti (probabilmente marginali) che il C ++ darà. Dato che non hai dichiarato di aver eseguito test delle prestazioni, presumo di no, nel qual caso questo puzza di ottimizzazione prematura. Scrivi in ​​Java, esegui test delle prestazioni, ottimizza Java. Solo allora considera una riscrittura C ++ - il tempo risparmiato mantenendo una base di codice, messo invece in optimaisation, quasi sicuramente funzionerà mantenendo due basi di codice, due serie di tutto (tranne i requisiti).
mattnz,

@thePrivateProject define funziona meglio , in entrambi i casi (C ++ o Java) il codice ben scritto dovrebbe essere portabile .

Risposte:


16

Risposta breve: non farlo se non assolutamente forzato.

Se devi usare C ++, potresti prendere in considerazione l'utilizzo di NDK per creare l'algoritmo per Android in C ++ e quindi aggiungere un sottile wrapper Java per l'interfaccia utente. Nota che l'uso di NDK significa che il tuo codice è molto meno portabile su diversi tipi di hardware. Questo non è sicuramente preferibile all'uso di Java ovunque, ma è meglio che avere due basi di codice.

Se non puoi assolutamente farlo e devi avere due basi di codice, ecco tre suggerimenti:

1) Cerca uno strumento come Unity orientato al software portatile.

2) Prova a inserire i bit complessi del codice nei dati o in alcuni linguaggi di scripting. Se riesci a scrivere un codice abbastanza generico per gestire il linguaggio di scripting, è più facile testarlo e farlo due volte. (Soprattutto se è un linguaggio standard creato da qualcun altro.) Quindi puoi avere una base di codice per i bit complessi. (Potresti provare Lua, che è orientata verso l'incorporabilità.)

3) Come indicato nell'altra risposta, creare una suite di test per convalidare entrambi i set di codici. Si noti che questo è davvero difficile da ottenere. Avendo fatto esattamente questo, posso dirti che ha suscitato molti dibattiti su quale versione sia "giusta", specialmente in casi di errore.

(2) e (3) possono essere usati insieme.


4
Punti buoni. Un'altra cosa a cui pensare è scrivere una serie di test di regressione e testare entrambe le implementazioni con esso (ad esempio tramite SWIG).
James Youngman,

15

Crea una singola suite di test esterna in grado di garantire che entrambe le basi di codice si comportino allo stesso modo. Metto maggiormente l'accento sulla parola "single" perché altrimenti dovrete mantenere due test suite che possono differire nelle loro affermazioni. Non ho alcun suggerimento su come farlo, ma sembra un modo per mantenere la sanità mentale (e dei futuri sviluppatori) quando si lavora su questo tipo di base di codice.


4

è possibile utilizzare un linguaggio che può essere compilato in codice macchina e codice byte java trasformandosi prima in java e C ++ o direttamente. L'ultima volta che ho controllato LLVM ha back-end per entrambi

modifica: un po 'di navigazione wiki mi ha portato a GCJ che può compilare Java in codice macchina


4

Secondo me, la regola più importante per un programmatore è "Non ripetere te stesso". Quello che suggerisci è una chiara violazione di questa regola.

Suggerirei seriamente di trovare un modo per implementare l'algoritmo solo una volta. Al momento posso pensare a due approcci diversi.

  • Utilizza una lingua specifica del dominio. Forse l'algoritmo può essere espresso meglio in una lingua diversa, ad esempio un linguaggio di script, per il quale potrebbe esistere un parser su tutte le piattaforme su cui ci si aspetta di eseguire l'applicazione, oppure è possibile generare codice C ++ / Java basato sul codice DSL.

  • Scrivi tutto in C ++. Il C ++ può essere compilato praticamente su qualsiasi piattaforma. Se su alcune piattaforme si richiede che l'applicazione principale sia scritta in Java, immagino che sia possibile chiamare una libreria nativa (non sono molto ben informato in Java, ma presumo che possa essere fatto).

Mantenere lo stesso algoritmo su due piattaforme diverse può solo causare dolore e bug.


Suppongo che secondo te ci dovrebbe essere un sistema operativo, sulla tuta per la produttività dell'ufficio, un pacchetto software per il lettore video ........
mattnz,

1
@mattnz - Hai completamente frainteso il mio punto. Mi riferisco al principio di programmazione di "DRY". Tale principio non suggerisce in alcun modo che ci dovrebbe essere un solo sistema operativo, una suite per ufficio, ecc. È possibile produrre facilmente un prodotto per più piattaforme mentre si utilizza DRY.
Pete,

2

Oltre all'eccellente consiglio di utilizzare una suite di test esterna comune, potresti voler esaminare la programmazione alfabetica . Gli strumenti di programmazione alfabetici ti danno la possibilità di produrre più file da un singolo file sorgente.

L'uso tradizionale di LP consente di intercalare la documentazione con il codice in un modo che consenta di mantenere la documentazione molto vicino al codice sorgente. Un singolo file noweb (ad esempio) può essere usato per generare un file di documentazione che può essere compilato in un documento più grande usando (diciamo) LaTex, e produce un file .cppe .hche può essere compilato nella tua applicazione.

Nel tuo caso, potrebbe consentire di tenere insieme sia le basi di codice che la documentazione, producendo anche un .javafile.

Mantenere la documentazione e le diverse versioni di codice in un unico file, suddiviso in sezioni logicamente equivalenti, dovrebbe rendere molto più facile mantenerle tutte sincronizzate.


2

Questo è un buon esempio di dove i test possono essere utili.

Suggerirei di avere una singola suite di test su cui entrambi la tua base di codice funziona contro. Allora sai che le tue basi di codice sono entrambe conformi alla stessa specifica!

(e, buona copertura del test!)



0

disconoscimento

Come accennato in precedenza, i post, se non hai davvero un'altra scelta, allora.

Risposta

Diversi suggerimenti pratici, anziché una singola risposta:

(1) Usa anche strutture comuni, se le stesse cose possono essere fatte diversamente.

Esempio: dovevo avere lo stesso codice in "Oggetto Pascal" e "C ++", dove esiste la frase "if" in entrambi, è richiesta la parentesi in "C ++", ma non in "oggetto Pascal".

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

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

Cambiato in:

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

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

Aggiunta parentesi in entrambe le lingue. Un altro caso saranno gli spazi dei nomi opzionali rispetto agli spazi dei nomi richiesti ("pacchetti").

(3) Conservare i nomi degli identificatori, la sensibilità al maiuscolo / minuscolo, in particolare i tipi, simili, utilizzare gli alias, la sottoclasse, il wrapping:

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

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

// C++
// 
include <iostream>

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

In:

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

...

Sommario

Di solito devo lavorare con diversi linguaggi di programmazione e ci sono alcune librerie "core" personalizzate, che conservo in diversi linguaggi di programmazione.

In bocca al lupo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.