2009-05-18 17 views
6

Sono un programmatore Ruby. Per me, monkeypatching è quello di modificare, in fase di runtime, i metodi di classi o moduli in un progetto esterno. Quello che mi interessa, è quale meccanismo hai in atto che ti proteggerà da alcuni degli abusi di quella bella funzionalità. Segue, alcuni scenari che ho incontrato, in cui la monkeypatching mi ha morso.Come si comporta Smalltalk con monkeypatching?

Mentre io non so Smalltalk a tutti, che il linguaggio sono stati lì a lungo prima di Ruby. Ho fatto qualche ricerca per vedere se e come Smalltalk ha risolto alcuni di questi problemi ma non ha trovato molto su Google. Quindi eccomi qui, a chiedere a Smalltalkers se possono condividere la loro saggezza.

Scenario A: bug fixing conflitto

Progetto A e B dipendono progetto C. Progetto C ha un bug. Progetto A e rilascia B contengono una correzione per il progetto C.

Se il codice utilizza Progetto A e B, come è possibile conoscere le patch non saranno in conflitto?

Scenario B: bug superata fissaggio

Progetto C rilascia una versione fissa minore del loro progetto.

Se si carica progetto A, sarà la patch ancora essere applicato, con un potenziale di rottura? Sono interessato a sapere se ci sono alcuni meccanismi in atto, ad esempio, per non caricare la patch se il codice è stato risolto.

Scenario C: conflitto estensioni

Progetto A e B l'uso progetto di classe di C Foo. Entrambi aggiungono un metodo di utilità a Foo, ad esempio #toDate. La versione toDate di A restituisce una stringa di data e quella di B a Date.

Se si carica entrambi i progetti (con C dep), c'è un meccanismo che avvisa/impedire che il conflitto? O dovrai aspettare fino a quando il runtime genera un errore a causa di un'aspettativa sbagliata in un metodo?

Chi l'aggiornamento domanda

Leggendo le risposte, mi rendo conto la mia domanda era troppo ampio e vago. Quindi ecco una versione riscritta di esso.

+0

è la capacità di monkeypatch davvero un problema? – CookieOfFortune

+0

Le tue critiche alla monkeypatching sembrano piuttosto lontane dal marchio. Non c'è nulla di intrinseco nel monkeypatching che porti a astrazioni che perdono nulla più che nella progettazione di classi iniziali. Né è intrinsecamente più "crufty" di altri codici. La suddivisione di un oggetto in file diversi è vera, anche se alcuni sostengono che avere moduli gestibili è una buona cosa - infatti, è considerato una buona pratica raggruppare le funzionalità correlate in Objective-C. Forse i tuoi problemi sono più con i programmatori che con le caratteristiche del linguaggio. – Chuck

+0

In qualsiasi cae, l'intera idea di dividere le cose in file separati è malriposta; smalltalk non fa le cose in questo modo. –

risposta

1

Dice "Sì! Vai!"

L'intera nozione è stata probabilmente visualizzata per la prima volta in Smalltalk.

Vai alla classe radice nel browser di classe, ed è possibile aggiungere tutti i metodi per l'immagine che ti piace.

Ricordate, però, che Smalltalk ha un quadro molto diversa del mondo rispetto alle altre lingue abituali (l'unico altro comune come Smalltalk era APL.) Di avere un'immagineche contiene l'intero insieme di codice e tempo di esecuzione pacchetto. Quando si modifica l'immagine, viene interessato ogni bit di codice nell'immagine. Altre immagini non sono cambiate. Puoi cambiare set per ricaricare i tuoi hack preferiti, ma in pratica stanno importando codice nell'immagine.

1

Smalltalkers non usare un termine 'scimmia patch', ma ho la sensazione che il 'metodo primario' è il termine più vicino.Cioè, si sovrascrive un metodo di una classe nel pacchetto A, con un metodo della stessa classe nel pacchetto B. Quindi quando si carica un pacchetto B, il metodo originale in A viene sovrascritto.

Gli override dei metodi hanno i loro vantaggi ma molto più svantaggi quando non vengono utilizzati con attenzione, quindi in generale tendiamo ad evitarli. Dipende anche dal dialetto Smalltalk - in VisualWorks, per esempio, gli strumenti supportano l'override abbastanza bene mentre in Squeak non lo è.

+0

+1 per riconoscere l'importanza dell'uso del termine in ciascuna (sotto) cultura, -1 per confondere con il metodo di sovrascrittura (una cosa completamente diversa) – Javier

+0

Ovviamente non è una cosa così totalmente diversa, dopo aver letto l'articolo di Wikipedia sulle patch delle scimmie. Bene, sembra che in Smalltalk siamo quindi patch scimmia semplicemente cambiando qualche metodo in un'immagine live? Lo facciamo comunque sempre. –

+0

In Newspeak è praticamente lo stesso :) –

5

In Smalltalk, abbiamo tradizionalmente chiamato questo override. A seconda degli strumenti di controllo della versione che usi con Smalltalk, anche tu;

  • creare una nuova versione del pacchetto che originariamente di proprietà della classe/metodo di (s) in questione
  • creare un nuovo pacchetto, che sarà proprio l'override della classe/metodo di (s) in questione

In VisualWorks e ObjectStudio (il Smalltalk con cui ho più familiarità), viene utilizzato l'ultimo approccio. In VA Smalltalk, dove viene utilizzato Invidia, viene adottato il primo approccio. Credo che Squeak avrebbe seguito quest'ultimo approccio usando Monticello, ma non ne sono del tutto sicuro.

Nella maggior parte delle implementazioni Smalltalk, è facile vedere sia la versione originale del codice sottoposto a override che l'override attualmente installato.

Nelle applicazioni client, le sostituzioni influiscono solo sull'aggiornamento a una nuova versione di Smalltalk da venere (o Squeak team, et. Al.). Per le app server, in cui più applicazioni possono essere residenti nel server, è necessario prestare molta più attenzione a ciò che si decide di fare.

Le sostituzioni (o patch di scimmia, come le chiami tu) sono uno strumento potente, ma devi stare attento a come le usi e, se le usi, dovresti riesaminare se ne hai ancora bisogno una base regolare. Nel mio aggregatore di notizie open source, BottomFeeder, ho rimosso molti degli override che ho inserito inizialmente.

0

Rispondere a me stesso, ecco il mio punto di vista attuale:

Scenario A e B

Poiché tutto il codice è aperto, la pratica migliore sarebbe quella di fissare direttamente il progetto rotto. Strumenti come git gestiscono già l'unione di codice, quindi non abbiamo bisogno di fare affidamento su una fusione di runtime, che non funzionerebbe sempre.

A seconda della disponibilità di upstream per unire la correzione e la velocità di rilascio di una nuova versione, è possibile che si preveda di produrre un monkeypatch. In tal caso, la cosa migliore sarebbe di avere un meccanismo che dire:

monkeypatch(ClassName, :method, &newcode) of the broken project 
is applied if project.version in [a set of releases where the bug exist] 
if the project version is unknown to the monkeypatch, 
    raise an error to tell the developer to fix the monkeypatch (check if bug exist). 
if a monkeypatch for that project, classname and method already exist, yell 

Questo è dalla parte superiore della mia testa. Potrebbe essere problematico se un bugfix richiede più di un cambio di metodo.

Scenario C: TODO

+0

Per lo scenario C, il modo migliore per evitare i conflitti è utilizzare il namespace del selettore, quindi se hai il pacchetto Foo e il pacchetto Bar, entrambi vogliono estendere il comportamento di qualche classe, come aggiungere #toDate: metodo , lo estendi 2 volte: pacchetto Foo estendi usando fooToDate: name, e package Bar, - barToDate:. e problema andato :) –

Problemi correlati