giovedì 29 marzo 2012

Classi SICP per JavaScript

Attenzione: Questo articolo è rivolto ai programmatori JavaScript. Parens stanno arrivando, ma solo per breve tempo e si può gestire e sarà un bene per voi.
In Struttura e interpretazione di linguaggi di programmazione Second Edition (SICP) a pagina 182, gli autori introducono l'idea del messaggio che passa con il seguente esempio nello schema di una funzione complessa costruzione numero.
(Define (make-da-real-imag xy)
  (Define (spedizione op)
    (Cond ((eq? Op 'real-parte) x)
          ((Eq? Op 'imag-parte) y)
          (Grandezza (eq? Op ')
           (Sqrt (+ (quadrato x) (quadrato y))))
          (Angolo (eq? Op ') (atan yx))
          (Altrimenti
           (Errore "Uknown op - MAKE-DA-REAL-IMAG" op))))
  spedizione)
La cosa importante da notare qui è che il valore restituito dal make-da-real-imag funzione di costruzione è in realtà una procedura di spedizione che è possibile chiamare con un argomento del messaggio. È possibile inviare i messaggi per ottenere la parte reale o la grandezza del numero complesso.
(C define (make-da-real-imag 3 4))
(C 'real-parte); 3
(C 'imag-parte); 4
(Magnitudine c '); 5
(Angolo c '); 0,927295218001612
(C 'asdf); ERROR: Uknown op - MAKE-DA-REAL-IMAG: asdf
Vediamo quello che il codice di cui sopra sembra in JavaScript, la nostralingua franca .
funzione makeFromRealImag (x, y) {
    funzione di invio (op) {
        switch (op) {
            case 'realPart': x ritorno;
            case 'imagPart': y ritorno;
            case 'grandezza':
                ritorno Math.sqrt (x * x + y * y);
            case 'angolo': return Math.atan2 (y, x);
            default:
                gettare 'op Unknown - makeFromRealImag:' + op;
        }
    }
    ritorno della spedizione;
}

var c = makeFromRealImag (3, 4);
c ('realPart'); / / 3
c ('imagPart'); / / 4
c ('magnitudo'); / / 5
c ('angolo'); / / 0,9272952180016122
c ('asdf'); / / "op Unknown - makeFromRealImag: asdf"
Ora, questo probabilmente non assomiglia a nessun orientato agli oggetti JavaScript che avete visto prima, ma illustra un punto importante. In JavaScript, possiamo rappresentare l'idea di un oggetto in funzione dei suoi messaggi. La funzione restituisce una funzione di costruzione di spedizione che hai scritto, che può inviare qualsiasi messaggio alcun modo che lo si desidera. Questo dà immediatamente Spidermonkey di __nosuchmethod__, Smalltalk di doesNotUnderstand e Ruby method_missing . Roba potente ma purtroppo il codice JavaScript viene eseguito al di sopra molto lentamente. Siamo in grado di muoversi verso uno stile JavaScript più veloce e più familiare.
SICP pagina 223, introduce l'idea di oggetti mutabili, ma il punto più interessante è la variazione della procedura di spedizione.
(Define (make-saldo)
  (Define (ritiro importo)
    (If (> = saldo dell'importo)
        (Begin (set! equilibrio (- importo del saldo))
               saldo)
        "Fondi insufficienti"))
  (Define deposito (importo)
    (Set! saldo (saldo + importo))
    saldo)
  (Define (spedizione m)
    (Cond ((eq? M 'recedere) revocare)
          (Deposito (eq? M ') deposito)
          (Else (errore "Unknown richiesta - MAKE-ACCOUNT"
                       m))))
  spedizione)

(Define account (make-account 10))
((Conto deposito ') 5); 15
((Account 'recedere) 3), 12
La conversione di questo JavaScript abbiamo la seguente.
Funzione makeAccount (saldo) {
    funzionare prelevare (importo) {
        if (saldo> = importo) {
            equilibrare = - importo;
            restituire equilibrio;
        }
        di ritorno "fondi insufficienti";
    }
    funzione di deposito (importo) {
        = saldo + importo;
        restituire equilibrio;
    }
    funzione di invio (m) {
        Interruttore (m) {
            case 'ritiro': return ritirarsi;
            caso di 'deposito': deposito di ritorno;
            default:
                gettare "richiesta Unknown - makeAccount:" + m;
        }
    }
    ritorno della spedizione;
}

var = conto makeAccount (10);
account ('deposito') (5); / / 15
account ('ritiro') (3); / / 12
Il modo in cui la spedizione funzione è disponibile per gli account è molto diversa rispetto al caso dei numeri complessi. Nel caso di numeri complessi, quando un messaggio è stato inviato alla spedizione funzione, eseguita l'operazione associata (cioè il metodo) immediatamente. Al contrario, l'account di spedizione funzione restituisce il metodo associato con il messaggio e che il metodo può quindi essere chiamato.
Questo è molto simile al funzionamento di JavaScript reciever.message (arg) opere sintassi e possiamo passare ad un più familiare stile orientato agli oggetti JavaScript.
Funzione makeAccount (saldo) {
    funzionare prelevare (importo) {
        if (saldo> = importo) {
            equilibrare = - importo;
            restituire equilibrio;
        }
        di ritorno "fondi insufficienti";
    }
    funzione di deposito (importo) {
        = saldo + importo;
        restituire equilibrio;
    }
    ritorno {
      ritiro: ritirare,
      Deposito: deposito
    };
}

var = conto makeAccount (10);
account.deposit (5); / / 15
account.withdraw (3); / / 12
In questa ultima versione, abbiamo smesso di scrivere la nostra logica propria spedizione e l'uso di JavaScript built-in di ricerca immobiliare.Ciò aumenta notevolmente la velocità. Abbiamo perso la capacità di fare la__noSuchMethod__ tipo di spedizione quando si utilizzano standard ECMAScript, ma che non sembra essere comunemente utili comunque.
Per le buone letture programmatori JavaScript là fuori, si possono riconoscere questa ultima versione, come gli oggetti durevoli dal libro di Douglas Crockford di JavaScript: le parti buone .
Trovo interessante che l '"eredità" la parola non appare nell'indice della SICP anche se il libro va avanti per attuare programmi complessi come interpreti del linguaggio e compilatori in stile message passing. Ciò dimostra questo stile semplice di programmazione object-oriented in grado di portare lontano.
La morale della storia è che i libri antichi sono la pena di leggere e può cambiare il modo in cui si programma oggi.





martedì 27 marzo 2012

Multitenancy in Google AppEngine

Multitenancy è un argomento che è stato discusso per molti anni, e ci sono molte ottime referenze che prontamente disponibile, quindi mi limiterò a presentare una breve introduzione. multitenancy è un'architettura software in cui una singola istanza del software viene eseguito su un server, che serve di più organizzazioni clienti (inquilini). . Con un'architettura multi-tenant, un'applicazione può essere progettato per virtualmente partizione suoi dati e la configurazione (business logic), e ogni organizzazione client lavora con un'istanza personalizzata un'applicazione virtuale Si adatta SaaS (Software as a Service) di cloud computing molto bene, tuttavia, possono essere molto complesse da implementare. L'architetto deve essere consapevole di sicurezza, controllo accessi, ecc multitenancy può esistere in vari gusti:

Multitenancy durante la distribuzione

  1. Logica di business completamente isolata (dedicato processo di business personalizzata del server)
  2. Application Server virtuale (server applicativo dedicato, VM singolo per server app)
  3. Condivise server virtuali (server applicativo dedicato il comune VM)
  4. Server applicativi condivisi (le discussioni e sessioni)

Questo spettro di diverse installazioni può essere visto qui:



Multitenancy e dati

  1. Dedicato server fisico (DB risiede in isolati host fisici)
  2. Shard ospite virtualizzato (DB separato su macchine virtuali)
  3. Database su host condiviso (DB separato sullo stesso host fisico)
  4. Schema dedicati all'interno di database condivisi (DB stesso, dedicato schema / tabella)
  5. Tabelle condivise (DB stesso schema, segregati dai tasti - righe)




Prima di saltare nella API, è importante capire come interno di Google memorizzazione dei dati di lavoro soluzione. L'introduzione di tecnologia di BigTable di Google: Si tratta di una soluzione di storage per le proprie applicazioni di Google come Search, Google Analytics, GMail, AppEngine, etc BigTable è NOT :

  • Un database
  • Un dato in orizzontale sharded
  • Una tabella di hash distribuita

E ' IS : un rado, distribuito, persistente mappa multidimensionale ordinati. In termini di base, si tratta di una hash di hash (la mappa di mappe, o di un dict di dicts). AppEngine dati si trova in una "tabella" distribuiti su più computer. Ogni entità ha una chiave con cui è identificato in modo univoco (genitore + figlio ID +), ma c'è anche metadati che indica che l'applicazione GAE (appId) un'entità a cui appartiene.Dal grafico qui sopra, BigTable distribuisce i propri dati in un formato chiamato compresse, che sono sostanzialmente fette dei dati. Queste compresse vivono su diversi server in the cloud. Per indicizzare in uno specifico record (record e di entità più o meno significano la stessa cosa) si utilizza una stringa di 64 KB, chiamato Key. Questa chiave contiene informazioni sulla riga specifica e il valore della colonna che si desidera leggere. Esso contiene anche un timestamp per consentire più versioni dei dati da memorizzare. Inoltre, i record per un gruppo di entità specifico si trovano contiguo. Questo facilita la scansione dei record. Ora siamo in grado di tuffarsi come Google implementa multitenancy. implementato nella versione 1.3.6 di App Engine, l'API dei nomi (vedi risorse) è progettato per essere altamente personalizzabile, con ganci nel tuo codice che è possibile controllare, in modo da poter impostare multi-tenancy in base alle esigenze dell'applicazione. L'API funziona con tutte le pertinenti App Engine API (Datastore, Memcache, Blobstore e code Task). In termini Gae,









namespace == inquilino

A livello di storage di archivio dati, uno spazio dei nomi è proprio come un app-id. Ogni spazio dei nomi guarda essenzialmente al datastore come un altro in vista dei dati dell'applicazione. Quindi, le query non possono estendersi su spazi dei nomi (almeno per ora) e intervalli di chiavi sono diverse per spazio dei nomi. Una volta che un ente è stato creato, lo spazio dei nomi non cambia, in modo da fare una



namespace_manager.set (...)

non avrà alcun effetto sulla sua chiave. Allo stesso modo, una volta che una query è stato creato, lo spazio dei nomi viene impostato. Stessa cosa con


memcache_service ()
e tutti gli altri APIS GAE. Quindi è importante sapere quali oggetti avere quale namespace. Nella mia mente, dal momento che tutte le vite di dati utente GAE ha a BigTable, aiuta a visualizzare un oggetto GAE chiave come: ID Application | Keys antenati | Nome Tipo | Nome chiave o ID Tutte queste valori di fornire un indirizzo per individuare i dati dell'applicazione. Allo stesso modo, si può immaginare la chiave multi-tenant come: Application ID | | Spazio dei nomi degli antenati Keys | Nome Tipo | Nome chiave o ID Ora brevemente l'API (Python):

Nome FunzioneArgomentiAPI
get_namespaceNessunoRestituisce lo spazio dei nomi corrente, o restituisce una stringa vuota se lo spazio dei nomi non è impostata.
set_namespacenamespace: Un valore di valore vengono annullati Nessuno spazio dei nomi predefinito.In caso contrario, 
([0-9A-Za-z._-] {0100})
Imposta lo spazio dei nomi per la richiesta HTTP corrente
validate_namespacevalore: stringa che contiene lo spazio dei nomi in corso di valutazione. Aumenta il BadValueError se non ([0-9A-Za-z._-] {0100}).eccezione = BadValueErrorSolleva l'eccezione BadValueError se la stringa spazio dei nomi non è valido.

Ecco un esempio veloce:

01.tid = getTenant ()
02. 
03.namespace = namespace_manager.get_namespace ()
04. 
05.cercare :
06.namespace_manager.set_namespace ( '-tenant' + str (tid))
07. 
08.N. Tutte le operazioni di datastore fatto qui
09.user = Utente ( 'Luis' 'Atencio' )
10.user.put ()
11. 
12.infine :
13. 
14.# Ripristina lo spazio dei nomi salvato    
15.namespace_manager.set_namespace (namespace)
La cosa importante da notare è il modello che fornisce GAE. Sarà la stessa identica cosa per le API Java.La fine del blocco è immensamente importante in quanto ripristina lo spazio dei nomi a ciò che era in origine (prima della richiesta). Omettendo la fine del blocco causerà lo spazio dei nomi da impostare per la durata della richiesta. Ciò significa che l'accesso API se si tratta di query datastore o recupero Memcache utilizzeranno lo spazio dei nomi precedentemente impostato. Inoltre, per eseguire una query per tutti i domini creati, GAE fornisce alcune query meta, in quanto tale:
01.da google.appengine.ext.db.metadata import Namespace
02. 
03.q = Namespace.all ()
. 04se start_ns:
05.q.filter ( '__key__> =' , Namespace.key_for_namespace (start_ns))
06.ifend_ns:
07.q.filter ( '__key__ <=' , Namespace.key_for_namespace (end_ns))
08. 
09.risultati = q.fetch (limite)
10.# Ridurre gli oggetti dello spazio dei nomi in una lista di nomi dei namespace
11.inquilini = map (lambda ns: ns.namespace_name, risultati)