Re: Meaning of Maintanability and Functionality in Coding Perl
by graff (Chancellor) on Oct 18, 2005 at 05:30 UTC
|
How can I tell if my Perl code (or others) is 'maintainable'
Look at something you wrote at least six months ago (i.e., something you haven't looked at in at least six months), and see whether you can understand it. If it didn't include "use strict", make a copy, add "use strict" to it, and see how long it takes to make it work like the original.
If it had "use strict", but not "use warnings" (or "-w" on the shebang line), add that as well, and see (1) how many warnings you get, and (2) how long it takes to make them all go away (while still making it work like the original -- assuming the original was doing the right thing ;^).
Look for repeat occurrences of:
- The same quoted string (or many strings that all have some common substring)
- The same "if" condition
- The same sequence of steps in different loops or subs or sections of the main code (with just some differences in the literal values or variables being used)
The more repetitions of strings, conditions or procedures you have in your code, the less maintainable it is.
(If your code already has "strict" and "warnings", post a snippet of it here, and see how people react to it.)
As for "good functionality", that's what we call "an empirical question" (i.e. testable): does it do what it is supposed to do, or not? You could change the question slightly, to "does it do its job effeciently?" but this isn't always relevant. In general, if it does the job without a lot of unnecessary steps, that should suffice.
As for points to pay attention to, the most important one is documentation! Write a coherent, human-readable description of what a program is supposed to do (what are its inputs and outputs, what goals does it accomplish, and -- briefly, succinctly -- how does it work), and do that first . Then write the actual code, in accordance with the description. Keep the description in the same file with the code, in pod format. | [reply] |
|
"Look at something you wrote at least six months ago (i.e., something you haven't looked at in at least six months), and see whether you can understand it."
I agree with you that legibility is part of maintanability. Just to add a little bit more: legibility does not directly gurantee maintanability. For example, we have this one application that is over-engineered, and the architecture determines that it is very difficult to maintain, even if all of the code are very easy to read and understand, the maintanability is still very poor.
Maintanability at least comes at two levels: coding level and application level (design and architecture).
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by ikegami (Patriarch) on Oct 18, 2005 at 05:56 UTC
|
If I were to answer this in a few words, I'd say:
- Consistency
-
Pick a style, and adhere to it when possible.
- Self Documentation
-
One should write code such that it appears to do what it actually does. This also means that one should write code such that bad code appears to be bad. Joel of "Joel on Software" has an interesting write-up called Making Wrong Code Look Wrong touching this subject. He's talking about Hungarian Notation which you may not want to use, but the underlying idea is very important.
- Document Assumptions
-
Almost all of the comments I've seen in my lifetime were completely useless, and what should be documented wasn't. The most important thing to document are the assumptions you (the programmer) made. For example, "$var must not be undef.", "This algorithm is only ideal for lists no bigger than XXX elements.", "The module may not be thread-safe." and "Uses features specific to Win32." are all valuable comments which document assumptions. These bits of information are not apparent from reading the code, therefore they must be documented.
On a less general note, I have a beef with documentation that fails to properly the causes and methods of failure of a unit. Very little is usually said about how a function might fail. I feel it's very important to document the state of relevant variables, structures and objects on failure.
Update: I incorrectly used the word "comment" where I meant "document". Fixed.
| [reply] |
|
The most important thing to comment are the assumptions you (the programmer) made. For example, "$var must not be undef.", "This algorithm is only ideal for lists no bigger than XXX elements.", "The module may not be thread-safe." and "Uses features specific to Win32."
I understand that you were merely making stuff up off the cuff, but I think those are bad examples. Any assumptions should really be coded as assertions and the comments should explain why the check is there.
#sub foo() which sets $var can never fail for such and such reason
defined($var) or die "\$var must not be undef.\n"
#I'm too lazy to make it work properly for all lists
(@list > $XXX) or warn "This algorithm is only ideal for lists no".
" bigger than $XXX elements."
#cross platform compatibility is comming in version 9.0
($^O eq 'MSWin32') or die "Platform not supported"
...etc. | [reply] [d/l] |
|
My mistake was in my word selection. I said "The most important thing to comment" when I meant to say "The most important thing to document" (like in the paragraph header). Those words are obviously not interchangeable. It is possible to document something with means other than comments. For example, the use of assertions are an excellent mean of documentation. I didn't mention the use of assertions specifically because I considered it an implementation detail and I was speaking at the conceptual level.
Looking at assertions further, I don't think they are always the best choice. For example,
($^O eq 'MSWin32') or die "Platform not supported";
could be replaced with
($^O eq 'MSWin32') or warn "Platform not supported";
depending on whether the unit is known to use features specific to Win32 (die), or whether the possibly of running the unit on another platform was simply not considered (warn). This would be consistent with Perl's spirit of flexibility and permissivity. It's not always necessary to know that something won't work; it's often sufficient to know when it might not work.
| [reply] [d/l] [select] |
|
Any assumptions should really be coded as assertions and the comments should explain why the check is there.
Really? What should the code do if, once promoted to production and deployed, the underlying assumptions are found to be wrong? What should those assertions *do* if they fail?
It depends a lot upon the implications of the assertion failure, and it's often not an easy problem.
What should I do if I catch a "POWER OUTAGE" signal on a machine with no UPS? It can't logically happen; so how should I code to handle it? Anything follows logically from a contradiction, so logically, any response I choose is wrong.
What about just an I/O error from the disk? Should I write a message to the logfile (on disk) complaining that the disk is broken? Should I spam the user with repeated console messages? How do I continue after such a failure?
It's bad if a program aborts when it doesn't need to. It's also bad if a program continues when it shouldn't. If you've got an situation that you didn't code for (can't legally happen), you don't know what to do.
For example, why did you choose to die() in one case, and warn() in another? Why not carp() or croack() instead?
The documentation for the *function* should tell the caller what the correct inputs and outputs are, and what error handling, if any, there is.
That way, if I call your spiffy new function with data that I haven't vetted, I'll *know* what the error handling for the routine is, and whether or not it is suitable, without having to wade through the ugly implementation details of your code. Reading code should be a thing of last resort; documentation designed for humans should be the first avenue of attack, and only when code is broken should it have to be investigated manually.
If you can't explain what your function does in plain English, then you need a simpler function (or English language lessons). Or both.
--
AC
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by greenFox (Vicar) on Oct 18, 2005 at 06:02 UTC
|
Ditto everything graff said. The point about looking at old code is one of the best ways I have learnt, when I have had to go back and maintain code which I wrote and found I couldn't understand chunks of it I knew I had work to do. I am probably overly verbose in my coding now but I know it will be clear when I come back to it in 1 year or 3. A lecturer in one of the few comp sci classes I took said that "a program is a letter from one programmer to another that a computer just happens to be able to understand", I think that is a good way to approach all your programs, like it is a letter to another programmer who you know nothing about.
Other resources which you might find useful are dominus's Program Repair Shop and Red Flags I, II and III. I haven't had a chance to read it yet but judging by the sample chapter you will also want Perl Best Practices by TheDamian.
-- Murray Barton Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by martinvi (Monk) on Oct 18, 2005 at 06:38 UTC
|
I really appreciate the question and, while being no master, will give some of my own crutches.
The first crutch is seeking peer-review, even if said peer isn't really your peer, but your better in the given field. There are monks around, who breathe, what I'striving for. To get their critical comments is a premium. If one isn't willing to post ones code to the monastery -- due of whatever reasons. Mine are false pride and cowardice. -- one can go for peers in an more familiar, more comfortable environment that an online community might provide. Personal note: I dare to discuss most of my code with the two developers at my site. That's good. But I know, when I'm able to face the wrath -- or more plausibly the giggle -- of my fellow monks, my personal maturation has done a quantum leap -- and my code will follow suite.
The second crutch is commenting. Don't go for the meaning of "comment" in an arbitrary programming language (and drop that lore of "real programmers don't comment" -- I rather like to be a good programmer instead of a real one, if those a the choices), but go for the meaning of "comment" in the press. There, a comment is an opinion -- or, at least, an opinionated summary -- of a factual event.
The first comment, I wrote, is my opinion, what the code should do, what I dreamed of its functionality. Sometimes, while writing down those fantasies, I'll see my error in plain language. The second comment isn't a comment following the above definition, but a report. It merely state, what my code has done in a test run.
Now for the hard part: Leave those comments in your code. It's much easier to follow ones intention, if the path from imagination to reality is laid down. As a consultant, who had to review some of my programm, once said after serveral time silently staring on the screen: "Whatever you smoke, I want some of it."
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by pajout (Curate) on Oct 18, 2005 at 07:32 UTC
|
I, of course, agree with previous comments. And I remember folowing:
1/ The conditions expected for usual code execution should be specified (OS, memory, user, environment, ...)
2/ The documentation should contain an ideas. Ideas about WHY this code exists, HOW it resolves the problem and WHAT it expects and/or not expects - for instance, some code may expect that some combination of arguments cannot occur, because real world logic.
3/ The code should't be too clever ;) In other words, imho, I want to _read_ the code, I don't want be quizzed. | [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by adrianh (Chancellor) on Oct 18, 2005 at 10:48 UTC
|
As well as TheDamian's excellent Perl Best Practices, Peter Scott's Perl Medic is also a darn good read for those new to this topic - with lots of useful advice on how to approach non-maintainable code.
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by derby (Abbot) on Oct 18, 2005 at 12:06 UTC
|
The second best thing out of MS world is Code Complete (the first being the wheel mouse). Buy or Borrow it ... read it ... and remember above everything else - high cohesion, low coupling (it's not just for OO).
| [reply] |
|
I agree that Code Complete is a great book. However, it's fairly old and IMO quite a few parts of it are rather dated. I'd expect the Second Edition rectifies that, but haven't read it yet.
Also, as an instructional guide to perl programming I'd go with Perl Best Practices over Code Complete.
Update: dragonchild is right, that last sentence was inappropriate. Let me try again:
If you're looking for practical tips on how to write maintainable perl code, I would first buy and read Perl Best Practices. If you then further want to educate yourself on software design principles and practices I very much recommend that you read Code Complete. Other fountains of knowledge in this and related areas are The Pragmatic Programmer, Test Driven Development: By Example and The Mythical Man Month.
| [reply] |
|
Perl Best Practices (aka PBP) isn't a Perl version of Code Complete (aka CC). While they certainly address the same basic topic (how to write maintainable code), CC provides a lot more detail in terms of why these practices are better than the others. PBP references no studies and works only in one language. I would recommend reading both books.
As for CC being dated ... yes, it was written over 10 years ago. I've also worked on at least two major projects that are around that age ... written in Perl. Plus, nearly every app I've ever worked on has had to interface with another application that's over 10 years old.
I would put forward that most applications are either under 3 years old or over 10. My theory is that every app is either new (under 3 years old), in the process of being rewritten, or it's survived. And, yes, 3 years old is new.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by dragonchild (Archbishop) on Oct 18, 2005 at 11:50 UTC
|
My sig's Rule #2 is all about maintainability. If anyone can make a change (simple or complex) and be reasonably certain they didn't introduce any bugs, your code is maintainable. A testsuite goes a long way to ensuring maintainability.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by samizdat (Vicar) on Oct 18, 2005 at 14:36 UTC
|
I think ikegami and pajout have made my main points, but I'll expand a bit.
{yak, yak, yak! it's good for the soul! :}
Limbic~Region said a lot also about "optimizing for what?" in that CB conversation, and he's sooo right. You don't need to go as far as I do (in Look at the Big Picture) in examining the meaning of life, but it's important to step back and think about why you've written this new program, what it's supposed to do (both specifically and for the good of your group | org | company | hobby), and how it has to be used to make it do all of that.
One thing we programmers are often blind to is how much of our programming process exists inside our heads and nowhere else. Programming is all about abstraction, and it's important to help the guy | gal coming after you to see what you have done in transforming need into solution. Equally important is to document what you haven't done, i.e., the boundary cases you haven't coded traps or solutions for. | [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by swampyankee (Parson) on Oct 18, 2005 at 15:55 UTC
|
I would add a few other trivial pieces of advice:
You're not writing code for the Obfuscated Perl contest (would any sensible programming manager hire somebody who put "winner 4 years on a row in the World Obfuscated <language of choice> contest" as a major award in their resume?).
Try to avoid Perlisms like the assumption that if(/.../) applies to $_. Be explicit, even if it looks "wordy" or "overly verbose".
Add use English, and use the English language forms for things like $|. (If there aren't use modules for other major languages, maybe there should be).
Find a coworker and have her or him try to figure out what you were doing, without your assistance.
Please, please, please, make comments meaningful, useful, properly spelled, and grammatical.
| [reply] |
|
Try to avoid Perlisms...
Why would you bother to use the perl interpreter if you want to write in some other language. That's only going to confuse real Perl programmers. There are plenty of other languages to choose from. Idioms are there for a reason.
...like the assumption that if(/.../) applies to $_.
Why is this an assumption? Is there any time when m/.../ doesn't match against $_?
| [reply] |
|
Every language has its esoterica and every language has features that make future maintenance more challenging than it should be. I'm not saying never use substr as an lvalue; I'm saying (turgidly, perhaps) is that idiom should be eschewed if it conflicts with clarity.
I doubt if writing
if($current_line =~ m/abc/)
will confuse a real Perl programmer, just as I doubt that
DO LOOP_COUNTER = START, FINISH
will confuse a real Fortran programmer. Why not write
DO I=J,K instead?
I will agree idioms are there for a reason, but the idioms are not the language. Fortran, a language I've dealt with for several decades, has all sorts of idioms which are generally considered Bad Things. Most corporate style guides forbid Fortran programmers from using computed and assigned gotos and arithmetic if statements, both perfectly legitimate idioms. Perl has a goto; it's there for a reason, but that doesn't make its use a good idea.
| [reply] [d/l] [select] |
|
You're not writing code for the Obfuscated Perl contest (would any sensible programming manager hire somebody who put "winner 4 years on a row in the World Obfuscated <language of choice> contest" as a major award in their resume?).
Aren't the winners of those contests the ones who are the most intimate with the given language? Note that Mr. Wall has won an IOCCC award, not once, but twice.
Add use English, and use the English language forms for things like $|.
use English does signify one important fact; the code that follows was written by a complete Perl newbie. And that's important information for any maintainer.
| [reply] [d/l] |
|
use English does signify one important fact; the code that follows was written by a complete Perl newbie. And that's important information for any maintainer
Frequently code maintenance is performed by programmers with little experience or little experience in the language. Even if the original programmer has eons of Perl experience, the person maintaining the code may be trying to figure out a Perl program with Learning Perl by one elbow.
Aren't the winners of those contests the ones who are the most intimate with the given language? Note that Mr. Wall has won an IOCCC award, not once, but twice.
I've never read Lary Wall's resume...does he consider winning the IOCCC contest a major achievement? Again, the chances are the maintainers are less experienced than the original programmers. Eschew esoterica.
| [reply] |
Re: Meaning of Maintanability and Functionality in Coding Perl
by EvanCarroll (Chaplain) on Oct 18, 2005 at 05:28 UTC
|
| [reply] |