Although we're agreed that, for chunks of code which are often-used, fns are a good thing it's maybe interesting to discuss the example you mentioned about db conn.
For example, I use the following library fn:
Code: Select all
function dbConnect()
{
$style = 'border: 1px dotted #000; padding: 8px; background-color: #def;';
$db_connection = mysql_connect(DB_SERVER, DB_USERNAME, DB_PASS);
if ($db_connection === false)
{
die('<p style="' . $style . '">'
. mysql_errno() . '</p>
<p style="' . $style . '">'
. mysql_error() . '</p>'
); }
if (@mysql_select_db(2, $db_connection) === false)
{
die('<p style="' . $style . '">'
. mysql_errno() . '</p>
<p style="' . $style . '">'
. mysql_error() . '</p>'
);
}
return $db_connection;
}
The css to tart up the output isn't really needed but the real benefit is that, with one edit, I can replace the die() message (with explicit mysql errors) with a simple "could not connect to the database" - and possibly add an error logging class which writes the error to a file, or a class which emails the db admin etc. On a live site, that would avoid revealing a database name if an error occured (it's best not to reveal db/table/col names since this could be useful information for a hacker).
Or, if I switched databases, I can quickly change mysql_connect to ibase_connect etc. It provides a very basic db abstraction layer.
Both are important reasons for "encapsulating" native db fns.
Anyway, the real point where we disagree is with creating fns for chunks of code which probably are not going to be re-used and this goes to the heart of what a programming language really is.
Computers have to read and work with code of course, but people also have to read and work with code. I'd say that at least two thirds of the effort of programming goes into the latter. Communication / systems engineering skills are a big part of the job as well as the relatively trivial task of making computers do stuff.
With loose code, I might have to read several lines before I figure what's going on. However, with:
..I instantly know what's going on without having to read any code at all.
Or, suppose I want to check up on how a user is authorised. Fns create "chapters" and "titles": I can go straight to the fn def and examine the code. With a loose script, I might have to sift through hundreds of lines of code to find the auth bit.
This is particularly important if you are working with other people. Even if it's all your own code, in three months time you'll have forgotten how it works and find yourself having to read through entire scripts just to track down a single item.
What about bugs? If you've got separate fns (or classes) you can track down bugs more easily, testing individual components rather than having to test the entire script at once and then try to figure out where the problem is.
"Good" fns are important for this, and for readability. A good fn should do just one thing and have a name which makes it immediately apparent what's going on.
For example, suppose you have to perform a logical test and then carry out one of two actions. The test and each action should usually be split into separate functions, ie:
Code: Select all
if(isAuthorised($user))
{
printProfile($user);
} else {
printNotAuthorisedMessage();
}
(but if the actions were simple one-line affairs, I probably wouldn't bother with seperate functions).
Lean fns which do just one thing lead to a more modular, layered app which is much easier to work with. It's easier to find what you want, easier to test individual units of functionaltiy, and easier to swap components in and out. Many of the fns you come up with will turn out to be be re-usable elsewhere.
The sea-change in perspective comes from thinking less about the computer end and more about how people interact with code. From the perspective of a computer, "good" code might perform exactly the same way as "bad" loose scripts. The server doesn't care. At the other end, making a script which is easy for people to understand and work with means you have to think about design.
Perhaps the essence of good design is encapsulation - everything in its own space. That could be wrapping a few lines of code in a fn (which tend to suggest themselves) or it could be a tricky OOP decision on whether ButteredToast should inherit a Toast base class - or is it more flexible to apply Butter/Jam/PeanutButter decorators to a ToastIterator?
Fns are just a first, tiny step in this regard: the real benefits (and lots of Eureka! moments) come with OOP.