Kirrily 'Skud' Robert [mailto:[EMAIL PROTECTED]] said:
>
> My main purpose with perlmodstyle was to give us a starting
> point for a Perl 6 style guide, in time for the Great Rewrite
> that's likely to happen with most of CPAN.
>
I have some raw material that may be useful (and I do mean raw).
Off and on for the last few months, I've been compiling notes on "Perl
for Enterprise Development." Topics range from style, formatting,
and naming conventions, all the way to team structure, culture, and
software engineering principles from a Perl perspective.
I originally planned to do a couple of things with this material:
- Create a developers' guide to be used within my own organization,
to help ensure the success of Perl-related projects.
- Educate the powers-that-be in the company I work for that Perl
is a reasonable choice for the development of maintainable,
scalable, reliable, [insert desirable trait here] systems,
despite what they may have heard otherwise.
However, in light of the recent style and SDK discussions here and on
P5P, I thought it might prove useful to the community at large.
Most of this stuff isn't new, of course. I was happy to see that
there's a lot of overlap between my random scribblings and
perlmodstyle, for example. Stylistic issues owe a lot to the perlstyle
manpage, the Camel book, and TomC's "Perl Style" talk. Much of it
comes from staring at my own Perl code and trying to figure out what's
good and what's not. The team dynamics / culture / pragmatism aspects
are the result of spending a lot of my life developing software,
and knowing what I like and what I don't like about the experience.
Some things to remember:
- This is a list of ideas, not a finished guide. The items are
discussion points, memory-joggers, and questions to myself, and
they shift gleefully among first, second, and third-person
viewpoints (whee, what fun).
- It's not done. The categories are ad hoc, items are in only
the vaguest order, and many areas are missing or woefully
under-represented.
- It's written from a Perl 5 perspective, not Perl 6.
- It's about large projects with multiple programmers or teams
of programmers. I'm not advocating the "one true way" to do
anything. TMTOWTDI and all that.
- It wasn't originally meant for public consumption. If something
doesn't make sense, ask me what I meant. I might even remember
the answer.
So if you're still interested after all the caveats, here it is.
Tear it apart.
:)
--Bill
===============================
Perl for Enterprise Development
===============================
----------
PHILOSOPHY
----------
Main idea: Many people consider Perl the ultimate tool for individual
programmer productivity and creativity. Despite its detractors, Perl
has proven fantastically well-suited for this role -- but often at the
expense of another role that it is also qualified to fill. Perl is an
excellent language for large-scale system development, and, properly
used, extremely adept at bestowing the same creative, productive boon
to enterprise projects that it has done so successfully for
individuals.
Pick your battles. Choosing to develop large systems in Perl *will* be
controversial, no matter how often it's been successful in the past,
so be sure to position the language choice appropriately. The
reputation of the Perl language and community is muddy enough already
without a failed multi-million-dollar project around our collective
neck.
Respect the developers. Often, methodologies (either consciously or
otherwise) paint the actual builders of a system -- the programmers --
as uncouth rabble that must be tolerated because they -- tsk, tsk --
are so gauche, so blue-collar, that they (horrors) write code and
(gasp) make the system *work*. *Don't do this* and don't allow it to be
done in your organization.
Allow Perl to work for you. The goal of this guide is not to turn Perl
into Java or Python or C++, but to show how Perl can be used as an
effective tool for team development and large system creation, and
*still be Perl*.
While it's certainly possible to write Perl that looks like Java,
you're probably using Perl because it affords a different approach and
a different philosophy to solving problems. Don't consign that
philosophy to the scrap heap just because the problem is bigger.
Be aware of the unique advantages that Perl brings. Many of the
strictures of other methodologies exist because it is so *hard* to do
anything with other languages. Taking a rigid, methodical approach is
the only way to ensure, or at least encourage, timely, reliable
results. Perl is different. In the time it might take to perfect one
particular version of a C++ program, the Perl programmer can try ten
different approaches, select the best one, and move on. This is the
form of TMTOWTDI that we don't often celebrate -- that it can be used
as a means to finding the *best* way to do it.
Perl programmers are rightly suspicious of this sort of guide. Too
often, it's an attempt to relegate programmers to diagram-reading,
spec-following drones -- just another set of interchangeable parts.
This guide will *not* be like that, and should work to gently but
firmly correct that line of thinking.
Yes, there's more than one way to do it -- but not all ways are
equally good. This guide is about selecting the ways that are best
for building software *of a particular type at a particular level*.
Attempting to promulgate the "One True Way" of Perl is silly and
pointless, so don't try.
Discuss the "big ideas" in software development, but from a Perl point
of view. Patterns, refactoring, XP, RUP, other methodologies, etc. Be
up-front about how the premises and underlying themes of these ideas
both agree *and conflict* with the Perl philosophy. One of Perl's
greatest strengths is its pragmatism; if something is stupid, it's
stupid no matter how much hype it has going for it.
Flout the conventional wisdom where it's appropriate. Example: Strong
typing, at least in its Pascal/Ada tradition, is a failure. Other
sacred cows are ripe for skewering, too. Perl is not a traditional
language -- don't force it to act like one.
Explain why the discussion should center on the language at all.
Aren't we supposed to design systems in a language-independent
fashion? Use Larry's Turing-complete example, as well as the respect
for programmers argument. How easy is it to find BCPL programmers
these days?
To OO or not to OO? Discuss Perl's pragmatic approach to
Object-Oriented Programming, and how this philosophy should and should
not be applied to large system development.
Train the teams. Perl is a powerful, rich, baroque language. Make sure
the builders know how to use their tools, to ensure the
highest-quality work, and to make sure there's no need to "dumb down"
the level of development so that untrained team members can keep up
with the rest of the class.
Reviews, reviews, reviews -- code should never be written or
incorporated in isolation. The richness of Perl makes this even more
important -- it's too easy to scatter land mines throughout a system
without additional sets of eyes to catch them early.
>From Larry's essay in _Open Sources_:
I began by talking about the virtues of a programmer: laziness,
impatience, and hubris. These are virtues of passion. They are also
virtues of an individual. They are not, however, virtues of
community.
The virtues of community sound like their opposites: diligence,
patience, and humility.
They're not really opposites, because you can do them all at the
same time. It's another matter of perspective. These are the
virtues that have brought us this far. These are the virtues that
will carry our community into the future, if we do not abandon
them.
If you must deliver an all-or-nothing edict, include the rationale.
People deserve to know why certain practices are forbidden and others
mandated, and they're also more likely to abide by them. It's also
useful to know the reason for a rule, so when the reason is no longer
applicable, the rule can be discarded.
QUESTION: Who's the target audience for this guide? Is there more
than one? Many of these suggestions are aimed at developers, but much
of the background information is most appropriate for team leaders and
technical managers (and PHBs?).
QUESTION: Can teams be smaller by using Perl? Individuals are
certainly more productive in Perl; does that translate to the team as
well? I think so, although this needs further thought and
stats/studies to back it up.
Include a reasoned, level-headed explanation of why Perl is a good
idea for large system development.
------
DESIGN
------
Don't reinvent the wheel. Perl is provided with many standard (and de
facto standard) modules and module bundles. Use them. You'll spend
less time building what's already been built, and you're more likely
to find developers familiar with standard modules than with those you
rolled at home. Do you think it will be easier to get assistance with
CGI.pm or with your custom web-page generation script? CGI.pm is just
the beginning, of course -- there's DBI, LWP, XML, HTML, Getopts,
Win32, etc., etc.
When you need a better wheel, start with one that already exists.
Subclass an existing OOP module, or wrap a non-OOP module. As a last
resort, patch an existing module (and submit the patches back to the
author/maintainer). Be careful of version and namespace issues.
TMTOWTDI is a tricky concept to apply to module design. In general,
it's best to do one thing and do it well. In this spirit, use a small
set of primitives (PoP 105), and resist the urge to provide many
different ways to accomplish the same task. The best modules have
lean, focused interfaces.
Avoid making design choices based on arcane internals knowledge
(usually for performance or memory optimization). This stuff changes,
and the choices you make today based on your nifty knowledge of how
hashes are implemented may change in the next revision. If you do
give in to temptation, however, and do this, document such choices so
future generations will know why your code is no longer working.
Adhere to the ideas of n-tier design. Rigorously separate
presentation, business logic, data, etc.
Where possible, use existing terms for processes, objects, entities,
etc.; don't invent new ones if reasonable terms already exist.
Program in the language that makes sense to your customer/audience.
Discuss available frameworks (and similar environments).
Choose your modules carefully. They can save lots of time and money
right up until they kill your project. Use resources that you can
trust. Establish that trust through research and thorough testing.
-------
CULTURE
-------
Be familiar with the common (and not so common) Perl idioms -- even if
your team doesn't use them all. They'll show up in a lot of code, and
understanding them is a big part of being a successful Perl
programmer.
Don't write Perl for programmers that disdain Perl -- Perl's idioms
and peculiar strengths are the *reason* to use Perl, not something to
be ashamed of. Trying to "un-Perl" Perl code removes much of its
power, and leaves it in a diluted, unpalatable state. It helps no
one, and certainly doesn't impress them.
Don't just program in Perl. Perl is such an adaptable, flexible tool
that skills and strengths learned in one language or environment can
often translate quite effectively to Perl. (It also helps you
appreciate how nice programming in Perl can be.)
Don't do something just because you can.
Emphasize hubris.
Isolate weirdness (code weirdness, that is).
Practice (and encourage) good behavior even when it can't be enforced.
(PoP 106).
Find a way to allow programmers to satisfy the urge to write
incredibly cryptic code -- without actually allowing such code to get
into the production system. Some naive ideas:
- Internal golf and obfuscation contests (part of training, perhaps)
- Code dissection
- Code that includes the terse code in docs above the lucid code
- Mandate that "creative" code has to be reusable, and it has to
be isolated in a module. Perhaps these excessively creative bits
of code should be treated like libraries of binary code. :)
These may be pretty silly ideas, but the central theme is this -- a
big part of the reason that Perl programmers program in Perl is
because it's fun, and part of that fun is in the incredible semantic
density of Perl. Take that away, and you might as well be
programming in VB.
----------------------
STANDARDS & GUIDELINES
----------------------
Establish company/organization standards for coding and documentation,
including the rationale behind the standards. Use it as a yardstick
for walkthroughs and code reviews. Such a guide should be tailored to
the organization, and often to a particular project. Update it often.
Establish documentation standards, both for structure and content.
Code is not complete and does not pass review until documentation is
complete. Document as you go.
Use the natural program structure to assist documentation. Don't
synthesize constructs when the existing code can be used as a
commenting framework (and this has the added benefit of encouraging
the parameter/variable/logic grouping). Personally, I despise huge
block comment headers that include the subroutine name, the
parameters, the return code, etc. Don't do this -- it's extra work,
and it practically encourages the header and the code to get out of
sync. Instead, place the description after the sub line. Same for
parameters -- provide a comment after the [my $param = shift; ]
statement, instead of repeating the parameter names in the header. As
for value vs. reference parameters -- practically all your parameters
should be value parameters, with the exception of references. Call
out the exceptions to the rule, instead of always specifying (in)
everywhere.
So what should be in a subroutine header?
- Description
- Return values
- Exceptions
- Change history (?)
And should it be POD or straight comments?
Recommend program structure, common coding style of CPAN authors, etc.
This is a tough one, as many of the most popular CPAN modules aren't
the best examples of maintainable code.
Recommend module structure. Consider recent experience with the need
for BEGIN blocks and the intermingling of pragmas and regular [use]
statements.
Recommend multi-file/multi-directory application structure. Include
detailed strategies for local library directories (@INC).
Recommend local namespace strategy. Consider the wisdom of
app-specific namespaces (and the problems that can cause for
reusability). Describe the standard Local:: namespace. Discuss the
use of per-project and per-organization namespaces.
Recommend versioning strategy. Consider/discuss proper use of [require
X.NNN] and [use SomeModule X.NN] statements. Discuss naming
strategies for multiple generations of a module, including backward
compatibility, addition of new interfaces, etc.
Limit line length to something reasonable. Break expressions into
meaningful chunks, using the included suggestions as a guide.
Be careful how quickly you allow your project to depend upon newer
features of the language. An example would be pseudo-hashes -- they
were a bad idea and now they're gone.
On the other end of the spectrum, don't use deprecated features.
They're gone for a reason, and are unlikely to be maintained in Perl 6
and beyond.
Avoid indirect object syntax. Explain why.
Avoid multiple inheritance. Explain why, and discuss exceptions.
Use objects for file and directory handles. Normally, these modules
would be a memory and performance hit, but in the context of a much
larger system, the impact is greatly outweighed by their usefulness.
Reference MJD's article on uses for local, esp. on filehandles.
Avoid typeglobs and symbol-table manipulation. When necessary, treat
them the way Perl treats overloading -- as a very special thing, to be
done only when absolutely required, and then to be isolated and
wrapped in a protective coating. There are probably other techniques
where this is a suitable attitude as well.
Don't depend on precedence. Use parens to be explicit.
Discuss effective use of context. Be explicit with scalar().
Be sparing with pre/post increment/decrement embedded in
expressions.
"Omit redundant punctuation as long as clarity doesn't suffer."
Provide examples of clarity vs. lack of clarity. Usually, putting
parentheses around function calls is a good example. It keeps you out
of trouble with the parser, which is sometimes too smart for your own
good. The right answer, as with most issues, is "do it when it makes
the code better."
Don't [goto] anything, except in the *very* special cases where it's
appropriate. Explain those cases.
Show restraint with AUTOLOAD. It's a good way to handle get/set
methods, but should probably be avoided elsewhere.
Discuss get/set/is methods vs. field access, and the use of lvalue
subs to get the best of both worlds.
Discuss loop and subroutine exits -- one place or multiple places? I
favor the Ada "comb" over Wirth's structure. Show examples of
successful combinations of both, with a single unavoidable exit
location, but with [last] statements to get you there. Consider
incorporating Larry's outdented [last] as part of the standard
formatting.
Suggest sectional markers for program header, pragmas, constants,
subroutines, and main program.
Provide statement formatting examples. Be comprehensive. Provide
templates for breaking long expressions and statements across multiple
lines. This is especially important for statements that may include a
block of code (like grep or map).
QUESTION: Should the main program have a "main" subroutine? I don't
do this (currently), but is there a maintenance advantage to it? It
might be useful for lexical variable isolation if nothing else. What
are some other good reasons to have it?
QUESTION: Should subroutines come before or after the main program? I
like them before, but I was raised on Pascal. Also, you don't need
the [use subs] pragma. Others find having the main logic of a program
or module at the top of the file is better, since it emphasizes the
main idea. However, there's a nearly mandatory chunk of code that
will be at the beginning of any non-trivial program or module, and you
have to get past that anyway. Also, POD comes after the __END__, and
there's usually a comment to that effect.
Provide guidelines for building a module, including POD.
Provide guidelines for building a class.
Provide guidelines for building a subroutine.
Explain why prototypes should be avoided, except when they shouldn't.
Provide naming conventions for packages, modules, subroutines,
lexicals, global/package variables, constants, filehandles,
dirhandles, heredoc tags, block/loop labels, methods (including
get/set routines). (See next few paragraphs for example discussion).
Provide rules for use of similar names among scalar/array/hash
namespaces. Don't forbid it -- sometimes it makes a lot of sense, and
can make the code much more readable.
Thoughts on sub/method naming conventions:
- sort => by_name
- boolean => is_dirty
- conversion => to_lower
- inplace conversion (like chop or chomp) => ???
Don't prefix sub/method names with the package/class/object name; the
package or object name provides the appropriate semantic cue.
Discuss grammatical and parts-of-speech guidelines for for naming of
modules, classes, methods, subs, etc.
QUESTION: Are there variable prefixes that *do* make sense? Since
array entries and scalars are so easily confused, for example, should
all arrays begin with 'arr' (or 'a') ? Al hashes with 'hash' How
about suffixes instead? 'ref' for references (perhaps as a suffix)?
DISCUSSION:
I intensely dislike Hungarian notation, and there are some very good
arguments against it (which I should probably find and read again).
However, I'd be lying to say it doesn't serve a useful purpose, and
it does get easier to read after a lot of exposure. Perl already
has some built-in prefixes, however, and adding textual prefixes to
the batch may make things worse instead of better.
Hungarian is probably most popular in VC++ and VB, due to the need
to know when to cast in C++, and a way of differentiating among all
the controls and objects in VB. Perl doesn't need these types of
things so often.
While I don't recommend going Hungarian, a set of reasonable
prefixes and suffixes is worthwhile if used selectively. They're
especially useful when your code contains a mix of objects and names
associated with those objects. For example, if you're dealing with
users, then what does $user refer to? Is it the user's ID, or an
object containing properties for this user (one of which is probably
the ID)? A set of suffixes and prefixes can avoid this confusion.
This also extends to problem-specific suffixes, which you probably
already use quite naturally. An example might be "dn" for
"Distinguished Name" in an LDAP application.
It's more natural to use a combination of funny characters, case
differences, and plurality to distinguish among different variable
semantics. (provide real examples; these are just a stub)
Use plural nouns for arrays:
@widgets
Use singular nouns for non-ref scalars:
$widget
$the_widget
$widget_width # this will probably bomb
Use 'is_' prefix for boolean scalars:
$is_dirty = 1;
(similar rules for hash keys)
Use '_of' suffix for hashes where appropriate:
$color_of{$widget} eq 'green'
How to handle references? '_ref' suffix seems popular, but it's
verbose. In pseudo-Hungarian, 'rWidget' is common. Maybe 'r_'
prefix? What's most readable in actual code?
Similar questions for objects. (If you have to affix it with a
marker, then it may not be much of an object?)
Expand on this citation from perlstyle:
You may find it helpful to use letter case to indicate the scope
or nature of a variable. For example:
$ALL_CAPS_HERE constants only (beware clashes with
Perl vars!)
$Some_Caps_Here package-wide global/static
$no_caps_here function scope my() or local() variables
Function and method names seem to work best as all lowercase.
E.g., $obj->as_string().
You can use a leading underscore to indicate that a variable or
function should not be used outside the package that defined it.
A couple of notes:
- Notice the warning about clashes with Perl vars, which may be
a good argument for a more modern constant naming convention.
It has certainly happened to me, with $RS.
- The leading underscore convention is a nice idea, but it seems
weak for the level of maintainability I'm trying to achieve
here.
Discuss exceptions to the established naming convention; Win32 code
is a good example. While $names_like_this are great in a Perl-only
world, they can be tough to deal with in a Windows project, where
$NamesLikeThis are the rule. In general, it may make the most sense
to adapt to the world you find yourself living in. Perl is a good
citizen, able to play well with others -- and sometimes that means
it has to adapt to the environment it's playing in.
Avoid variable names that differ in case only. *Possible*
exceptions include names that are all upper (CGI) vs. all lower
($cgi).
It would be easy (and wrong) to declare a blanket prohibition
against giving different types of variables (scalar, hash, etc.) the
same name. However, it often makes a lot of sense, and makes the
code very easy to understand (and practically self-documenting).
Similar variable names should live in the same semantic space. For
example, $widget and @widgets make sense -- but be careful not to
create such mental associations where they're not appropriate.
Avoid action at a distance and adhere to the "Principle of Least
Astonishment." This does *NOT* mean a blanket prohibition against
Perl idioms.
Choose the appropriate loop for the task. Don't force one to be
another. Also, some types of loops are best avoided altogether. The
do {} and do {} until are both suspect. Be clear about when to use
them.
The "postfix conditionals" are "postfix iterators" are *easy* to
overuse. Don't. Consider limiting to statements with "atomic
impact," like debug statements.
Put important things first. This applies to statements, but may also
make sense for subs and modules.
Be wary of boolean operators used to control program flow. It's
probably best to limit such use to [ some_statement or die ] style
constructs. Another exception to the rule may switch-style statements.
Use spaces instead of tabs. If you absolutely must use tabs, use
standard tabs. But just make life easier on all of us and use spaces.
Minimize "synthetic code" (see articles by MJD).
Discuss exporting names into the calling namespace. Never, but with
lots of :tags to make it easy? Also discuss from the angle of the
importer, i.e., how much to import?
Pick a style of switch statement. Simpler is probably better. Don't
be ashamed of the if .. elsif .. else if it's appropriate.
Don't refer to a package by static name within the package itself.
Discuss alternatives, including __PACKAGE__ , caller(), etc.
Generalize to rules regarding module names and position independence.
Discuss appropriate use of $_. Again, don't just forbid it; use what
makes the code easier to maintain and to understand.
- Best used in short code segments.
- Can't depend on $_ having a very long lifetime.
- If you use it, localize it.
- Discuss places where it's mandatory.
Discuss the wisdom of initializing variables at the point of
declaration, vs. providing initial values as part of program logic.
(Of course, if variables are always defined as close as possible to
their point of use, then this issue may just go away.)
PRO:
- Provides a clue as to the expected type of value that this
variable will hold, at least for scalars.
- Avoids spurious "use of uninitialized value" warnings.
CON:
- Masks *real* uninitialized value warnings.
- Perl already provides useful initial values for you,
so why do it again?
- Clutters the code
Should initial values only be 0 or empty string for scalars, and
empty list for arrays and hashes? Initializing to other values
mixes logic and declarations, which is generally a bad idea.
Use by-name interfaces to functions where they are available.
Examples include time and stat, among others.
Provide guidelines on dealing with the subtleties of true/false,
defined/undef, "", 0, etc. Be sure to consider context issues, esp.
around return statements.
Avoid using the older &subname style of subroutine calls. For the
situations where it's necessary (to bypass prototype checking, for
example, or to automatically pass @_ ), document the heck out of it.
Even better, figure out why you need to do it and eliminate the cause
of the trouble.
Use the /x option for complex regexes. Comment liberally.
Build complex regexes a piece at a time, for easier maintenance and
understanding.
Declare variables one line and one variable at a time, for ease of
maintenance and documentation.
Do this:
my $var1; # documentation on $var1
my $var2; # documentation on $var2
Instead of this:
my ($var1, $var2);
(This is likely to be a flashpoint, and I doubt it's worth the
effort to argue with people over it.)
Select an object reference notation and stick with it. $self, $this,
$me, whatever... just be consistent. $self seems to be the most
popular, but this is also a topic ripe for holy war.
Discuss bracing styles, and be prepared for a backlash.
Discuss advantages and disadvantages of the English module. I don't,
but the advent of Perl 6 may change that.
Of course, use the strict and warnings pragmas. Discuss use
diagnostics, especially in a debugging context.
Discuss the applicability of taint mode. It's not just for web apps.
Know when to use local, and only use it then.
Always local'ize punctuation variables before changing them.
Prefer our to use vars, except in cases where backwards compatibility
is an issue.
Use constants. Discuss the pros and cons of different constant
creation techniques. Discuss constant naming techniques (ALL_CAPS vs.
prefix vs. etc.).
Avoid direct use of subroutine parameters via @_, even for reading.
Avoid changing parameter values. Return lists / hashes instead of
modifying incoming variables. Less chance of blowing up when passed
constant values, too.
Name parameters using
my $param = shift || "default value";
instead of this:
my ($p1, $p2, $p3) = @_;
The first allows for cleaner documentation and easier maintenance,
esp. w/ default values.
Use named sub arguments for complex argument lists. Show techniques
for doing so. Prefer list vs. anonymous hash except in rare cases
where a subroutine accepts both types of lists.
When it can't be avoided, group access of external data (such as
global variables, file-scoped lexicals, or program configuration
values) into a single location near the beginning of a routine.
Consider these values to be like special parameters. Of course, if
access to such external data can be avoided, avoid it.
Define guidelines for use of [ # end block ] markers. They're a
little silly when the whole statement is five lines long -- you can
see the whole thing on the screen at once, and there's no doubt where
it starts or stops. For a nested statement twenty lines long,
however, an ending statement marker is a good idea.
Discuss: Define all the variables for a routine at once, or define
variables as close to the scope that uses them as possible? In any
case, declare all variables for a program or a scope at the beginning
of the block.
The ready availability of hashes and lists sometimes keeps us from
using other more advanced data structures, even when they're the right
answer. Know your options, and use a more exotic structure when you
need it.
Explain when to use exception handling vs. return-value tests.
Discuss the appropriate use of exceptions (i.e., eval/die/$@). The
conservative approach is that exceptions are only for exceptional
conditions, and are not part of the normal logic flow of a program.
However... exceptions can often clean up the "happy path" of a
routine, and can make it more understandable. This topic deserves a
lot more discussion (and research).
Build and use a real error/exception handler. Discuss the appropriate
scoping of such a handler, and the alternatives available (i.e.,
Graham Barr's Error module) for more advanced handling. Look at Matt
Sergeant's presentation on this subject, too.
Avoid doing anything in a BEGIN block that can change the external
environment.
On whether or not to always use double quotes:
Performance isn't the issue -- understanding is. During compilation,
Perl will resolve double-quoted strings to determine whether or not
interpolation is required, so using double quotes doesn't decrease
performance (ignoring the infinitesimal difference in compilation
time).
But that's not the point. Double quotes *mean* something -- to the
reader of the code, they say "there's stuff in here that's
interpolated." If that's not true, then the maintainer either
spends time looking for variables where there aren't any, or misses
them when they *are* there because you've accidentally taught him
that double-quoting doesn't necessarily mean anything in your code.
So use double quotes when you need interpolation, and use single
quotes otherwise -- not for some nanosecond improvement in
performance, but for a real improvement in understandability.
Don't wait until you need to use a routine twice to make a subroutine
or a method for it. Instead, build subs in order to capture ideas and
discrete tasks; this allows for more concise expressions of
higher-level routines. Consider using "my subs" if the routines
absolutely *must* be private.
(BTW, this may be a good way to allow for "extra creativity" -- give
it a descriptive name and hide it in a subroutine.)
------------
TESTING & QA
------------
(This is a huge topic that's undergoing a lot of positive change in
the Perl world. Research it heavily before getting too far out on a
limb.)
----------
DEPLOYMENT
----------
Discuss deployment techniques to ensure the integrity of your
application, and avoid "DLL-Hell."
Examples include:
- Local installation of all modules with your application
- Private Perl installation
- Version checking of all modules used (at a single point
during app startup?)
Discuss app servers and their equivalents.
--------------------
TOOLS & ENVIRONMENTS
--------------------
Developers should, whenever possible, select their own tools. It's
downright stupid to demand that a developer switch tools just because
of some misguided policy. Interoperability is a valid concern, of
course, but don't get carried away.
Select tools that can be automated in Perl.
Use source code management software, and make sure that using it is so
transparent that no one has to think about it.
Use automated tools for testing and validation, such as perltidy and
the B:: modules.
-------------------
MISCELLANEOUS NOTES
-------------------
Good sources to cite/consult, along with the O'Reilly Canon and
Damian's OOPP:
Kirrily Robert's "In Defense of Coding Standards"
MJD's articles, esp. on strong typing, "Sins of Perl," synthetic
code
_Effective Perl Programming_
_The Practice of Programming_
_The Elements of Programming Style_
(lots and lots of others)
Include a recommended reading list, perhaps per topic (like Damian's
OO book does).
QUESTION: What aspects of successful Open Source development also
apply here?
Include sections on _Reliability_, _Scalability_, _Security_,
_Performance_, and _Portability_.
There are techniques and tools that are not as widely known as they
should be, and should be given some attention. Memoize is a good
example.
Scott Meyers' "Prefer X to Y" style of recommendation may be
appropriate. It worked well for _Effective Perl_, too.
Contact other people who've done this before, and include their
experiences and lessons learned.