[Part 3] Learning the Basics of Coding: Best Practices
The third part of my four part article will focus on better coding: Improving the efficiency and logic of your existing code. This skill literally makes the difference between your novice vb.org hack and a full-fledged modification that people will pay for.
The Basics I'm going to fully assume you have read or already have an understanding of [Part 1] Learning the Basics of Coding and [Part 2] Learning the Basics of Coding: Database Interaction. I'm going to assume you have knowledge of types, variables, constants, objects, resources, classes, methods, properties, table structures, etc.,. If you don't, you're probably going to get lost. ;) PHP PHP is a fast language, capable of performing countless operators in microseconds. However, when poorly coded, something that should have executed in .006 seconds may end up taking .06 seconds. Don't think that's a big difference? Then leave the article - because that's slower by a factor of 10. loops Knowing which type of loop to use may seem trivial, but it's like using the wrong type of screwdriver or wrench. Sure, it'll get the job done, but it's going to take longer and waste more energy. Here are some general rules when trying to figure out what type of loop to use: for is for when you know how many times you want to execute a loop. PHP Code:
while is when you aren't sure how many times, but you want to loop until a condition is met. PHP Code:
foreach is generally just for looping through an array. PHP Code:
Though all loops have their differences, they all have their similarities too: Do not use count() or its alias sizeof() in any loop expression. PHP Code:
PHP Code:
Now you may have noticed I am consistently pre-incrementing instead of post-incrementing my $i. Why? It's about 10% faster. Pre-increment where possible! Let's move on to another common loop problem. Can you spot it? PHP Code:
PHP Code:
functions Calling user-defined functions is expensive. Whenever possible, don't be afraid to inline a function. PHP Code:
PHP Code:
Now I feel obligated to mention that you shouldn't inline all user-defined functions you possibly can. This is just silly. You should only do this in obvious cases where the function is either hardly used, or is so short it just doesn't make sense. Functions centralize your code and make life easier. Don't throw away a cup because you can drink from the tap! But DO get rid of that old cup your great-aunt gave you that no one ever uses yet it takes up the room of 3 normal cups. Secondly, don't get cocky and try to inline built-in functions, either, because that will be counter-productive. Built-in functions use optimized C code and you're not going to beat that with PHP. Another problem is sometimes you don't need to use a function at all! You can use a language construct which are faster than functions! PHP Code:
PHP Code:
use the right function Don't use preg_split instead of explode when you don't need regular expressions. This goes for any function that supports regex. If you aren't using regex then use an alternative. e.g: str_replace instead of preg_replace. freeing memory This should be obvious, but it's something that isn't done as often as it should (sometimes I find code with arrays that should have been unset a long time ago, but that's not even the bad part - the bad part is it's my code.). PHP Code:
PHP Code:
initialize! This is such an underestimated coding practice. Whenever you are using a variable or an array element you should always be sure it exists before doing anything besides assigning a value to it! Why? Keep reading! PHP Code:
logic One thing novice coders often do is making a mess of their logic (I do that a lot, too, actually). Examples include evaluating the same expression multiple times in a script, within an if condition, redundant code, etc. There's a popular principle called "DRY"; it stands for don't repeat yourself. PHP Code:
PHP Code:
Let's take it up a notch: PHP Code:
Let's look at a few things first. We have $access = true twice! Certainly we can refactor the code to remove this redundancy? Secondly, it seems we still have not initialized $access! If a user meets none of those conditions then there's a possibility he may get unauthorized access! PHP Code:
Thirdly, look at the nesting. For such simple checks do we really need double nested code? Certainly not! So how would you rewrite this code better? PHP Code:
misconceptions I've taken the time to find out many optimization tips for PHP and have found that a few of the more popular ones are absolutely false. I'm going to include them in here because part of writing good code actually involves knowing what good code is and is not. single quotes vs. double quotes There's no noticeable difference in performance between using single and double quotes. Single quotes is indeed a bit faster but the percentage is < .01%. If you want to shave a nano-second in parsing time then by all means convert all double quotes to single quotes. Personally, I'm not going to. As a side note: I use single quotes whenever possible but if double quotes make my life easier I will not hesitate to use them. PHP Code:
Don't. You'll waste far more time pressing the backspace button then the amount of processing time saved will ever come close to. In fact, I encourage consistent indentation, spacing and commenting. Keep your code clean, neat, and understandable. PHP Code:
The practice of rewriting variables, constants, functions, classes, etc,. to use as little characters as possible. Similar to the above: Don't. "Keep your code clean, neat, and understandable." general tips Contrary to the above, I've also taken the time to confirm many common optimization tips.
Going to assume we're in a vB enviornment and that $db is an object, yes? Also going to assume you?ve read [Part 2] Learning the Basics of Coding: Database Interaction, yes? Good! query_first Remember that this doesn't add LIMIT 1. This means that unless querying only one result your query will be inefficient. Why? Imagine you want to buy a bottle of honey. You drive to the database (store), and then you go to the table (aisle), and then you SELECT honey. But wait, you didn't limit yourself to one bottle of honey; you grabbed ALL the bottles of honey. So now you're walking to the check-out with your arm full of bottles of honey and proceed to buy them. Then you drive back home with your bounty of honey and while putting away your groceries you throw out all those bottles of honey and put one inside your cabinet. Understand? If you're going to get more than one result add LIMIT 1! PHP Code:
PHP Code:
But to be terribly honest, if you want to select the last post in a thread you should be doing this: PHP Code:
avoid filesort Sometimes it's unavoidable, but most of the times it is (avoidable). Not sure what I mean? Enable debug mode and look in the extra column. It may take you awhile, but you're bound to see "using filesort" or "using temporary". using temporary The temporary table where rows are being put in has gotten so big that it needs to be sorted on a disk. using filesort A sort that isn't being performed on indexes. Yes, it is horribly named. To avoid these, in 99% of the cases, you need to either fix your query or fix your table structure. You should never be sorting on non-indexes unless the amount of rows in question is a relatively small amount: say < 1000. This is because with so relatively few rows it's going to be faster sorting 1 by 1 then hitting the indexes anyway. PHP Code:
PHP Code:
normalization This is, truthfully, deserving of an article of its own. I may someday decide to make one, but, for now, I'll touch the basics of this VERY IMPORTANT practice. What is normalization? redundancy Take, for example, the following table structure: STUDENT (student_id, name, birthday, gender, class) This is horrible. Multiple classes = multiple nearly identical rows. We want each table to be responsible for one set of data. Let?s rework this a bit. STUDENT (student_id, name, birthday, gender) CLASS (name, student_id) This is better, but still terrible. What if the name changes? What if we want to add more data about the class? We need three tables: STUDENT (student_id, name, birthday, gender) CLASS (id, name) CLASS_STUDENT (class_id, student_id) num_rows Like in part 2, I mentioned that you should always check to make sure you have a mysql resource before doing anything to it. This is the ONLY way I know of to do this without causing a warning, notice, fatal error, blackhole, etc. UPDATE: It seems the fetch_array function actually suppresses errors so num_rows is not TECHNICALLY needed to avoid that nasty error being shown. In fact, I now think it is more efficient to avoid num_rows in cases except where you wish to error out early. Reasoning? It's unnecessary overhead without any difference in actual results. If we weren't within a vB environment I'd fully recommend it but since we are there's no reason to call a function to avoid an error that would be suppressed anyway! PHP Code:
PHP Code:
PHP Code:
[Legacy info] Now why would you want to use num_rows before fetch_array? Besides the error message, let's dig a bit deeper into these functions. http://php.net/manual/en/function.mysql-num-rows.php As you can see, num_rows either returns the number of rows in the result set or false on failure. Now what about fetch_array? http://php.net/manual/en/function.mysql-fetch-array.php It returns an array. There is no false on failure. If you use this function on a non-result set you will get: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in path/to/script.php on line x It should be noted that part of being a good coder is to avoid notices, warnings, fatal errors, database errors, etc. :D [/Legacy Info] Welp! That?s about it. I probably should dive into MySQL more but nothing else comes to mind at this ungodly hour. Let me know what you think! Hopefully a few of the more infamous coders around here read this and soak it in. :D |
woooow
your Learning of the Basics is the best |
Well I'm a bit embarrassed. :(
It's been pointed out to me by a better coder that the vB function "fetch_array" suppresses errors so it's actually redundant to check with num_rows. That's what happens when you assume things! I've updated the article to reflect this and changed my recommendation over this. I'm going to benchmark error suppression and num_rows later to see if vB using error suppression is actually faster. |
for one liner codes i prefer using ternary operators over if/else statement.
So, this code PHP Code:
PHP Code:
|
Nothing wrong with ternaries, I use them all the time. :)
|
very nice priceless article
reserved .... |
I followed the first part and the second and third of the Coding cycle, but I think it lacks other lessons to understand significantly in this area
|
All times are GMT. The time now is 08:44 AM. |
Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information | |
---|---|
|
|
More Information | |
Template Usage:
Phrase Groups Available:
|
Included Files:
Hooks Called:
|