Clean code and refactoring

Embed Size (px)

Citation preview

Clean Code and Refactoring

Yuriy Gerasimovemail: [email protected]: ygerasimovskype: yuriy_gerasimov

d.o.: http://drupal.org/user/257311

Disclaimer

Not rules but recepies

You are not the last person who will look at this code

Leave the code in better shape that you found it

Debates are welcome

Learn PHP and Drupal functions

Build array (5 => 5, 6 => 6, , 10 => 10);drupal_map_assoc(range(5, 10));

Sort form elementuasort($form, 'element_sort'); // by #weight

uasort($form, 'element_sort_by_title');

Validation: valid_email_address(), valid_url()

Get all keys not prefixed with # for (element_children($form) as $key) {}

Names

Names

Variables, classes nouns. Methods, functions verbs

Shorter variable name for local scope ($i)

One name per concept ($user, $account, $person, $site_visitor)

Domain names ($student, $course, $lesson...)

Patterns names (singleton, visitor )

Funciton name prefixes isSomething(), setSomething(), getSomething(), doSomething()

Constants

Use constants to describe what static vars meanif ($user->uid == 2) if ($user->uid == USER_SUPER_ADMIN_UID )if ($user->uid == self::USER_SUPER_ADMIN_UID)

Function names
(double underscore)

Functions

Functions should do one thing and be small and clean. Example menu_execute_active_handler():Checks whether site is online or not

Executes menu callback

Deliver callback result

_menu_router_build() has more than 200 lines!

Functions

Group arguments to eliminate number of arguments

Pass structures that function is going to alter if results are complex

Functions

Groupped arguments, apply default values

Function

Helper functions underscore prefix (_menu_delete_item())

Group helper functions into classes with static methods. Autoloading.

Comments

Comments get outdated first!

Comments should be written when we fail to find good variables / function names

Think twice about names before writing a comment explaining your intentions

Why it is done this way and not What is this

Spaghetti code

Return result early (continue and break cycles)

Spaghetti code (refactored)

Use switch construction

(example from locale.inc)

Return conditions

simply return value (return ($a == $b); )

backup_migrate/includes/destinations.file.inc

Long conditions

one condition per line

operators in front

identation

Use Exceptions

Use Exceptions

_io_checkout_page_ajax_validate__if_email_exists()

Use Polymorphism

D8 plugins system

Views handlers

Take a look at function names in form.inc:form_type_checkbox_value(), theme_checkbox(), form_process_checkbox()

form_type_select_value(), theme_select(), form_process_select()

Organize your code right

Separate files

Follow traditions

1000 lines you do it wrong

Organize your code right

Sort by source and not by name

First hooks implementations, then helpers

Use IDE collapsed view

Do not Repeat Yourself (DRY)

panels/includes/plugins.inc

DRY

panels/includes/plugins.inc

Functional programming

anonymous functions (closures) php 5.3.0

variables can be functions

functions can be passed as arguments

Functional programming

Functional used

Functional used

Refactoring loves tests

Some tests better than no tests at all

Use DrupalUnitTestCasefor unit testing (fast)

To read

Robert C. Martin. Clean Code: A Handbook of Agile Software Craftsmanship

Martin Fowler. Refactoring: Improving the Design of Existing Code

http://www.slideshare.net/rdohms/bettercode-phpbenelux212alternate

http://london2011.drupal.org/conference/sessions/code-stinks

http://chicago2011.drupal.org/sessions/aphorisms-api-design