Nützliche Tools für Entwickler: perlcritic & corelist

Begonnen von RichardCZ, 27 März 2020, 10:10:14

Vorheriges Thema - Nächstes Thema

RichardCZ

Perl::Critic (https://metacpan.org/pod/Perl::Critic)

und

Module::CoreList (https://metacpan.org/pod/Module::CoreList)

Perl::Critic

Wie schon an anderer Stelle ausgeführt (und siehe Moduldokumentation), handelt es sich dabei um eine programmatische Version von PBP.
Nicht ein RichardCZ läuft herum und sagt wo's (angeblich) hakt, dieses Modul macht das.  ;)
Genau genommen interessiert uns das Skript "perlcritic", das mit diesem Modul daherkommt. Auf der Kommandozeile gibt man ein

$ perlcritic 59_WUup.pm
59_WUup.pm source OK


Und schon weiß man, dass der Code im Prinzip nicht die eigene Katze fressen wird. Dann wird man mutiger:

$ perlcritic -4 59_WUup.pm
Subroutine "WUup_stateRequestTimer" does not end with "return" at line 184, column 1.  See page 197 of PBP.  (Severity: 4)
Subroutine "WUup_receive" does not end with "return" at line 315, column 1.  See page 197 of PBP.  (Severity: 4)


und noch mutiger ;-)

$ perlcritic -3 59_WUup.pm
Subroutine "WUup_stateRequestTimer" does not end with "return" at line 184, column 1.  See page 197 of PBP.  (Severity: 4)
Reused variable name in lexical scope: $version at line 214, column 5.  Invent unique variable names.  (Severity: 3)
Regular expression without "/x" flag at line 225, column 20.  See page 236 of PBP.  (Severity: 3)
Cascading if-elsif chain at line 243, column 9.  See pages 117,118 of PBP.  (Severity: 3)
Regular expression without "/x" flag at line 243, column 22.  See page 236 of PBP.  (Severity: 3)
Regular expression without "/x" flag at line 246, column 25.  See page 236 of PBP.  (Severity: 3)
Regular expression without "/x" flag at line 262, column 25.  See page 236 of PBP.  (Severity: 3)
Subroutine "WUup_receive" does not end with "return" at line 315, column 1.  See page 197 of PBP.  (Severity: 4)


Und dann lässt man es erstmal gut sein. perlcritic sollte auf Stufe 5 (-5 oder kein Argument) definitiv den Schnabel halten. Wenn man es auf -4 zum Schweigen bringt ist das super, den Rest schauen wir uns später an.




Module::CoreList

Auch hier interessiert uns in erster Linie das Skript "corelist", das mit diesem Modul daherkommt. Was macht es? Es sagt uns für ein angefragtes Perl Modul ob bzw. wann dieses Teil der Perl CORE Distribution wurde. Warum interessiert uns das?

Nun - vielleicht wollen wir nicht alle Räder neu erfinden und bereits vorhandene perl Module nutzen, auf der anderen Seite wollen wir den update-Prozess der FHEM User so geschmeidig wie möglich halten (und halten uns mit der Verwendung von CPAN Modulen zurück). Jetzt wäre es ganz nett, wenn uns jemand sagen könnte, auf welche Module wir vertrauen können, dass sie tatsächlich da sind - beim User.

$ corelist Time::HiRes

Data for 2019-11-10
Time::HiRes was first released with perl v5.7.3


Stand 10.11.2019 also, Time::HiRes wird seit Perl 5.7.3 ausgeliefert. Dieses "Stand" Datum ist nur wichtig um zu sehen ob wir nicht veraltete Info haben - prinzipiell zeigt es wie aktuell die Datenbank eures Module::CoreList ist. 2019 ist prima.

Wir sehen also, Time::HiRes gibt es seit Perl 5.7.3 und damit seit 5. März 2002 im Perl.  8)
Den 5. März weiß ich wegen: https://perldoc.perl.org/perlhist.html

Verdikt: Kann man uneingeschränkt nutzen - wird ja auch gemacht.

Kann man List::Util nutzen? https://metacpan.org/pod/List::Util

$ corelist List::Util

Data for 2019-11-10
List::Util was first released with perl v5.7.3


Na klar! Und plötzlich ist euer Arsenal und ready-made code 100x größer und ihr müsst keine Angst haben wenn ihr es nutzt einem FHEM User den Boden unter den Füßen wegzuziehen. => So lange ihr - derzeit - nix nutzt was erst nach 5.10.1 reingekommen ist. Jeder der heute "5.10" verwendet, verwendet eigentlich 5.10.1

corelist kann noch mehr. Ihr könnt nachsehen, ab wann es ein bestimmtes Feature gab in Perl.

$ corelist -f say
feature "say" was first released with the perl v5.9.5 feature bundle


Ab wann gibt es statische Variablen in Perl?

$ corelist -f state
feature "state" was first released with the perl v5.9.5 feature bundle


Ha! Können wir nutzen!

Was wäre Perl ohne reguläre Ausdrücke? Was gibt es so an Hash-Funktionalität? (Hab das Data for raus)

$ corelist /Hash/
Hash::Util was first released with perl v5.8.0

Hash::Util::FieldHash was first released with perl v5.9.4

Module::CoreList::TieHashDelta was first released with perl v5.17.3 and removed from v5.27.9

SubstrHash was first released with perl 5.001 and removed from 5.002

Test2::Util::HashBase was first released with perl v5.25.1

Tie::Hash was first released with perl 5.002

Tie::Hash::NamedCapture was first released with perl v5.9.5

Tie::RefHash was first released with perl 5.004

Tie::SubstrHash was first released with perl 5.002

TieHash was first released with perl 5 and removed from 5.002


Hier sehen wir auch, wenn irgendwelche Module wieder aus Core geschmissen wurden. Die fassen wir gar nicht erst an.

Alles was NICHT auftaucht

$ corelist Net::SNMP

Data for 2019-11-10
Net::SNMP was not in CORE (or so I think)


ist ein (externes) CPAN Modul und somit eine Abhängigkeit, die der User selber noch installieren muss und die bei einem Perl Update nachinstalliert werden muss. Wie schon oben ausgeführt, sowas nicht leichtfertig einsetzen.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

RichardCZ

PerlTidy (http://perltidy.sourceforge.net/)

&

Benchmark (https://metacpan.org/pod/Benchmark)

PerlTidy

PBP beschäftigt sich in Kapitel 2 (Seite 8 - 33) damit, wie man am besten seinen Code formatieren sollte. Den dortigen Empfehlungen kommt das Skript perltidy bereits mit den Default-Parametern sehr nahe. Zumindest so nahe, wie man mit rein statischer Codeanalyse kommen kann. Aber hey "80% machen ist besser als 100% wollen". Ich verwende perltidy (in der Default Einstellung) zum Normalisieren von FHEM code und es funktioniert ganz gut.

Wer sehen möchte wie sein Modul mit perltidy formatiert aussieht ohne jetzt das Tool selbst installieren zu wollen/können, kann derzeit (*) unter https://gl.petatech.eu/root/HomeBot/-/tree/master/FHEM nachschauen.

Warum sollte man perltidy benutzen?

ωєιℓмαη∂αηкяι¢нтιﻭєяչєι¢нєηѕєтչυηﻭﻭяσßυη∂кℓєιηѕ¢няєιвυηﻭѕσωιєℓєєяչєι¢нєηαη∂єηяι¢нтιﻭєηѕтєℓℓєηѕєιηєтєχтєƒüя∂ιємιтмєηѕ¢нєηℓєѕвαяєямα¢нт∂αяυм

Benchmark

Wozu Benchmark? Weil messen immer besser ist als vermuten! Wenn man einen Code geändert hat (oder wenn man gerade dabei ist) und man möchte sehen ob, bzw. wieviel er schneller (oder langsamer) ist, dann bietet Benchmark objektive Daten.

Die Anleitung zu Benchmark steht natürlich in der verlinkten CPAN Doku, aber wer da berührungsängste hat, für den eine ultrakurz-Anleitung:

* Benchmark modul installieren.
* wolltet ihr schon immer wissen ob ein sort { b cmp a } schneller ist als ein reverse sort {a cmp b} ?

use Benchmark qw(:all);

my @list = qw(a d e w q s c x y b g t z h j u n m k i o p l);

sub rs {
  @list = reverse sort @list;
}

sub ss {
  @list = sort { $b cmp $a } @list;
}

timethese(10000000, {
                  'native sort'  => \&ss,
                  'reverse sort'  => \&rs,
                 });


Ausgabe (bei mir):

$ benchmark.pl
Benchmark: timing 10000000 iterations of native sort, reverse sort...
native sort: 14 wallclock secs (12.77 usr +  0.00 sys = 12.77 CPU) @ 783085.36/s (n=10000000)
reverse sort: 14 wallclock secs (12.77 usr +  0.00 sys = 12.77 CPU) @ 783085.36/s (n=10000000)


Natürlich muss man aufpassen, dass einem nicht die Turbotaktung moderner CPUs einen Streich spielt. Je nach Geschwindigkeit der zu untersuchenden Routinen die Anzahl der Iterationen anpassen. Vielleicht so, dass der Testlauf pro Routine nicht 10 Sekunden unterschreitet.



(*) Möglich, dass das zu einem späteren Zeitpunkt unter  https://gl.petatech.eu/root/HomeBot/-/tree/master/lib liegen wird.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.