http://www.perlmonks.org?node_id=947908

First: Who uses module-starter? Who copies an existing project and throws away most of it, then edits what's left? Who has another method? Please think about this and include your answer in any reply.

I'm deeply unhappy with module-starter and Module::Starter*. I started using them because there is indeed a lot of boilerplate that needs to be created for each project. It seemed better to set this up programmatically than by copy-edit; and I still believe this. But I've started my last several projects by hand.

I'm aware h2xs has been used for this purpose. I'm agin it, on principle: not the primary purpose of the tool.

Here are a few issues I'd like to clear up:

  • Why is module-starter so complex? This seems to me to be merely a matter of copying a set of templates and making substitutions of placeholders. The Module::Starter distribution contains five modules and a script.
  • Why is module-starter so inflexible? Adding a new template file should be as easy as dropping it into the master template folder. It's not. Adding a new placeholder type should be as easy as defining the variable somewhere. It's not. Much of the boilerplate produced actually is hardcoded right into one of the Module::Starter modules, as heredocs. I'm talking pages of it.
  • Why does Module::Starter do so little? Part of the complexity seems to be to allow a variety of plugins to do the real work. There isn't even a standard method of adding a new module into an existing project; for that you need Module::Starter::Smart. I'd rather see the base tool get the job done... although I agree it should be extensible.
  • Why is only one config file supported? What if I want several "profiles", multiple template sets? Not all my projects are alike. Why is that single config file in a superficially simple, fusty format? Why can't I supply a config file in any one of the accepted config formats, or in plain straight Perl?
  • Why the lengthy command line invocation? Yes, yes, I know many are quite happy constructing lengthy commands. But this interface gets less fun the more options must be passed in; and more difficult the less often a given tool is used. I don't start a new project from scratch every week. This is a case for a little interactivity, when demanded.

I suppose I can subclass and redefine the guts to do what I want. This is the approach taken by Module::Starter::Plugin::Template and Module::Starter::PBP. I don't feel it's worthwhile to cram a new tool into a difficult API.

I'm thinking seriously of starting work on a replacement. This will use the widely respected Template::Toolkit as backend for placeholder substitution and Config::Any to allow developers to edit multiple config files in their choice of YAML, JSON, INI, Perl, or what-have-you. There will be the expected lengthy command line interface but also interactive setup of configuration. And the whole thing must be kept simple! This is, after all, a way to start a Perl project; at some point you have to go to work and write code.

Before I roll, I'd like to hear what alternatives make other Monks happy.

I'm not the guy you kill, I'm the guy you buy. —Michael Clayton

Replies are listed 'Best First'.
Re: Alternatives to Module::Starter
by rjbs (Pilgrim) on Jan 20, 2012 at 23:15 UTC

    Hi. I did a lot of early work on Module::Starter, and can answer some of those questions. I also wrote something that I use instead, and can tell you something about that.

    The original module-starter program was very simple, and had a number of routines named things like "build_Makefile_PL_guts" that would, as you expect, take a few configuration bits and return the whole file to be generated. It did exactly what its original author wanted, and was better for me than most anything out there at the time. The problem I had was that it put things together a little differently than I wanted, and it wasn't easy to customize its output.

    The first thing it needed was for the templates to be replaceable. I did that by making the module-starter command accept an optional class name to use instead of "Module::Starter." That way, I could write a subclass that replaced the "guts" methods. (As I recall, this also necessitated the conversion of the package Module::Starter to act like a class.)

    Once I'd done that, I realized that I didn't really want to hardcode my templates. I wanted to store them in files that I could edit without breaking my library's syntax, or swap out between different projects. This meant writing the Module-Starter-SimpleStore distribution, and doing more refactoring. I also wrote some other stores that I don't think I released, like one for keeping your templates in a Kwiki.

    The problem with all this was that I was doing all the work on something that wasn't built for it, and I was only thinking one step ahead. The program started out quite simple, and I tried to grow it into something complex without re-engineering to make room. I was young and foolish! Once the problems became clearer to me, I started to dream about writing a new kind of Module::Starter system that would build up "kits" of files in memory, then write them out. They could have dependency on each other, and could be more interesting than just a name and contents. That's when Module::Starter::Simple was born. I never went much further than that, though. I mucked about, but it was clear that I needed to radically break backward compatibility, and I didn't feel good about that.

    I stopped using Module::Starter, now a good bit more featureful, but definitely a lot more complicated to use, and I went back to copying and existing dist and editing and renaming stuff. Once in a while I'd be tempted by some other Module::Starter-like system. David Golden's never-released Module::Boilerplate really hooked me for a while. Nothing ever really satisfied me, though.

    A few years later, I realized that I didn't really want much boilerplate anyway. I hated having to edit all that crap: the VERSION section in the Pod, the copyright years, etc. I hated thinking about making a MANIFEST or MANIFEST.SKIP. This is when I wrote Dist::Zilla, which let me not write the boilerplate at all, and instead have it crammed in just in time for each release. With that done, I deleted a large amount of non-code in many of my dists and started using Dist::Zilla for releasing them -- it would now add the kind of boilerplate Module::Starter made, but I'd almost never have to see it in my editor.

    This changed how I felt about things like Module::Starter. Now I didn't want a better one at all. I didn't see any need. I wouldn't need any boilerplate. To start a new dist, I literally just ran mkdir and started editing code. Done.

    Despite this, every once in a while, someone would ask when Dist::Zilla would start "doing what Module::Starter does." I would scoff: never! Module::Starter totally misses the point! People kept asking, though, and not just random people. I'd get this question from people who I knew were smarter than I was. I started to ask why on Earth they'd want such a thing. The answers were great.

    Some people wanted it to create the dist.ini file -- which was fine, but not a very interesting answer. Someone else suggested that a Dist::Zilla-based system would allow things like creating a Git (or Subversion, or whatever) repository during dist creation; or checking that the name wasn't already in use; or starting a work-tracking timer. Or all kinds of stuff. Dist::Zilla provided a lot of generic framework for plugins, and having a pluggable "make a new dist" command seemed quite useful.

    So I wrote it.

    I really don't use dzil new for very much. Mostly, I use it to get an initial Git repository made, although I'll probably start using the "...and make a Github repo and push it there" plugin sometime soon. Using Dist::Zilla instead of Module::Starter, even if you don't use Dist::Zilla to release your modules, seems like a pretty sane bet to me. It's really, really easy to build new templates, if that's the only behavior you want. If you want lots of other behavior (register it at Ohloh; announce it on your Perl Monks scratchpad) those are easy to add, too.

    ...but if you don't want to bother with Dist::Zilla, there are plenty of other systems on the CPAN. Module::Start, Distribution::Cooker, ExtUtils::ModuleMaker, and probably a dozen more. I wish you the best of luck in finding the one that floats your boat!

    rjbs
Re: Alternatives to Module::Starter
by Anonymous Monk on Jan 14, 2012 at 20:10 UTC

      My advice is to not quickly dismiss dzil and similar distribution builder tools like ShipIt, etc.

      Sure, creating an empty distribution template takes just under a minute with module-starter (or its equivalent), and 30 minutes with dzil (or its equivalent), due to having to install more than a few dozen CPAN modules and read the documentation.

      But creating an empty distribution is the easiest part, the tip of the iceberg. And you just do it once for each distribution you create.

      The harder and more tedious part after that is building the distribution, updating the various standard files (README, MANIFEST, META.yml, etc), testing and releasing it. This needs to be done *many* times. dzil (or its equivalent) will help you automate these tasks.

      The 30 minutes that you "lost", will save you hours and hours later.

      Even if you think you will only release one distribution to CPAN, consider using a distribution builder tool anyway. Since releasing a distribution becomes so easy and quick with dzil, this will actually encourage you to release more CPAN modules. That's what happened to me. :)

        My advice is to not quickly dismiss dzil and similar distribution builder tools like ShipIt, etc.

        Spoken like someone who's never tried to bend dzil et all to his will :)

        The harder and more tedious part after that is building the distribution, updating the various standard files (README, MANIFEST, META.yml, etc), testing and releasing it. This needs to be done *many* times. dzil (or its equivalent) will help you automate these tasks.

        Heard of ExtUtils::MakeMaker or Module::Build or Module::Install? ExtUtils::MakeMaker or Module::Build or Module::Install do the updating of MANIFEST and META, dzil not required.

        Same goes for both testing and releasing

        The 30 minutes that you "lost", will save you hours and hours later.

        strawman for sure, I've yet to meet a programmer that cares how long it takes cpan/cpanp/cpanm to download/install dzil among the criteria for usefulness of dzil

        Maybe dzil saves dzil authors time, it didn't save me any, for me it was just a hassle

        Even if you think you will only release one distribution to CPAN, consider using a distribution builder tool anyway. Since releasing a distribution becomes so easy and quick with dzil, this will actually encourage you to release more CPAN modules. That's what happened to me. :)

        :) Cannot find pauseid http://search.cpan.org/~sedusedan/

Re: Alternatives to Module::Starter
by repellent (Priest) on Jan 15, 2012 at 00:31 UTC
    Like many others, I started with some sort of module starter (which I don't remember now). But after spending much time hanging out on CPAN, I've learned to trim off the excess fat needed for a CPAN package.

    Looking back, I think it would have been fine if I found a bare boiler plate package to start. Just start somewhere and improve on it. So here's to helping my past self...

    I've added a script to my public scratchpad that creates a basic Kwalitee-compliant, semantic-versioned package for a pure-Perl module. Among other things, it shows how to specify minimum version requirements for Perl and dependency modules, as well as barring tests from running on certain platforms.

    Grep for 'XXX' to change. After modifications to XXX-Module-1.001001/*, one can create the dist package with the following commands:
    cd XXX-Module-1.001001; perl Makefile.PL; make disttest tardist; ls -l XXX-Module-1.001001.tar.gz; # submit this to PAUSE

      I'm down to just:

        cd ~/src/p5/p5-my-module
        perl-makeall
        perl-publish My-Module-1.000.tar.gz
      

      perl-makeall is a shell alias for perl Makefile.PL && make all test dist && make clean && rm Makefile.old.

      perl-publish is an alias for sudo cpanm $1 && cpan-upload $1 && mv $1 ~/perl5/published/.

Re: Alternatives to Module::Starter
by moritz (Cardinal) on Jan 15, 2012 at 10:19 UTC

    I've both used module-starter, and have copied the files from another project, and substituted the name and version.

    Both work fine, though Module::Starter was a bit nicer to use.

    Why is module-starter so complex?

    As a user, this question doesn't bother me. I don't find it complex to use. As long as it's maintained, why bother about internal complexity?

    Why is module-starter so inflexible?

    That doesn't bother me either. I don't need more flexibility from it.

    Why does Module::Starter do so little?

    Because otherwise it would be even more complex? Again, it does enough for me.

    So, after reading your questions, is the starting of modules an actual concern of yours? How often do you start a new module?

    I don't want to discourage you from improving things, but from our CB discussions I get the impression that you often get stuck in small details that wouldn't bother me for more than a minute. If you draw satisfaction from that style of development, then you're fine. I know I enjoy getting results much more than beating small points to death.

      I'm working on a separate project, a Module::Build subclass I expect, which will, during development, pretty well screw up any project upon which it's tested. I'll want to create a wide variety of dummy projects quickly.

      I do agree that I tend to focus on details. As I've retired from engineering for pay, I enjoy the luxury of perfectionism free from money and time constraints. I highly appreciate elegant tools, of which I'm sorry to say I don't consider the topic of this post an example. My entire effort in Perl thus far has been tool development. Please accept my promise that something, eventually, will roll out the door.

      I'm not the guy you kill, I'm the guy you buy. —Michael Clayton

        Module::Build comes with a pretty extensive collection of test cases. If you ensure that your Module::Build subclass is still able to pass all those tests (except any tests that check for behaviour you are deliberately changing with your subclass), then that's probably a good start.

Re: Alternatives to Module::Starter
by JavaFan (Canon) on Jan 14, 2012 at 22:16 UTC
    I once spend an hour or so determining what I want as a boilerplate. Which is just a few files: Makefile.PL (tailered to what I want), MANIFEST, MANIFEST.SKIP (for .git, .gitignore, and MANIFEST.SKIP itself), Changes (with just one line), README (empty), t/000_load.t (just tests whether the module loads), t/001_pod.t (checks for pod compliance), a skeleton .pm file, and a .gitignore file. Then I spend another hour writing a simple Perl script which takes the name of the module-to-be as argument, and uses that to create the mentioned files, in a appropriate directory. It also sets up the directory as a git repository, and does an initial checkin of the files created.

    Two hours very well spend. Sure, I end up with something that only works for me, but who cares? Now I can just type "cpan-start My::Module", and two seconds later I can start actual coding, instead of manually editing whatever a more general module or script has produced. If my preferences change over time, I just modify the script (and since it's just my script, I don't have to care about backwards compatibility, or have it do something something else way want). If I ever were to create XS modules on a more regular basis, I'd modify the script to take an -xs option, and create a different skeleton. Now I create XS modules so infrequently, I just use h2xs and do some manual editing afterwards.

    My advice: figure out what *you* want, and write a script that just does that. Takes far less time than trying to find out whether someone has written and published something that does exactly what you want.

      My advice: figure out what *you* want, and write a script that just does that. Takes far less time than trying to find out whether someone has written and published something that does exactly what you want.
      This. I started with the stuff generated by h2xs -AXn, deleted the unwanted bits, and created a script printing templates based on what was left. That took an hour or so, and I can now create new modules without dealing with silly prereqs and mountains of BS from Module::Starter and friends.
Re: Alternatives to Module::Starter
by tobyink (Canon) on Jan 14, 2012 at 20:32 UTC

    For my first few distributions, I used h2xs. Eventually I grew tired of having to make a dozen adjustments to the generated stubs before getting to work.

    So I created a template distribution, and would svn export it as needed.

    But now I have my own script to create my stub distributions. It's called mkdist and is bundled with Module::Package::RDF. It's not especially configurable though - if you don't want to build your distributions exactly the same as I do, then you're out of luck.

Re: Alternatives to Module::Starter
by petdance (Parson) on Jan 20, 2012 at 16:51 UTC

    Hi, I'm the creator of Module::Starter, but have handed off maintenance to someone else. When I created Module::Starter in 2004, there was literally no tool to create a skeleton module. h2xs created a .pm file, but none of the other trappings of a good module distribution like .t files.

    I've stopped maintaining Module::Starter for two reasons: Module::Starter as it stands now works just fine for what I want, and Dist::Zilla is (to me) the heir apparent to the throne.

    I suggest that you look seriously at dzil and talk to RJBS about any ideas you have before you go and roll your own. Ricardo is a fantastically responsive author.

    xoxo,
    Andy