<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jean-Michel Feurprier &#187; tips and tricks</title>
	<atom:link href="http://www.jmfeurprier.com/blog/category/tips-and-tricks/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jmfeurprier.com/blog</link>
	<description>LAMP Web Developer</description>
	<lastBuildDate>Sat, 13 Feb 2010 00:16:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SVN trunk, branches and tags</title>
		<link>http://www.jmfeurprier.com/blog/2010/02/08/svn-trunk-branches-and-tags/</link>
		<comments>http://www.jmfeurprier.com/blog/2010/02/08/svn-trunk-branches-and-tags/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 00:27:20 +0000</pubDate>
		<dc:creator>Jean-Michel Feurprier</dc:creator>
				<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[beginners]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.jmfeurprier.com/blog/?p=258</guid>
		<description><![CDATA[In this post, I provide details about how I personnaly handle SVN trunk, branches and tags. This approach is also known as “branch always”, with minor differences. This might not be the best approach, but it will give beginners some explanations on what trunk, branches and tags are, and how to handle them.

Of course, feel [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, I provide details about how I personnaly handle SVN trunk, branches and tags. This approach is also known as “branch always”, with minor differences. This might not be the best approach, but it will give beginners some explanations on what trunk, branches and tags are, and how to handle them.<br />
<span id="more-258"></span><br />
Of course, feel free to leave comments on this post if some clarifications are needed, if some mistakes were made, or if you disagree with my statements.</p>
<h2>An easy comparison</h2>
<p>Working with SVN is somewhat like growing a tree:</p>
<ul>
<li>a tree has a trunk and some branches</li>
<li>branches grow from the trunk, and thinner branches grow from thicker branches</li>
<li>a tree can grow with a trunk and no branch (but not for long)</li>
<li>a tree with branches but no trunk looks more like a bundle of twigs fallen on the floor</li>
<li>if the trunk is sick, so are the branches and eventually, the whole tree can die</li>
<li>if a branch is sick, you can cut it, and another one may grow</li>
<li>if a branch grows too much, it may become too heavy for the trunk, and the tree will fall down</li>
<li>when you feel your tree, your trunk, or a branch is nice looking, you can take a picture of it to remember how nice it was that day</li>
</ul>
<h2>Trunk</h2>
<p>With the &#8220;branch always&#8221; approach, the trunk is the main place were stable code can be found. This is like the assembly line of a car factory, putting finished car parts together.</p>
<p>Here is how you should deal with a SVN trunk:</p>
<ul>
<li>do NEVER work directly on the trunk, unless you have to deal with a bug which is quick and easy to fix (a few characters), or if you have to ADD a few files which hold no logic (like media files: images, videos, css, etc)</li>
<li>do not make too many exceptions to the previous statement, those are really special cases, every other situation must imply the creation of a branch (see below)</li>
<li>do not commit changes (from a branch merge) to the trunk which may break it</li>
<li>if at some point you happen to <em>break the trunk</em>, bring some cake the next day (&#8221;with great power comes&#8230; huge cake&#8221;)</li>
</ul>
<h2>Branches</h2>
<p>A branch is a &#8220;cheap copy&#8221; of a subtree (ie, the trunk or a branch) of a SVN repository. It works a little bit like symbolic links on UNIX systems, except that once you make modifications to files within a SVN branch, these files evolve independently from the original files which were &#8220;copied&#8221;. When a branch is completed and considered stable, it must be merged back to its original copy, that is: back to the trunk if it was copied from the trunk, or back to its parent branch if it was copied from a branch.</p>
<p>Here is how you should deal with SVN branches:</p>
<ul>
<li> if you need to alter your application or develop a new feature for it, create a new branch from the trunk, and make your development on that branch</li>
<li>new branches must be created from the trunk, except for new sub-branches (if needed) which must be created from a branch</li>
<li>when you create a new branch, you should switch to it immediately; if you don&#8217;t, why did you create the branch in the first place?</li>
</ul>
<h2>Tags</h2>
<p>Internally, SVN branches and SVN tags are the same thing, but conceptually, they differ a lot.<br />
Remember the &#8220;take a picture of the tree&#8221; thing written earlier? Well, this is exactly what a SVN tag is: a snapshot with a name of a specific revision of the trunk, or of a branch.</p>
<p>Here is how you should deal with SVN tags:</p>
<ul>
<li>as a developer, do never switch to/checkout from/commit to a SVN tag: a tag is some sort of &#8220;picture&#8221;, not the real thing; tags are to be read, never written</li>
<li>on specific/critical environments (production, staging, testing, etc), checkout and update from a fixed tag, but do never commit to a tag</li>
<li>for the aforementioned environments, create tags with names like &#8220;production&#8221;, &#8220;staging&#8221;, &#8220;testing&#8221;, etc. You can also tag by sofware version and/or by project maturity: &#8220;1.0.3&#8243;, &#8220;stable&#8221;, &#8220;latest&#8221;, etc.</li>
<li>when the trunk is stable and ready to be released publicly, re-create tags accordingly, then update the concerned environments (production, staging, etc)</li>
<li>do not tag a tag</li>
</ul>
<h2>Example workflow</h2>
<p>Say you have to add a feature to a project under version control. Here are the steps you should achieve to do so:</p>
<ul>
<li>get a new working copy of the project (through a SVN checkout or a SVN switch) from the trunk</li>
<li>create a new SVN branch and give it a name which allows to understand what it is all about (say, &#8220;feature-faq-development&#8221;)</li>
<li>SVN switch to the new branch (&#8221;/branches/feature-faq-development&#8221;)</li>
<li>make the needed development to complete the new feature (and of course, make a lot of tests, <a href="http://www.agiledata.org/essays/tdd.html">even before you start coding</a>), commit sub-parts of your development when needed</li>
<li>once the feature is complete and stable (and committed), merge the trunk into the branch and resolve conflicts if there are some, then commit your changes</li>
<li>with the approval of your peers, switch to the trunk</li>
<li>merge your branch within your working copy (trunk), and resolve conflicts if there are some</li>
<li>re-check your development with the merged code</li>
<li>if possible, ask one of your peer to do a code review of your changes with you</li>
<li>commit your merged working copy to the trunk</li>
<li>if some deployment must be achieved on specific environments (production, etc), update the related tag to the revision you just committed in the trunk</li>
<li>deploy on the concerned environments with a SVN update</li>
<li>rename the branch so that it&#8217;s made clear it won&#8217;t be used anymore (&#8221;/branches/obsolete-feature-faq-development&#8221;)</li>
<li>eventually, delete the branch after a while</li>
</ul>
<p>Extra resources:</p>
<ul>
<li><a href="http://svn.apache.org/repos/asf/subversion/trunk/doc/user/svn-best-practices.html">Subversion Best Practices</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.jmfeurprier.com/blog/2010/02/08/svn-trunk-branches-and-tags/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>method_exists() vs. is_callable()</title>
		<link>http://www.jmfeurprier.com/blog/2010/01/03/method_exists-vs-is_callable/</link>
		<comments>http://www.jmfeurprier.com/blog/2010/01/03/method_exists-vs-is_callable/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 07:17:24 +0000</pubDate>
		<dc:creator>Jean-Michel Feurprier</dc:creator>
				<category><![CDATA[php5]]></category>
		<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.jmfeurprier.com/blog/2010/01/03/method_exists-vs-is_callable/</guid>
		<description><![CDATA[One thing I often see when re-factoring PHP applications, is the improper use of the method_exists() function, and I think this needs a little bit of clarification.]]></description>
			<content:encoded><![CDATA[<p>One thing I often see when re-factoring PHP applications, is the improper use of the <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> function, and I think this needs a little bit of clarification.<br />
<span id="more-221"></span><br />
Here is a typical example of what I&#8217;m talking about:</p>
<pre class="brush: php">

if (method_exists($object, &#039;SomeMethod&#039;))
{
  $object-&gt;SomeMethod($this, TRUE);
}
</pre>
<p>The purpose of this code snippet is quite easy to understand (even if I don&#8217;t encourage to do this kind of not-very-OOP-stuff): having an object named &#8220;$object&#8221;, we try to know if it has a method named &#8220;SomeMethod&#8221;, if so, we call it, and provide some arguments to it.</p>
<h3>Yes, but&#8230;</h3>
<p>This code will probably run very well during all its lifetime, but what if the object&#8217;s method is not visible from the current scope (like&#8230; a private or protected method)? PHP&#8217;s <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> function does what it says: it checks if the provided class or object has a method named like the provided one, and returns TRUE if so, or FALSE if not, visibility is not questionned. So, if you provide a private or protected existing method name (being out of current scope) to <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, you&#8217;ll get TRUE as the return value, and a nice &#8220;Fatal error: Call to private method&#8230;&#8221;, immediately terminating the current script execution.</p>
<h3>The right tool for the right job</h3>
<p>The real intent of the previous code snippet was in fact to know if the application could <strong>call</strong> a method on the object, from the current scope.</p>
<p>This is why (among other reasons) <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> is part of the PHP built-in functions.</p>
<h3>How does it work?</h3>
<p><a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> receives a <a href="http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback">callback</a> as its first argument, which, in our case, consists of an array of two values: the first being an object (or a string holding a class name), and the second being a string holding a method name. <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> returns TRUE when the provided callback can be called from the current scope, or FALSE if not. </p>
<pre class="brush: php">

if (is_callable(array($object, &#039;SomeMethod&#039;)))
{
  $object-&gt;SomeMethod($this, TRUE);
}
</pre>
<p>Here is another snippet of code to illustrate the differences between <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> and <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> in action:</p>
<pre class="brush: php">
class Foo {
  public function PublicMethod() {}
  private function PrivateMethod() {}
  public static function PublicStaticMethod() {}
  private static function PrivateStaticMethod() {}
}

$foo = new Foo();

$callbacks = array(
  array($foo, &#039;PublicMethod&#039;),
  array($foo, &#039;PrivateMethod&#039;),
  array($foo, &#039;PublicStaticMethod&#039;),
  array($foo, &#039;PrivateStaticMethod&#039;),
  array(&#039;Foo&#039;, &#039;PublicMethod&#039;),
  array(&#039;Foo&#039;, &#039;PrivateMethod&#039;),
  array(&#039;Foo&#039;, &#039;PublicStaticMethod&#039;),
  array(&#039;Foo&#039;, &#039;PrivateStaticMethod&#039;),
);

foreach ($callbacks as $callback) {
  var_dump($callback);
  var_dump(method_exists($callback[0], $callback[1])); // 0: object / class name, 1: method name
  var_dump(is_callable($callback));
  echo str_repeat(&#039;-&#039;, 40), &quot;\n&quot;;
}
</pre>
<p>Run it, and you&#8217;ll see that every test returns TRUE with <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, even private methods, while <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> returns FALSE for these (and will also trigger strict errors with non-static methods being queried as static ones, be aware of this).</p>
<h3>More details</h3>
<p><a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> has other uses, like checking the syntax of the provided callback, without checking if there really is a class or a method with the provided names.<br />
Like <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> can trigger a class autoloading process if the provided class is not already loaded.<br />
If an object has the magic <a href="http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods">__call()</a> method implemented, then <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> will return TRUE for any non-existent method, while <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> will return FALSE. I guess the same behavior can be observed with the recent (PHP 5.3.0) <a href="http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods">__callStatic()</a> magic method, but I did not test it (yet).<br />
Everything else you need to know is in the <a href="http://www.php.net/manual/">PHP manual</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmfeurprier.com/blog/2010/01/03/method_exists-vs-is_callable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple introduction to SVN externals</title>
		<link>http://www.jmfeurprier.com/blog/2009/12/10/simple-introduction-to-svn-externals/</link>
		<comments>http://www.jmfeurprier.com/blog/2009/12/10/simple-introduction-to-svn-externals/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 20:36:34 +0000</pubDate>
		<dc:creator>Jean-Michel Feurprier</dc:creator>
				<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[beginners]]></category>
		<category><![CDATA[externals]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[SVN]]></category>

		<guid isPermaLink="false">http://www.jmfeurprier.com/blog/2009/12/10/simple-introduction-to-svn-externals/</guid>
		<description><![CDATA[This is a quick and basic introduction to SVN externals, explaining what they are and how they work with a simple real-life example.]]></description>
			<content:encoded><![CDATA[<p>Not so long ago, we&#8217;ve had to include a third-party library into a new project (using SVN). Our first idea (the one which did not imply thinking) was to SVN-export library files from the remote repository, paste them into the project, SVN-add them, then SVN-commit files.</p>
<p>Having to keep these library files up-to-date with official patches and improvements sounded like a full-time job.<br />
This solution sucked.<br />
A lot.<br />
<span id="more-40"></span><br />
We are programmers, and we really hate repetitive tasks because <a title="Why Good Programmers Are Lazy and Dumb" href="http://blogoscoped.com/archive/2005-08-24-n14.html">we are lazy</a>. We spend most of our time building applications which automate human tasks, why not take care of this one?</p>
<p>Good news, a quick googling revealed our issue was a common one, and there was already a ready-to-use solution: <a title="SVN externals definitions" href="http://svnbook.red-bean.com/en/1.5/svn.advanced.externals.html">SVN externals</a>.</p>
<p><strong>What are SVN externals?</strong></p>
<p>SVN externals allow to include (nest) a remote SVN repository into another SVN repository. They are set through <a title="SVN properties" href="http://svnbook.red-bean.com/en/1.5/svn.advanced.props.html">SVN properties</a>.</p>
<p><strong>How to use them?</strong></p>
<p>If you&#8217;re a command-line geek, type:</p>
<p><code>svn propset svn:externals "http://svn.3rdapp.com/super-library/ library" .</code></p>
<p>This will create a SVN property at the current location (don&#8217;t miss the final dot &#8220;.&#8221; at the end) named &#8220;svn:externals&#8221;, and its value will be &#8220;http://svn.3rdapp.com/super-library/&nbsp;library&#8221;. Which means: insert a directory named &#8220;library&#8221;, which will retrieve its content from a distant SVN repository located at &#8220;http://svn.3rdapp.com/super-library/&#8221;. The next time you run a SVN-update, the third-party files will be added to your SVN project.</p>
<p>You can do the same with <a title="TortoiseSVN, Windows Shell Extension for Subversion" href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> Windows Shell Extension for Subversion: right-click when browsing your SVN project with the Windows file explorer, highlight &#8220;TortoiseSVN&#8221;, then click &#8220;Properties&#8221;:</p>
<p><img class="alignnone size-full wp-image-164" src="http://www.jmfeurprier.com/blog/wp-content/uploads/2009/12/svn-externals-1.png" alt="SVN externals: TortoiseSVN, step 1" width="228" height="155" /></p>
<p>Now, click &#8220;New&#8230;&#8221;, type or pick &#8220;svn:externals&#8221; in the &#8220;Property name:&#8221; drop-down, then type &#8220;http://svn.3rdapp.com/super-library/ library&#8221; in the &#8220;Property value:&#8221; textarea. Click &#8220;OK&#8221; twice:</p>
<p><img class="alignnone size-full wp-image-165" src="http://www.jmfeurprier.com/blog/wp-content/uploads/2009/12/svn-externals-2.png" alt="SVN externals: TortoiseSVN, step 2" width="574" height="302" /></p>
<p>Now, every time a new version of the third-party application will be released, it will be reflected when you SVN-update your local copy of your project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmfeurprier.com/blog/2009/12/10/simple-introduction-to-svn-externals/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improving performance with return values caching</title>
		<link>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/</link>
		<comments>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 06:26:29 +0000</pubDate>
		<dc:creator>Jean-Michel Feurprier</dc:creator>
				<category><![CDATA[concepts and principles]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/</guid>
		<description><![CDATA[A simple technique to improve a PHP project overall performance.]]></description>
			<content:encoded><![CDATA[<p>Many functions (and methods) in a project will often provide the same return value for the same arguments, like:</p>
<ul>
<li>mathematical functions:</li>
</ul>
<pre class="brush: php">
function SomeMaths($x)
{
	return $x + pow($x, 3.2) - cos($x);
}
</pre>
<ul>
<li>functions which retrieve content from a file:</li>
</ul>
<p><span id="more-38"></span></p>
<pre class="brush: php">
function GetConfiguration()
{
	return parse_ini_file(&#039;configuration.ini&#039;);
}
</pre>
<ul>
<li>functions which retrieve content from a database:</li>
</ul>
<pre class="brush: php">
function GetArticleById($id)
{
	$sqlId  = mysql_real_escape_string($id);
	$result = mysql_query(&quot;SELECT `id`, `title` FROM `article` WHERE `id` = &#039;$sqlId&#039; LIMIT 1&quot;);

	if (FALSE === $result)
	{
		throw new Exception(&#039;Query failed.&#039;);
	}

	return mysql_fetch_assoc($result);
}
</pre>
<p>If your project holds a function like one of these, and:</p>
<ul>
<li>your <a title="Xdebug" href="http://www.xdebug.org/">prefered</a> <a title="KCachegrind" href="http://kcachegrind.sourceforge.net/">profiling</a> <a title="WinCacheGrind" href="http://sourceforge.net/projects/wincachegrind/">tool</a> reveals that a lot of the execution time is spent in this function</li>
<li>its returned value is always the same during a single run (script execution), when providing the same arguments</li>
<li>this function is called more than once per run</li>
</ul>
<p>Then consider caching (saving) its return values.</p>
<p>Here is how it can be achieved (yes, there are <a href="http://memcached.org/">more advanced</a> <a href="http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/">techniques</a> to do it, but this is not the point of this post): add a static variable in the body of the function, which will hold an associative array, mapping every parameter combination with a return value:</p>
<pre class="brush: php">
function GetArticleById($id)
{
	static $cache = array();

	// Return value is not in cache yet?
	if (!isset($cache[$id]))
	{
		$sqlId  = mysql_real_escape_string($id);
		$result = mysql_query(&quot;SELECT `id`, `title` FROM `article` WHERE `id` = &#039;$sqlId&#039; LIMIT 1&quot;);

		if (FALSE === $result)
		{
			throw new Exception(&#039;Query failed.&#039;);
		}

		// Add return value to cache
		$cache[$id] = mysql_fetch_assoc($result);
	}

	// Return cache content
	return $cache[$id];
}
</pre>
<p>Here it is, the (possibly heavy) process of querying the database will only be executed once at the first function call. Every other function call with the same argument will use the cached return value.</p>
<p>Keep in mind that the amount of cached return values must be reasonable (available memory is limited). If there are millions of possible arguments combinations for a function in a single run, you&#8217;ll have to consider a more elaborate way of optimizing it (this could be the subject of a future post).</p>
<p>Also, always, <strong>always</strong>, <strong>ALWAYS</strong> profile your code <strong>BEFORE</strong> you decide to apply an optimization like this one (and wait for your project to be nearly completed before profiling).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
