Quando divido grandi metodi (o procedure o funzioni) questa domanda non è specifica per OOP, ma poiché lavoro nelle lingue OOP il 99% delle volte, è la terminologia con cui mi trovo più a mio agio) in molti piccoli , Mi trovo spesso scontento dei risultati. Diventa più difficile ragionare su questi piccoli metodi rispetto a quando erano solo blocchi di codice in quello grande, perché quando li estraggo, perdo molti presupposti di base che provengono dal contesto del chiamante.
Più tardi, quando guardo questo codice e vedo i singoli metodi, non so immediatamente da dove vengono chiamati e penso a loro come normali metodi privati che possono essere chiamati da qualsiasi parte del file. Ad esempio, immagina un metodo di inizializzazione (costruttore o altro) suddiviso in una serie di piccoli: nel contesto del metodo stesso, sai chiaramente che lo stato dell'oggetto non è ancora valido, ma in un normale metodo privato probabilmente passi dal presupposto che l'oggetto è già inizializzato ed è in uno stato valido.
L'unica soluzione che ho visto per questo è la where
clausola in Haskell, che consente di definire piccole funzioni che vengono utilizzate solo nella funzione "padre". Fondamentalmente, assomiglia a questo:
len x y = sqrt $ (sq x) + (sq y)
where sq a = a * a
Ma altre lingue che utilizzo non hanno nulla di simile: la cosa più vicina è definire un lambda in un ambito locale, che è probabilmente ancora più confuso.
Quindi, la mia domanda è: ti capita di incontrare questo e vedi anche che questo è un problema? Se lo fai, come lo risolvi in genere, in particolare nei linguaggi OOP "mainstream", come Java / C # / C ++?
Modifica dei duplicati: come altri hanno notato, ci sono già domande che parlano di metodi di divisione e piccole domande che sono una linea. Li ho letti e non discutono della questione delle ipotesi sottostanti che possono essere derivate dal contesto del chiamante (nell'esempio sopra, oggetto in fase di inizializzazione). Questo è il punto della mia domanda, ed è per questo che la mia domanda è diversa.
Aggiornamento: se hai seguito questa domanda e discussione sotto, potresti apprezzare questo articolo di John Carmack sull'argomento , in particolare:
Oltre alla consapevolezza dell'attuale codice in esecuzione, le funzioni di allineamento hanno anche il vantaggio di non consentire di chiamare la funzione da altri luoghi. Sembra ridicolo, ma c'è un punto. Man mano che la base di codice cresce nel corso degli anni di utilizzo, ci saranno molte opportunità di prendere una scorciatoia e chiamare semplicemente una funzione che fa solo il lavoro che pensi debba essere fatto. Potrebbe esserci una funzione FullUpdate () che chiama PartialUpdateA () e PartialUpdateB (), ma in alcuni casi particolari potresti rendersi conto (o pensare) che devi solo eseguire PartialUpdateB () e sei efficiente evitando l'altro opera. Molti e molti bug derivano da questo. La maggior parte dei bug è il risultato dello stato di esecuzione che non è esattamente quello che pensi sia.