Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Naming of modules that are mean to be inherited only?

by leocharre (Priest)
on Aug 09, 2007 at 20:48 UTC ( #631654=perlquestion: print w/ replies, xml ) Need Help??
leocharre has asked for the wisdom of the Perl Monks concerning the following question:

Warning. This post is about naming modules. If you think having a discussion about namespace is second class devel work, or simply a waste of time, don't bother reading me.

For the rest of you who also have previous experience having to deal with someone else's demented code- and would be too guilty to do that to someone else in turn- Good Karma to you, bless your classy self.

I tend to separate code into various modules if things get large. I can get around vi pretty alright, but I get feel safe with under 500 lines of code per module.
I am concerned that I could be making it more obvious to others, and to myself- which modules are meant to be used directly, and which to be used indirectly (they are inherited). Briefly put, I was thinking of prepending the module name with an udnerscore.

I have a few projects that are large-ish. They comprise of various scripts, tests, modules.. etc..

For example I have a DMS, a document management system- which we use in an office environment.

I have a DMS module, which abstracts the concept of many users, projects, etc. This is an oo module that can be instanced, tested, etc stand alone.
I have a DMS::Client module, which represents a client project's information, etc. This is also an oo module that can be tested, instanced, by itself.

I also try to organize my code and docs so I don't lose my freaking mind. So I have other modules like DMS::Setup (aid with installation, check current machine's installation) and maybe DMS::Database, DMS::Configuration... etc
These last modules do not do anything by themselves, they are inherited by the DMS object, sometimes by DMS::User, DMS::Client.

So, since these modules are there for organization's sake, since, they are always used inherited (use base..)- I was considering naming these something like DMS::_Setup, DMS::_Database, so any module names that start with an underscore can be assumed to be inherited.

I want to know if this sounds good. I also would like to know if in your experiences, separating the code up is indeed good, at what line count do you feel good about doing that- and do you have other ways of dealing with this other then to just put a big warning in the description that says 'dont use me' ?

(What about putting all private methods in external modules, and all public methods in main object? It sounds good, but I fear it would be hairy to maintain?)

Comment on Naming of modules that are mean to be inherited only?
Re: Naming of modules that are mean to be inherited only?
by dsheroh (Parson) on Aug 09, 2007 at 21:11 UTC
    I suppose your underscore idea would be fairly clear, given its similarity to the existing convention for indicating "private" methods/properties, but appending "::Abstract" to the class name seems to be the more common way of handling it.

    As far as your side questions, yes, separating the code up is good, provided you don't have to couple the modules too tightly. I break things up based on conceptual integrity rather than line count - if the Employee class needs 10,000 lines to implement, then it gets a 10,000 line file. But that's extremely rare. Looking over my current project, all of the modules but one are under 300 lines. (The exception is about 600, mostly because it has a lot of calculations in it.)

    Aside from a comment at the top of my abstract class modules, I also emit warnings if the any methods are called on it that don't make sense, which also helps in catching calls that should be overridden, but weren't.

Re: Naming of modules that are mean to be inherited only?
by Mutant (Priest) on Aug 10, 2007 at 11:32 UTC

    I don't really like the prefixed '_' ... agree with the previous comment that ::Abstract (or similar) would be a better option.

    I also agree that naming things properly (not just modules, actually variables and methods are probably more important), is extremely important, and often overlooked by novice programmers. It can make code substantially easier to read. Sometimes a good name is not obvious, and it requires some thought. It's also important to rename things (despite the maintenance overhead) when it's purpose changes, or a better name becomes apparent.

      I agree with the importance of naming -- but I don't agree with renaming things.

      • Renaming function / method calls : breaks your interface, and backwards compatability.
      • Renaming packages / namespaces : same problem.
      • Renaming variables : probably not things that users of the code should be worried about, but the odds of introducing errors aren't often worth it.

      In your example, you mentioned two cases:

      Change of purpose
      In this case, there is often a valid time for creating _new_ entities, and in some cases, deprecating the older one. If you add new functionality to a method, sure, it needs a new name -- but it's a new function, not simple a renamed function. If the 'purpose' of the function changes (what it's being used for, as opposed to what it actually does), and the name reflected the purpose, then it may have been named poorly, which gets us to...
      A better name becomes apparent
      I don't believe I can disagree more with this one. Now, there are cases where you're completely _replacing_ the entity, but if it's just a case of 'I don't like that name, I think I'll name it (x)', you're often asking for trouble. Good documentation about the entities and what their roles are is likely a better solution. I wouldn't want to go through a few hundred or few thousand lines of code making sure I didn't screw something up in the process. (yes, use strict/use warnings are your friend for variables and functions, but keys to hash elements, autoloaded functions, and method calls don't get picked up so quickly). Not to mention the confusion when one of the other programmers tries to come along a year later while you're on vacation, and can't figure out what the hell happened.

      Unless you come up with the new name very early in the development process (ie, well before it goes to q&a), I'd be loathe to change it just because a better name came along. Document it, and save it for when you're doing the next major rewrite.

        There's no need to break the interface. You can simply extend it (i.e. keep the old method name, or even module). The old method name can redirect to the new one. You can add docs and even warn about the old one being deprecated. How much of an issue this is depends on exactly how public your interface is. If it's in a class in your code base that you know is used no where else, and maybe is only called once or twice, then you don't have to worry. If, at the other extreme, it's a CPAN module, then you have to be a lot more careful, and maybe even never remove the old name.

        Still, the effort is worth it to me. I try to think of someone coming at my code (from either a user or a maintainer point of view) completely fresh, knowing next to nothing about the code. They'll find it a lot easier to understand if things are named consistently and appropriately. I'm not suggesting renaming things on a whim, or making a change that's *slightly* better (except during early development as you suggest), but sometimes a method has changed subtley over time, to the point where it's doing something completely different to what it's name suggests. Or sometimes the original name was just plain wrong.

        Unfortunately, I don't have time right now to list some examples, but I do have some that I may add at a later date :)

      Could I have an example name? If the main module is PDF::Puppy, and part of the code is in PDF::Puppy::Database, are you suggesting it could be named PDF::Puppy::DatabaseAbstract, or PDF::Puppy::Database::Abstract ?

        I would prefer "PDF::Puppy::Database::Abstract". But as valdez mentioned, another option is to prefix 'Base', e.g. Base::PDF::Puppy::Database. In hindsight, I'd probably prefer that (or even prefixed Abstract::).

        However, there's no real convention here. The important thing is that it makes sense to you, it's fairly clear to anyone who might be maintaining your code in the future, and that you're consistent throughout your codebase.

Re: Naming of modules that are mean to be inherited only?
by rir (Vicar) on Aug 10, 2007 at 14:40 UTC
    If an object is not supposed to be of type Abstract, I would enforce this in my code.

    When looking for shortness, I tend toward abbreviating the the entire class name, like DBO for DatabaseObject. The advantage over a obscure prefix is that it is basic to find the DBO.pm file, while it is unclear (easy to forget) where to look up the prefix naming conventions of a project.

    To me, this convention seems to invert the normal meaning of _name.

    This convention runs counter to the non-pragma modules start with upper-case convention.

    Be well,
    rir

Re: Naming of modules that are mean to be inherited only?
by valdez (Monsignor) on Aug 11, 2007 at 14:06 UTC

    Ciao Leocharre,

    usually I create a dedicated namespace called Base, much like Abstract described above, where all the base classes are kept; then everytime I need a concrete class I 'use base' one of those classes. For example, DMS::Database::Configuration would use DMS::Base::Configuration as base.

    Ciao, Valerio

Re: Naming of modules that are mean to be inherited only?
by adrianh (Chancellor) on Aug 12, 2007 at 08:57 UTC
    I also try to organize my code and docs so I don't lose my freaking mind. So I have other modules like DMS::Setup (aid with installation, check current machine's installation) and maybe DMS::Database, DMS::Configuration... etc These last modules do not do anything by themselves, they are inherited by the DMS object, sometimes by DMS::User, DMS::Client.

    As a design point I'd be sort of suspicious if a DBS::User and a DMS::Client had isa relationships to Configuration and Setup classes - seems odd...

    So, since these modules are there for organization's sake, since, they are always used inherited (use base..)- I was considering naming these something like DMS::_Setup, DMS::_Database, so any module names that start with an underscore can be assumed to be inherited.

    When I have abstract classes I usually us a suffix of "Base" so I might have MyApp::Page::Base as the abstract class and MyApp::Page::Search as a concrete class that inherits from MyApp::Page::Base.

    I want to know if this sounds good. I also would like to know if in your experiences, separating the code up is indeed good, at what line count do you feel good about doing that

    Line count isn't really the kind of distinction that I use when deciding to cut up code into modules. Instead break up classes around units of behaviour so we get low coupling and high cohesion in the design.

    That's what worries me about having those Setup classes as common classes that everything inherits from. Tweaking Setup seems to affect everything in your code - which is probably a bad thing.

    and do you have other ways of dealing with this other then to just put a big warning in the description that says 'dont use me' ?

    Personally I don't worry about it. If it's an abstract class I'll document it as one. If it's something private/implementation specific that might change I'll mention that too. If the user uses something that I've told them I might change at a later date that's their problem.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2014-09-19 00:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (128 votes), past polls