日付処理モジュール化


perl weekly newsletterの私の最初のポストに言及して、多くの人々は記事のこのシリーズの最初の部分を読みました.(まだわからないのですが、どのように多くの部品があります)それで、私はフォローアップを書くことに決めました.
あなたは何を期待できますか
  • モジュールへの機能の移動
  • テスト機能が自動的に
  • モジュールを
  • に変更する
  • は基底クラス
  • からクラスを継承する
    私たちがパート1で我々の小さいskriptを去ったところを要約するために:
    use strict;
    
    use Getopt::Long;
    use DateTime;
    use DateTime::Duration;
    
    my $date;   ## the starting date argument
    my $dt;     ## DateTime Object of starting date
    
    
    GetOptions(
            "date=s"         => \$date,
            );
    
    $dt = get_dt($date);
    my $today = DateTime->today();
    
    
    
    if(!$dt) {
        print "submitted value $date is no date\n";
    }
    if(is_last_week($dt)) {
        print "submitted date was in the last week\n";
    }
    
    sub is_last_week {
        my $dt = shift;
        return unless ref $dt eq "DateTime";
        return if($dt > $today) ;
    
        my $dur = DateTime::Duration->new(days => 7);
        $today->subtract_duration($dur);
        return 1 if $today < $dt;
    }
    
    
    sub get_dt {
        my $date = shift;
    
        my($y, $m, $d) = $date =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
        my $dt;
        eval {
            $dt = DateTime->new(year => $y, month => $m, day => $d);
        }; 
        if ($@) {
            print STDERR "Error while generating DateTime: $@\n";
            return 0;
        }
        else {
            return $dt;
        }
    }
    
    
    スクリプトは有効な日付であればパラメータ- dをチェックし、日付が最後の週にあることを確認します.
    スクリプトをパレメータ終了せずに呼び出します.

    perl skript.pl
    Error while generating DateTime: Validation failed for type named DayOfMonth declared in package DateTime::Types (/home/kroll/.plenv/versions/5.32.1/lib/perl5/site_perl/5.32.1/x86_64-linux/DateTime/Types.pm) at line 29 in sub named (eval) with value undef

    Trace begun at Specio::Exception->new line 57
    Specio::Exception::throw('Specio::Exception', 'message', 'Validation failed for type named DayOfMonth declared in package DateTime::Types (/home/kroll/.plenv/versions/5.32.1/lib/perl5/site_perl/5.32.1/x86_64-linux/DateTime/Types.pm) at line 29 in sub named (eval) with value undef', 'type', 'Specio::Constraint::Simple=HASH(0x55a2fa53c0a8)', 'value', undef) called at (eval 201) line 91
    DateTime::_check_new_params('year', undef, 'month', undef, 'day', undef) called at /home/kroll/.plenv/versions/5.32.1/lib/perl5/site_perl/5.32.1/x86_64-linux/DateTime.pm line 176
    DateTime::new('DateTime', 'year', undef, 'month', undef, 'day', undef) called at skript.pl line 45
    eval {...} at skript.pl line 44
    main::get_dt(undef) called at skript.pl line 15

    submitted value is no date


    我々は、後でのために我々のto - doリストにこれを書きます.
    しかし、今日のために、スクリプトの後でスクリプトを後置することができるように、スクリプトの中でスクリプトの日付処理を置きたいです、しかし、日付処理は他のスクリプトで再利用されることができます.

    新規で空のモジュールを生成する
    Perlの人々のために、それは全く明らかです、あなたはディレクトリlibを生成して、モジュールを入れて、通常のPerlボイラー板をします:
    package Date;
    
    use strict;
    
    use DateTime;
    use DateTime::Duration;
    
    
    1;
    
    そして、私は通常、テスト駆動ガイとして、私はあまりにも私の最初のテストを追加しました.T/日付で.T :
    use Test::More;
    
    use_ok("Date");
    
    done_testing();
    
    もちろんこれは緑になります.

    $ prove -lv
    t/date.t ..
    ok 1 - use Date;
    1..1
    ok


    それで私たちはそれをコミットすることができます.

    Author: Volker Kroll
    Date: Thu May 6 11:59:53 2021 +0200

    new Module Date

    • Date is empty
    • t/date.t has a test, that it loads correctly


    getSum DTを日付に移動します.PM
    それからスクリプトからコードを得て、我々のモジュールでペーストしないでください.しかし、私はもう少しオブジェクト指向のモジュールを好むので、少し奇妙な古いOO Perlスタイルでコンストラクターを追加しました.
    sub new {
        my $class = shift;
        my $datestring = shift|| undef;
        if ($datestring) {
            bless get_dt($datestring), $class;
        }
    }
    
    もちろんもう少しテストします.
    use_ok("Date");
    
    my $d = Date::get_dt('2020-01-02');
    isa_ok($d, DateTime);
    my $date = Date->new('2020-01-02');
    isa_ok($date, "Date");
    
    結果:

    $ prove -lv
    t/date.t ..
    ok 1 - use Date;
    ok 2 - An object of class 'DateTime' isa 'DateTime'
    ok 3 - An object of class 'Date' isa 'Date'
    1..3
    ok


    それをコミットするのに十分なコード

    Author: Volker Kroll [email protected]
    Date: Thu May 6 12:11:15 2021 +0200

    get_dt now in Date

    • get_dt is called like in skript.pl Date::get_dt(yyyy-mm-dd)
    • additionally you can do a Date->new(yyyy-mm-dd) returned is an object of class Date (that is a DateTime)


    日付をdatetimeの子にしない理由は?
    私のモジュールで作業している間、datetimeから継承するのが良いアイデアであると考えました.DateTimeオブジェクトを返します.しかし、それはすぐには動作しませんでした.なぜなら、そのコンストラクターに従ってdatetimeのコードをたくさん追加する必要があるからです.(正直に言うと、私のコンストラクタで少しだけ追加して、"本当のコンストラクタ"にDateTimeの重いリフティングをする方法を忘れてしまったので、このプロジェクトでコンストラクタの名前を変更することを決めました.
    package Date;
    
    use strict;
    
    use base qw(DateTime);
    use DateTime;
    use DateTime::Duration;
    
    
    sub create {
        my $class = shift;
        my $datestring = shift|| undef;
        if ($datestring) {
            return bless get_dt($datestring), $class;
        }
    }
    
    
    また、私も私の小さなスクリプトで前にそれを持っていましたモジュールで私の関数isshrlaweek週を望みました.テストをより簡単にするために、私は、「今日、カンニングをする」という可能性を付け加えました.私が今日、呼び出しにパラメタを加えるとき、それは「本当の今日」でなくそれを使います:
    sub is_last_week {
        my $dt = shift;
        return unless ref $dt;
        my $today = shift ||  DateTime->today();
        return if($dt > $today) ;
    
        my $dur = DateTime::Duration->new(days => 7);
        $dt->add_duration($dur);
        return 1 if $today < $dt;
        return 0;
    }
    
    今、もう少しテストを加えることができました.
    use Test::More;
    use Data::Dumper;
    use DateTime;
    
    use_ok("Date");
    test_new();
    test_is_last_week();
    done_testing();
    
    sub test_new {
        my $d = Date::get_dt('2020-01-02');
        isa_ok($d, DateTime);
        my $date = Date->create('2020-01-02');
        isa_ok($date, Date);
        isa_ok($date, DateTime);
    }
    
    sub test_is_last_week {
        my $date = Date->create('2020-01-02');
        my $today = DateTime->new(year => 2020, month => 01, day => 05);
        can_ok($date, "is_last_week");
        isa_ok($date, "Date");
        isa_ok($today, "DateTime");
        is($date->is_last_week($today), 1, "2020-01-02 was in the week before 2020-01-05 ");
        is($date->is_last_week(), 0, "2020-01-02 was not last week from today ");
    
    }
    
    
    再び期待される出力になります.

    $ prove -lv
    t/date.t ..
    ok 1 - use Date;
    ok 2 - An object of class 'DateTime' isa 'DateTime'
    ok 3 - An object of class 'Date' isa 'Date'
    ok 4 - An object of class 'Date' isa 'DateTime'
    ok 5 - Date->can('is_last_week')
    ok 6 - An object of class 'Date' isa 'Date'
    ok 7 - An object of class 'DateTime' isa 'DateTime'
    ok 8 - 2020-01-02 was in the week before 2020-01-05
    ok 9 - 2020-01-02 was not last week from today
    1..9
    ok


    次のステップはもちろん-通常通り-コミット

    Author: Volker Kroll
    Date: Fri May 7 11:38:11 2021 +0200

    added Tests for date was in last week

    • changed new to create to not interfere with DateTime new
    • add function for is_last_week
    • for testing purposes it is possible to call is_last_week with a given "today" so tests don't become red


    もう2、3のテスト
    sub test_is_last_week {
        my $date = Date->create('2020-01-02');
        my $today = DateTime->new(year => 2020, month => 01, day => 05);
        can_ok($date, "is_last_week");
        isa_ok($date, "Date");
        isa_ok($today, "DateTime");
        is($date->is_last_week($today), 1, "2020-01-02 was in the week before 2020-01-05 ");
        is($date->is_last_week(), 0, "2020-01-02 was not last week from today ");
        is($date->is_last_week(), 0, "2020-01-02 was not last week from today ");
    
    }
    
    
    今ではモジュール全体が十分にテストされています.

    t/date.t ..
    ok 1 - use Date;
    ok 2 - An object of class 'DateTime' isa 'DateTime'
    ok 3 - An object of class 'Date' isa 'Date'
    ok 4 - An object of class 'Date' isa 'DateTime'
    ok 5 - Date->can('is_last_week')
    ok 6 - An object of class 'Date' isa 'Date'
    ok 7 - An object of class 'DateTime' isa 'DateTime'
    ok 8 - 2020-01-02 was in the week before 2020-01-05
    ok 9 - 2020-01-02 was not last week from today
    ok 10 - 2020-01-02 was not last week from today
    1..10
    ok


    最終的なコミット

    Author: Volker Kroll
    Date: Fri May 7 14:21:09 2021 +0200

    some more testing in date.t



    結論
    いくつかの変化だけが変わった.今、我々は簡単に我々が開発した機能をテストすることができます.さらに、後で我々の(現在datetime)オブジェクトを再利用することができます.しかし、次の作業の最大の利点は、他の作業を行うスクリプトから日付処理を削除することです.それで、私たちはそれらを変更して、使用するのがより簡単にする異なった部分を取り除きました.
    次の論理ステップは何でしょうか?それはソフトウェアの要件とユーザに依存します.しかし、パラメータなしで呼ばれるとき、私はおそらく「悪いエラーメッセージ」を修正します.通常、私は必須のパラメタがなくなっているとき、ヘルプ機能(まだ書かれる必要がある)を呼びます.しかし、それは3番目の部分で行われます-多分-滞在調整.