Bad practice!
Moderator: General Moderators
The main argument here seems to be creating code that is logical. By this I mean:
1. HTML and logic are separated.
2. Functions are used with self-referencing names to relieve your code from too many lines of comments.
3. Any comments are written succinctly with good grammar and are spell-checked.
4. Work is documented in a separate file listing what does what and where for quick reference six months later.
By sticking to the these general points I find that stuff I write can be understood even by (reasonably intelligent) non-programmers.
I have one question, though. When it comes to including functions do you place all linked functions in one file or do you place each function in its own file?
1. HTML and logic are separated.
2. Functions are used with self-referencing names to relieve your code from too many lines of comments.
3. Any comments are written succinctly with good grammar and are spell-checked.
4. Work is documented in a separate file listing what does what and where for quick reference six months later.
By sticking to the these general points I find that stuff I write can be understood even by (reasonably intelligent) non-programmers.
I have one question, though. When it comes to including functions do you place all linked functions in one file or do you place each function in its own file?
- Ixplodestuff8
- Forum Commoner
- Posts: 60
- Joined: Mon Feb 09, 2004 8:17 pm
- Location: Queens, New York
I don't pass number 3 in that list 
a comment in my current project:
I usually have a file called common.php that has all commonly used functions, and another one called uncommon.php for less used ones (so they aren't loaded if not needed), also when I have a bunch of functions that are related but not common, I give them their own file.
My classes are almost always in a different file, usually a file for each class, but for smaller classes I might group two or more in a single file if they are related to each other.
a comment in my current project:
Code: Select all
<?php
//path to tooy of site (edit like 2 days after this comment was written: WOW i
//mispelled that badly.. I don't even know what tooy stands for, I KNOW it can't
//be toy, moral of the story: if you comment somthing to make code more
//readable, make it spelled right :\)
?>My classes are almost always in a different file, usually a file for each class, but for smaller classes I might group two or more in a single file if they are related to each other.
Hi...
yours, Marcus
I get wary of this now. Libraries named common, utilities, utils and misc seem to end up as disorganised dumping grounds. I think it is better to split libraries up with meaningful names, even if small. If everything ends up bitty then there is probably a better way to group them into modules than the current design.Ixplodestuff8 wrote:I usually have a file called common.php that has all commonly used functions,
yours, Marcus
- Ixplodestuff8
- Forum Commoner
- Posts: 60
- Joined: Mon Feb 09, 2004 8:17 pm
- Location: Queens, New York
Actual functions (and more commonly classes) that are meant to be reusable and aren't project specific always get their own file in the folder where I store such things, so in storage they are pretty well organized.
When I'm working on something however, I find having dozens of files for every little function too cubersome, I copy the things into the common.php, so it isn't a dumping ground since everything is used by the current project by more than a few pages, and less commonly used functions do get their own files (or I group some into a file) so they aren't loaded unless needed.
When I'm working on something however, I find having dozens of files for every little function too cubersome, I copy the things into the common.php, so it isn't a dumping ground since everything is used by the current project by more than a few pages, and less commonly used functions do get their own files (or I group some into a file) so they aren't loaded unless needed.
Hmm, sounds like I'm on the right track. Until fairly recently I just threw everything into the same page file. Obviously, this caused chaos when revisiting the code after a couple of months, hence 1, 2 and 4 becoming law. I wasn't really using functions either (I know, I know, I am pretty new to PHP.)
Now, though, I'm placing site-wide functions into one file, section-wide functions in another, and page-specific functions in their own files. It's pretty much the same route I took with CSS.
Next step, classes ... I'm shaking as I speak!
Now, though, I'm placing site-wide functions into one file, section-wide functions in another, and page-specific functions in their own files. It's pretty much the same route I took with CSS.
Next step, classes ... I'm shaking as I speak!
Last edited by dartcol on Mon Apr 12, 2004 9:11 am, edited 1 time in total.
Have a hunt around on phppatterns.com.dartcol wrote:Next step, classes ... I'm shaking as I speak!
- llanitedave
- Forum Commoner
- Posts: 78
- Joined: Thu Jan 15, 2004 11:24 am
- Location: Las Vegas, NV.
Back to the question about making everything a function --
I can see that it's a good idea, but that if you do that it makes it doubly important to write self-commenting code, and if the functions go in separate files, make sure the comments tell you where the file is!
I've wasted a lot of time trying to figure out code that looked really nice in the main logic, but then it took me forever to track down the locations of the individual functions.
The code wasn't spaghetti, but the function placement sure was!
Also, when the function itself is in a different file from the code that calls it, the arguments and returns of that function need to be really clear. Otherwise, I have to keep jumping back and forth between multiple files just to follow one process!
I'm just starting to use classes, but it looks like the same caveats hold for them as well.
I can see that it's a good idea, but that if you do that it makes it doubly important to write self-commenting code, and if the functions go in separate files, make sure the comments tell you where the file is!
I've wasted a lot of time trying to figure out code that looked really nice in the main logic, but then it took me forever to track down the locations of the individual functions.
The code wasn't spaghetti, but the function placement sure was!
Also, when the function itself is in a different file from the code that calls it, the arguments and returns of that function need to be really clear. Otherwise, I have to keep jumping back and forth between multiple files just to follow one process!
I'm just starting to use classes, but it looks like the same caveats hold for them as well.
I am using classes in both VB and Php. But somehow, the VB classes are much easier to use mainly thanks to the IDE enforcing more uniform class structure. I have two questios there:
- is there php code editor specifically oriented on handling classes?
- Php5 is supposed to be more OOP than 4. I have not yet used it, anybody has experiences with the Php5 objects?
Thank you.
- is there php code editor specifically oriented on handling classes?
- Php5 is supposed to be more OOP than 4. I have not yet used it, anybody has experiences with the Php5 objects?
Thank you.
-
malcolmboston
- DevNet Resident
- Posts: 1826
- Joined: Tue Nov 18, 2003 1:09 pm
- Location: Middlesbrough, UK
-
d3ad1ysp0rk
- Forum Donator
- Posts: 1661
- Joined: Mon Oct 20, 2003 8:31 pm
- Location: Maine, USA
ok.McGruff wrote:malcolmboston wrote:Dont use functions for the sake of it, i rarely use functions because i find it much easier in most instances to do it without![]()
I'd strongly recommend that everything is wrapped up in a function. Better still, in classes. This has all been covered earlier in the thread.
Code: Select all
include("functions.php");
$myobj = new myClass();
$myobj->connect();
$myobj->print_html();
$myobj->print_head();
$myobj->print_title("My website");
$myobj->print_endhead();
$myobj->print_body("blue");
$myobj->print_content("page1");
$myobj->print_endbody();
$myobj->print_endhtml();
$myobj->disconnect();Code: Select all
class myClass {
function connect(){
//do connection stuff
}
function print_html(){
echo "<html>";
}
function print_head(){
echo "<head>";
}
function print_title($title){
echo "<title>".$title."</title>";
}
function print_endhead(){
echo "</head>";
}
function print_body($bgcolor){
echo "<body bgcolor="" .$bgcolor. "">";
}
//etc etc
}That was my long way of saying, functions and classes aren't always needed. Sometimes linear code is just fine.
Loose code in the global scope works but it's not a good way to program.
Without fns or classes you'll find yourself repeating the same code again and again rather than using something ready-rolled from your library. Also, with a library, you can make one edit to instantly update all scripts rather than have to edit many files.
Fns and classes, re-usable or not, simply make code better organised, more layered & modular, and therefore easier to read and to maintain. For anything but the simplest of projects, this is essential. Fns are a start but really you should use OOP if you are developing server apps. The benefits are enormous although it will take a little while to suss it out properly. It takes a little bit of experience to learn how to "usefully encapsulate" parts of a program and how to make classes work together.
The example you posted above isn't much of an argument for OOP, as you say. Static html would normally be defined in an html file. In the simplest of templating systems, this would be included somewhere and page vars echo'd out in the html template. A database connection would normally be a separate class (or fn) of its own rather than being defined as a class method (the connection code is not readily re-usable = bad encapsulation).
Iterators and the Decorator pattern are a good example of the power of OOP. Suppose you have a search script which returns a collection of unranked results (an iterator). It's very simple to decorate with a Ranker class to add a rank key to each member of the collection:
A decorator basically provides the same interface as the decorated class, but adds something extra. A common iterator interface is:
reset
isValid
next
getCurrent
getKey
So, a Ranker decorator might look like this:
The decorator uses the iterator's interface for reset, isValid, etc, but amends the value returned by getCurrent (adding a rank key in this case).
Decoration is very flexible: you can easily swap a different Ranker class which has a different ranking algorithm. Or you could declare the _rank() method as an abstract interface and use inheritance to create different ranking systems (derived classes overide the abstract interface). The code which calculates rank is clearly delineated in its own method and therefore easy to find, test and edit.
A bit more decoration, this time a Table class which will print collection rows in a table, allows you to present the results (and the new rank key):
Again, different presentation classes can be swapped in and out very easily. Decorated iterators are very powerful and flexible.
phppatterns.com has more info on Decorator and other patterns.
Without fns or classes you'll find yourself repeating the same code again and again rather than using something ready-rolled from your library. Also, with a library, you can make one edit to instantly update all scripts rather than have to edit many files.
Fns and classes, re-usable or not, simply make code better organised, more layered & modular, and therefore easier to read and to maintain. For anything but the simplest of projects, this is essential. Fns are a start but really you should use OOP if you are developing server apps. The benefits are enormous although it will take a little while to suss it out properly. It takes a little bit of experience to learn how to "usefully encapsulate" parts of a program and how to make classes work together.
The example you posted above isn't much of an argument for OOP, as you say. Static html would normally be defined in an html file. In the simplest of templating systems, this would be included somewhere and page vars echo'd out in the html template. A database connection would normally be a separate class (or fn) of its own rather than being defined as a class method (the connection code is not readily re-usable = bad encapsulation).
Iterators and the Decorator pattern are a good example of the power of OOP. Suppose you have a search script which returns a collection of unranked results (an iterator). It's very simple to decorate with a Ranker class to add a rank key to each member of the collection:
Code: Select all
<?php
$ranked_results =& new Ranker($terms, $cols, $results);
?>reset
isValid
next
getCurrent
getKey
So, a Ranker decorator might look like this:
Code: Select all
<?php
class Ranker
{
/*
param (object) $results - an iterator (the collection should be a 2D array)
param (array) $cols - list of cols to use in the rank calculation
param (array) $terms - search terms
*/
function Ranker($terms, $cols, &$results)
{
$this->it =& $results;
$this->terms = $terms;
$this->cols = $cols;
}
function reset()
{
$this->it->reset;
}
function isValid()
{
$this->it->isValid();
}
function next()
{
$this->it->next;
}
function getCurrrent()
{
$row = $this->it->getCurrent();
$row['rank'] = $this->_rank($row);
return $row;
}
//////////////////////////////////////////
// PRIVATE //
//////////////////////////////////////////
function _rank($row)
{
// ranking algorithm here
// uses _isRankable method to check which cols in $row should be used to calculate rank
}
/*
param (string) $col - a column name
return (bool)
*/
function _isRankable($col)
{
return in_array($col, $this->cols);
}
}
///////////////
// END CLASS //
///////////////
?>Decoration is very flexible: you can easily swap a different Ranker class which has a different ranking algorithm. Or you could declare the _rank() method as an abstract interface and use inheritance to create different ranking systems (derived classes overide the abstract interface). The code which calculates rank is clearly delineated in its own method and therefore easy to find, test and edit.
A bit more decoration, this time a Table class which will print collection rows in a table, allows you to present the results (and the new rank key):
Code: Select all
<?php
$table =& new Table(new Ranker($terms, $cols, $iterator));
$html = '<table>';
for($table->reset(); $table->isValid(); $table->next())
{
$html .= $table->getCurrent();
}
$html .= '</table>';
?>phppatterns.com has more info on Decorator and other patterns.
Last edited by McGruff on Tue Aug 09, 2005 4:04 am, edited 1 time in total.
-
malcolmboston
- DevNet Resident
- Posts: 1826
- Joined: Tue Nov 18, 2003 1:09 pm
- Location: Middlesbrough, UK
i agree completely, however, i think alot of newcomers (og which i am one) tend to use functions when it really is'nt necessary, if i create a piece of code and think, yeah mal, ill be using that a few times, then ill wrap it in a function, it when people create a function for absolutely n apparent reason but to self - satisfy that does my head in.McGruff wrote:Loose code in the global scope works but it's not a good way to program.
Without fns or classes you'll find yourself repeating the same code again and again rather than using something ready-rolled from your library. Also, with a library, you can make one edit to instantly update all scripts rather than have to edit many files.
Fns and classes, re-usable or not, simply make code better organised, more layered & modular, and therefore easier to read and to maintain.
for eg a DB connection, why oh why?
Code: Select all
<?php
require ("database_conn.php");
?>I just tend to see in various projects that functions often used when they really are'nt needed.
Or maybe its just my love for the "step-by-step" programming way, i dont know, functions are great, i use them often, but alot of the time i see no real gain
just my $0.02
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:
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:
(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.
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;
}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:
Code: Select all
if(isAuthorised($user))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();
}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.