Domanda

Qual è la differenza tra scrivere sotto-funzioni e metterle tutte in un file e scrivere pacchetti?L'orientamento agli oggetti è migliore di quello procedurale quando si tratta di Perl?

Fondamentalmente alla ricerca di esempi di scenari in cui OO è migliore di procedurale.

Grazie!

È stato utile?

Soluzione

In primo luogo, solo per chiarire, la differenza tra procedurale e OO non è la stessa della differenza tra mettere tutto il codice in un file e metterlo in moduli separati. Puoi avere moduli separati pieni di funzioni che chiami proceduralmente.

Dove l'utilizzo di moduli, OO o procedurale, è vantaggioso è se il codice verrà riutilizzato o se è solo una grande base di codice. Se hai un CMS con 10 diversi script CGI che fanno tutti molte delle stesse cose, come forse la verifica di una sessione utente, allora ha senso inserire quel codice in un modulo separato piuttosto che riscriverlo in ogni CGI. Se è una funzione di 20 righe specifica per quello script, lasciala nello stesso file.

Se andare con OO o procedurale dipende da quello che stai facendo. La maggior parte delle persone preferirà l'OO la maggior parte delle volte in questi giorni. Sono d'accordo con loro perché penso che ti aiuti a pensare al tuo codice in modo logico e a raggruppare le cose in un modo sano che sarà facile da gestire e aggiornare in seguito.

Altri suggerimenti

Mi piace mettere quanto più codice possibile nei moduli. La cosa bella dei moduli è che puoi usare gli strumenti di test di Perl (prove e Test :: More) per scrivere e gestire facilmente gli unit test. Quindi, se quasi tutto il tuo codice è in moduli, quasi tutto è testabile.

Quando scrivo uno script, mi piace avere un wrapper sottile che analizza la configurazione e le opzioni della riga di comando nel mio script (probabilmente utilizzando moduli come Config :: Any o Getopt :: Long). Lo script contiene anche una subroutine usage. Quindi aggiungo una subroutine main. main è molto semplice:

sub main {
    my $cfg = shift;

    my @collected_data;

    for my $file ( @{ $cfg->{files} ) {
        eval {
            my $fh = get_handle_from_file($file);

            my $xyz_data = parse_xyz_data( $fh );

            push @collected_data, extract_data( $xyz_data, $cfg->{filter} );

            1;
        } or do {
            my $e = $@;
            $e = "an unknown error occurred" unless defined $e;

            warn "Error parsing '$file': $e\n";
        };        
    }

    my %summary_data = summarize_data( @collected_data );

    write_summary( $cfg->{summary_target} );

    return;
}

Praticamente tutte le subroutine di supporto risiederebbero in uno o più moduli.

OOP è un bel modo per associare dati e comportamento. Ciò può rendere il codice più leggibile e ridurre il disordine.

 $foo->eat_something( $sandwich )

è più facile da capire di:

 eat_something( $sandwich, $likes_salty, $likes_sour, $likes_sweet, $likes_spicy );

Tutta la merda extra è racchiusa in utili attributi dell'oggetto $foo e viaggia senza ingombrare la chiamata secondaria.

Certo che potresti fare:

eat_something( $foo, $sandwich )

Dove $ foo è solo un normale hash di preferenze di gusto. Questo è essenzialmente ciò che fa Perl OO, comunque. L'invocante (nome oggetto o classe) viene passato come primo argomento a ciascun metodo. Si perde la comoda spaziatura dei nomi, l'ereditarietà e le chiamate di metodi dinamici. Dei tre costi, i comodi spazi per i nomi saranno quelli che mancheranno di più. IMO, l'eredità è sopravvalutata e dovrebbe essere usata solo raramente. Le chiamate ai metodi dinamici possono essere utili per gli stessi motivi per cui sono utili le tabelle di invio.

Non c'è niente che non puoi fare in OO Perl che non puoi fare in Perl procedurale. Ma OO rende alcune cose molto convenienti.

Concludo riscrivendo la mia mitica sceneggiatura in stile OO (esagererò un po 'con l'OO, solo a scopo illustrativo):

sub main { my $ cfg= shift;

    my $cd = Data::Collection->new();

    for my $file ( $cfg->files ) {
        eval {

            # skip the step of creating a handle first.  The parsing object
            # can take a file and get a handle or could be passed a handle.               

            my $xyz_parser = File::XYZ::Parse->new( file => $file );

            # The parser returns an XYZ::Data object

            my $xyz_data = $xyz_parser->parse;

            $cd->add_data( $xyz_data->extract_data( $cfg->filter );

            1;
        } or do {
            my $e = $@;
            $e = "an unknown error occurred" unless defined $e;

            warn "Error parsing '$file': $e\n";
        };        
    }

    # Skip the step of separate summarization, since the cd object can check if
    # the summary has been done, and if not generate and cache it as needed.

    $cd->write_summary( $cfg->summary_target );

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