CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

Neil Crookes - Bake Master Class

After an introduction to bake, and what this shell means within CakePHP, Neil went on to explain and show examples of the code generation templates and capabilities provided by default. The bake shell is broken down into tasks and a main shell. These tasks separate out the logic required for various main task subsets including controller, model and view baking, amongst others. The main bake shell is found in the CakePHP directory cake/console/libs/bake.php. Tasks used by this shell are defined in the $tasks variable. Bake extends the CakeShell class and executes calls based on whether the users want interactive or non-interactive tasks through the __interactive() and bake() methods respectively. Neil made the suggestion that a persistent MySQL connection might be a good idea to stop database connection timeouts. Following this introduction, a great walkthrough of customisation of the bake process and templates was demonstrated. This included the addition of a new Shell that allows for multiple bakes to be done automatically of the same type. Neil has been kind enough to host the code, and you can find this over at the CakeFest downloads page.

Felix Geisendörfer - Recipies for succ...

Felix liked to Get Things Done™. And through experience and what became an interactive idea and experience sharing productivity session, he explained mechanisms and methods that he has used to achieve the best results for projects in the shortest time possible. Communication. While this means your team should be in contact, and that those contact points should be quality communication, it doesn't mean that instant communication is a requirement. Communication mechanisms would ideally be: decentralised and work in an offline capacity (at least for partial functionality). Return on investment is an interesting statistic to consider when responding to or creating a new item of communication. Provide a concise message. Enough to ensure the intention of the communication is clear, and ambiguity is reduced if not eliminated. Email is a great tool, especially for the following: Timezone differences, announcements, spawning debates that require discussion, emergency notifications / reports, mailing lists, shared email accounts and automated reporting / information. Using Email over an instant messaging mechanism for spawning debates allows contributors to formulate a constructed response. This can assist the better understanding of some ones input to the discussions, as instant messaging can be difficult for items that require discussion. Instant messaging has good and bad traits:

  1. Good Stuff
    1. Instant
    2. Group Chats / conference calls
    3. Varying methods of communication
    4. Various formats (text, voice, video)
  2. Bad Stuff
    1. Distracting (interrupts workflow)
    2. History tracking / compatibility
    3. Citations / logs
Task management helps keep projects on track. However the truth is that there is no overall solution. We do the best we can to manage all the information we need to be successful, through a variety of tools.
Problems that exist are:
  1. Getting tasks into the system (May be the laziness of users)
  2. Tracking tasks that manage to make it into the system
  3. Getting those tasks done
Tools available:
  1. Pen and Paper (plain text files)
  2. OmniFocus (Mac Only)
  3. Lighthouse / TheChaw
One of the CakeFest attendees suggested post-it notes on a wall, so that the tam involved in pursuing the tasks can have some physical interaction with them, making the experience more productive and fun.
So with this in mind, Felix quickly went over what has worked for him and his company:
  1. Check emails twice a day only.
  2. Turn off instant messaging tools in the morning
  3. Set clear distinct goals for the day, and achieve those goals
How to fail at unit testing. Felix described some common myths about unit testing, how he feels failing is possible and how to improve your approach.
Failed unit testing can come from factors such as: Attempting to reach 100% code coverage all the time, misunderstanding test driven development and expecting that all developers / users can write unit tests.
Success can be achieved by approaching projects with a top-down approach, incorporating performance tests and re-factoring code. Continuous integration was presented in a basic format, going through the setup that Felix has found useful, making use of git post-receive hooks, and parsing of results to send notifications when necessary. In terms of increasing productivity and performance overall, Felix has begun testing Pair programming, where there is one computer for two people, and the development process is discussed ongoing, meaning that a lot of bugs an individual would miss are caught by the secondary developer on the first code pass. Virtualization though open source and free products like VirtualBox and VMWare Server are worthwhile investigating for cheap scaling testing during development.
Version control was introduced, referencing the change of CakePHP to git from subversion, pointing out the benefits including: decentralization, can work offline, can work semi-online though the use of adhoc networks, its very fast to operate and its more intelligent with the storage of information. Following this, a detailed example of three separate working repositories was demonstrated.

Joël Perras - Demystifying Webservices...

Joël's presentation on Web Services and CakePHP identifies important and interesting points that really demystify both implementation of datasources, and what web services mean for developers trying to take advantages of their offerings. A Web Service is a defined interface. The interface is made known and public, however the implementation may not be known (and its not really important). The developer should be interested in the data supply and the data returned from the web service. Various mechanisms are available for communicating with a web service. Such as: RPC, SOA, REST and more. Much of this presentation covered best practices, better practices, and why people tend to make decisions like implementing components when they really want datasources, as well as implementing datasources, and going about the implementation the wrong way. In the case of web services datasources implementation, curl is presented as a good example of something that works, but a better solution is available through the use of HttpSocket. HttpSocket being one of the CakePHP core libraries provided, allowing a complete implementation of Http communication, extending the CakeSocket class. Authentication and Authorization options were presented, with specific reference to OpenID and OAuth. Authentication and Authorzation are part of the application flow graph. This means implementation should be at the controller level, and in terms of implementing easily managed pluggable sections of code in cakephp converntions, this means a component. Data Sources are the closest layer to the actual data. Correct implementation of a data source will allow models to connect and communicate in a transparent fashion, meaning easy access to data in a standard way. The basics of a datasource should implement the following: __construct, listSources, describe, create, read, update, delete as well as defining $_schema. Some great datasource examples can be seen in the core. When implementing a datasource, to ensure maximum use and compatibility, try to make use of CakePHP libraries such as HttpSocket in the place of curl. Google Charts was presented as a good example of what should not be implemented as a datasource. The data in this instance is handed by some other data source, and the formatted chart request is sent with an image response supplied. This is more appropriate for a helper than a datasource. Joël mentioned that he has a partial google charts helper that he would be willing to share if someone asked.

Garret Woodworth - CakePHP then, now a...

Beginning with an overview of the CakePHP project, changes and evolution of direction and development team members, Garret provided a great overview of where the project stands, and how it has grown to be as successful as it has today. Garret gave a great description of the types of participation that are seen in open source teams, and these are relevant to CakePHP. He also described the attributes that make a good team member in such projects. Contribution Levels:  

  1. No effort (tickets are subimitted with little explanation)
  2. Some effort (well explain the ticket, and have attempted to reproduce the issue to confirm it)
  3. Attempted effort ("Some effort" with patch)
  4. Good Effort ("Some effort" with test case)
  5. Ultimate effort ("Some effort" with test case and patch)
Good team member attributes:
  1. Communicate often.
    1. To keep people motivated and interested on working for / with a project, its important to talk about what they want to work on, and what they feel they can assign some of their time to. Developing for open source shouldn't feel like "work".
  2. Show diffs of code, and get feedback to ensure the quality of work overall for the project is as high as it can be.
  3. Think longer about the problems faced, and as a result, write code faster.
  4. Details, Details, Details.
  5. Give back to the project more than you take from it.
  6. Think outside the box, and be creative.
CakePHP is growing, and the stats presented spoke for themselves, with America, Japan, India, France and Germany being the top countries at the moment in terms of hits on the CakePHP websites at the moment. This is resulting in 24% unique new visitors per month. A statistics that is truly extraordinary.
  With the feature development and more developers available to the CakePHP Core Development Team, git has been implemented widely and is the future of version control for source code for the CakePHP project. This should ease feature development, and remove some of the pain associated with merging with Subversion. Announcements! Garret announced new versions of CakePHP, currently being actively developed by the CakePHP core development team. Version 1.3 is available on code.cakephp.org and is a Step up with several enhancements over 1.2. Most notably Bake, Session, Javascript changes, Inflector and some library renames. Deprecated methods were also removed. There is even a wiki page describing migration steps from 1.2, to help ease the transition. CakePHP 2.0 was also announced. This is a huge move, stepping forward to drop PHP4 support, and move towards PHP5 Strict compliance, and much better Object Orientation and performance throughout. This new version is in active development, and code is also available on code.cakephp.org but does not yet have a stable release for download. code.cakephp.org was launched at the time of the Keynote, and is designed to consolidate systems. it's running on thechaw.com code, and uses git for the main projects. Its available now for everyone to use. Closing things up, Garrett urged the community to "get involved". CakePHP isn't where it is today without the extensive help and support of the community. There are a number of ways that you can contribute, and he mentioned the following in particular:  
  1. Interact with the community and the core developers.
  2. Get interested in Bakery 2.0 which is currently under development
  3. Plugins and Plugin Server
  4. Forks
  5. Join #cakephp-bakery on the IRC server
 

Benchmarking requestAction

Now there has been a lot of discussion in the past few months about requestAction() and how it can very easily create a negative impact on your application. In fact I even wrote such an article myself. However, its high time that someone did the number crunching to really see if requestAction() is actually as slow as we all seem to think it is. So onto the testing method and the results.

Testing method

To test this theory I used a small CakePHP application and the SVN head (revision 8064) of CakePHP. I used a simple sample application with 2 controllers and 2 models. My model method directly returned the results without touching the database, so that database retrieval time and model processing would not be a factor in these tests. As I was only interested in the performance implications inherent in requestAction() itself, I wanted to remove the variance created by connecting to a database. I set debug = 0, and used basic file caching. After warming up the cake core caches, I tested 4 different controller actions.
  • Using Relations / ClassRegistry::init() - The method I originally proposed, and often touted as the 'best' solution to requestAction()
  • Using RequestAction with a string URL
  • Using RequestAction with and Array URL
  • Using a cached RequestAction - This more accurately simulates how we use requestAction at CakeDC.
Benchmarks were generated with Siege I used 10 concurrent users with 110 reps each. My local development web-server is running Apache 2.2/PHP 5.2.6 o n a 2.6GHz Core 2 Duo iMac with 2GB of ram. I ran each test 3 times and took the best result of each.

Using model relations / ClassRegistry::init()

First up was my originally proposed solution of using model relations to access the correct information. I used the following command and got the following results. siege -b http://localhost/benchmark/posts/using_relations Transactions: 1100 hits Availability: 100.00 % Elapsed time: 63.21 secs Data transferred: 1.50 MB Response time: 0.55 secs Transaction rate: 17.40 trans/sec Throughput: 0.02 MB/sec Concurrency: 9.60 Successful transactions: 1100 Failed transactions: 0 Longest transaction: 1.76 Shortest transaction: 0.10

Using RequestAction with a string URL

Up next was using request action with a string url. String URL's are often the slower way to perform a requestAction as parsing the URL string is one of the more expensive operations in request dispatching. I used the following command and the best results were. siege -b http://localhost/benchmark/posts/using_requestaction Transactions: 1100 hits Availability: 100.00 % Elapsed time: 64.60 secs Data transferred: 1.51 MB Response time: 0.57 secs Transaction rate: 17.03 trans/sec Throughput: 0.02 MB/sec Concurrency: 9.72 Successful transactions: 1100 Failed transactions: 0 Longest transaction: 1.76 Shortest transaction: 0.11

RequestAction with an Array URL

Up next is requestAction() witn an array url. Using an array URL is supposed to expedite the dispatching process as it bypasses much of the parameter parsing done by Router. This theory turned out to be true, as Array URL's clocked in marginally faster than their string counterparts. siege -b http://localhost/benchmark/posts/using_requestaction_array Transactions: 1100 hits Availability: 100.00 % Elapsed time: 64.08 secs Data transferred: 1.53 MB Response time: 0.57 secs Transaction rate: 17.17 trans/sec Throughput: 0.02 MB/sec Concurrency: 9.78 Successful transactions: 1100 Failed transactions: 0 Longest transaction: 1.66 Shortest transaction: 0.11

RequestAction using Array URL's and Caching

In my mind this was going to be the most performant requestAction option, due to the cached nature. The results were as expected with this method clocking to be only slightly behind the relation call. It is important to note as well, that this test does not reflect the time savings earned from not having to make an additional query/ round of result parsing. In a real world situation, the savings of using a cached element would be magnified by the cost of the query. siege -b http://localhost/benchmark/posts/using_cached_requestaction Transactions: 1100 hits Availability: 100.00 % Elapsed time: 63.60 secs Data transferred: 1.52 MB Response time: 0.56 secs Transaction rate: 17.30 trans/sec Throughput: 0.02 MB/sec Concurrency: 9.62 Successful transactions: 1100 Failed transactions: 0 Longest transaction: 1.77 Shortest transaction: 0.09

Results Summary

In case you quickly scanned through the full results here is a summary of what happened.
Method Requests per second (mean) Total time taken (seconds)
Using relations/ClassRegistry::init() 17.40 63.21
Using requestAction and string urls 17.03 64.60
Using requestAction and array urls 17.17 64.08
Using cached requestaction 17.30 63.60
In closing requestAction() can be slower than a direct method call. There are some benefits to using requestAction though.
  • You have the opportunity to reduce the number of repeated lines of code by putting the requestAction inside the element. In doing so, you create an encapsulated element, that can be included anywhere without having to worry about having the correct method calls in your controller.
  • You can more easily cache the element. By using requestAction in conjunction with element caching you have an easy to use, simple to implement caching. Getting the same results with model method calls in your controller requires additional caching logic in your models.
  • The potential for increased performance. As we saw in the benchmarks above, a cached element performed almost as fast as the direct method call. This margin will grow when a database query is added into the mix.
Now am I retracting my previous stance on requestAction? No, I still feel that there are many situations where requestAction is the incorrect solution and signals poor application design. However, when the need arises it is good to know that requestAction can be as fast or faster than other approaches when implemented properly. You can download all the files I used for this process and run your own tests as well.

We Bake with CakePHP