in reply to Project management

You're confusing design issues (how do I make a program that will deal with different databases and platforms) with packaging issues (MakeMaker and make). To answer your question, you have to decide whether these things can be changed on the fly (perhaps by user configuration) or whether you'll be producing specific versions for a given platform.

Conditional compilation a la C doesn't work too well in Perl, though there's a command-line switch that will run your code through a C preprocessor first. Instead, we generally use run-time conditionals. It is possible to make a module that provides a consistent interface to two or more different modules, so that clients don't have to concern themselves with cross-platform issues.

You probably will find it easier to stay in pure Perl and have a single version of your program that can run (possibly with different configuration) across multiple platforms. MakeMaker is more of a packaging tool.

Consider using object-oriented design for your system. If you have two different ways of doing something, make adapter classes (packages) with the same interface that do the something in each of the different ways. This way you can even mix the different ways (imagine having to deal with more than one different barcode scanner on a system at a time, or dealing with more than one database to allow copying and exporting).

Replies are listed 'Best First'.
Interface design
by Ea (Chaplain) on Jul 16, 2001 at 16:44 UTC
    My program will not require changes. (Although, I can forsee the possibility where it would be useful to scan student marks into one database and then scan books into another. OTOH, I should work on my Laziness before I start worrying about Impatience.) You seem to be saying that modules are a good way of simplifying design issues.

    Module Interface design: (never having written a module) Should I put all of my different database connections in one module, my input methods into another and keep the logic in the main program? Going through the Cookbook, I still don't see in what manner I should divide up my program into different modules.

      I find it virtually impossible to believe that your spec will never change and you know up front that changing circumstances will never cause you to need to modify your program. The real world simply does not, in my experience, work out that way. Nor do I know anyone else for whom it works that way. (Well I do know of exactly one widely used program which is no longer being modified in any way, shape, or form.)

      Therefore if you wish to avoid digging a pit for yourself, I strongly recommend starting with the opposite assumption. Assume that your program will change. Assume further that you don't know how it will change. With these two assumptions you should now see the benefits of trying to modularize the internals of your program as much as possible. Break it up into functions. Make each function do one thing. Make the name of the function say exactly what that function does. Avoid globals. Use strict.pm to remind yourself of globals you might have missed. So on and so forth.

      If you do this, then you will be ready to face the inevitable point where reality meets your optimistic hope that you can just write your program and it will really, truly, be done.

        Assume that your program will change. Assume further that you don't know how it will change...
        I like this. I had to say that in addition to a ++! As usual, excellent advice from tilly. All too often I get bad lazy and just assume that my software is a rock and an island. The real magic is in the chunnel! Just like MI2.
        :)
        This was the whole point of the question (which of course gets muddled as brain tries to dump to keyboard). I've got one setup where I know that the spec won't change for a year or two and we worked out what the users really want/need from version 1.0. The next version is to be a lot more presentable and in it's avarice, the department would like to sell it to the other departments, whose setups I will not know ahead of time. Good suggestions, both of you. I'd thought of the easier ones, but strict.pm and OOP hadn't occured to me. I shall be following the latest module thread with interest.
      <quote>My program will not require changes</quote>

      Hmm, where have I heard this before? I thought you were already talking about changes. My experience is that once a program is useful, people will come up with more and different things they want it to do. Assume it's going to change.

      There's roughly two different things you can do with a module: define new packages (also called namespaces or classes) with their own subroutines (and maybe local data) and/or add subroutines (and maybe data) to existing packages (like especially 'main'). You can accomplish the same thing with code in a single large program, except that it's bigger, harder to find things, and impossible to re-use that way. By breaking up your program into modules, you can re-use common functionality. If you've designed it right, that is (modules are no guarantee of reusability, any more than object design is).

      I use object-oriented design, in which I view my programs as a group of collaborating objects which call on each other to get the job done. Objects have a single responsibility.

      Inheritance (@ISA in Perl) can be used where you have common behavior that you want to share between packages. You can put common behavior in one package, and inherit others from that one, adding specialized behavior to each of them.

      I don't know your program, but one way to start breaking it up might be to ask where do I have behavior that might change for different platforms or hardware?. If you have several kinds of barcode readers, for instance, you might have a common package ("base class" in object-speak) that several reader-specific packages inherit from. Whether you put these in separate files or the same file depends mostly on how comfortable you are with the file sizes and number of files. It's easy to change later, assuming you don't share lexical variables between multiple packages in a single file.