Cosa può fare il codice OOP che il codice procedurale non può fare? - pagina 3

 

Con progetti su piccola scala si può dimostrare che qualsiasi problema può essere scomposto in codice procedurale. Tuttavia le cose diventano molto più difficili quando si hanno basi di codice di diversi milioni di linee con team di 100+ sviluppatori, diversi analisti di business e architetti che vogliono tutti fare modifiche al "modello" contemporaneamente. In queste circostanze il modello "business" è generalmente definito in uno strumento di progettazione come UML ed è accessibile all'intero team.

Il modello di business da solo contiene più di 5000 classi. Da questo modello di business ci sono strumenti che "generano" classi per il modello di oggetti, le interfacce SQL e i livelli di rete, portando il numero di classi di base a 15.000 classi.

Per questa discussione mi piace suddividere l'argomento procedurale vs. OOP in tre "estensioni" che sono state aggiunte al procedurale dagli anni 1960/1970

1) "Object Based" (basato sugli oggetti) questo è dove gli oggetti e il codice sono incapsulati per fare una "struttura" avanzata che può anche avere dei comportamenti

2) "Class based": gli oggetti possono ereditare l'uno dall'altro ed essere organizzati in gerarchie

3) "Object oriented" questo è dove l'utente può definire comportamenti "polimorfici" (metodi virtuali o interfacce) all'interno delle gerarchie di classe

C'è un argomento per cui tutto quanto sopra può essere implementato nei linguaggi procedurali con sufficiente sforzo, per esempio la maggior parte dei toolkit GUI negli anni 80/90 erano creati in c e avevano queste caratteristiche, ma non sono facili da implementare dal programmatore occasionale e non sono realmente applicabili a questa discussione.

Quindi, per rispondere alla domanda, possiamo implementare un progetto di molti milioni di linee con 100+ sviluppatori senza usare le 3 caratteristiche OOP?

La mia opinione personale è che è virtualmente impossibile realizzare un progetto su larga scala senza 1) e 2) perché senza un sistema "class based" è così difficile mappare le strutture dati e i comportamenti del mondo reale nel codice in modo pulito e conciso. E più precisamente, man mano che le dimensioni del progetto aumentano, quello che inizia come un "possiamo implementarlo in C" diventa una lista infinita di metodi con meno struttura che diventano più difficili da mantenere.

Ora i linguaggi che forniscono solo 1) e 2) non sono completamente OOP. Quindi dovremmo considerare se i "metodi polimorfici (virtuali)" sono davvero necessari. Questo è un po' più di un "forse", o "qualche volta" perché il polimorfismo non è sempre lo strumento corretto per risolvere un problema e può complicare eccessivamente il design. Per esempio quando si modellano alcune strutture di dati che mappano su un object store o su un database SQL l'aggiunta di comportamenti virtuali può rendere la mappatura dei dati più difficile, tuttavia quando si definiscono toolkit estensibili o API l'uso di una "interfaccia" o classe base con "metodi virtuali" è inestimabile. Nel complesso sono un grande fan del polimorfismo quando viene usato con parsimonia e nel giusto contesto.

Ho lavorato su alcuni codebase multimilionari in "C" e molti altri codebase multimilionari in C++/Java/C#, e la maggior parte dei codebase in "C" cadono in "modalità manutenzione" dopo 5 anni perché gli sviluppatori hanno paura di cambiare l'architettura perché il codice è semplicemente troppo fragile e le modifiche spesso causano mesi di doloroso sviluppo e test. In generale i progetti orientati agli oggetti sono molto più resistenti alle modifiche e al refactoring.

 
Alain Verleyen:
La dichiarazione "if...then...else..." dovrebbe fare il lavoro.

if...then...else non è in grado di codificare metodi "virtuali".

Ci sono diverse implementazioni del "polimorfismo" in "C" e la maggior parte di esse usa vettori di puntatori di funzioni per contenere le mappature necessarie. Più precisamente, questi "vettori di puntatori di funzioni" devono essere definiti per ogni "tipo" che si vuole modellare nella "gerarchia". Naturalmente il "C" non supporta direttamente le gerarchie, quindi dovrete risolvere anche questo problema.

Se volete davvero entrare nel sacco di vermi che sono i metodi "virtuali" implementati in "C", allora potete tirare fuori i toolkit di X Windows che sono liberamente disponibili in ogni distribuzione Linux.

Windows naturalmente deve essere leggermente diverso e usa strutture estensibili con id dei messaggi interi, il che significa che il comportamento "polimorfico" è implementato tramite dichiarazioni di switch sugli id. (probabilmente il modo più sporco di farlo, ma vi porterà lì)

 
Alain Verleyen:

Sei d'accordo che il sistema operativo Windows offre una buona interfaccia grafica? Per quanto ne so, è scritto in C. Linguaggio procedurale, non OOP.

Ti sbagli Dirk se pensi che un programma complesso possa essere costruito solo con OOP. Dovresti piuttosto spiegare perché è meglio codificarlo con OOP.

Il kernel di Windows è in "C", ma il kernel è solo una piccola componente del codice di Windows e gran parte del codice di livello superiore è implementato in C++ con interfacce esterne in stile "C" per supportare più lingue.

Anche i componenti legacy di Windows GUI implementano il loro "comportamento polimorfico" arrotolato a mano che sono effettivamente "OOP" implementati in "C". Per esempio, quando si ottiene un "Handle" da un controllo GUI, si sta ottenendo una struttura estensibile "C" con un comportamento polimorfico disponibile, questo è OOP appena avvolto in un brutto set di sintassi "C".

Dire che Windows non è OOP perché è scritto in "C" non è del tutto accurato.

 
Alain Verleyen:

Non costruirò una GUI in linguaggio procedurale per dimostrare che hai torto. Ma potrei senza alcun dubbio.

A proposito, è anche facile scrivere codice illeggibile e molto più lento in OOP, e come sapete la libreria standard Metaquotes è una buona prova di questo.

Il fatto che l'OOP sia molto più lento del codice procedurale è un mito completo. La ragione per cui molti progetti OOP sono più lenti è perché sono progettati male. L'overhead per una chiamata di funzione virtuale è molto più piccolo di quanto ci si aspetti, specialmente con le attuali architetture di fetch di memoria su chip che possono cercare ed eseguire in parallelo.

https://hbfs.wordpress.com/2008/12/30/the-true-cost-of-calls/

Citazione dal link sopra: "Ma il costo di una chiamata, qualunque sia il sapore, è dominato dalla valutazione dei suoi argomenti. Abbiamo visto che le chiamate indirette, che siano metodi virtuali in stile C o C++, sono intrinsecamente poco costose. Una chiamata a un metodo virtuale non è più costosa di una chiamata indiretta usando un membro della struct (qualcosa->funzione(arg1,arg2)) quindi ritenere la funzione virtuale incredibilmente lenta è solo disinformato."


Java può essere molto più lento di C++ perché ogni pezzo di dati incapsulati deve essere esso stesso una classe basata sull'heap, quindi si hanno molti più dereferenziazioni di oggetti. Comunque anche Java può essere esattamente la stessa velocità di C nei loop e nelle operazioni matematiche di base.

Se si confronta C con C# è davvero molto difficile scrivere del codice che sia significativamente più veloce in C rispetto a C#, anche quando si includono alcune delle caratteristiche OOP.

Se la libreria standard Metaquotes è lenta, allora sarà al 90% dovuto al design delle caratteristiche della libreria e avrà molto poco a che fare con le caratteristiche OOP utilizzate.

(Per fare un paragone, la Standard Template Library del C++ supera il 95% di qualsiasi progetto C mai scritto).

 
James Cater:
...

Grazie per il tuo grande contributo.

 
Alain Verleyen:

Grazie per il tuo grande contributo.

Grazie, e non ti stavo prendendo in giro, è solo che sei l'unico a difendere l'argomento della procedura :)
 
James Cater:
Grazie, e non ti stavo prendendo in giro, è solo che sei l'unico a difendere l'argomento della procedura :)

Non preoccuparti, devo svolgere il mio ruolo di "moderatore".

 

Certo, sarebbe bello vedere alcuni esempi di qualsiasi cosa di cui state parlando. Parlare e scrivere va bene per le persone che hanno esperienza in tutto questo, ma io sono un tipo di studente che ha le mani in pasta, per favore postate degli esempi.

Sono indeciso se continuare o meno ad imparare mql4, passare a mql5 o semplicemente andare con un'altra piattaforma.

Grazie Alain per aver iniziato questo thread. Questo forum ha davvero bisogno di questo.

 

Vi aspettate davvero che qualcuno di professionale pubblichi una libreria di compex, così come una "prova"? ;) Potrei postarti un link a qualcosa di pronto che non può essere venduto sul mercato qui, ma Alain mi prenderà a calci se lo faccio ;) Puoi visitare il mio profilo e dare un'occhiata alla foto del muro per farti un'idea o mandarmi un pm.

Un'altra piattaforma? Non troverete nessun'altra piattaforma con un compilatore così potente. Assolutamente no.

@James Cater - grazie mille per i tuoi commenti.

 
Doerk Hilger:

Vi aspettate davvero che qualcuno di professionale pubblichi una libreria di compex, così come una "prova"? ;) Potrei postarti un link a qualcosa di pronto che non può essere venduto sul mercato qui, ma Alain mi prenderà a calci se lo faccio ;) Puoi visitare il mio profilo e dare un'occhiata alla foto del muro per farti un'idea o mandarmi un pm.

Un'altra piattaforma? Non troverete nessun'altra piattaforma con un compilatore così potente. Assolutamente no.

@James Cater - grazie mille per i tuoi commenti.

Hai mancato il punto Dirk. Le persone non specializzate vogliono esempi di codice semplici e chiari, che in effetti era il mio obiettivo con questo argomento. Ma questo sembra completamente al di là della comprensione degli specialisti.