This page outlines our best practices for programming within Drupal. It concerns higher level issues than those dealt with in the Coding Standards document or the Configuration & Usage Best Practices page(s).

The purpose of these pages is not to teach one how to program, but to teach one how to become a better programmer within this framework. Many people can write code, but many of those people do not know that there is a science to programming for Drupal. Why are speed and performance so important? Why document code? Why is this commonly used code snippet actually a mistake? These questions and so many more are answered and explained below.

Proposed topic outline

  • Writing efficient code
    • Using recursive functions
    • Engineering fast code
    • Avoiding unnecessary coupling
  • Writing code that comments itself
  • The necessity of documentation
  • Naming your functions
    • Using private functions
  • Using global variables
  • Making your modules extensible
    • Reference bigger logic in hook functions rather than placing all logic in hook functions.
    • Writing hook functions and theme functions
    • When should you build an API for your module and how to do this
  • OO code versus procedural and where Drupal stands on this
  • Links to useful documentation on PHP programming best practices, e.g. http://www.odi.ch/prog/design/php/guide.php
  • Database specific considerations
    • e.g. how to store information efficiently, use of the system table, the watchdog table, etc
  • Programming pitfalls to avoid
    • Creating code that already exists
    • Overusing if-else, switch-case, and try-catch
    • The dichotomy of the ternary operator
    • Not using a code repository to keep track of changes to your files.
    • Creating duplicates of files in order to prevent overwriting changes.

Comments

dww’s picture

Sure, you can/should avoid needlessly inefficient code. However, don't make the mistake of preemptively optimizing everything. Many of your functions won't be called in performance critical situations. It's far more important for your code to be clear and understandable than it is for every last function to be optimized with obfuscated logic and code.

A) When you start writing the code, you're likely to be wrong about where the bottlenecks are, and you'll spend time optimizing something completely irrelevant when some other function is what really needs your attention.

B) The complicated logic for your "optimization" might be optimizing for the wrong problem. Maybe the really slow thing is you have a query that needs a DB index, and the processing on the results of that query are dwarfed by the cost of retrieving the data in the first place. You really need to understand what the problem is before you try to fix it.

C) The additional complication in your code will make debugging or extending the code more difficult. In the vast majority of cases, the extra cost in human developer time far outweighs the minor savings in computational power that your "optimization" made. Computers are fast and cheap. Humans are slow and expensive.

D) Correctness is always more important than speed. First write your code so it provides the correct results. Often, that's enough of a challenge. ;) Once it actually does what it's supposed to, you can use a profiler to see if there are problem spots that can be fine tuned. But focus on correctness first.

___________________
3281d Consulting

dww’s picture

If something needs to be optimized, in a large majority of cases, the only optimization it needs is to cache the expensive result instead of recomputing it all the time. Learn how to use static variables (same function being called multiple times for the same page load) and the DB cache (same answer being used on multiple page loads) to save expensive results and reuse them. It's pretty rare that it's worth spending time speeding up the expensive computation -- just save the result and reuse it.

___________________
3281d Consulting

dww’s picture

User input and what your code prints out are basically the root of all security problems. Pay EXTRA attention any time your code is touching user-supplied data or is generating output.

If your code is touching the filesystem at all you should be extra careful about that, too.

Oh, and whenever your code is generating output, consider using a theme function. ;)

___________________
3281d Consulting

beginner’s picture

in hook_update_N() functions, we usually have queries to performs. Sometimes however, there is no query but some other operation is performed (like updating some variables). Instead of returning an empty array, return some useful message this way:

mymodule_update_6000() { // Number your update function according to core compatibility. 

 // do what you have to do.

return array('success' => TRUE, 'sql' => 'We upgraded this and that...'); // don't do: return array();
}

This will prevent having an unhelpful No queries message printed when performing the upgrade.