2015-10-19 18 views
5

stavo guardando attraverso la struttura interna di Pharo e ho notato che la definizione di aritmetica + e - aspetto molto simili:Perché la definizione Pharo di aritmetica + e - codice sostanzialmente duplicato?

+ aNumber 
"Refer to the comment in Number + " 
aNumber isInteger ifTrue: 
    [self negative == aNumber negative 
     ifTrue: [^ (self digitAdd: aNumber) normalize] 
     ifFalse: [^ self digitSubtract: aNumber]]. 
aNumber isFraction ifTrue: 
    [^Fraction numerator: self * aNumber denominator + aNumber numerator denominator: aNumber denominator]. 
^ aNumber adaptToInteger: self andSend: #+ 

e

- aNumber 
"Refer to the comment in Number - " 
aNumber isInteger ifTrue: 
    [self negative == aNumber negative 
     ifTrue: [^ self digitSubtract: aNumber] 
     ifFalse: [^ (self digitAdd: aNumber) normalize]]. 
aNumber isFraction ifTrue: 
    [^Fraction numerator: self * aNumber denominator - aNumber numerator denominator: aNumber denominator]. 
^ aNumber adaptToInteger: self andSend: #- 

come la vedo io, questo è completamente contro il OO modo di progettare le cose ed è generalmente cattivo. Perché nessuno trova una soluzione migliore?

risposta

4

La cosa più semplice che posso pensare è:

- aNumber 
    ^self + aNumber negated 

Tuttavia, questo avrà un costo:

  • creazione di un altro LargeInteger intermedio, o frazione
  • altri due messaggi invia al eseguire l'operazione -

Quello che vediamo qui è un omaggio all'opti ottimizza-. Ottimizzazione non prematura, questa è un'operazione di basso livello utilizzata ampiamente.

Ci sono altre cose in questo codice che non sono perfetto:

  • utilizzo di TestIntero e isFraction potrebbe anche essere sostituito con una sorta di doppio invio
  • metodi digitAdd: e digitSubtract: il lavoro per gli interi memorizzati come segno - grandezza piuttosto che 2-complemento che è un dettaglio di implementazione non del tutto ovvio e meriterebbe un commento - o forse dovrebbe meglio essere rinominato digitAddMagnitude: digitSubtractMagnitude:
0

e ' non contro OO - il comportamento è incapsulato, nascondendo il comportamento complicato dietro una semplice API. (o il protocollo dei messaggi, come ci piace chiamarlo in Smalltalk).

C'è molta duplicazione di codice. Sarebbe possibile inserire uno strato di riferimento indiretto e mantenere il codice in un posto comune, ma questo è un esempio di sacrificare la compattezza per la velocità, eliminando l'impronta di memoria per la velocità. Inoltre, negozia la velocità a scapito dello OnceAndOnlyOnce che ritengo sia la vostra principale preoccupazione.

Nella prima Smalltalk ho usato, LearningWorks, (sulla base di un'implementazione ParcPlace, iirc) la funzione - semplicemente negato l'argomento e quindi richiama la funzione +. Ciò ha reso l'operazione - più lenta dell'operazione +.

Ci sono molti potenziali compromessi e ottimizzazioni nello sviluppo del software: i principali sono la velocità per l'impronta di memoria (e viceversa), la velocità di esecuzione per la velocità di sviluppo (e viceversa) e la facilità di ottenere qualcosa lavorando proprio ora contro la facilità di tenerlo funzionante e ottimizzato nel lungo periodo.

Lo sviluppo OO è generalmente ottimizzato per ottimizzare la velocità di sviluppo a scapito della velocità di esecuzione, utilizzando linguaggi di alto livello che sono più veloci da sviluppare, ma che funzionano più lentamente; ottimizzazione per la manutenzione a lungo termine rispetto all'immediatezza; e consumare molta memoria per strappare il maggior numero possibile di prestazioni dal codice più lento.

Queste sono tuttavia generalizzazioni. Ci sono contro-esempi per tutti loro, ne sono abbastanza sicuro.

Problemi correlati