Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Choosing the right module

by Bod (Parson)
on Oct 22, 2022 at 20:56 UTC ( [id://11147598]=perlquestion: print w/replies, xml ) Need Help??

Bod has asked for the wisdom of the Perl Monks concerning the following question:

There are occasions when several modules will perform the task required. I would like to explore your thought process for deciding which module to use. The problem I have is very real and I have to make this decision. But, I am not so interested in only this case, I would love some insight into how you generally choose modules when several will do the job.

I need to make a call to a web endpoint. Nothing very special. It's an HTTPS endpoint using GET with the query string appended to the URL. The endpoint returns some simple text with the result. It does not use HTTP status codes other than if there is a network problem. I have no need to read the status codes, just the returned text.

There are three modules I could use. There are probably lots more but these three are ones I have used and I am familiar with. They are also all already installed.
- HTTP::Tiny
- LWP::Simple
- LWP::UserAgent

Portability is not an issue - only I will be using the script so HTTP::Tiny being a core module doesn't make any difference here.

So, which would you choose and why?
More importantly, how do you generally make choices like these?

Replies are listed 'Best First'.
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

      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.

      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)

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

        I'd add the whole ACME:: namespace to the list of discouraged modules

        Good point! I've updated my response with an Acme link (for Perl users not around in Acme's heyday of the early 2000s) along with a warning:

        it is almost certainly a very silly idea to use an Acme module in production code!

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". ;-)

      Excellent list of criteria. The only thing missing to my mind is a quick visit to the test results to see that the module has a chance of working on my OS and Perl version.

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      I would add some things to that:

      1. If it is a module that works with network stuff, the module must support IPv4-only AND IPv6-only AND IPv6/IPv4 dual-stack systems. Missing IPv6 support is completely unacceptable in this day and age.
      2. The module should NOT force me to use it's own event loop. In 99.9% of my use cases, i already have an existing cyclic executive.
      3. A usable changelog or some other sort of "we change xy in version xy" is a valuable bonus. A proper, read-only version control system is even more helpful. I don't care if it's git, mercurial, subversion. Heck even SCM is better than nothing. Basically, if something breaks after an update, i want to be able to find out what the author(s) have changed. Manually written changelogs might or might not be complete or correct, access to the version control of the source code as a last resort can come in quite handy.
      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
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.


    🦛

      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.

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.

      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.

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11147598]
Approved by GrandFather
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2024-04-19 01:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found