Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

To Extend, to Use, to Create

by Bod (Parson)
on Dec 06, 2020 at 17:06 UTC ( [id://11124753]=perlquestion: print w/replies, xml ) Need Help??

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

I need to create some configuration files on a server that will be pulled down by a client application - the remote config file. The client application will also have its own local config file.

In the past I would have just hard coded the logic for reading/writing the config files into the program on both the the client and the server which could create a mismatch if this code is ever updated in the future. Being led in the ways of well-written, easy to maintain code by the esteemed Monks of the Monastery, I am going to write this code as a module that can be installed on both the client and the server. That way, provided both are using the same version of the module, no mismatch will be possible. The first step was to search CPAN for suitable modules. I didn't expect to find anything that fitted the task perfectly but I did find a few possible candidates of which the top choice would be Config::Simple.

I don't need blocks so want what this module calls a SIMPLIFIED INI-FILE. There are two bits of functionality missing from this module that I need:

  • Creating Simplified ini-files
  • Fetching the config file from a server
So this gives me three options: (or are there more?)
  1. Create a module that extends Config::Simple and add the required functionality
  2. Create a module which makes use of Config::Simple
  3. Write a module from scratch
In this case I think 3 is most appropriate because Config::Simple does quite a bit of stuff that I don't want and of the the 3 things I want it to do (read/write/get), I have to write methods for 2 of them.

But this is not a one off situation...how do you decide between extending a class by including that class in @ISA or bringing the class into your class with the use statement and having your module call its methods? Some cases seem clear cut but there is a lot of middle ground where the answer is not clear to me.

Replies are listed 'Best First'.
Re: To Extend, to Use, to Create
by stevieb (Canon) on Dec 06, 2020 at 17:56 UTC

    Way I look at it is like this... if I'm extending a module (adding functionality to it), want to override one or more of its methods, or need access to the internals, I inherit (ie. @ISA) it. If all I want to do is use its functionality, use it is.

    You want to add functionality to an existing module. If all your new module is for is to extend the original without adding anything unrelated, inherit from it.

    Aside from that, I've taken to use JSON for all of my configuration anymore. It's cross platform, and is very easily converted into a language specific data structure. I've used JSON between Perl, Python, C++, C#, JS/jQuery etc. JSON is easily transmitted over the web without having to worry about files at all, and all languages I work with can easily handle it without writing custom parsers. Not only that, JSON strings store very easily in a database (or on Windows, the registry) as well.

Re: To Extend, to Use, to Create
by karlgoethebier (Abbot) on Dec 07, 2020 at 13:30 UTC

    See also Config::Tiny and Net::Curl::Easy. If you want JSON see JSON::Tiny. If you really feel that you need to inherit see parent. But if i were in your shoes i would try to keep things simple: If you want a lib create a plain old module. Or consider a role using Role::Tiny. And XML still might be an option: See XML::LibXML::Simple. Still a bit better to read by humans than JSON.

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

      Personal opinion I'd quibble with your last sentence, at least if we were to limit to "humans who program". Especially for deeply nested hashes I prefer reading the tidy'd output from (say) jq . config.json than trying to unroll an XML representation which is probably going to be much . . . "chattier". Then again I may have been biased by having to decode (say) Jenkins' XML configs (and other Java ecosystem offenders).

      Not to mention on the third hand I marginally like YAML better than JSON still for arbitrary applications in general, so . . .

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        "...deeply nested ..."

        Yes sure. But I'm still convinced that configuration files shouldn't be deeply nested. And writing JSON config files by hand? I'm not sure if this is a good idea. Considered harmful. "May be it's just a matter of taste" said the ape and bit into the soap ;-) (is bit simple past?)

        «The Crux of the Biscuit is the Apostrophe»

        perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

        I agree with you Fletch that JSON is more human readable than XML. But equals separated key/value pairs are even more human readable, even to humans who don't program. Sure, they are not able to hold nested data but that isn't always needed.

        Many years ago I created what is essentially a hierarchical database for recording rights of way entirely in XML with separate files for every entry. So my code has generated 100's of 1000's of XML files!

Re: To Extend, to Use, to Create
by perlfan (Vicar) on Dec 07, 2020 at 20:03 UTC
    You don't need to use blocks with Config::Tiny, it hides "global" variables under the _ key:
    ;;config var1=foo var2=bar

    readconfig.pl:

    use Config::Tiny; my $conf = Config::Tiny->read('test.ini'); require Data::Dumper; print Data::Dumper::Dumper($conf);

    dump:

    $VAR1 = bless( { '_' => { 'var1' => 'foo', 'var2' => 'bar' } }, 'Config::Tiny' );

      I did look at Config::Tiny but I cannot see now why I rejected it...

      I have written a module which does what I need to do and I'm currently trying to get my head around POD and test files - neither of which I have used before.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-04-19 03:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found