Understanding internal and external code in Zend Studio

A project in Zend Studio is simply a root folder.

Assuming that the boundaries of the folders subtree delimit internal code is accurate for almost any project at its beginnings, but as time goes by, limitations arise. For example, version and documentation files are not to be considered part of the code of the project.

Zend Studio overcomes those issues by means of the Build Path concept, so that only code that is reachable through the Build Path is internal code. The build Path is then used by Zend Studio for knowing what code to validate. In fact, if you want to exclude some code from the validation check, you have to exclude that code from the Build Path.

Related to the Build Path concept is the Include Path concept. The magic behind “Navigate/ Open Declaration” succeeds for any code that is reachable through the Include Path. If you exclude some code from the Build Path, sooner or later you’ll discover that “Navigate/ Open Declaration” fails for any excluded code. The solution is to add that code as an external source folder.

All of the above makes sense if you consider how Build Path and Include Path are set up. The Build Path is by default anything inside the root folder of the project, and the Include Path is always at least the Build Path. These settings make a standard / simple project work without added configuration. If a project needs fine tuning, then internal code can be defined changing the Build Path, and external code can still be referenced changing the Include Path.

Summary

  • the Build Path defines what is the internal code (by default the project subtree)
  • the Include Path defines what is the code context (always internal code + external code)
  • if you exclude something from the Build Path, chances are that you need to add that something to the Include Path as an external source folder

Example

The build process of Zend Studio finds issues in code from third parties that you host in a library folder of your project. There are so many issues that you can’t easily see your own, and you can’t solve those issues because you want to use third party code “as is”, so that when a new version of that code is available you can simply drop it in place. The solution here is to exclude the library folder from the Build Path and add it to the Include Path as an external source folder.

The above picture shows that the Build Path of a project includes all but the library folder.

The above picture shows that the Include Path of the same project lists the library folder as an external source folder.

Zend Studio Documentation: http://files.zend.com/help/Zend-Studio/configuring_build_paths.htm

Playfish Job Application Test

I’ve recently failed the application for a web developer job at Playfish. After a phone call between Kim and me, Kim made Marius send me a PHP / JavaScript test on Thursday. I sent my solution back the day after and began to wait. I waited 4 days, before sending a whatsup email. Then they came back to me saying that they decided to move on with other candidates. I’ve tried to get some feedback about what was wrong with my solution, but I’m still waiting. Here is the test and my solution.

The test

Marius Berg to Kim, me on Thu, Dec 16, 2010 at 9:49 AM

Hi Andrea

Thanks for applying for the position and taking the time to talk to us.
Sending a practical test, as described by Kim earlier.

Practical test:

—————————

JavaScript / PHP

  • Read the data from attached example
    PHP file into javascript. And represent the data in an HTML UI. Example
    graphics attached.

  • Create a set of countdown timers from
    the awards data. Each of the awards should count down to next_time.
    Once the timer is completed invoke a animated UI presenting the user
    with the award he has received.

  • On award acceptation the javascript
    should post the the data back to a PHP page using AJAX and validate
    that the award is ready for collection as well as validate the awarded
    number. You can chose how to store needed data.

  • Once collected the users data should
    update accordingly in the UI and the timer should restart counting down
    based on the “interval” in the corresponding award array.

Layout:

  • The page should be scaled for view on
    mobile devices ( iOs / Android )

  • Page loading and graphics should be
    optimized for fast loading where possible.

You can use jQuery.

Attached files:

jQuery library, example main screen
and award graphics, as well as an example data file.

Feel free to use other graphics, and
data structure if you feel necessary.

—————————

If you have any questions regarding the test, just email me.

Thanks and best regards
Marius

On 14 December 2010 16:27, Kim Daniel
Arthur wrote:

style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex">Hi
Andrea,

Thanks for taking time to chat today, was great to be
introduced!
As agreed we will send you a practical tech test on thursday
morning which you can spend time over the weekend completing and then
send the code back to us on monday. I’ve CC’ed Marius runs our mobile
development efforts and who will be sending the test  to you and
you will get to speak to about tech stuff next week 🙂
if you have any questions in the meanwhile, feel free to
email.
Cheers,
Kim
webdev.zip
1154K   Download  

Contents of webdev.zip

Contents of data.php

{[ .data | 1.hilite(=php=) ]}

My solution

When I spoke with Kim I made it clear that I never work with graphics, so I was surprised to see graphics as an element of the test, but I thought that the test could be standard for them, so I didn’t complain but asked (twice) if they really wanted me to do graphics. I got no answer. So I simply didn’t do anything with the layout thing.

Files sent back

Demo

Before presenting the contents of any file of my solution, I’d like you to see a short screencast of a demo of my solution. It’s simpler than having a live demo on my server. Note that I made the screencast for this post, I didn’t send it to Playfish.

Contents of playfish-test.css

Nothing to notice here, except the template class (@25-27).

{[ .test-css | 1.hilite(=css,ln-1=) ]}

Contents of playfish-test.html

Elements initially invisible (@19-22, @25) have a style=”display: none;”. On the contrary, the reward popup template (@27-31) is explicitly identified by the template class.

{[ .test-html | 1.hilite(=html,ln-1=) ]}

Contents of playfish-test.js

The “on load” handler (@20-82) binds click handlers to two buttons: Start (@21-67) and Stop (@69-81).

  • The Start handler posts the user name back to data.php (@23-62), marks the game as started (@63), and updates (@64-66) UI elements (playfish-test.html@16-26).
    • The “on success” handler of the post to data.php verifies and extracts received data (@25-44, @48-53), and creates upcoming awards (@54-59).
    • The first next_time received from the server is checked (@55) against the current time so that all awards get a chance to popup. If the first next_time of a given award is in the past, then that next_time is set to now + award.interval (@57).
    • The timeout id is saved (@58) so that it can later be used to clear that timeout (@72-76), in the Stop handler.
    • The timeout handler is bound (@58) to the timeout by means of the makeHandler meta function (@84-87) because a specific call is needed for each award. If it was bound without the meta function, but like this (compare with @134-136) {[ .bad-code | 1.hilite(=javascript,ln-58=) ]} then 4 (the last i value) would be used for each timeout call. The meta function makes each call different.
  • The Stop handler marks the game as stopped (@71), clears current (@77-79) and upcoming (@72-76) awards, and updates (@80) UI elements (playfish-test.html@23-25).

The “on timeout” handler (@121-142) immediately exits (@122-125) if the game is over, otherwise sets the handler (@128-140) for the Accept action (playfish-test.html@30) in the reward dialog (playfish-test.html@27-31), and displays (@141) the dialog.

  • The “on timeout” handler is called many times, the first being set from the “on success” handler of the post to data.php (which is executed by the Start handler), and any other time set from inside the “on success” handler of the post to validate.php (which is executed by the Accept handler).
  • The “on success” handler (@129-139) of the post to validate.php checks the validation result and udpates the status of the game if the award is ready for collection (@131-133), then sets the next timeout for the same award (compare with @58).
  • The “on timeout” handler only sends the Accept event of a given award to the server. Reward value and current user coins are only displayed by the client. After an event is validated the new user coins are displayed as they come from the server.
  • The award showing function (@89-115) clones the template, updates placeholders, sets up fade in / fade out / remove animations, binds the Accept handler to the button, and appends the dialog to the body (another animation effect).

{[ .test-js | 1.hilite(=javascript,ln-1=) ]}

Contents of data.php

Nothing to notice here, except that user data is saved into the session.

(I’ve shortened times for speeding up testing)

{[ .data-php | 1.hilite(=php,ln-1=) ]}

Contents of validate.php

If the awards were into an associative array with keys suitable for identifying them (like playing, winning, friends, completing) one could access them directly in PHP (and save the selection find) but in that case it would be more difficult to manage more or less awards, functionality that is now already implemented in the JavaScript code “for free”.

This code (@26-33) takes control of what the JavaScript code simply displays, thus making sure that the client cannot steal awards or just mess things up.

{[ .validate-php | 1.hilite(=php,ln-1=) ]}

Contents of validate.log

Here are two consecutive logs that show validation input / output. The first log tells that a “Reward for completing” accept event has been generated in the client by the “Miho San” user, which currently holds 1483 coins. The second log tells that the award was ready for collection and now the user holds 2473 coins (= 1483 + 990).

46b6bab34d828616a0970222380bd180 - 2010-12-17T17:19:37+0000 - array (
  'request' => 
  array (
    'text' => 'Reward for completing',
  ),
  'user_data' => 
  array (
    'user' => 
    array (
      'coins' => 1483,
      'name' => 'Miho San',
    ),
    'awards' => 
    array (
      0 => 
      array (
        'next_time' => 1292606378,
        'interval' => 25,
        'reward' => 354,
        'text' => 'Reward for playing',
      ),
      1 => 
      array (
        'next_time' => 1292606389,
        'interval' => 18,
        'reward' => 466,
        'text' => 'Reward for winning',
      ),
      2 => 
      array (
        'next_time' => 1292606391,
        'interval' => 19,
        'reward' => 249,
        'text' => 'Reward for friends',
      ),
      3 => 
      array (
        'next_time' => 1292606376,
        'interval' => 25,
        'reward' => 990,
        'text' => 'Reward for completing',
      ),
    ),
  ),
)

46b6bab34d828616a0970222380bd180 - 2010-12-17T17:19:37+0000 - array (
  'response' => 
  array (
    'ready_for_collection' => true,
    'coins' => 2473,
  ),
  'user_data' => 
  array (
    'user' => 
    array (
      'coins' => 2473,
      'name' => 'Miho San',
    ),
    'awards' => 
    array (
      0 => 
      array (
        'next_time' => 1292606378,
        'interval' => 25,
        'reward' => 354,
        'text' => 'Reward for playing',
      ),
      1 => 
      array (
        'next_time' => 1292606389,
        'interval' => 18,
        'reward' => 466,
        'text' => 'Reward for winning',
      ),
      2 => 
      array (
        'next_time' => 1292606391,
        'interval' => 19,
        'reward' => 249,
        'text' => 'Reward for friends',
      ),
      3 => 
      array (
        'next_time' => 1292606401,
        'interval' => 25,
        'reward' => 990,
        'text' => 'Reward for completing',
      ),
    ),
  ),
)