Perché è sbagliato scrivere qualcosa nella lingua X come se si stesse scrivendo un programma in linguaggio Y in termini di utilizzo di un paradigma di codifica condiviso [chiuso]

25

Qualche tempo fa, ho fatto una domanda su SO di qualcosa scritto in C ++, ma invece di ottenere una risposta al problema in questione, i commenti sono andati pazzi per il mio stile di codifica, anche quando ho indicato che era un < a href="http://en.wikipedia.org/wiki/Work_in_progress" title="work in progress"> WIP pezzo di codice e che intendevo ripulirlo più tardi quando avevo il caso base in esecuzione . (Ho ottenuto così tanti voti negativi che ho deciso di tirare la domanda, dato che il mio rappresentante su SO è già quasi abissale)

Mi sono chiesto perché le persone adottino una linea così dura "sei un noob, vai fottiti". Ero accusato di scrivere C ++ come se fosse Java. Qualcosa che non riesco a capire, e questo mi confonde ancora.

Ho programmato in alcune lingue OOP per un certo numero di anni, anche se a intervalli regolari. Scelgo la lingua da utilizzare in termini di librerie disponibili e ambienti di esecuzione ottimali per il lavoro da svolgere. Adotto i modelli di progettazione nel codice OOP e sono abbastanza fiducioso che il mio uso dei pattern sia sano e che OO saggio, posso tenere il mio. Capisco la toolbox OOP, ma scelgo di usare gli strumenti solo quando penso che sia veramente necessario, non solo di usare un trucco accurato per mostrare il mio ingegno di codifica. (Che so che non sono di prim'ordine, ma penso che non siano nemmeno al livello n00b).

Ho progettato il mio codice prima di scrivere una singola riga. Per definire i test, elenco gli obiettivi di una determinata classe e i criteri di test a cui deve aderire. Poiché è più facile per me creare diagrammi di sequenza e quindi scrivere codice, ho scelto di scrivere i miei test dopo che l'interfaccia è diventata ovvia.

Devo ammettere che nel pezzo di codice che ho postato nella domanda, stavo ancora usando i puntatori, invece di usare i puntatori intelligenti. Uso RAII ogni volta che posso. So che RAII corretto significa salvaguardare da nullpointers, ma lavoro in modo incrementale. Era un lavoro in corso e volevo ripulirlo più tardi. Questo modo di lavorare è stato condannato con forza.

A mio avviso, dovrei prima avere un esempio funzionante, così posso vedere se il caso base è un modo di pensare praticabile. Penso anche che ripulire il codice sia tipico della fase di refactoring dell'agile, dopo che il caso base è stato dimostrato. Devo ammettere che anche se sto lentamente ottenendo lo standard Cxx, preferisco usare quello che capisco, invece di correre il rischio di usare concetti che non ho ancora imparato nel codice di produzione. Cerco di provare cose nuove una volta ogni tanto, ma di solito nei progetti di gioco che ho sul lato, solo per quello scopo.

[modifica] Vorrei chiarire che il suggerimento di gnat [1] non è apparso nella ricerca che ho fatto prima di iniziare a porre la mia domanda. Tuttavia, sebbene il suo suggerimento copra un aspetto della domanda, la domanda a cui si è collegato non risponde al cuore della mia domanda, solo una parte di essa. La mia domanda riguarda più la risposta che ho ottenuto al mio stile di codifica e gli aspetti professionali della gestione di diversi stili di codifica e (apparenti) livelli di abilità. Con la mia precedente domanda su SO e la risposta è un esempio calzante. [/ Modifica]

La domanda quindi è: perché deridere qualcuno che non usa il tuo stile di codifica?

Le questioni / sottodivisioni in corso per me sono:

  • Perché sarebbe una cattiva pratica di programmazione utilizzare più codice soggetto a errore in situazioni di prototipo, se il refactoring lo rende più robusto in seguito?
  • Come può il programma scritto in C ++ essere come se fosse scritto in Java? Cosa lo rende un cattivo programma, (considerando che ho indicato l'intento dello stile attuale e il lavoro previsto per migliorare?)
  • Come sarei un cattivo professionista se scegliessi di utilizzare un costrutto che viene utilizzato in un certo paradigma di programmazione (ad esempio OOP / DP)?

[1] Sviluppa velocemente e con errori, quindi correggi gli errori o sii lento, attento per ogni riga di codice?

    
posta Onno 26.03.2014 - 17:14
fonte

5 risposte

26

Senza vedere il codice in questione, ci sono alcuni modi per scrivere codice Java in C ++, alcuni peggio di altri.

  1. All'estremo opposto, la tua fonte è come Java: tutto in un unico file, tutto all'interno della definizione della classe, ecc .:
    class HelloWorldApp {
    public:
        void main() {
            cout << "Hello World!" << endl;
        }
    };
    
    Questo è il modo in cui sarebbe presentata la sorgente Java. È tecnicamente legale in C ++, ma mettere tutto nel file di intestazione e tutto inline (definendolo nella dichiarazione della classe) è terribile e ucciderà le tue prestazioni di compilazione. Non farlo
  2. Eccessivamente OO - Per semplificare eccessivamente, in Java, è il Regno dei nomi , dove tutto è un oggetto. Il codice C ++ buono (cioè idiomatico) ha più probabilità di utilizzare funzioni, modelli, ecc. Gratuiti, invece di provare a racchiudere tutto in un oggetto.
  3. No RAII - L'hai già detto - usando i puntatori e la pulizia manuale invece dei puntatori intelligenti. C ++ ti fornisce strumenti come RAII e puntatori intelligenti, quindi un codice C ++ (cioè, idiomatico) buono usa quegli strumenti.
  4. No C ++ avanzato - Le basi di Java e C ++ sono abbastanza simili, ma una volta entrate in funzioni più avanzate (modelli, libreria di algoritmi di C ++, ecc.), iniziano a divergere.

Fatta eccezione per # 1, nessuno di questi rende un programma C ++ un programma errato, ma non è nemmeno il tipo di codice su cui preferisco lavorare come programmatore C ++. (Inoltre non mi piacerebbe lavorare con Perl non-idiomatico o stile C, Python non idiomatico, ecc.) Un linguaggio ha i suoi strumenti, i suoi idiomi e la sua filosofia, e il buon codice usa quegli strumenti e questi idiomi invece di provare ad usare il minimo comune denominatore o il tentativo di riprodurre l'approccio di un'altra lingua. Scrivere un codice non idiomatico in un particolare dominio linguistico / problema / qualsiasi cosa non renda qualcuno un programmatore malvagio, significa solo che hanno ancora molto da imparare su quel linguaggio / dominio problema / qualsiasi cosa. E non c'è niente di sbagliato in questo; c'è una lunga lista di cose su cui ho ancora molto da imparare, e il C ++ in particolare ha un sacco di cose da imparare.

Riguardo alla particolare questione di scrivere codice soggetto a errori con l'intento di ripulirlo più tardi, non è in bianco e nero:

  • Se alcuni codici prototipo non riescono a gestire tutte le possibili eccezioni e tutti i casi d'angolo possibili, allora è prevedibile. Falla funzionare, quindi fallo funzionare in modo efficace. Nessun problema.
  • Se un codice prototipo è scritto in quello che è semplicemente uno stile cattivo o un disegno errato (cattivo per il linguaggio dato e i suoi idiomi, un design fondamentalmente cattivo per il problema , ecc.), quindi a meno che tu non lo stia scrivendo come bozza di prova da buttare via, non stai guadagnando nulla.

Per usare puntatori grezzi contro puntatori intelligenti come esempio, se lavorerai in C ++, l'uso di RAII e puntatori intelligenti sono fondamentali abbastanza che dovrebbe essere più veloce scrivere codice in questo modo tornare indietro e ripulirlo più tardi. Di nuovo, non farlo non significa che qualcuno sia un programmatore cattivo, poco professionale, ecc., Ma significa che c'è ancora molto da imparare.

    
risposta data 26.03.2014 - 17:42
fonte
42

Ogni linguaggio di programmazione ha una serie di idiomi e best practice, che di solito portano a un codice elegante, corretto e performante. Qui ci sono alcune pratiche peggiori che stanno perfettamente bene in qualche altra lingua:

  • urlerò se scrivi for ($i = 0; $i < 42; $i++) { … } in Perl, ma non in PHP
    (in Perl, le variabili dovrebbero essere dichiarate e tali loop dovrebbero scorrere su un intervallo)
  • Piangerò se scrivi new Foo() in C ++ senza una buona ragione, ma non in Java (C ++ non ha garbage collection, quindi dovrebbe essere usato RAII. Noobs perderà la memoria altrimenti)
  • Mi vergognerei se dichiarassi tutte le tue variabili nella parte superiore della tua funzione, tranne in C89, Pascal o JavaScript.
  • Farò facepalm se metti tutte le tue funzioni in una classe in Python, ma non in Java
    (Python è un linguaggio multi-paradigma che invece costringe "OOP" e supporta le funzioni al livello superiore)
  • Piangerò se tu return null in Scala, ma non in qualsiasi linguaggio simile a C
    (perché Scala ha un tipo Option )
  • Mi lamenterò se scrivi un algoritmo ricorsivo in Java, ma non in OCaml
    (perché lo stack di Java si espande rapidamente, mentre OCaml ha l'ottimizzazione della coda)
  • ...

È facile usare una nuova lingua come se fosse qualcosa che sai, e con un po 'di fortuna funzionerà anche. "Puoi scrivere Fortran in qualsiasi lingua". Ma davvero non vuoi ignorare le caratteristiche specifiche offerte dal linguaggio X, perché è probabile che X offra qualche vantaggio rispetto a U.

" Scelgo la lingua da utilizzare in termini di librerie disponibili e ambienti di esecuzione ottimali per il lavoro in corso " - ma se questa lingua X è effettivamente migliore della lingua U per il lavoro a portata di mano dipende anche da quanto sia familiare con quel linguaggio, o quanto tempo ci vorrà per diventare sufficientemente familiare per poterlo usare bene. Non daresti una pesante motosega solo perché taglia il legno più velocemente, quando in realtà vuoi il tuo vecchio coltello a penna perché si adatta perfettamente alla tua mano. A meno che tu non voglia davvero abbattere un albero.

Ma la tua domanda riguarda più un problema culturale : l'apprendimento di tutte le best practice richiede molto tempo ei neofiti fanno più domande, mentre i guru rispondono. Ma ciò che è ovvio per un guru non è ovvio per un novizio, ei guru a volte lo dimenticano. Come novizio, la soluzione non è quella di smettere di fare domande. Tuttavia, uno può mostrare un'apertura per apprendere e applicare le migliori pratiche, ad es. cercando di pulire il tuo codice il più possibile prima mostrandolo agli altri. La maggior parte delle lingue ha alcune best practice di base facili da imparare, anche quando l'intera curva di apprendimento è in realtà molto lunga.

Un problema comune è che le persone nuove alla programmazione ignorano qualsiasi indentazione o altra formattazione e quindi sono confusi perché il loro programma non funziona. Sarei anche confuso, e il primo passo per capire un programma è assicurarsi che sia perfettamente strutturato. Quindi, errori semplici come una citazione di chiusura dimenticata o una virgola mancante diventano improvvisamente evidenti. Confido che tu stia già esercitando una buona formattazione, e qui è una metafora per altre best practice: le migliori pratiche prevengono gli errori, le best practice rendono più facile trovare errori, applicando le migliori pratiche prima trovando il problema .

È troppo economico dire "Lo aggiusterò più tardi", quando ripararlo ora avrebbe risolto il tuo problema (anche, quella favolosa "fase di pulizia" potrebbe non arrivare mai, quindi l'unica opzione responsabile è fare è giusto la prima volta). Per lo meno, provare a rendere il tuo codice il più buono possibile prima di chiedere aiuto agli altri rende più facile ragionare sul tuo codice, quindi è una cosa educata da fare.

    
risposta data 26.03.2014 - 18:05
fonte
12

Non sono uno sviluppatore C ++ hardcore, ma ...

Why would it be a bad programming practice to use more error prone code in prototype situations, if refactoring makes it more robust afterward?

Una cosa da tenere a mente è che un errore in C ++ di solito significa "comportamento indefinito". In un linguaggio sicuro, il peggio che potrebbe accadere è un'eccezione che interrompe immediatamente il tuo programma. In C ++, sei fortunato se ottieni un segfault. È assolutamente possibile che il tuo programma continui a fare qualcosa di leggermente sbagliato. Potrebbe anche comportarsi correttamente per un certo periodo di tempo e manifestare bug molto più tardi, oppure potrebbe comportarsi in modo corretto tutto il tempo ma alla fine consumare tutta la memoria.

In ogni caso, basta un solo errore per portare l'esecuzione del programma completamente fuori dai binari e in un territorio inesplorato. È probabile che per lo sviluppatore C ++ a tempo pieno, il "caso base" significhi "nessuna possibilità di comportamento indefinito o perdite di memoria".

How would can program written in C++ be like it was written in Java? What makes it a bad program?

Non penso che ci sia una risposta a questo che non sarà in gran parte speculativo e supponente. Se vuoi la mia opinione su di esso, Java tende ad avere un paio di antipattern associati come il fatto che tutto deve essere un oggetto. Dove in altre lingue si passa un puntatore, un functor o una funzione, in Java solitamente si trovano tonnellate di% ca_de% vacue e poco utili, ThingDoers e FooFactories che sono solo funzioni mascherate.

Allo stesso modo, dove in altre lingue potresti passare una semplice struttura tupla o senza nome, in Java per unire anche solo 2 oggetti in un semplice contenitore di dati è necessario predefinire una classe NamedThing di oltre 30 linee con setter, getter e Javadoc . La relativa mancanza di funzionalità di Java costringe i programmatori a fare double backflip orientati agli oggetti per fare le cose a volte. Il codice risultante è raramente idiomatico al di fuori di Java.

Quindi c'è il fatto che in C ++ è necessario un grafo di oggetti molto semplificato per gestire manualmente la memoria; di solito un oggetto è di proprietà esattamente di un altro oggetto. In Java non è necessario seguire vincoli così stretti, perché il garbage collector garantisce che le cose vengano ripulite quando non ci sono più riferimenti a esse. Quindi c'è sicuramente il rischio di una gestione errata della memoria se si esegue la traslitterazione del codice da Java a C ++.

Infine, potrebbe essere solo l'elitarismo. Non farò finta di esserne la maggioranza, ma ho sicuramente sentito un sentimento di "Non ho bisogno di un linguaggio che mi tenga la mano e mi impedisca di fare cose stupide" tra alcuni sviluppatori C ++. Nelle loro menti il C ++ è un linguaggio "reale" e se non puoi gestire le sue idiosincrasie non sei un "vero programmatore".

    
risposta data 26.03.2014 - 17:53
fonte
6

Risposta leggermente fuori tema ...

Non preoccuparti - questo è un "comportamento" comune in qualsiasi comunità di esperti. E sii onesto, se sei bravo in qualsiasi lingua, e incontrerai un codice che è "strano", probabilmente lo criticherai anche tu. (perché, vuoi TEACH).

Sono nel perl-world - quando vedrà qualcosa di simile:

$imax=$#array;
$str=""
for($i=0; $i<$imax; $i++) {
    $str = "$str" . $array[$i];
}

invece di:

my $str = join '', @array;

sicuramente lo commenterà - (leggi: insegna all'autore) sulla funzione join .

In ogni caso, la critica troppo è controproducente e uno dei migliori esempi è il seguente: (afferrato da: link )

(Questo bit è stato pubblicato in modo anonimo su un pastebot il 23 marzo 2011. È collocato qui per i posteri dopo alcune modifiche.) - leggermente modificato anche

Question: how can I switch on my TV?

What the OP wants to hear?

For example: Locate on/off button your TV remote a press it. The button is usually red and located at the topmost line on the remote.

The #perl expert's answer: First, what do you mean with "switch on"? Define it first. Nopaste your TV, TV remote and the living room too.

... after a nopaste:

Your room is ugly. And the TV looks terrible. Use Mr. Clean on the screen, and clean your living room first. Use three cleaning mops instead of two. Use HDMI and never use scart (?) connectors, unless you really want to. Your TV remote has unreadable buttons, clean up first. You're a beginner, so read:

http://experts.blog/how_to_design_a_future_3D_TV.html http://experts.blog/the_basics_of_tv_repairing.html http://experts.blog/viruses_in_living_room_short_essay.html http://experts.blog/global_chip_replacement_guide.html

IRC guest: But, i don't want be a TV expert.

Answer: Why do you want to switch the TV on then?!

    
risposta data 26.03.2014 - 19:27
fonte
1

Why would it be a bad programming practice to use more error prone code in prototype situations, if refactoring makes it more robust afterward?

Quando scrivi in modo veloce e sporco con la mente di fissare in seguito, c'è il pericolo di dimenticare qualcosa che devi correggere.

How would can program written in C++ be like it was written in Java? What makes it a bad program, (considering that I indicated the intent of the current style and the planned work to improve?)

In java non devi pensare a chi possiede un determinato oggetto, basta passare il riferimento e dimenticarlo come se nulla fosse. Tuttavia in C ++ deve esserci una chiara definizione di chi possiede l'oggetto e chi è responsabile della sua pulizia.

How would I be a bad professional if I chose to use a construct that is used in a certain programming paradigm (e.g. OOP/DP)

Non lo faresti; C ++ è un linguaggio multi-paradigma, sembra supportare OOP piuttosto bene, ma può fare anche molte altre cose. Tuttavia, la maggior parte si riduce a utilizzare lo strumento corretto per il lavoro invece di estrarre il martello ogni volta che è necessario guidare una punta appuntita in un pezzo di legno.

Il motivo per cui hai avuto una brutta risposta è che la maggior parte delle persone su SO tende a giudicare le abilità da quanto è idiota che puoi codificare nella lingua che stai chiedendo. Le persone che hanno familiarità con C ++ tendono a impazzire quando vedono un codice errato che assomiglia a qualcosa che li ha morsi in passato.

    
risposta data 26.03.2014 - 17:29
fonte

Leggi altre domande sui tag