Upload
nicolas-perriault
View
69.993
Download
1
Embed Size (px)
DESCRIPTION
These are the slides of the talk I gave at Symfonyday Cologne '09 (http://www.symfonyday.com/)
Citation preview
Nicolas Perriault
30 Symfony Best Practices
30 Symfony Best Practices
SymfonyDay ’09, Cologne, GermanySeptember 4th, 2009
30 Symfony Best Practices
Nicolas Perriault
Best Practices?A Best practice is a technique, method, process, activity, incentive or
reward that is believed to be more effective at delivering a particular outcome than any other technique, method, process, etc. The idea is that with proper processes, checks, and testing, a desired outcome
can be delivered with fewer problems and unforeseen complications. Best practices can also be defined as the most
efficient (least amount of effort) and effective (best results) way of accomplishing a task, based on repeatable procedures that have
proven themselves over time for large numbers of people.
-- Wikipedia, august 2009
2
30 Symfony Best Practices
Nicolas Perriault
Best Practices?
Making. Stuff. Efficient.
3
30 Symfony Best Practices
Nicolas Perriault
Best Practices?
• Moreover, best practices in software development and symfony are all about:
• improving communication between developers through standardization
• enhancing security, maintainability, portability and interoperability by increasing code quality
4
30 Symfony Best Practices
Nicolas Perriault
Disclaimer• These best practices are not sorted by
importance, nor criticality
• All best practices listed here are debatable, at least because they’re based on my own experience
• There are always exceptions
• Some best practices are not symfony-specific ; “Zake Igniter” developers, you can take some notes too.
5
Nicolas Perriault
30 Symfony Best Practices
Let’s begin...
30 Symfony Best Practices
Nicolas Perriault
#0
• Always write “symfony” starting with a small cap.
7
30 Symfony Best Practices
Nicolas Perriault
#0
• Always write “symfony” starting with a small cap.
• Or maybe not (mostly depends on the result of rand(0, 1))
7
30 Symfony Best Practices
Nicolas Perriault
#1• Manage the View within the View
• View is intended to be handled in templates
• Try to avoid the use of the view.yml file
• Try to avoid handling the view from the controller (eeeek) or the model (you’re fired)
• Slots can help (a lot)
8
30 Symfony Best Practices
Nicolas Perriault
#1For example, handling <title> tag and assets:
Note: here the value of $defaultTitle could (should) be handled in an app.yml configuration file
9
30 Symfony Best Practices
Nicolas Perriault
#1
• Remember this: if you’re a graphic designer/integrator, you don’t want to deal with YAML or complex PHP code to manage the presentation
10
30 Symfony Best Practices
Nicolas Perriault
#2
• Always enable output escaping and CSRF protection
• starting with symfony 1.3, they’re enabled by default
11
Nicolas Perriault
GOOD30 Symfony Best Practices
12
30 Symfony Best Practices
Nicolas Perriault
#3• Always call a redirect after posting data
• for security purpose
• for ergonomy
• to avoid duplicates in database
• don’t forget to add a flash message to the end user after every transaction made
13
Nicolas Perriault
BAD30 Symfony Best Practices
14
Nicolas Perriault
GOOD30 Symfony Best Practices
15
30 Symfony Best Practices
Nicolas Perriault
#4• No Propel Criteria or Doctrine_Query
instances, SQL queries and any ORM/RDBMS specific calls should ever be found neither in the templates nor in the actions.
• The more you couple your model to your controllers and views, the more it’ll be hard to change your persistence backend or strategy.
16
Nicolas Perriault
BAD30 Symfony Best Practices
Doctrine_Collection
17
Nicolas Perriault
BETTER30 Symfony Best Practices
Array
18
Nicolas Perriault
GOOD30 Symfony Best Practices
Array (ideally)
19
30 Symfony Best Practices
Nicolas Perriault
#5• Symfony core files should never be
modified to add or change the features they provide, but replaced through the autoloading mechanism, or way better: extended.
• Tweaking the factories.yml file and catching native symfony events can help a lot achieving this goal.
20
Nicolas Perriault
BAD30 Symfony Best Practices
Unused
21
Nicolas Perriault
GOOD30 Symfony Best Practices
22
30 Symfony Best Practices
Nicolas Perriault
#6
• The templates must contain PHP alternative templating syntax, for readability and ease of use.
23
Nicolas Perriault
BAD30 Symfony Best Practices
24
Nicolas Perriault
GOOD30 Symfony Best Practices
25
30 Symfony Best Practices
Nicolas Perriault
#7• Verify cache settings, especially that the
cache is actually enabled in prod environment. Don’t laugh, it happened quite a lot.
• If you use cache, create a staging environment to test the caching strategy if it doesn't exist.
• Better: avoid using cache. No kidding.
26
Nicolas Perriault
GOOD30 Symfony Best Practices
27
30 Symfony Best Practices
Nicolas Perriault
#8
• Use routes instead of raw module/action couple in url_for(), link_to() and redirect() calls.
• Also, default routes should be deactivated by default (at least in apps which don’t run admin-generator 1.0 modules)
28
30 Symfony Best Practices
Nicolas Perriault
#9
• All code comments, phpdoc, INSTALL, CHANGELOG and README files, variables, functions, classes and methods names and more generally the developer documentation, should be written in English.
29
Nicolas Perriault
BAD30 Symfony Best Practices
30
Nicolas Perriault
GOOD30 Symfony Best Practices
31
30 Symfony Best Practices
Nicolas Perriault
#10
• Catch and log exception messages, display human readable error messages to the end user
32
Nicolas Perriault
BAD30 Symfony Best Practices
33
Nicolas Perriault
GOOD30 Symfony Best Practices
34
30 Symfony Best Practices
Nicolas Perriault
#11
• Only deploy production front controllers in production
35
Nicolas Perriault
BAD30 Symfony Best Practices
36
Nicolas Perriault
BAD30 Symfony Best Practices
37
30 Symfony Best Practices
Nicolas Perriault
#12
• Ideally:
• A typical controller method should never exceed ~30 lines.
• A typical controller class should never have more than ~15 action methods.
38
Nicolas Perriault
BAD30 Symfony Best Practices
x~2000 lines on this actions class (the slidescreen size was to short to list them all). Unmaintenable. 39
30 Symfony Best Practices
Nicolas Perriault
#13
• Always apply consistent coding standards.
• Always apply Symfony’s coding standards.http://trac.symfony-project.org/wiki/HowToContributeToSymfony#CodingStandards
40
Nicolas Perriault
BAD30 Symfony Best Practices
41
Nicolas Perriault
GOOD30 Symfony Best Practices
42
30 Symfony Best Practices
Nicolas Perriault
#14
• Session persistence logic should reside in sfUser derived class methods, and only them.
43
Nicolas Perriault
BAD30 Symfony Best Practices
44
Nicolas Perriault
GOOD30 Symfony Best Practices
45
30 Symfony Best Practices
Nicolas Perriault
#15
• Never serialize objects in the session
46
Nicolas Perriault
BAD30 Symfony Best Practices
47
Nicolas Perriault
GOOD30 Symfony Best Practices
Note: of course, a setRecentlySeenProducts() method could have been implemented in the myUser class.
48
30 Symfony Best Practices
Nicolas Perriault
#16
• Always create customized 404 error and 500 error pages
49
Nicolas Perriault
BAD30 Symfony Best Practices
50
Nicolas Perriault
GOOD30 Symfony Best Practices
51
30 Symfony Best Practices
Nicolas Perriault
#17• There should never be any direct use of
sfContext inside the Model layer (eg. sfContext::getInstance())
• Because the sfContext instance you get can differ a lot regarding the used env (cli, test, dev, prod...)
• It would make your code quite untestable
• Yes, it’s hard.
52
Nicolas Perriault
BAD30 Symfony Best Practices
53
Nicolas Perriault
BAD30 Symfony Best Practices
54
Nicolas Perriault
GOOD30 Symfony Best Practices
55
Nicolas Perriault
GOOD30 Symfony Best Practices
56
30 Symfony Best Practices
Nicolas Perriault
#18
• Avoid creating a big generic utility class with many static methods
• It's like reinventing procedural programming or using functions
• Write specialized classes
57
30 Symfony Best Practices
Nicolas Perriault
#19
• Use sfLogger for debugging instead of echoing variable or debug messages
• FirePHP(1) or FireSymfony(2) custom loggers can be more than helpful to debug your app (webservices for example)
(1) http://firephp.org/(2) http://firesymfony.org/
58
Nicolas Perriault
GOOD30 Symfony Best Practices
The FireSymfony Firebug extension for Firefox in action
factories.yml
59
30 Symfony Best Practices
Nicolas Perriault
#20• If source code is managed through a SCM
tool, versioned files should NEVER contain passwords, local paths, etc.
• Files containing them should be added to the ignore directive
• Typical example: the databases.yml file
• Distribute platform-dependent configuration files
60
Nicolas Perriault
BAD30 Symfony Best Practices
61
Nicolas Perriault
GOOD30 Symfony Best Practices
62
30 Symfony Best Practices
Nicolas Perriault
#21• Write unit and functional tests:
• Unit test your business logic (please don’t test symfony or Doctrine again, it’s already done)
• Functionally test the user interface when it’s important (eg. 404/403/401 HTTP codes, security and user authentication, transactions and forms, etc.)
63
30 Symfony Best Practices
Nicolas Perriault
#21Hint: you can write your own functional browser/
tester to avoid duplicate test code
64
30 Symfony Best Practices
Nicolas Perriault
#22
• Never use absolute paths in code, or at least put them in YAML configuration files.
• Make your symfony project portable: use dirname(__FILE__) to point at the symfony libs in the project configuration class.
• You can put symfony lib in a lib/vendor dir.
65
Nicolas Perriault
BAD30 Symfony Best Practices
66
Nicolas Perriault
GOOD30 Symfony Best Practices
67
30 Symfony Best Practices
Nicolas Perriault
#23• Data objects should always be represented
by a slug in urls, not a primary key
• For security: numeric PKs are easily guessable, whereas slugs are not
• For URL usability and SEO: /article/symfony-rulez.html is sexier than /article/123.html
68
30 Symfony Best Practices
Nicolas Perriault
#24• Every application or project specific
configuration variable should be stored in its app.yml file
• You can share project-wide (cross-applications) settings by putting an app.yml file within the root config/ folder of the project
69
Nicolas Perriault
BAD30 Symfony Best Practices
70
Nicolas Perriault
GOOD30 Symfony Best Practices
Default value
71
30 Symfony Best Practices
Nicolas Perriault
#25
• Avoid versioning any generated Base* class file, especially if you want to write reusable plugins or redistribute your work.
• Maybe people will want to extend or add behaviors to your model classes.
72
30 Symfony Best Practices
Nicolas Perriault
#26• Use symfony tasks system for CLI batch
scripts
• Tasks have access to all the symfony facilities
• Tasks are designed for the CLI
• Text output
• Pretty printing
73
30 Symfony Best Practices
Nicolas Perriault
#26
74
30 Symfony Best Practices
Nicolas Perriault
#27• Alter request and response
programmatically by using filters.
• You can use the request.filter_parameters and response.filter_content events too.
• Filters are easy to setup and to debug, whereas events are more clean and powerful. Matter of taste.
75
Nicolas Perriault
GOOD30 Symfony Best Practices
76
Nicolas Perriault
GOOD30 Symfony Best Practices
77
30 Symfony Best Practices
Nicolas Perriault
#28
• Always write a README, an INSTALL and a CHANGELOG file at the root of the project (or the plugin). If open sourced, a LICENSE file is appreciated too.
• And please don’t release plugins under the terms of the GPL license. Symfony Plugin != Operating System
78
30 Symfony Best Practices
Nicolas Perriault
#29
• Share features and modules across applications by writing plugins
• If it’s really cool, release it publicly
79
30 Symfony Best Practices
Nicolas Perriault
#30
• Study other frameworks code!
• They might have good, even better ideas to solve the problem you have
• Even frameworks written in other languages than PHP (Django, Rails, Spring...)
80
Nicolas Perriault
30 Symfony Best Practices
Questions?
Nicolas [email protected]+33 660 920 867
prendreuncafe.com | symfonians.net | symfony-project.org