Re: Choosing the right module (Judging the Quality of a CPAN module)
by eyepopslikeamosquito (Archbishop) on Oct 23, 2022 at 00:32 UTC
|
Thanks for asking this Bod.
I will focus on how to generally make choices like these.
Judging the Quality of a CPAN module
Warning signs:
- Bad reviews
- Only one release and/or hasn't had releases for many years
- Its test statistics show a lot of failures
- Lots of unresolved bugs
- CPANTS Kwalitee score
Recommended modules:
Discouraged modules:
See Also
Updated: Minor reorganisation of the material in the original post. Added "See Also" section.
Added warning re using Acme modules (thanks cavac).
| [reply] |
|
Thanks for asking this
You are welcome - I thought you would like the question eyepopslikeamosquito
Task::Kensho - a list of recommended modules for various tasks
Thanks!
I had not come across this module previously.
Interestingly, it recommends all three of the modules I listed as being good choices for the application. Plus others as I expected.
| [reply] |
|
I'd add the whole ACME:: namespace to the list of discouraged modules, too. Older PerlMonks will already know this, i newbie might not.
And i'd also put up a warning flag around most of the JSON:: modules. They work fine for most stuff, but can be VERY flaky when it comes to nested JSON structures in combination with Unicode/UTF8. (Why would you have nested JSON structures? Because you can, apparently)
| [reply] |
|
| [reply] |
|
|
|
Re: Choosing the right module
by afoken (Chancellor) on Oct 22, 2022 at 22:25 UTC
|
A side note: LWP::Simple is a wrapper around LWP::UserAgent.
Here is how I choose new modules from CPAN. This is my way, it works for me, it is full of biases, unfair, not formalized, and probably wastes some time.
I usually start with the docs. Present just the default skeleton and a synopsis of nothing more than use This::Junk::Module; and your module is out, no matter how excellent it might be. I want to see at least a few lines of code for some basic usage. I want at least some error handling. Preferably, something like "all functions die() on error, use eval BLOCK or Try::Tiny to handle errors", especially when I need to call a lot of functions.
Also, the version number should not be 0.01 or 1.00.
I look at the tests. Testing just that the module loads without errors, or even no tests at all is almost as bad as having no usable documentation. I expect that at least some of the tests are usable examples for using the module.
I look at the source code. I expect to find mostly clean indenting, comments explaining non-obvious stuff, good names for variables and functions. I expect to be able to understand at least some relevant parts of the code at first sight.
I look at the dependencies. I prefer modules that don't require half of CPAN plus 20 3rd party libs just to save three characters in a line of code that runs once every thousand years. Modules that just depend on core perl or really common modules are ranked up.
And of course, I simply try the module if it survived that filtering process. If I can't get a hello-world example running within a few minutes, I drop that module and try the next one.
Sometimes, there is not much choice. Probably the most prominent example is DBI. DBI is excellent and the de-facto standard for accessing any kind of database from Perl. Older standards are gone and replaced by compatibility layers, like Oraperl (replacing special-built perls with Oracle OCI compiled in) or Win32::DBIODBC (replacing the old Win32::ODBC).
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
Re: Choosing the right module
by hippo (Bishop) on Oct 23, 2022 at 15:11 UTC
|
So, which would you choose and why?
In almost every URL-fetching case I use LWP::UserAgent because it is the most flexible of those you have listed. Even for a trivial action I think it is worth it because at some point in the future something about that particular process will change and possibly in a way that might not be supported by one of the "simpler" modules. Starting with the most flexible module saves re-engineering the code if/when that situation arises.
There may be other concerns which might count against it for a particular purpose, of course. I have yet to find one which is a showstopper.
More importantly, how do you generally make choices like these?
It is a balancing of the various criteria discussed in the I am most likely to install a new module from CPAN if: poll and thread.
| [reply] |
|
Even for a trivial action I think it is worth it because at some point in the future something about that particular process will change and possibly in a way that might not be supported by one of the "simpler" modules
Interesting...
This is not a selection criterion I had considered but it totally makes sense.
A few times I have created something using LWP::Simple, that used to be my go to web module, only to have to change to LWP:UserAgent later on because I needed to access or set something that wasn't available using LWP::Simple. More recently I have generally used HTTP::Tiny but for no other reason than it being core. That in itself is not a good enough reason for anything that doesn't need to be portable as both the LWP modules are installed on my system.
| [reply] |
Re: Choosing the right module
by sectokia (Pilgrim) on Oct 23, 2022 at 21:26 UTC
|
Over a long time I have eventually learned that you should never use a synchronous library when an asynchronous one exists - especially for anything that takes time - like remote communications.
The reason is that async code is going to be so much more flexible and has far more re-usability (and of course can be used as 'sync' code if you want).
So in this case I would go to AnyEvent::HTTP. The benefits over the 3 you mention is ability to simultaneously do multiple requests, and simultaneously handle user input to start new requests or abandon ones already in progress etc. This also gives you the flexibility to more easily convert your script/program to a on-demand service (example: your program could use AnyEvent::HTTPD to have its own web server where users could go to it in a webbrowser and on-demand get your program to do whatever it is that it does).
Furthermore, with modules like 'Promises' you can write async code very much like sync code.
| [reply] |
|
I do many a thing async as well. But for code that isn't time critical, i prefer the "sync" path, because it makes the code (almost always) more readable and easier to understand and to bugfix.
This goes especially for the first versions of a new code (proof of concept, one-off project, etc). The last thing you want to deal with is network lag based race conditions when you are just trying to find out if your basic idea will even work.
| [reply] |