سؤال

ما الفرق بين كتابة الوظائف الفرعية ووضعها كلها في ملف واحد مقابل كتابة الوظائف الفرعية؟حزم الكتابة؟هل التوجه الشيئي أفضل من الإجرائي عندما يتعلق الأمر بـ Perl؟

البحث بشكل أساسي عن أمثلة للسيناريوهات التي يكون فيها OO أفضل من السيناريوهات الإجرائية.

شكرًا!

هل كانت مفيدة؟

المحلول

أولاً للتوضيح فقط ، الفرق بين الإجرائي و OO ليس هو نفسه الفرق بين وضع كل التعليمات البرمجية في ملف واحد مقابل وضعها في وحدات منفصلة. يمكن أن يكون لديك وحدات منفصلة مليئة بالوظائف التي تستدعيها إجرائيًا.

عندما يكون استخدام الوحدات النمطية ، OO أو الإجرائية ، مفيدًا إذا كان سيتم إعادة استخدام الكود أو إذا كانت مجرد قاعدة رمز كبيرة. إذا كان لديك نظام إدارة محتوى به 10 نصوص CGI مختلفة تقوم جميعها بالعديد من الأشياء نفسها ، مثل التحقق من جلسة المستخدم ربما ، فإن وضع هذا الرمز في وحدة منفصلة بدلاً من إعادة كتابته في كل CGI أمر منطقي. إذا كانت دالة مكونة من 20 سطرًا خاصة بهذا النص البرمجي ، فاتركها في نفس الملف.

يعتمد ما إذا كنت تريد الذهاب مع OO أو الإجراء على ما تفعله. يفضل معظم الناس OO معظم الوقت هذه الأيام. أنا أتفق معهم لأنني أشعر أنه يساعدك على التفكير في شفرتك بشكل منطقي وتجميع الأشياء معًا بطريقة عاقلة يسهل إدارتها وتحديثها لاحقًا.

نصائح أخرى

أحب أن أضع أكبر قدر ممكن من الكود الخاص بي في الوحدات النمطية.الشيء الجميل في الوحدات هو أنه يمكنك استخدام أدوات اختبار Perl (الإثبات والاختبار::المزيد) لكتابة اختبارات الوحدة وإدارتها بسهولة.لذلك، إذا كانت جميع التعليمات البرمجية تقريبًا موجودة في وحدات، فكلها تقريبًا قابلة للاختبار.

عندما أكتب برنامجًا نصيًا، أحب أن يكون لدي غلاف رفيع يوزع خيارات التكوين وسطر الأوامر في البرنامج النصي الخاص بي (ربما باستخدام وحدات مثل Config::Any أو Getopt::Long).يحتوي البرنامج النصي أيضًا على أ usage روتين فرعي.ثم أقوم بإضافة أ main روتين فرعي. main هو بسيط جدا:

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;
}

ستعيش جميع الإجراءات الفرعية الداعمة تقريبًا في وحدة واحدة أو أكثر.

OOP هي طريقة لطيفة لربط البيانات والسلوك.وهذا يمكن أن يجعل التعليمات البرمجية أكثر قابلية للقراءة ويقلل من الفوضى.

 $foo->eat_something( $sandwich )

أسهل للفهم من:

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

يتم تجميع كل حماقة إضافية في متناول يدي $foo سمات الكائن ويسافر دون تشوش المكالمة الفرعية.

بالطبع يمكنك القيام بما يلي:

eat_something( $foo, $sandwich )

حيث $foo هو مجرد تجزئة عادية لتفضيلات الذوق.وهذا هو في الأساس ما يفعله Perl OO، على أي حال.يتم تمرير المستدعي (اسم الكائن أو الفئة) كوسيطة أولى لكل أسلوب.ستفقد مساحة الاسم الملائمة والميراث واستدعاءات الأساليب الديناميكية.من بين التكاليف الثلاثة، سيتم تفويت مساحات الأسماء الملائمة بشدة.IMO، الميراث مبالغ فيه ويجب استخدامه نادرًا.يمكن أن تكون استدعاءات الطريقة الديناميكية مفيدة لنفس الأسباب التي تجعل جداول الإرسال سهلة الاستخدام.

لا يوجد شيء لا يمكنك فعله في OO Perl ولا يمكنك فعله في Perl الإجرائية.لكن OO يجعل بعض الأشياء مريحة للغاية.

اسمحوا لي أن أختم بإعادة كتابة السيناريو الأسطوري الخاص بي بأسلوب OO (سأبالغ قليلاً في OO، فقط للتوضيح):

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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top