La domanda è nel titolo. Voglio che il mio modo di pensare sia verificato da persone esperte. Puoi aggiungere altro o ignorare la mia opinione, ma dammi una ragione.
Ecco un esempio di esempio: Supponiamo che sia necessario implementare un gioco di combattimento. Inizialmente, il gioco include solo i combattenti, che possono attaccarsi a vicenda. Ogni combattente può pugni, calci o blocchi di attacchi in arrivo. I combattenti possono avere vari stili di combattimento: Karate, Judo, Kung Fu ... Questo è tutto per il semplice universo del gioco. In un OO come Java, può essere implementato in questo modo:
abstract class Fighter {
int hp, attack;
void punch(Fighter otherFighter);
void kick(Fighter otherFighter);
void block(Figther otherFighter);
};
class KarateFighter extends Fighter { //...implementation...};
class JudoFighter extends Fighter { //...implementation... };
class KungFuFighter extends Fighter { //...implementation ... };
Questo va bene se il gioco rimane così per sempre. Ma, in qualche modo, i game designer decidono di cambiare il tema del gioco: invece di un semplice gioco di combattimento, il gioco si evolve fino a diventare un GdR, in cui i personaggi non possono solo combattere ma svolgere altre attività, ad esempio il personaggio può essere un prete, un ragioniere, uno scienziato ecc ... A questo punto, per renderlo più generico, dobbiamo cambiare la struttura del nostro progetto originale: Fighter
non è più usato per riferirsi a una persona; si riferisce a una professione. Le classi specializzate di Fighter (KaraterFighter, JudoFighter, KungFuFighter). Ora dobbiamo creare una classe generica denominata Person
. Tuttavia, per adattare questa modifica, devo cambiare le firme dei metodi delle operazioni originali:
class Person {
int hp, attack;
List<Profession> skillSet;
};
abstract class Profession {};
class Fighter extends Profession {
void punch(Person otherFighter);
void kick(Person otherFighter);
void block(Person otherFighter);
};
class KarateFighter extends Fighter { //...implementation...};
class JudoFighter extends Fighter { //...implementation... };
class KungFuFighter extends Fighter { //...implementation ... };
class Accountant extends Profession {
void calculateTax(Person p) { //...implementation...};
void calculateTax(Company c) { //...implementation...};
};
//... more professions...
Ecco i problemi:
-
Per adattarsi alle modifiche al metodo, devo correggere i luoghi in cui i metodi modificati sono chiamati (refactoring).
-
Ogni volta che viene introdotto un nuovo requisito, è necessario interrompere l'attuale progettazione strutturale per adattare le modifiche. Questo porta al primo problema.
-
La struttura rigida rende difficile il riutilizzo del codice. Una funzione può accettare solo i tipi predefiniti, ma non può accettare tipi sconosciuti futuri. Una funzione scritta è legata al suo universo attuale e non ha modo di adattarsi ai nuovi tipi, senza modifiche o riscrittura da zero. Vedo che Java ha molti metodi deprecati.
OO è un caso estremo perché ha ereditarietà per sommare la complessità, ma in generale per il linguaggio tipizzato staticamente, i tipi sono molto severi.
Al contrario, un linguaggio dinamico può gestire il caso precedente come segue:
;;fighter1 punch fighter2
(defun perform-punch (fighter1 fighter2) ...implementation... )
;;fighter1 kick fighter2
(defun perform-kick (fighter1 fighter2) ...implementation... )
;;fighter1 blocks attacks from fighter2
(defun perform-block (fighter1 fighter2) ...implementation... )
fighter1
e fighter2
possono essere qualsiasi cosa purché abbia i dati richiesti per il calcolo; o metodi (digitazione anatra). Non devi cambiare dal tipo Fighter
a Person
. Nel caso di Lisp, poiché Lisp ha una sola struttura di dati: lista, è ancora più facile adattarsi alle modifiche. Tuttavia, altri linguaggi dinamici possono avere anche comportamenti simili.
Io lavoro principalmente con linguaggi statici (principalmente C e Java, ma lavorare con Java era molto tempo fa). Ho iniziato a imparare Lisp e altre lingue dinamiche quest'anno. Posso vedere come aiuta a migliorare la mia produttività.