Domanda

Nel mio attuale lavoro Sto costruendo una serie di script Perl che dipendono pesantemente sugli oggetti. (Usando bless() di Perl su un hash per arrivare il più vicino a OO possibile)

Ora, in mancanza di un modo migliore di mettere questo, la maggior parte dei programmatori di mia azienda non sono molto intelligente. Peggio ancora, non lo fanno come la lettura di documentazione e sembrano avere un problema comprensione codice di altre persone. codifica Cowboy è il gioco qui. Ogni volta che incontrano un problema e cercare di risolvere il problema, sono venuti fuori con una soluzione terribile che in realtà non risolve nulla e di solito lo rende peggiore.

Questo si traduce in me, francamente, non li fiducia con il codice scritto in anatra digitato lingua. Per fare un esempio, vedo troppi problemi con loro non ottenere un errore esplicita per abuso oggetti. Per esempio, se il tipo A ha membro foo, e lo fanno qualcosa di simile, instance->goo, che non stanno andando a vedere il problema immediatamente. Si restituirà un valore nullo / undefined, e saranno probabilmente sprecare un'ora trovare la causa. Poi finiscono per cambiare qualcosa perché non identificare correttamente il problema originale.

Quindi sono di brainstorming un modo per mantenere il mio linguaggio di scripting (il suo rapido sviluppo è un vantaggio) ma indica un messaggio di errore esplicito quando un oggetto non viene utilizzato correttamente. Mi rendo conto che dal momento che non v'è una fase di compilazione o di tipizzazione statica, l'errore dovrà essere in fase di esecuzione. Io sto bene con questo, a condizione che l'utente ottiene un avviso molto esplicito dicendo "questo oggetto non ha X"

Come parte della mia soluzione, non voglio che sia necessario che controllano se un metodo / variabile esiste prima di tentare di usarlo.

Anche se il mio lavoro è in Perl, credo che questo può essere il linguaggio agnostico.

È stato utile?

Soluzione

Se avete qualche colpo di aggiunta di moduli per l'uso, prova a Moose . Esso fornisce più o meno tutte le caratteristiche che ci si vuole in un ambiente di programmazione moderno, e altro ancora. Lo fa il controllo di tipo, eccellente eredità, ha introspezione capacità, e con MooseX :: Declare , una delle interfacce più belli per le classi Perl là fuori. Date un'occhiata:

use MooseX::Declare;

class BankAccount {
    has 'balance' => ( isa => 'Num', is => 'rw', default => 0 );

    method deposit (Num $amount) {
        $self->balance( $self->balance + $amount );
    }

    method withdraw (Num $amount) {
        my $current_balance = $self->balance();
        ( $current_balance >= $amount )
            || confess "Account overdrawn";
        $self->balance( $current_balance - $amount );
    }
}

class CheckingAccount extends BankAccount {
    has 'overdraft_account' => ( isa => 'BankAccount', is => 'rw' );

    before withdraw (Num $amount) {
        my $overdraft_amount = $amount - $self->balance();
        if ( $self->overdraft_account && $overdraft_amount > 0 ) {
            $self->overdraft_account->withdraw($overdraft_amount);
            $self->deposit($overdraft_amount);
        }
    }
}

Penso che sia abbastanza freddo, me stesso. :) E 'uno strato sopra il sistema oggetto di Perl, quindi funziona con roba hai già (in pratica).

Con Moose, è possibile creare sottotipi molto facilmente, in modo da poter assicurarsi che il vostro ingresso è valido. programmatori pigri d'accordo: con così poco che deve essere fatto per rendere il lavoro in sottotipi Moose, è più facile fare loro che no! (Da Cookbook 4 )

subtype 'USState'
    => as Str
    => where {
           (    exists $STATES->{code2state}{ uc($_) }
             || exists $STATES->{state2code}{ uc($_) } );
       };

E Tada, l'USState ora è un tipo che si può usare! Nessuna confusione, nessun muss, e solo una piccola quantità di codice. Sarà gettare un errore se non è giusto, e tutti i consumatori della classe hanno a che fare è passare uno scalare con quella stringa in esso. Se va bene (che dovrebbe essere ... giusto? :)) L'usano come normale, e la classe è protetto da spazzatura. Che bello è che!

Moose ha tonnellate di roba impressionante come questo.

Fidati di me. Controlla. :)

Altri suggerimenti

In Perl,

  • rendono necessario che use strict e use warnings sono in in 100% del codice

  • Si può provare a fare un quasi variabili membro private attraverso la creazione di chiusure . Un ottimo esempio è "private variabili membro, sorta di" sezione http : //www.usenix.org/publications/login/1998-10/perl.html . Non sono al 100% privata, ma piuttosto non-ovvio come l'accesso a meno che non si sa davvero quello che stai facendo (e richiedono loro di leggere il codice e fare ricerca per scoprire come).

  • Se non si desidera utilizzare le chiusure, il seguente approccio funziona un po 'così:

    Fai tutte le variabili membro dell'oggetto (alias chiavi oggetto hash in Perl) avvolto in funzioni di accesso. Ci sono modi per farlo in modo efficiente da standard di codifica POV. Uno dei meno cassaforte è Class :: Accessor :: veloce. Sono sicuro che Moose ha modi migliori, ma io non sono che la familiarità con Moose.

    Assicurati di "nascondere" variabili membro effettivo nei nomi dei privati ??e congressi, ad esempio $object->{'__private__var1'} sarebbe il membro variabile, e $object->var1() sarebbe una funzione di accesso getter / setter.

    NOTA: Per l'ultimo, Class :: Accessor :: veloce è male dato che le sue variabili membro condividono nomi con funzioni di accesso. Ma si può avere molto facile costruttori che funzionano esattamente come Class :: Accessor :: Veloce e creare valori chiave come $ obj -.> { '__ private__foo'} per "foo"

    Questo non impedirà loro si zappa sui piedi, ma renderà molto più difficile farlo.

    Nel tuo caso, se usano $obj->goo o $obj->goo(), si otterrebbe un errore di runtime, almeno in Perl.

    Si potrebbe naturalmente andare fuori del loro modo di fare $obj->{'__private__goo'}, ma se lo fanno la merda cowboy gonzo a causa di pigrizia, il secondo è molto più lavoro che fare il $obj->foo() corretta.

    Si può anche avere una scansione del codice di base che rileva le stringhe di tipo $object->{"_, anche se dalla tua descrizione che potrebbe non funzionare come deterrente che molto.

È possibile utilizzare Class :: InsideOut o oggetto :: InsideOut che vi danno la vera privacy dei dati. Invece di memorizzare dati in un riferimento hash benedetta, un riferimento ad uno scalare benedetta viene utilizzato come chiave per hash dati lessicali. Per farla breve, se i vostri collaboratori cercano $obj->{member} che otterranno un errore di tempo di esecuzione. Non c'è nulla in $obj per loro di afferrare in e nessun modo facile per ottenere ai dati se non per mezzo di accesso.

Ecco una discussione della tecnica inside-out e varie implementazioni .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top