Un piccolo case study: un pattern matcher in due pseudo-lingue, prima OO e poi funzionale
In OOP, progettazione dell'interfaccia prima
interface IPatternMatcher {
bool Match(string toMatch)
}
Quanto sopra è l'unica interfaccia di cui abbiamo bisogno, ma in realtà non ci fornisce alcun indizio su come progettare i nostri tipi di implementazione. Probabilmente vorrai dei compositi, quindi implementerai un OrPatternMatcher
class OrPatternMatcher : IPatternMatcher {
OrPatternMatcher(list<IPatternMatcher> submatchers);
bool Match(string toMatch) {
return _submatchers.Any(s => s.Match(toMatch));
}
}
Ma ora hai iniziato ad implementare funzionalità, senza aver completato la tua gerarchia. È praticamente impossibile separare questi due stadi in OOP perché le tue funzioni e tipi sono così intrecciati
In FP, progettazione di tipo prima
type PatternMatcher =
| OrPatternMatcher : list<PatternMatcher>
| AndPatternMatcher : list<PatternMatcher>
| SubstringPatternMatcher : string
| RegexPatternMatcher : regex
Qui abbiamo tutti i tipi necessari progettati in anticipo, che coprono tutti i casi a cui puoi pensare. Il tipo di unione PatternMatcher
in FP è correlato all'interfaccia IPatternMatcher
OOP, con la differenza cruciale che l'unione dichiara la sua struttura di tipo senza funzioni , mentre l'interfaccia dichiara le sue funzioni con no type structure .
Ora è banale implementare una funzione match
semplicemente osservando la forma dei tipi che hai disposto. Se hai progettato i tipi in modo ragionevole per il tuo dominio, sei già quasi tutto il modo di avere un componente funzionante. Questo è ciò che significa prima progettare i tuoi tipi - per modellare accuratamente il tuo dominio senza preoccuparti di comportamento
Secondo me le interfacce OOP e i tipi FP sono quasi l'opposto l'uno dell'altro, ei vantaggi ottenuti dalla progettazione dei tuoi tipi FP in anticipo sono molto diversi da quelli ottenuti dalla programmazione su un'interfaccia.
Come ulteriore ripensamento, la frase "progetta le tue interfacce prima" non è la stessa cosa di "programma su un'interfaccia" e quindi quest'ultima non può essere veramente paragonata a "progetta i tuoi tipi prima".
- "programma su un'interfaccia" sostiene il disaccoppiamento dei componenti non assumendo i dettagli di implementazione
- "progetta i tuoi tipi prima" è un consiglio su come modellare sensibilmente il tuo dominio prima di implementare il comportamento
I due in realtà non sono paragonabili, in quanto si riferiscono a situazioni diverse