Tue, 28 Aug 2001 00:47:04 -0500 Off and on for the last few months, I've been compiling notes on "Perl for Enterprise and Team 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 any Perl-related projects. - Educate the powers-that-be that Perl is a reasonable choice for the development of large, scalable, reliable, [insert desirable trait here] systems, despite what Sun and/or Microsoft might have them believe. 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 from the 1998 TPC. Much of it comes from staring at my own Perl code and trying to figure out what's good and what's not so good. 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, many areas (such as Testing & QA) are 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 and Team 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 it* 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 poor 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) Contact other people who've done this before, and include their experiences and lessons learned. Case studies could be very useful. QUESTION: What aspects of successful Open Source development also apply here? Big sections on _Reliability_, _Scalability_, _Security_, _Performance_, and _Portability_. Include a recommended reading list, perhaps per topic (like Damian's OO book does). 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.