debuggable

 
Contact Us
 
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48

Composing Methods: Split Temporary Variable

Posted on 2/7/07 by Tim Koschützki

When you have the same temporary variable assigned to more than once, split it up into two, unless it is a loop variable.

Motivation

Temporary variables have various uses. They can be used as counters in loops, as collecting variables building up a result or as simple containers containing the result of a long-winded expression for easy reference.

These kinds of variables (containers) should be assigned to only once. Else one could think they have more than one responsibility, resulting in your code being less readable. Using a temp for two things is very confusing for the reader. Introduce a new temp for every new thing.

Don't listen to the performance people who say that introducing another variable will use up more memory unnecessarily. Optimize your application where it is having performance bottlenecks and don't believe such silly crap. Registering a new variable within your memory will not eat it up - especially not these days where at least one Gig of RAM is common among the webhosters.

Readable code will lead you to refactorings that will improve upon the application's speed enormously anyway. If you hadn't done the refactoring you would have never gotten the chance of seeing that performance bottleneck in the first place.

Mechanics

  1. Change the name of a temp at its declaration and its first assignment. Don't change collecting or building variables (like $i = $i + some expression; $i .= some expression, etc.).
  2. Change all references of the temp up to its second assignment.
  3. Declare and name a new temp at the second assignment of the old temp.
  4. Repeat the stages, renaming at the declaration and changing references until the next assignment.

Example Code

When calculating two things for the same object, having the same temp for both calculations is quite common. Let's look at a possible scenario for a rectangle and fix it up:

function rectangle($width=1, $height=1) {
  $temp = 2 * ($width + $height);
  echo "Perimter: $temp
"
;
 
  $temp = $width * $height;
  echo "Area: $temp";
}

As you see, $temp is used for both the perimeter and the area computation. It is still readable within that example, but imagine slightly more complicated code. Wouldn't you want the code to look something like the following then instead?

function rectangle($width=1, $height=1) {
  $perimeter = 2 * ($width + $height);
  echo "Perimter: $perimeter
"
;
 
  $area = $width * $height;
  echo "Area: $area";
}

Always introduce a new temp for a different thing. Performance most often is not an issue. Make your code readable, please.

 

Composing Methods: Introduce Explaining Variable

Posted on 2/7/07 by Tim Koschützki

Introduce Explaining Variable

When you have a complicated expression that clutters up your code, introduce temporary variables for parts of the expression so the expression itself is readable again.

Motivation

Expressions can become very complex and hard to read. In such a circumstance temporary variables can be very helpful to maintain the readability of your code.

Introduce Explaining Variable is particularly useful with long if-statements. You can take each condition, introduce an explaining variable and the conditional logic will read very well.
Another occasion is a long algorithmn where each step in the calculation can be explained with a well-named temporary variable.

If you ask me you should prefer Extract Method if you can, because more smaller methods are usually more readable and (re-)usable. However, there are times when Extract method doesn't work, because you the code is too cluttered up. In such a case you should use Introduce Explaining Variable
to see what's going in the code. Then you can decide whether Extract Method is the way to go.

Mechanics

The mechanics of Introduce Explaining Variable are very simple:

  1. Declare a temporary variable and set it to the result of a part of the complex expression.
  2. Replace the result part of the expression with your new temp.
  3. Repeat for other parts of the expression.

Example Code

Okay we start with a calculation for a fictive price of an item. It could look something along the lines of the following:

function price() {
  // price is base price - quantity discount + extra fee
  return $this->quantity * $this->item_price -
    max(0, $this->quantity - 200) * $this->item_price * 0.08 +
    min($this->quantity * $this->item_price * 0.1, 100.0);
}

You probably agree it's very hard to read. We are in dare need of a comment to maintain readability. Without the comment, not only
your colleagues would get lost in the code, but so would you. :) We deicde we can introduce a temp for the base price to start things off:

function price() {
  // price is base price - quantity discount + extra fee
  $basePrice = $this->quantity * $this->item_price;
  return  $basePrice -
    max(0, $this->quantity - 200) * $this->item_price * 0.08 +
    min($basePrice * 0.1, 100.0);
}

Cool, a bit better so far. Now let's go for the quantity discount:

function price() {
  // price is base price - quantity discount + extra fee
  $basePrice = $this->quantity * $this->item_price;
  $quantityDiscount = max(0, $this->quantity - 200) * $this->item_price * 0.08;
  return  $basePrice - $quantityDiscount + min($basePrice * 0.1, 100.0);
}

Finally, the extra fee (whatever it is, it is evil:p):

function price() {
  $basePrice = $this->quantity * $this->item_price;
  $quantityDiscount = max(0, $this->quantity - 200) * $this->item_price * 0.08;
  $extraFee = min($basePrice * 0.1, 100.0);
  return  $basePrice - $quantityDiscount + $extraFee;
}

Notice that with our last refactoring the code speaks for itself and we should remove the comment altogether, as otherwise it would be
Duplicate knowledge.

We could have gone for Extract Method as well,
because small methods for all parts of the price expression would be very neat in an object environment. Why? Because they would be visible to all other methods of the class and can be used there. Initially, they would be private,
but you can always relax that later to make them visible to other objects as well.

Here is what this computation would look like with Extract Method:

function price() {
  return  $this->basePrice() - $this->quantityDiscount() + $this->extraFee();
}

function basePrice() {
  return $this->quantity * $this->item_price;
}

function quantityDiscount() {
  return max(0, $this->quantity - 200) * $this->item_price * 0.08;
}

function extraFee() {
  return min($this->basePrice() * 0.1, 100.0);
}

Looking good yes? For this example Extract method is indeed better, but I couldn't think of anything better to explain Introduce Explaining Variable to you. :) Perhaps some kind of conditional logic to check whether we are on IE or Mozilla would have been nice? Argh, too bad. :)

Cheers!

 

How To Compose Methods: The Extract Method Refactoring

Posted on 28/6/07 by Tim Koschützki

When you have a code fragment that can be grouped together, turn the fragment into a method whose name explains the purpose of the method. Eliminate all conflicts with local variables as you go.

Motivation

Extract Method is one of the refactorings that you will do most often. It just happens too often that as a deadline comes near people tend to take their programming not as seriously as they should. The result? Godclasses and god methods, that try to do too much. If you manage to break classes down into smaller classes and methods into smaller methods you will be better off for several reasons: your code will read like a series of comments; you give other methods a better chance to use your code; you will make your code a lot more testable. Oh and ou will feel a lot more comfortable about your code.

Finally, you will also make your code a lot easier accessible for fellow coders and improve your overall reputation within your company. The problem with short methods is the naming. You really have to pay attention to your naming. With many short methods you will end up with really long names that may be longer than the code in their body. That's perfect, though - don't worry about this. If your method names speak for themselves you are on your way to success.

"So, how long should a method be?" I hear you asking. To me, length is not an issue. They key is the closeness of the method name and the method body. If extracting improves clarity then do it. Even do it, when the new name of the method is longer than its new body.

Mechanics

  1. Create a new method and name it after the new intention of it (name it by what it does and not by how it does it).
  2. Copy the code to extract into the new method.
  3. Check the extracted code for any variables that are local in scope to the source method.
  4. If any temporary variables are only used within your target method, make them local variables there.
  5. Make the local-variable checks: See if Inline Temp or Replace Temp With Query
    make sense. If one variable is modified, you can most often treat the extracted code as a query and assign the result to the variable concerned. If there are several such variables, don't extract the method and try to encapsulate the temporary variables first.
  6. Pass local-scope variables from the source method as parameters into the target method.
  7. Replace the extracted code in the source method with a call to the target method.
  8. Test.

Examples

No Local variables

In its simplest case, extract method can be done on the fly and is trivilially easy:

function printHeader {
  $output = < <<HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">

  <title> PHP Coding Practices - Become an expert PHP Programmer</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
  <meta name="generator" content="WordPress 2.1.1" /> <!-- leave this for stats please -->
        <meta name="verify-v1" content="beuH5Tc0J6zi6YCVt6RnxwIeqR/Zq1WhRwgi7I5hNZo=" />
  <meta name="robots" content="index,follow" />
<meta name="language" content="en" />
<meta name="author" content="Tim Koschuetzki" />

<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="http://php-coding-practices.com/wp-content/themes/digg-3-col/style.css" type="text/css" media="screen" />
  <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://php-coding-practices.com/feed/" />
  <link rel="alternate" type="text/xml" title="RSS .92" href="http://php-coding-practices.com/feed/rss/" />
  <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://php-coding-practices.com/feed/atom/" />
  <link rel="pingback" href="http://php-coding-practices.com/xmlrpc.php" />

    <link rel='archives' title='June 2007' href='http://php-coding-practices.com/2007/06/' />
  <link rel='archives' title='May 2007' href='http://php-coding-practices.com/2007/05/' />
  <link rel='archives' title='April 2007' href='http://php-coding-practices.com/2007/04/' />

  <link rel='archives' title='March 2007' href='http://php-coding-practices.com/2007/03/' />
   
<!-- META Tags added by Add-Meta-Tags WordPress plugin. Get it at: http://www.g-loaded.eu/ -->
<meta name="description" content="We provide easy-to-read, fun and practical articles about php best coding practices. Implement the tips given and you will become an expert php programmer." />
<meta name="keywords" content="php coding practices, best practices, php webdevelopment, coding guidelines, coding standards, coding principles, security, test driven development, unit tests, coding practice principle secure" />
HTML;
  echo $output;
}

This function prints the header of http://php-coding-practices.com. We could as easily define it as:

function printHeader {
  $output = buildDoctype();
  $output .= buildTitle();
  $output .= buildRelations();
  $output .= buildMetaTags();
 
  echo $output;
}

function buildDoctype() {
  $output = < <<HTML
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head profile="http://gmpg.org/xfn/11">
HTML;
  return $output;
}

function buildTitle() {
  $output = < <<HTML
    <title> PHP Coding Practices - Become an expert PHP Programmer
HTML;
  return $output;
}

function buildRelations() {
  $output = < <<HTML
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
    <link rel="stylesheet" href="http://php-coding-practices.com/wp-content/themes/digg-3-col/style.css" type="text/css" media="screen" />
    <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://php-coding-practices.com/feed/" />
    <link rel="alternate" type="text/xml" title="RSS .92" href="http://php-coding-practices.com/feed/rss/" />
    <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://php-coding-practices.com/feed/atom/" />
    <link rel="pingback" href="http://php-coding-practices.com/xmlrpc.php" />
 
      <link rel='archives' title='June 2007' href='http://php-coding-practices.com/2007/06/' />
    <link rel='archives' title='May 2007' href='http://php-coding-practices.com/2007/05/' />
    <link rel='archives' title='April 2007' href='http://php-coding-practices.com/2007/04/' />
 
    <link rel='archives' title='March 2007' href='http://php-coding-practices.com/2007/03/' />
 
HTML;
  return $output;
}

function buildMetaTags() {
  $output = < <<HTML
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    <meta name="generator" content="WordPress 2.1.1" /> <!-- leave this for stats please -->
          <meta name="verify-v1" content="beuH5Tc0J6zi6YCVt6RnxwIeqR/Zq1WhRwgi7I5hNZo=" />
    <meta name="robots" content="index,follow" />
    <meta name="language" content="en" />
    <meta name="author" content="Tim Koschuetzki" />
    <meta name="description" content="We provide easy-to-read, fun and practical articles about php best coding practices. Implement the tips given and you will become an expert php programmer." />
    <meta name="keywords" content="php coding practices, best practices, php webdevelopment, coding guidelines, coding standards, coding principles, security, test driven development, unit tests, coding practice principle secure" />
HTML;
  return $output;
}

Looks much cleaner already, no? Now if we wanted to use variables to build the site title or to load a css file based on user input, then that would be a lot easier than before.

Using Local Variables

The problem with local variables are parameters passed into the original method and temporaries built in the original method. Local variables are only in scope within the source method and they sometimes cause problems or prevent you from doing the refactoring altogether.

The easiest case is when the locals are only read, but not changed. In this case you can just pass them in as parameters:

function printSumOfAnyOtherArrayValue($array) {
  $result = 0;
  $i = 0;
  foreach($array as $value) {
    $i++;
    if($i % 2 == 0) {
      $result += $value;
    }
  }
 
  echo "Some HTML Formatting for the result: {$result}"; // $result is the local in this case
}

I can extract the printing of the result into its own method:

function printSumOfAnyOtherArrayValue($array) {
  $result = 0;
  $i = 0;
  foreach($array as $value) {
    $i++;
    if($i % 2 == 0) {
      $result += $value;
    }
  }
 
  printResult($result);
}

function printResult($result) {
  echo "Some HTML Formatting for the result: {$result}";
}

Reassigning A Local Variables

It's the assignment to locale variables that becomes complicated. If you see an assignment to a parameter you should immediately remove it.

For temps that are assigned to, there are two cases. The simpler cases is that in which the variable is a temp used only in the extracted code. In this case you can remove it into the extracted code.

If the variable is not used after the code is extracted, you can make the change in just the extracted code. If it is used afterward, you need to make the extracted code return the changed value of the variable. Check the following code that illustrates this:

function printSumOfAnyOtherArrayValue($array) {
  $result = 0;
  $i = 0;
  foreach($array as $value) {
    $i++;
    if($i % 2 == 0) {
      $result += $value;
    }
  }
 
  printResult($result);
}

function printResult($result) {
  echo "Some HTML Formatting for the result: {$result}";
}

Now I extract the calculation:

function printSumOfAnyOtherArrayValue($array) {
  $result = calculateSumOfAnyOtherArrayValue($array);
  printResult($result);
}
function calculateSumOfAnyOtherArrayValue($array) {
  $result = 0;
  $i = 0;
  foreach($array as $value) {
    $i++;
    if($i % 2 == 0) {
      $result += $value;
    }
  }
  return $result;
}
 
function printResult($result) {
  echo "Some HTML Formatting for the result: {$result}";
}

The $result variable is used in both places - so I need to return it from calculateSumOfAnyOtherArrayValue(). Now we can rewrite our printSumOfAnyOtherArrayValue() method to:

function printSumOfAnyOtherArrayValue($array) {
  printResult(calculateSumOfAnyOtherArrayValue($array));
}

If something more involved should happen to the $result variable, like an initial value depending on some class attribute, we would pass it to calculateSumOfAnyOtherArrayValue() as a parameter:

function printSumOfAnyOtherArrayValue($array) {
  $result = $this->start;
  $result = calculateSumOfAnyOtherArrayValue($array,$result);
  printResult($result);
}
function calculateSumOfAnyOtherArrayValue($array, $initialValue) {
  $result = $initialValue;
  $i = 0;
  foreach($array as $value) {
    $i++;
    if($i % 2 == 0) {
      $result += $value;
    }
  }
  return $result;
}

After some testing, we can refactor this and make it even better:

function printSumOfAnyOtherArrayValue($array) {
  $result = calculateSumOfAnyOtherArrayValue($array,$this->start);
  printResult($result);
}

Now this looks neat no? Now the calculation of the actual value can be very easily changed. We could just call another calculation method, or strategy, if you want to speak in terms of Design Patterns.

What Happens When More Than One Variable Needs To Be Returned?

Here you have several options. The way I prefer is to have a method for each return value. Usually you can arrange things for that and you will be fine. However, if you somehow can't do it and things look awkward, return an array of return values instead and live with it. Document it as some *nasty* stuff, though, and refactor it again with the next opportunity.

 

Simple global Ajax activity indicator with jQuery

Posted on 27/6/07 by Felix Geisendörfer

Hey folks,

I'm currently doing something very cool which I intend to write about in great detail later on. I'm refactoring all JS for my current web app (the secret one that was supposed to launch like 3 month ago ^^) from an MVC-ish class approach to jQuery plugins. It's gorgeous!. My code is getting smaller, easier to read and more robust. I really can't await writing a more lengthy post about this topic and why I believe that JS is one of the hottest languages these days but requires a different mindset then what we are used to from PHP and other scripting languages.

Anyway, back to the topic. One of the things I just refactored was the code I use to display a little ajax activity indicator so Users know when the app is working on somethings for them. Since the result is a pretty generic little script I thought it might be interesting for others to look at:

$(function() {
    var $headline = $('h1:first');
    $(document).ajaxSend(function() {
        $headline
            .removeClass('activity')
            .addClass('activity');
    });
    $(document).ajaxStop(function() {
        $headline.removeClass('activity')
    });
});

Notes: I don't use the $headline variable out of PHP habits but as a mean to indicate jQuery objects throughout my application. The 'removeClass' call in the ajaxSend closure is neccessary since otherwise you might add the 'activity' class twice to the $headline if two requests are going on at the same time which is something I usually try to avoid.

In the application you can then see a little ajax spinner show up whenever requests are taking place:

I hope some of you find this little snippet useful ; ).

Some unrelated news: I don't know how many unique downloads my svn screencast received but my stats say it swallowed around 250 GB in traffic which is sort of nuts. When I found out about it I was kind of scared for a second but then remembered that I recently upgraded my web hosting plan to one where I have unlimited traffic - which saved me 100 euros in bandwidth fees ; ).

So stay tuned for upcoming stuff like the finished Containable behavior, some other code and posts I got in my backlog as well as the launch of my little web application.

-- Felix Geisendörfer aka the_undefined

 

Things To Avoid In A Team-Programming Environment

Posted on 26/6/07 by Tim Koschützki

I have been working within a team of programmers directly within the same office for almost three months now. It's my first experience of such a nature considering my freelancing background. I am going to share with you, what things, in my opinion, one HAS TO avoid in such an environment.

Putting Parse Errors Into The Version-Control-System

The Problem

Yes of course, this should go without explanation. However, when you are in a rush for a deadline or the person above you is nitpicking or you simply have a bad day, it can happen - you check in parse errors. I have found myself checking in parse errors as well. It's just the desire to get it finally working (!) without thinking about possible consequences. With a test server set up this is usually not a problem. It doesn't improve your reputation among the team, though.

The Solution

Relax. Test everything before you check it in. Simply refresh your current test page to see if a parse error popped up. It only takes five seconds. Five very valuable seconds.

If you find yourself having a bad day, relax even more before you check something in. I have found myself willing to be the fastest in feature completion sometimes. However, well tested, slowly-developed code is a lot more worthy in the longterm.

Undeliberate Code-Replacement

The Problem

Sometimes you are getting conflicts within your version control system, but the person you need to ask which code fragment is the correct one is in a meeting or out to lunch. What do you do? You replace the code with your good will so you can continue working, right? Wrong!

This is again one of those things that only bring a quickfix for your situation, but result in pure malice in the longterm.

The Solution

Relax. Work on something else. Blog a bit ;) or work on another component. Of course in a tightly coupled system this may be a problem, but you always can do something else and wait for the person to check the conflict. The bad news is that conflicts should not happen in the first place as they are a result of miss-communication within the team. However, in a non-OOP environments it tends to happen a lot more often.

Checking In Untested Code

The Problem

Being in a rush for a deadline you forget to test your code thoroughly or even forget to write unit tests for it alltogether. Or, even worse, you are not addicted to writing tests.

The Solution

Make an appointment with yourself to write unit tests. This appointment is just as important as the upcoming meeting with your CEO. Write them. Simple!

They do not need to be under version control. They can be on your local machine and that's it. They just need to be there somewhere and get used.

Wrong Assertions Or Better "What Does It Need To Do Exactly?"

The Problem

You find your own code (components) not returning what is expected by the clients (your colleagues) regularly. This is due to wrong assertions and unclear communication in the phase where requirements for the new code are written down.

The Solution

Well there is no ultimate solution to this, as it boils down to communication problems. The only thing I can suggest is that you think about it from an engineer's perspective: What does come in and what should go out? In which format? What should happen when the wrong thing goes in?

It's these things that make Test-driven Development so successful. TDD forces you think about this stuff a lot more thoroughly.

No Handling Of Exceptional Behavior

The Problem

This goes hands in hands with the last one. You find yourself not handling exceptional behavior (the preconditions for your code are not met) on a regular basis.

The Solution

Make it a quality standard that everything you write takes care of most if not all circumstances possible in your application. If you fetch currency rates from your database and your application's output greatly depends on it, this is extremely critical stuff. Of course, the fetching from the database may go wrong, as the table may be crashed. You at least need to send a critical log email to yourself if this happens. If it happens, show a friendly page to your visitors explaining that something went wrong, without telling them the truth.

If you find yourself developing an application where you lose the overview about in which state the app is in, rewrite it. Simple. The risks of security issues, slow development times etc. far outweigh the time lost without new features in most cases.

Unclear Documentation Within The Code

The Problem

Your code can be understood by you easily. However, your teammates struggle understanding your code. Your code documentation is wrong, is based on wrong assertions or is simply unclear.

The Solution

Keep your code documentation up to date with your thoughts. If you write good code that speaks for itself, less documentation is needed, which is a good thing. Other than that:

  • Make it a quality standard that you use PHP Doc Comments for every little class, method, function or whatever.
  • Document the uneasy code fragments as well. Do not explain what the code does, but explain why it does what it does.
  • Regularly ask your teammates if they understand your code. Do this especially when their code depends on yours.

Finding The One To Blame

The Problem

Your team spends way too much time searching through revision logs to find out whom of the team checked in crappy code that suffers from one or more of things from above.

The Solution

Do not spend your time doing this, it's way too expensive. If everybody works for everybody, the code improves over time to a great extent. We are only humans and mistakes happen. Things in our family and friends may cause us to be unrelaxed and uncomfortable. This may ultimately cause us to "have a bad day", a definite problem from a programmer's point of you. Also some colleagues may be young and have less experience in a team environment (like me :)). Working closely together, building good relationships and "allowing" people to do mistakes eliminates the problems.

Conclusion

I have outlined only some problems that regularly occur in team environments here. However, I think they are some of the most important ones and ones that happen in many teams.

The ultimate thing to prevent these problems is to relax and think about what you are doing. Program consciously so to speak. :) Then sit together with your team, make up your mind with regards to how you can improve the overall team culture and things will improve greatly.

Have a good one!
Tim

 
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48