odore di codice: passando attraverso le variabili [chiuso]

2

Considera questo semplice esempio:

def a(val_x, val_y):
    return 5 + b(val_x, val_y)

def b(val_x, val_y):
    return 1 + c(val_x, val_y)

def c(val_x, val_y):
    return val_x * val_y

Passare gli argomenti val_x , val_y da a a b a c sembra un odore di codice comune (so che è qualcosa che faccio troppo spesso quando prototipo di codice!) ma posso trovarne un nome.

Qualche suggerimento?

    
posta jobevers 30.03.2018 - 18:00
fonte

4 risposte

4

Questa architettura è l'opposto dell'inversione di dipendenza. Non sono a conoscenza di un nome ufficiale, ma potresti chiamarlo dipendenza non invertita. È un componente di alto livello che dipende da un componente di livello inferiore. Quando si invertono le dipendenze, si finisce con qualcosa del tipo:

def a(b_result):
  return 5 + b_result

def b(c_result):
  return 1 + c_result

def c(val_x, val_y):
  return val_x * val_y

E lo chiami come:

a(b(c(x, y)))
    
risposta data 30.03.2018 - 21:23
fonte
5

Non c'è niente di sbagliato in tutto questo, anche se se hai un metodo che non fa altro che chiamare un altro metodo, varrebbe la pena vedere se puoi eliminare il metodo intermedio.

È la cosa che stai implicitamente cercando di chiedere?

Se è così - ci sono molte ragioni per cui vuoi un tale metodo intermedio.  Ad esempio, forse a è pubblico ma b è privato. O forse b è un segnaposto e otterrà più codice aggiunto in seguito.

[MODIFICA per indirizzare l'esempio più specifico]

No, questo è assolutamente buono e non un antipattern. Ogni metodo è solo una cosa nominata che vuoi fare, e alcune di queste cose potrebbero richiedere dati provenienti da una catena di cose che stai cercando di fare.

Supponiamo che tu stia cercando di calcolare il volume di un cilindro. La formula per questo è (pi * radius^2) * height . Puoi definire una classe getCylinderVolume(radius, height) che restituisca direttamente il risultato.

Ma dimmi che decidi di voler estrarre il pezzo "moltiplica per l'altezza" di quello (per esempio, perché vuoi avvisare l'utente che la cosa il cui volume stanno calcolando supererà un limite di altezza legale). Potresti quindi modificare l'implementazione di getCylinderVolume per restituire invece getCircleArea(radius) * checkHeightAndBubbleErrorIfTooTall(height) .

Potresti anche rend contoere che è necessario tenere conto dei volumi interni ed esterni separatamente ...

Il punto è che ci sono molte ragioni per cui potresti voler passare una variabile direttamente in una pila di chiamate. Fare così spesso significa che stai facendo un buon lavoro mantenendo le tue funzioni piccole.

    
risposta data 30.03.2018 - 18:23
fonte
1

Sono totalmente d'accordo con l'autofago e voglio presentare un'alternativa in cui mi imbatto troppo spesso che in realtà è male.

Posso solo immaginare perché la gente lo fa, ma penso di aver capito perché. Devono pensare qualcosa come

"Ehi, avrò bisogno di queste variabili in un certo numero di metodi, quindi potrei anche dichiararli come membri della classe, in modo da poterli accedere comodamente da qualsiasi metodo." "ASCIUTTO!"

Questo è ciò di cui dovresti diffidare. A livello di classe si tratta di rumore puro, queste variabili non significano nulla a livello di classe, ma qualsiasi estraneo / successore che cerchi di mettere la testa in classe non lo sa, quindi la sua testa farà male a cercare di capire cosa significa tutto questo. Gli ci vorrà un po 'di tempo ed energia per capire che sono solo variabili locali o argomenti del metodo. E ti odierà e ti odierà per avergli lasciato questa merda. E poi refactoring, lamentandosi con i suoi colleghi di ciò che sei un idiota.

I casi non validi avranno due o tre membri di dati che sono veri membri della classe e dieci o più variabili handy-dandy che li oscurano.

    
risposta data 30.03.2018 - 21:00
fonte
0

Estrai un oggetto. Raccogli xey in una nuova classe Point. Quindi sposta le funzioni a, b, c nella classe Point.

    
risposta data 30.03.2018 - 18:52
fonte

Leggi altre domande sui tag