Wednesday, May 21, 2014

Debug better, faster and make your code stronger

Anyone can code. But when it comes to building a dynamic web or software system, especially from scratch, a tremendous amount of time can be required depending on the chosen approach, the available resources, the design complexity it is given and mainly, your troubleshooting dexterity. Whether the page of code to fix is a stand-alone or depends on another page (one-to-one dependency), or on many other pages (one-to-many dependency) or vice-versa (many-to-one dependency), you definitely want to quickly find the line that is giving you headaches, makes you live in a major depression for days or prevents you from sleeping at night (Developers will recognize themselves in some of these scenarios). Here are 4 must-know reliable debugging medications that will refuel your faith in coding.



- Log files: Undoubtedly, the best clear-cut process to get informative data about a bug. When setup properly, they can help you record operations, system processes and errors that occur during the execution of a code. You can use the built-in log of the used IDE system or web server. For instance, in Apache, it is possible to configure the logs by editing your site's config file (In Linux, it is generally /etc/apache2/sites-available/mysite)
Furthermore, it is possible to write your own log method if you are not satisfied with the built-in one. An efficient way to do it is by asking yourself 3 questions: what message do I want to record (the content), what type of message to record (error, info, debug,..) and the context in which the message is recorded (the time, the location, the referrer,...). A full example of a log entry would look like this:
Error :: user [Joe Smith] data [<junk entry123>] didn't match rule 107 :: 5/8/2014 @ 2:46pm

- Breakpoints: If you have never heard of this one, you better start digging into it. These are temporary halters that are used to stop the program in specific locations so that the status of the program can be examined in stages. It is really useful in isolating the line that is running, and even the called variable, when the code goes south . In C#, the code can be broken via the System.Diagnostics.Debugger.Break() method; stop in VB, vardump()/die() in PHP. Their location in your code is up to you. However, it's a good practice to make the interpreter/compiler hit the breakpoint ONLY when you are debugging; otherwise, in production, it will continue to hit it and may abruptly reveal confidential data to users or break the program run.

- Stack traces extraction: Sometimes, you have situations where functions have to nestedly collaborate in order to have a well-implemented code i.e function a() calls function b() which calls function c() and so on and so forth. Such coding style is pretty much prevailing in complex systems and tracking a bug in this kind of vicious circle becomes a nightmare when you have hundreds of functions to scrutinize. To find the x-spot, it is more appropriate and time saving to have a broad view on the code execution; and the memory is the best place to have it. By enabling a run report on the memory stack frames, you will be able to detect that specific function where the error occurs, which considerably reduces your investigation domain. Some open-source extensions/plugins are available to do this memory forensics: Xdebug which is widely used by PHP developers and even has a plugin for Firefox. In C/C++, we have the powerful GDB that is also breakpoints-capable.

- Hard coding: This approach is mainly meant to variables definition issues and consists of implanting the input data directly in the source code. For instance, suppose you are working on integrating an API authentication system in your code and after a visual review of your code, everything looks fine : the API call, the syntax and the logic. Furthermore let's say the API call is used as follow:
function useAPI ($username, $password){
$message = loginAPI ($username, $password);
if($message == "good") {makeCall(); return "Ok"; } else return ""Bad password/login";
}

Now, when you run the code, things get unpropitious and a response like "Bad password/login" is returned to you despite the correctness of the passed credentials. Given the message, the blame is definitely not on the makeCall() function; thus, the first wise move would be to investigate on loginAPI() by hard coding the parameters sent to it. If the subsequent result is still the same, then the probability that the API URL used in loginAPI() is wrong is pretty high. If the result was different ("good") after the hard coding, then the bug would simply reside in the mistyping of the credentials initially sent to useAPI() during the earlier run.

As you may have already noticed, the techniques shown earlier are more of a dynamic analysis approach (i.e to find the bug you have to execute the code/program). If you want to use static analysis to find the bug, it might be a bit more onerous to achieve depending on the model, data flow and logic of the platform to fix.

No comments:

Post a Comment