È una buona pratica riutilizzare un'API su bersagli selvaggiamente diversi?

2

Diciamo che ho qualcosa chiamato "Attuatori". Ogni "Attuatore" può avere delle capacità ad esso associate. Dovrei riutilizzarlo ovunque si adatti, o dovrei creare tipi di attuatori completamente separati per ogni tipo di target?

Ho obiettivi di blocco, ho obiettivi di oggetti, ho obiettivi di entità e ho obiettivi di comando.

Un attuatore può avere delle capacità ad esso associate, ad es. "può aprire GUI" (giocatori normali), "può guidare entità" (giocatori normali, entità), "ha posizione" (giocatori normali, giocatori falsi, entità), "può visualizzare testo" (giocatori normali, console), ecc.

È una buona idea riutilizzare una tale API su più target, anche se tali target potrebbero essere molto diversi tra loro? Ciò ridurrebbe i costi di manutenzione? Questo renderebbe l'implementazione un dolore?

    
posta SoniEx2 20.08.2016 - 15:37
fonte

2 risposte

3

Si tratta di design dell'interfaccia. Un'interfaccia definisce come parli con qualunque cosa stai parlando. Riutilizzare la stessa interfaccia significa che non devi parlare in modo diverso da quello che hai fatto parlando con quell'altra cosa. Questa nuova cosa può fare qualcosa di diverso quando ci parli, ma quello che dici è lo stesso che stavi dicendo prima.

In questo modo posso scambiare ciò che viene detto perché quello che sta facendo il discorso non sa nemmeno a cosa sta parlando. È una buona cosa. Il termine di fantasia per questo è il polimorfismo. È anche una buona cosa. Fatto in questo modo non lo stai facendo con l'ereditarietà, lo stai facendo con la composizione.

Questo è tutto a posto, a condizione che la tua interfaccia ti permetta di dire tutto ciò che devi dire. Questo può andare di lato quando ti rendi conto, oh, dobbiamo essere in grado di dirlo. Oh che mi dici di questo. Prima che tu lo sappia, hai una dozzina di interfacce nella tua API e tutti fanno metà o tre quarti di ciò che fanno gli altri.

Credo profondamente che la cosa che parla (tradizionalmente chiamata un cliente) dovrebbe definire quale sia l'interfaccia. Che cosa è l'ascolto (un servizio) è qualcosa a cui puoi pensare in seguito finché permetti a quella cosa di essere qualsiasi cosa.

Questo atteggiamento può sembrare strano se ti venisse chiesto di scrivere la parte che non ascolta la parte che parla ma ti imploro di scrivere almeno una cosa che parla prima di scrivere la parte che ascolta. Altrimenti finisci per ascoltare i lavelli della cucina che non arrivano mai.

Il cliente possiede l'interfaccia. Il servizio no. Quando si progetta l'interfaccia, pensa al cliente. Il termine di fantasia per questo è il principio di separazione delle interfacce

In altre parole, come cliente, non me ne importa quanto siano diversi i tuoi obiettivi (servizi). Mi interessa se fanno quello che ho bisogno che facciano quando dico loro di farlo. Non mi interessa come lo fanno. E fintanto che non ha niente a che fare con me, non mi interessa davvero quello che fanno davvero finché è ciò che dovevano fare. Davvero, non so cosa fanno. Non voglio saperlo. Basta andare a farlo.

    
risposta data 20.08.2016 - 16:29
fonte
1

Oltre all'ottima risposta di @ CandidedOrange:

Is it a good idea to reuse such an API across multiple targets, even if such targets may be wildly different from each other?

Se trovi la comunanza tra oggetti molto diversi, specialmente tra tipi di oggetti molto diversi, questo suggerisce una gerarchia di interfacce piuttosto che un'interfaccia piatta o una struttura di classe più semplice. Usando la gerarchia di interfacce (e / o classi) possiamo avere cose estremamente generali nella parte superiore e cose specializzate in ogni sottolivello.

Quindi, l'idea è di aggiungere funzionalità nella posizione corretta nella gerarchia, che a volte significa creare un nuovo livello da qualche parte. A volte, in seguito, scopriamo che qualcosa è più generale che avremmo pensato, quindi lo spostiamo verso l'alto nella gerarchia. Altre volte scopriamo che qualcosa è più specializzato e dovrebbe spostarsi verso il basso nella gerarchia, e possibilmente al suo stesso livello gerarchico. (Tutti questi potrebbero essere considerati refactoring.)

L'obiettivo è fornire ai clienti astrazioni molto usabili e coerenti: astrazioni che possono usare direttamente, senza raggiungere sotto o intorno (tale dover testare il tipo di un oggetto).

Would this reduce maintenance cost? Would this make implementation a pain?

Mettendo le tue astrazioni al giusto livello di generalizzazione / specializzazione, IMHO è la chiave per avere un software orientato agli oggetti gestibile. Tende a disaccoppiare client e implementazioni, facilitando la manutenzione. Quando la gerarchia delle classi non viene calcolata bene, si ha molta più sofferenza nell'aggiungere nuove funzionalità. Tuttavia, non ci si può aspettare di farlo subito, quindi questo è uno dei motivi per cui abbiamo alternato il refactoring (rimodellando la funzionalità esistente) con l'aggiunta di nuove funzionalità.

    
risposta data 20.08.2016 - 17:23
fonte

Leggi altre domande sui tag