Quali sono le differenze tra questi paradigmi di programmazione e sono più adatti a problemi particolari o eventuali casi d'uso favoriscono uno rispetto agli altri?
Esempi di architettura apprezzati!
Quali sono le differenze tra questi paradigmi di programmazione e sono più adatti a problemi particolari o eventuali casi d'uso favoriscono uno rispetto agli altri?
Esempi di architettura apprezzati!
Risposte:
Tutti sono bravi a modo loro - Sono semplicemente approcci diversi agli stessi problemi.
In uno stile puramente procedurale, i dati tendono ad essere altamente disaccoppiati dalle funzioni che vi operano.
In uno stile orientato agli oggetti, i dati tendono a portare con sé una raccolta di funzioni.
In uno stile funzionale, i dati e le funzioni tendono ad avere più cose in comune tra loro (come in Lisp e Scheme), offrendo al contempo una maggiore flessibilità in termini di utilizzo effettivo delle funzioni. Gli algoritmi tendono anche a essere definiti in termini di ricorsione e composizione piuttosto che loop e iterazione.
Naturalmente, il linguaggio stesso influenza solo lo stile preferito. Anche in un linguaggio puramente funzionale come Haskell, puoi scrivere in uno stile procedurale (anche se questo è altamente scoraggiato), e anche in un linguaggio procedurale come C, puoi programmare in uno stile orientato agli oggetti (come in GTK + e API EFL).
Per essere chiari, il "vantaggio" di ogni paradigma è semplicemente nella modellazione dei tuoi algoritmi e strutture di dati. Se, ad esempio, l'algoritmo coinvolge elenchi e alberi, un algoritmo funzionale potrebbe essere il più sensato. Oppure, se, ad esempio, i tuoi dati sono altamente strutturati, potrebbe avere più senso comporli come oggetti se questo è il paradigma nativo della tua lingua - oppure potrebbe essere facilmente scritto come un'astrazione funzionale di monadi, che è il paradigma nativo di lingue come Haskell o ML.
La scelta di ciò che usi è semplicemente ciò che ha più senso per il tuo progetto e le astrazioni che la tua lingua supporta.
Penso che le librerie, gli strumenti, gli esempi e le comunità disponibili superino completamente il paradigma in questi giorni. Ad esempio, ML (o qualsiasi altra cosa) potrebbe essere il linguaggio di programmazione universale per tutti gli usi , ma se non riesci a ottenere buone librerie per quello che stai facendo, sei fregato.
Ad esempio, se stai realizzando un videogioco, ci sono altri buoni esempi di codice e SDK in C ++, quindi probabilmente stai meglio con quello. Per una piccola applicazione web, ci sono alcuni fantastici framework Python, PHP e Ruby che ti faranno funzionare molto velocemente. Java è un'ottima scelta per progetti più grandi grazie al controllo in fase di compilazione e alle librerie e piattaforme aziendali.
In passato, le librerie standard per le diverse lingue erano piuttosto piccole e facilmente replicabili: C, C ++, Assembler, ML, LISP, ecc. Venivano fornite con le basi, ma tendevano a impazzire quando si trattava di standardizzare le cose come comunicazioni di rete, crittografia, grafica, formati di file di dati (incluso XML), anche le strutture di dati di base come alberi bilanciati e hashtable sono state escluse!
I linguaggi moderni come Python, PHP, Ruby e Java ora hanno una libreria standard molto più decente e hanno molte buone librerie di terze parti che puoi facilmente usare, grazie in gran parte alla loro adozione di spazi dei nomi per evitare che le biblioteche si scontrino tra loro, e garbage collection per standardizzare gli schemi di gestione della memoria delle librerie.
Questi paradigmi non devono essere reciprocamente esclusivi. Se guardi a Python, supporta funzioni e classi, ma allo stesso tempo tutto è un oggetto, comprese le funzioni. Puoi mescolare e abbinare lo stile funzionale / oop / procedurale in un unico pezzo di codice.
Ciò che intendo è che, nei linguaggi funzionali (almeno in Haskell, l'unico che ho studiato) non ci sono dichiarazioni! alle funzioni è consentita una sola espressione al loro interno !! MA, le funzioni sono cittadini di prima classe, puoi passarle come parametri, insieme a un sacco di altre abilità. Possono fare cose potenti con poche righe di codice.
Mentre in un linguaggio procedurale come C, l'unico modo in cui puoi passare le funzioni è usando i puntatori a funzione, e questo da solo non consente molte attività potenti.
In Python, una funzione è un cittadino di prima classe, ma può contenere un numero arbitrario di istruzioni. Quindi puoi avere una funzione che contiene un codice procedurale, ma puoi passarlo in giro proprio come i linguaggi funzionali.
Lo stesso vale per OOP. Un linguaggio come Java non ti consente di scrivere procedure / funzioni al di fuori di una classe. L'unico modo per passare una funzione è avvolgerla in un oggetto che implementa quella funzione e quindi passare quell'oggetto.
In Python non hai questa limitazione.
Per la GUI direi che il paradigma orientato agli oggetti è molto adatto. La finestra è un oggetto, le caselle di testo sono oggetti e anche il pulsante OK è uno. D'altra parte, cose come l'elaborazione delle stringhe possono essere fatte con molto meno sovraccarico e quindi più semplici con un semplice paradigma procedurale.
Non penso sia una questione di lingua. Puoi scrivere funzionale, procedurale o orientato agli oggetti in quasi tutti i linguaggi popolari, anche se in alcuni potrebbe essere un ulteriore sforzo.
Per rispondere alla tua domanda, abbiamo bisogno di due elementi:
Un elenco di stili / modelli di architettura software è mostrato nell'articolo sull'architettura software su Wikipeida. E puoi fare ricerche su di loro facilmente sul web.
In breve e in generale, Procedurale è buono per un modello che segue una procedura, OOP è buono per la progettazione e Funzionale è buono per la programmazione di alto livello.
Penso che dovresti provare a leggere la storia su ogni paradigma e vedere perché le persone la creano e puoi capirli facilmente.
Dopo averli compresi entrambi, è possibile collegare gli elementi degli stili / modelli di architettura ai paradigmi di programmazione.
Uno dei miei amici sta scrivendo un'app grafica usando NVIDIA CUDA . L'applicazione si adatta molto bene al paradigma OOP e il problema può essere scomposto in modo ordinato in moduli. Tuttavia, per usare CUDA devi usare C, che non supporta l' ereditarietà . Pertanto, devi essere intelligente.
a) Elaborate un sistema intelligente che emulerà l'eredità in una certa misura. Si può fare!
i) È possibile utilizzare un sistema hook , che prevede che ogni bambino C del genitore P abbia un determinato override per la funzione F. È possibile fare in modo che i bambini registrino i loro override, che verranno memorizzati e chiamati quando richiesto.
ii) È possibile utilizzare la funzione di allineamento della memoria struct per trasmettere i bambini ai genitori.
Questo può essere pulito ma non è facile trovare una soluzione affidabile, a prova di futuro. Trascorrerai molto tempo a progettare il sistema e non vi è alcuna garanzia che non incontrerai problemi a metà del progetto. L'implementazione dell'ereditarietà multipla è ancora più difficile, se non quasi impossibile.
b) È possibile utilizzare una politica di denominazione coerente e utilizzare l' approccio di divisione e conquista per creare un programma. Non avrà alcuna eredità ma poiché le tue funzioni sono piccole, di facile comprensione e formattate in modo coerente, non ne hai bisogno. La quantità di codice che devi scrivere aumenta, è molto difficile rimanere concentrati e non soccombere a soluzioni facili (hack). Tuttavia, questo modo ninja di codifica è il modo C di codifica. Rimanere in equilibrio tra libertà di basso livello e scrivere un buon codice. Un buon modo per raggiungere questo obiettivo è scrivere prototipi usando un linguaggio funzionale. Ad esempio, Haskell è estremamente buono per gli algoritmi di prototipazione.
Tendo ad avvicinarmi b. Ho scritto una possibile soluzione usando l'approccio a, e sarò onesto, mi è sembrato molto innaturale usare quel codice.