Il "codice applicazione" dovrebbe andare nella classe o altrove?

4

Sto cercando di insegnarmi a programmare, ma sono sempre stato molto confuso dall'approccio orientato agli oggetti.

Recentemente, ho letto dei SOLID principi di sviluppo.

Quando creo le classi, usando Python, sembra che aggiungo la logica dell'applicazione lì. Tuttavia, questo sembra sfidare il principio di responsabilità singola e i principi di iniezione.

Per un semplice esempio del mio problema, supponiamo che il mio obiettivo finale sia quello di cambiare la TV al canale 10, girare il sistema audio surround collegato (ma separato) al massimo, e quindi girare il TV spento.

Vorrei fare qualcosa di simile:

from SpeakerSystem import DolbyDigital

Class Tv(object):

def __init__(self):
    self.speakers = DolbyDigital()
    self.volume = 10
    self.channel = 1
    self.power = 'Off'

def turnOn(self):
    self.power = 'On'

def turnOff(self):
    self.power = 'Off'

def channelUp(self):
    self.channel += 1

def channelDown(self):
    self.channel -= 1

def volumeUp(self):
    self.speakers.volumeUp()

def volumeDown(self):
    self.speakers.volumeDown()

def setChannel(self, station):
    self.channel = station

def process(self):
    self.channel = 10
    while self.volume != self.max_volume:
        self.volumeUp()
    self.turnOff()

Ignora per un minuto che questo è un esempio forzato!

Quindi, per risolvere il mio problema, istanzerò semplicemente Tv ed eseguirò process() .

Il problema è che creo sempre molti metodi come process () qui; Fondamentalmente faccio il mio codice dell'applicazione con la classe.

Penso che sia sbagliato? La stragrande maggioranza dei metodi nella mia classe risolve il mio problema direttamente; chiaramente non saranno utili a nessuno, o persino a me stesso, al di fuori del mio specifico dominio problematico.

Nell'esempio, process non è utile a nessuno (utile solo per il mio problema di nicchia). Immagina altri 10 metodi del genere, che sono totalmente inutili.

Inoltre, ho letto che la cottura in self.speakers = DolbyDigital() è anche un cattivo design, perché ora Tv dipende da esso. E questo diventa complicato durante il test unitario; dover continuamente deridere altri oggetti. Molti libri suggeriscono che gli oggetti non dovrebbero nemmeno essere responsabili dell'inizializzazione di altri oggetti ....

Più leggo su OOP e OODesign, sembra che la classe stessa dovrebbe essere generale , dovrebbe fornire solo i metodi di base (non dovrebbe fare l'intero lavoro), e che il il codice dell'applicazione dovrebbe in qualche modo essere separato. È vero? Se sì, dove dovrebbe andare il codice dell'applicazione?

Ho pensato di creare un semplice vecchio file main() , tuttavia sembra che, se lo facessi, il paradigma di programmazione passerà poi a quello procedurale. E l'intero punto di apprendimento OOP è quello di attenersi a OOP!?

Sono veramente completamente confuso a riguardo. Ancora una volta, mi dispiace per la domanda apparentemente stupida, ma non ho una formazione formale, quindi sto solo cercando di migliorare con il tuo aiuto!

Ho letto diversi libri orientati agli oggetti, compresi quelli di Gamma et. al, lo zio Bob e molti altri libri seminali. Sembra che la mia domanda sia così stupida / inesperta che in realtà non la coprono.

    
posta BBedit 05.04.2015 - 21:51
fonte

1 risposta

4

Il tuo metodo process è effettivamente in un posto sbagliato.

Qual è il contesto in cui passerai al canale 10? Perché il canale 10 e non il canale 9?

  • Forse l'utente ha chiesto specificamente il canale 10. In questo caso, 10 dovrebbe essere l'input, non un valore all'interno della classe.

  • Forse questo è il canale predefinito, quello che verrà mostrato ogni volta che si accende la TV. In questo caso, questa dovrebbe essere una costante o, spesso, una voce di configurazione.

    Rendendolo una costante, puoi essere sicuro che in seguito, quando i requisiti cambiano e il canale predefinito diventa il canale 9, devi apportare la modifica solo in una posizione.

    Spostandolo nella configurazione, acquisisci il vantaggio di consentire all'amministratore di sistema di modificare il valore in un secondo momento, senza dover modificare e ridistribuire l'applicazione.

Per quanto riguarda la parte self.speakers = DolbyDigital() , dovresti lasciare al chiamante la possibilità di impostare gli altoparlanti. Questo è utile in due casi:

  • Quando il chiamante non vuole usare DolbyDigital , ma vuole usare qualcos'altro.

  • Quando stai testando la tua classe. Puoi quindi impostare gli altoparlanti su SpeakersMock o SpeakersStub per mettere a fuoco i test sulla classe stessa e isolarli per evitare effetti collaterali.

Questo non ti impedisce di avere un valore predefinito per il campo speakers . Il vantaggio di averne uno è quando inizializzi Tv in punti diversi del tuo codice. Invece di dover pensare ogni volta all'inizializzazione di speakers , lascia che la classe applichi il valore predefinito.

La mancanza di tali valori di default può a volte portare a costruttori che richiedono una dozzina di parametri. Non intrinsecamente cattivo, ma ancora difficile da usare.

    
risposta data 05.04.2015 - 22:39
fonte

Leggi altre domande sui tag