tag:blogger.com,1999:blog-23889192230094507712024-03-14T02:03:36.972-07:00Danny's Learning BoxArticles about my findings in Programming, CakePHP, PHP, C++, cross platform programming, and just life in general.Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-2388919223009450771.post-35275869046962332222009-03-04T00:19:00.000-08:002009-03-04T01:49:33.799-08:00Problems with 404 error, Query string, ASP and international (Hebrew) charactersEDIT: Fixed a typo in the code where I had "QUERY_STRING" instead of "HTTP_URL"<br /><br />Today I had to move a website for a client. The website is very old, and is written in ASP, and was hosted on a shared host. <br /><br />The former developer wanted to have <a href="http://en.wikipedia.org/wiki/Search_engine_optimization">SEO friendly</a> URLs but didn't have a <a href="http://en.wikipedia.org/wiki/Mod_rewrite">URL Rewrite module</a> available.<br /><br />What he did was making a custom 404 error page, that would redirect the SEO URL and take care of the error if the URL shouldn't be redirected. As part of the script, he took the QUERY_STRING and processed it like so:<br /><pre name="code" class="asp"><br />Urlstring = Request.ServerVariables("QUERY_STRING")<br /><br />Response.Write UrlString<br />Response.Write URLDecode( UrlString )<br /></pre><br /><br />Long story short, when moved, this code started to result in a very weird behavior. The QUERY string of international URL's turned to "???" question marks. After checking the settings for IIS, and making sure all the correct code pages are set, I found out that the behavior is changing depending if the text was before or after the '?' in the URL.<br /><br />For instance, the following URL:<br />http://www.example.com/something.asp?something=something<br /><br />If you replaced 'something.asp' with international characters, they would turn to question marks, but if you replaced 'something=something' with international characters they would display properly.<br /><br />After some trial and error the solution was to use "HTTP_URL" instead of "QUERY_STRING" and strip out a part of it, like so:<br /><pre name="code" class="asp"><br />Urlstring = Request.ServerVariables("HTTP_URL")<br /><br />Set RegularExpressionObject = New RegExp<br />With RegularExpressionObject<br /> .Pattern = "\/err404\.asp\?"<br /> .IgnoreCase = True<br /> .Global = True<br />End With<br />UrlString = RegularExpressionObject.Replace(UrlString, "")<br />Set RegularExpressionObject = nothing<br /><br />Response.Write UrlString<br />Response.Write URLDecode( UrlString )<br /></pre><br /><br />Of course, this is just a quick and dirty RegExp example, and I wouldn't advise using RegExp because they're expensive on memory and resources, but I think you're good to go from here.<br /><br />Any other ideas? Feel welcome to ask questions or comment!Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com5tag:blogger.com,1999:blog-2388919223009450771.post-72725325927803081892009-02-20T14:36:00.000-08:002009-02-20T14:37:22.248-08:00What content would you like to see next?Hey guys. I was just wondering - what content would you like to see posted next? Is there any particular subject of interest or question on anyone's mind?<br /><br />Feel free to answer in the comments...Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0tag:blogger.com,1999:blog-2388919223009450771.post-45016062118134236882009-02-17T15:30:00.000-08:002009-02-17T15:32:34.978-08:00Don't wanna be Obama's Elf<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/A_B5UrI7nAI&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/A_B5UrI7nAI&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0tag:blogger.com,1999:blog-2388919223009450771.post-36842231174126543462009-02-17T15:21:00.000-08:002009-02-17T15:28:46.165-08:00How to update a single field in CakePHPHere's a quick line of code to demonstrate how to update a single field in CakePHP.<br /><br />Suppose we will be updating a field named 'confirmed' in a model called 'User' with the id of 5. We will then have an array with just that value, like this:<br /><br /><pre name="code" class="php"><br />$data = array(<br /> 'User' => array(<br /> 'id' => 5,<br /> 'confirmed' => 1<br /> )<br /> );<br /></pre><br /><br />We should then pass it on to a save function:<br /><pre name="code" class="php"><br />$this->User->save( $data, false, array('confirmed') );<br /></pre><br /><br />You can RTFM about the save() function <a href="http://book.cakephp.org/view/75/Saving-Your-Data">here</a>.Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com9tag:blogger.com,1999:blog-2388919223009450771.post-81757633779131779892009-02-11T11:43:00.000-08:002009-02-11T12:01:12.444-08:00How to undelete text files on linuxToday was a hard day. Someone accidentally deleted a bunch of files with code containing the last two days' work.<br /><br />Fortunately, all the files were successfully recovered. I'll share the way that worked here with you.<br /><br />First of all, the moment you lose your text data, make sure that if you can, you unmount the drive the files were on, so you won't overwrite the lost data.<br /><br />Then you will have to run a utility called <a href="http://unixhelp.ed.ac.uk/CGI/man-cgi?strings">strings</a>. Basically what it does is extracting all string data from it's input, and outputs it to STDOUT or whatever output you specify.<br /><br />We will tell it to read our partition on the hard drive the lost files were. (<a href="http://www.cyberciti.biz/faq/linux-partition-naming-convention-and-ide-drive-mappings/">Learn more about Linux partitions</a>) and output it to a file on another partition.<br /><br />So the command should look something like this:<br /><blockquote>strings /dev/sda1 > /some/path/for/output.txt</blockquote><br /><br />Note that '/dev/sda1' should be replaced by your partition path, and you should provide a path to where you want the output file to be. (<span style="font-weight:bold;">NOTE: AVOID WRITING IT TO THE SAME PARTITION AT ANY COST. THE RESULTING FILE WILL BE HUGE, MORE THAN 10GB, AND YOU DON'T WANT TO OVERWRITE YOUR PRECIOUS DATA!</span>).<br /><br />After the process finishes (takes quite a while), you should have a HUGE text file that contains ALL of the text from your hard drive, deleted or not. <br /><br />Now, basically all you need to do is to grep and locate the text you lost inside the whole mass.<br /><br />Hope it helps you! It sure helped me!Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com8tag:blogger.com,1999:blog-2388919223009450771.post-48696597870024246522009-02-10T23:27:00.000-08:002009-02-10T23:35:43.699-08:00Linux - working with filenames and directories starting with a - (dash)I use SVN daily on my Linux development server, but today I ran into a silly problem that took me some figuring out.<br /><br />If you try to work with filenames that start with - (dash) such as "-filename.ext", you will get errors such as:<br /><blockquote>svn: invalid option character: i<br />Type 'svn help' for usage.</blockquote><br /><br />After some looking around, the solution for it was, instead of:<br /><blockquote>svn rm -filename.ext</blockquote><br />To pass '--' as the first argument:<br /><blockquote>svn rm -- -filename.ext</blockquote><br /><br />Hope it helps anyone out there.Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0tag:blogger.com,1999:blog-2388919223009450771.post-63323559267594922862008-06-25T07:54:00.000-07:002009-02-11T11:45:36.072-08:00Do It Yourself - Plugins (PHP Tutorial)Today I would like to share with you a quick way to have a plug-in engine running at your site. I came up with this concept quickly a few days ago when I needed to make an extensible layer for one of our projects.<br /><br />Today we are going to achieve some fundamental functionality of a plug-in system. Please note that any of the external classes used in this tutorial's code can be replaced with only a few lines of code. I was too lazy to do so while copy-pasting my code. And of course you can comment and ask for help.<br /><br />First of all, let's define the functionality we expect from our system:<br /><ul><br /><li>The plugin creator shouldn't have to touch any code other than his plugin<br /><li>There should be minimal installation needed<br /><li>The plugin should be standalone and deployable to any system using our framework without any hassle<br /></ul><br /><br />Sounds hard? It isn't. First of all, let me walk you through a few key concepts we are going to exercise while creating this system. I am basing all of this on the presumption that you already are familiar with object oriented programming, if you are not, I advise you to <a href="http://www.google.com/search?q=object+oriented+php">fill in the gaps</a><br /><br /><h3>Static Keyword</h3><br />So, you are probably familiar with classes and objects, and you know that to use a class, you first must instantiate it using the <a href="http://www.google.com/search?q=new+keyword+object+oriented++php">new keyword</a>.<br /><br />You also probably know that every time you create an object of the class' type, you are creating all the methods and properties, and they belong to that specific object.<br /><br />Basically, when you put the keyword <b>static</b> before a property or method definition, you are declaring that this method or property will belong to the class type itself, rather than instances of it (objects), and therefore be common to all the instances of the same class, and be <b>callable without even creating an instance of a class</b><br /><br />Let me give you a quick example. <br /><pre name="code" class="php"><br />class className{<br /> static private $variable = 25;<br /> function get_variable(){<br /> return className::$variable;<br /> }<br /><br /> function __construct( $inputNumber = null ){<br /><br /> if(!is_null( $inputNumber )){<br /> className::$variable = $inputNumber;<br /> }<br /> }<br />}<br /><br />// We create the first instance. Since we don't give a new value, it stays 25, like <br />// in the initialization<br />$firstInstance = new className();<br />// We create a second instance, this time we change the variable to 45<br />$secondInstance = new className(45);<br />// We create a third instance<br />$thirdInstance = new className();<br /><br /><br />// Since the variable is static, the change we did in the second function affects<br />// all of them, because the variable belongs to the class itslef, and not a separate <br />// instance of it<br />// All the three functions will output: 45<br />echo $firstInstance->get_variable();<br />echo $secondInstance->get_variable();<br />echo $thirdInstance->get_variable();<br /></pre><br /><br />Now that you know what the static keyword is, let us move to the next thing you need to know before attempting to write a plugin engine.<br /><br /><h3>Dynamic Access & Creation</h3><br />This is a very controversial feature in PHP. And some will argue (and will be right in a way) that it shouldn't be there (its just like the argument about strongly typed and weakly typed languages). But since the feature is there, why not make use of it?<br /><br />Simply enough, PHP lets you call functions and classes dynamically. For instance, you can dynamically decide which class to create.<br /><pre name="code" class="php"><br />$variable = 'myClass';<br />$myObject = new $variable();<br /></pre><br />The code above will create an instance of the class 'myClass'.<br /><br />Also, PHP lets us call functions and methods dynamically.<br /><pre name="code" class="php"><br />$functionName = 'multiply';<br />// Same as doing: multiply( 5, 2 );<br />$functionName( 5, 2 );<br /><br />// Same as doing: multiply( 5, 2 );<br />call_user_func( 'multiply', 5, 2 );<br /><br />// Same as doing: $myObject->myMethod( 'some text' );<br />call_user_func( array( 'myObject', 'myMethod' ), 'some text' );<br /><br />// Same as doing: myStaticClass::myMethod( 'some text' );<br />call_user_func( array( 'myStaticClass', 'myMethod' ), 'some text' );<br /></pre><br /><br /><h3>Let's Get Started</h3><br />Oh, I almost forgot, we were going to build a plugin engine... Well, let's get started.<br /><br />First of all, before writing any code, I always figure out <b>what</b> I'm going to make. Then we figure out <b>how</b>, and then after I have everything in mind, I start writing some actual code.<br /><br />The first planning stage is pretending to be a user of our to-be-written module, and making a quick list of how the final product will act.<br /><br />So for our plugin system it will be:<br /><ul><br /><li>All the plugins reside in a plugins/ subdirectory of our website. Each in it's own directory.<br /><li>There will be a class that handles all the plugins, and registers them to the system.<br /><li>A plugin can be turned off.<br /><li>The plugin installation should be as simple as copying it to the plugins/ directory, and turning it on.<br /></ul><br /><br />Then, after some thinking, I decided that I will go with this kind of code architecture:<br /><ul><br /><li>Plugin engine is a fake-singleton class (Read some stuff about actual <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton classes</a>. By fake-singleton, I mean that it is an absolutely static class of which you can't create instances, but it isn't a traditional singleton class (which actually has one instance of a class)<br /><li>Each plugin is also a static class. Why did I choose static classes? Code readability and aesthetics mainly. As well as ease of implementation.<br /><li>Each class has a corresponding table entry in MySQL, that tells us if we enabled the plugin or not.<br /><li>There are multiple "hook checkpoints" where plugins can hook in their code.<br /></ul><br /><br /><h3>Plugin Engine</h3><br />Basically, what I'll do next here is give the final code, copy-pasted right off my application, and then explain what needs explanation. Please note that you can't just copy-paste my code as it won't work right away. You will need to replace a few lines of code. Nothing too bad.<br /><br /><b>plugin.class.php</b><br />This is the heart of the plugin system. It checks the plugins directory for any plugins, validates them with our database, and then registers them to be ran at the hook checkpoints.<br /><pre name="code" class="php"><br /> // This bit checks if we are currently<br /> // running inside our website. It prevents<br /> // from overly curious people to launch <br /> // this php file from outside of our script<br /> if( !defined( "INPROCESS" ) ){<br /> header("HTTP/1.0 403 Forbidden");<br /> die();<br /> }<br /> <br /> // Those two are classes that I wrote<br /> // to simplify access to mysql and other<br /> // databases. You will have to delete those<br /> // two lines, and <a href="http://www.google.com/search?q=php+mysql+tutorials">write your own code</a><br /> // to access mysql<br /> require_once( 'data.class.php' );<br /> require_once( 'data.mysql.class.php' );<br /> <br /><br /> // This is the parent class for all plugins<br /> // It contains a private constructor, that<br /> // basically makes sure we won't have any<br /> // instances of our static classes. Making<br /> // them completely static.<br /> class plugin{<br /> private function __construct(){}<br /> }<br /> <br /> // This is the actual plugin class.<br /> class pluginClass{ <br /> // This will be the list of active plugins<br /> static private $plugins = array();<br /><br /> // Again, we don't want any instances <br /> // of our static class.<br /> private function __construct(){}<br /> <br /> static function initialize(){<br /> // I have those variables elsewhere in<br /> // a config.php file. you can replace<br /> // those with your own<br /> global $config_fullpath;<br /> global $config_username;<br /> global $config_password;<br /> global $config_server;<br /> global $config_database;<br /> <br /> $list = array(); <br /> // Populate the list of directories to check against<br /> if ( ($directoryHandle = opendir( $config_fullpath . '/plugins/' )) == true ) {<br /> while (($file = readdir( $directoryHandle )) !== false) {<br /> // Make sure we're not dealing with a file or a link to the parent directory<br /> if( is_dir( $config_fullpath . '/plugins/' . $file ) && ($file == '.' || $file == '..') !== true )<br /> array_push( $list, $file );<br /> }<br /> }<br /> <br /> <br /> // Get the plugin list from MySQL. Note that you will have to replace<br /> // this code with your own, since I'm using classes that I didn't <br /> // include in this article. Fortunately, it <a href="http://www.google.com/search?q=php+mysql+tutorials">won't be too much of a problem</a>.<br /> <br /> // Connect to mysql<br /> $mysqlConnection = new mysqlConnection( $config_username, $config_password, $config_server, $config_database );<br /> // We select all the plugins from our database<br /> // Each plugin has it's name stored, and whether<br /> // it is active or not (active = 0 or 1)<br /> $mysqlConnection->prepareQuery( 'SELECT * FROM plugins' );<br /> $results = $mysqlConnection->executeQuery();<br /> $results = $mysqlConnection->resultToObjects( $results );<br /> $newResult = array();<br /> <br /> <br /> <br /> // Create an array: 'plugin name' = 'active' (1 or 0)<br /> foreach ( $results as $result ){<br /> $newResult[$result->name] = $result->active;<br /> } <br /> <br /> // Register the active plugins<br /> foreach( $list as $plugin ){<br /> if($newResult[$plugin] == "1"){<br /> pluginClass::register( $plugin );<br /> }<br /> }<br /> }<br /> <br /> // Hook the active plugins at a checkpoint. <br /> // You will see exactly how it works later on.<br /> static function hook( $checkpoint ){<br /> // Cycle through all the plugins that are active<br /> foreach(pluginClass::$plugins as $plugin){<br /> if(!call_user_func( array( $plugin, $checkpoint ) ))<br /> // <a href="http://il.php.net/exceptions">Throw an exception</a> if we can't hook the plugin<br /> throw new Exception( "Cannot hook plugin ($plugin) at checkpoint ($checkpoint)" );<br /> }<br /> }<br /> <br /> // Registration adds the plugin to the list of plugins, and also<br /> // includes it's code into our runtime.<br /> static function register( $plugin ){<br /> global $config_fullpath;<br /> require_once( $config_fullpath . "/plugins/$plugin/$plugin.class.php" ); <br /> array_push( pluginClass::$plugins, $plugin );<br /> }<br /> }</pre><br /><br />index.php<br /><pre name="code" class="php"><br /> // Tell the class it is safe to run<br /> define( "INPROCESS", true );<br /> <br /> // My configuration file <br /> require_once( './config.php' );<br /> // Our plugin class<br /> require_once( './include/plugin.class.php');<br /> <br /> // Initialize our plugin engine<br /> pluginClass::initialize();<br /> // Create a new hook point called "onLoad"<br /> // Now all the plugins that can be hooked here<br /> // will be ran.<br /> pluginClass::hook( "onLoad" );<br /></pre><br /><br />A Sample Plugin<br />A sample plugin will reside in it's own directory inside plugins/. For example plugins/helloworld/. Then we need to go (or have a script that does it automatically. Homework for you...) to our database and add it, with its name there and active = 1. That's it, we're done with installing our plugin!<br /><br /><b>plugins/helloworld/helloworld.class.php</b><br /><pre name="code" class="php"><br /><br />if( !defined( "INPROCESS" ) ){<br /> header("HTTP/1.0 403 Forbidden");<br /> die();<br />}<br />// We <a href="http://www.google.com/search?q=php+inheritance">inherit</a> the parent class plugin to make sure we will have no accidental instances of this class.<br />class helloworld extends plugin {<br /> // That's right. We create a function with the name <br /> // of our hook, and walla! We have a plugin hooked at <br /> // onLoad.<br /> static function onLoad(){<br /> print 'Hello World!';<br /> return true;<br /> }<br />}<br /></pre><br /><br />That's it. I am sorry for not doing this one step by step, but if you have any questions, you are welcome to comment. Of course, I didn't include the whole code here. You can create an installer that installs classes automatically, you can make sure there is no trash entries in MySQL by disabling the non existent plugins automatically, but one article won't be enough for that.<br /><br />I hope it got your gray matter all buzzing and running, and now you'll create some awesome plugin systems for whatever project you're working on.<br /><br />You're welcome to comment!!!Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com13tag:blogger.com,1999:blog-2388919223009450771.post-91437115853576007112008-06-24T06:44:00.000-07:002008-06-24T07:36:56.341-07:00The Right Mind - StylizeOne of the most important aspects of coding visually is your coding style. Each person chooses his own style, but good coding style is always <b>readable</b> and <b>consistent</b>. In this post I will share with you my own coding style, separated to elements.<br /><br /><h3>Naming</h3><br />One of the most important elements in understandable code is variable names. Let's look at the wrong way to do it.<br /><pre name="code" class="php"><br />if($var1 <= $var2){<br /> funcOne();<br />}<br /></pre><br />What can you gather about what the program will do in funcOne() from this code? Probably nothing. Now let's look at a better way to do it.<br /><pre name="code" class="php"><br />if($nextLoginTime <= $currentTime){<br /> login();<br />}<br /></pre><br />Isn't this much better? Without any amazing knowledge in programming you can know right away that the given code will check if the next login time passed, and login if it did.<br /><br />When writing programs, whether it is compiled C# or C++ code, or open source PHP code, I always try to keep the names of the variables, classes, namespaces and functions relevant to their functionality and contents. This way even after a year, I will read my own code easily.<br /><br /><h3>Indentation</h3><br />Indentation helps to understand the hierarchy and structure of your code. I use tabs to indent any code that logically belongs to another piece of code.<br /><br /><h2>PHP Examples</h2><br /><pre name="code" class="php"><br />function someFunction(){<br /> ...<br /><br /> if($success = false){<br /> runFunction();<br /> }<br /><br /> ...<br />}<br /></pre><br /><pre name="code" class="php"><br />class someClass{<br /> private $privateVariable = null;<br /> function get_privateVariable(){<br /> return $privateVariable;<br /> }<br /> function set_privateVariable( $newValue ){<br /> $privateVariable = $newValue;<br /> }<br /><br /> public $publicVariable = null;<br /><br /> function someFunction(){<br /> ...<br /> }<br />}<br /></pre><br /><br />Note that even though the functions get and set for the private variable are not located in between curly brackets, I still indent them, because logically they are just a small subset that belongs to the variable.<br /><br /><br /><h3>Commenting</h3><br />Commenting may seem tiring and unnecessary at first, but after it becomes your second nature, you can really appreciate it. <br />I take it as a rule to insert both comments that help reading the code, and comments that describe, functions, classes and variables and are <a href="http://www.phpdoc.org">phpDoc</a> compliant for PHP ( SharpDevelop also has similar documentation style for C# ).<br /><br />While you may not want to comment so extensively, I do recommend you to take as a rule to comment everything that may take more than a moment to figure out while skimming the code.<br /><br />For instance, compare the following two code fragments.<br /><pre name="code" class="php"><br />...<br />if(preg_match( "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/", $string ))<br /> nextStep();<br />}<br />...<br /></pre><br /><pre name="code" class="php"><br />...<br />// If the string is a valid email address, move to the next step<br />if(preg_match( "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/", $string ))<br /> nextStep();<br />}<br />...<br /></pre><br />You have to admit that you can't easily skim through the first fragment without wondering, and then stopping to figure out what the regular expression does, while reading the second fragment's comment saved you this time.<br /><br /><h3>Tabular Variable Assignment</h3><br />When there is a big list of variable assignments, I always prefer to have them in a table like structure. The following fragment is an example from a C# application.<br /><pre name="code" class="csharp"><br /> public firebirdConnection( string newServer, string newDatabasePath, string newUser, string newPass){<br /> this.server = newServer;<br /> this.path = newDatabasePath;<br /> this.username = newUser;<br /> this.password = newPass;<br /><br /> ...<br /> }<br /></pre><br /><br />The function starts with four variable initialization assignments. By formatting them into a tabbed structure, I make them more readable.<br /><br /><h3>Consistency - Brackets, Function Operators, Spaces e.t.c</h3><br />Aside from the other rules above, I also set myself a general style according to my own personal taste. I try to always keep all my code consistently formatted with this coding style.<br /><br />Below is a quick summary of those rules.<br /><br /><pre name="code" class="php"><br /> // First curly bracket is always on the same line with it's function or statement.<br /> // There is a padding one one space within the function declaration or calling brackets, and there is a space after the comma.<br /> function doThis( $operator, $anotherOperator ){<br /> // No space within if, for or other statement brackets<br /> if($condition == true){ <br /> // Functions with lots of operators have a line break after each comma<br /> login( $username,<br /> $password,<br /> 'www.server.com',<br /> 1234 );<br /> ....<br /> }<br /> ...<br /> }<br /></pre>Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0tag:blogger.com,1999:blog-2388919223009450771.post-8495275710951624992008-06-24T05:54:00.000-07:002008-06-24T06:44:37.260-07:00The Right Mind - "Love yourself as your fellow"Welcome to my mini-series of mini-articles about development techniques and challenges. Adding to the little you can already read from my profile description, I will say that I work at a finance and real estate management company as a senior developer of all the infrastructures, data applications and web software.<br /><br />Being in a position of a senior developer in our company, I have complete control over the coding standards and practices of the projects that we do, which turned out to be a curse, before I could turn it into a blessing.<br /><br />The first thing I wanted to talk about in this series was a very general rule that I adopted after learning from my mistakes: <br><br /><div align="center">Write for Others. Always.</div><br />Let me explain. Sometimes, when you write a code for your own project, or for something only, or mostly you will be working on, you may be tempted to shortcut and write messy code, with the presumption that you will understand it later because you wrote it.<br /><br />Well, in that case, you're wrong.<br /><br />Try to open an uncommitted script you knew very well a year ago, but didn't touch for the last few months, and you're most likely to spend a long time figuring your own code out if it isn't written properly.<br /><br />So what is writing "for others"? I will sum it up with a few points, and elaborate on each one in a separate article.<br /><br />Write code for others. Always:<div align="center"><br /><b>M</b>aintain<br /><b>E</b>xtend<br /><b>S</b>eparate<br /><b>S</b>tylize<br /></div>Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0tag:blogger.com,1999:blog-2388919223009450771.post-23698378336209434972008-05-13T09:40:00.000-07:002008-05-13T09:41:25.010-07:00First PostHello World!<br />No one is probably going to read this one anyway. At least not anywhere close to the posting date. But it is nice to start this blog with a "Hello World". Hope the world will "Hello" me back.Danny.Phttp://www.blogger.com/profile/10052002350609248003noreply@blogger.com0