Skip navigation
Currently Being Moderated

Sharing Knowledge: Effective way of coding (Give suggestions)

Mar 14, 2012 1:50 AM

Hi All,

 

Assume you have a case that you need to perform a condition check and then add string based on that condition.

 

Usually we'll (I did) do nested if else conditions. But recently I have came across a code this will avoid multiple if else statements.

 

Example:

With Nested IF conditions

 

if (app.documents.length == 1){
    var inddDoc = app.documents.item(0);
    }
else{
    if (app.documents.length == 0){
        alert("Please open a document");
        }
    else{
        alert("More than one document is opened\rPlease close other documents");
        }
    }

 

Effective way (according to me)

 

if (app.documents.length == 1){
    var inddDoc = app.documents.item(0);
    }
else{
    alert(app.documents.length == 0?"Please open a document":"More than one document is opened\rPlease close other documents");
    }

 

Your sugesstions are welcome, and please do share the similar kind of techniques if anyone have.

 

Green4ever

 

Message was edited by: Green4ever

 
Replies
  • Currently Being Moderated
    Mar 14, 2012 3:42 AM   in reply to Green4ever

    The (condition) ? (if true) : (if false) construction is quite powerful, but it sometimes makes it easy to write unmanageable code. If, for example, you start with two conditions, you can use it as you show here. If you have to add a third option, you can even expand it:

     

    (condition¹) ? (true¹) : ((condition²) ? (true²) : (false));

     

    and so on (yeah I find myself doing this at times). If your scripts are meant to be read by someone else, Clarity Rules! And "someone else" may very well be you -- six months later.

     

    Note that nested if/else also tend to get confusing after the third or fourth or so. If you are performing actions based on the number of items, and it's either 1 or 2 (or 0 or 1), you can safely use an if/else. For anything more, you should use a switch:

     

    switch (app.documents.length)

    {

      case 0: alert ("none"); break;

      case 1: okayGoAhead (); break;

      default: alert ("two or more"); break;
    }

     

    That way,  you can easily add 'case 2', 'case 3' etc., or remove 'case 0' if your function can work with it after all.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 14, 2012 5:26 AM   in reply to Green4ever

    The SDK way is like this:

     

    do{

     

    if(condition1 == false)

    break;

    if(condition2 == false)

    break;

    if(condition3 == false)

    break;

    if(condition4 == false)

    break;

     

    // all conditions passed

    doYourStuff()

     

    }while(false)

     

    Harbs

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 14, 2012 7:21 AM   in reply to Green4ever

    To me switch/case is usually the way to go when you have to process various conditions. The code is cleaner and more flexible, I think.

     

    In very specific cases, however, you can directly select a choice—or an action—through a litteral Array.

     

    For example:

     

    alert( ["No document!", "OK (1 document)", "More than one document."][Math.min(2,app.documents.length)] );
    

     

    or:

     

    [myFunc0, myFunc1, myFuncMore][Math.min(2,app.documents.length)]();
    

     

    @+

    Marc

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 15, 2012 12:41 AM   in reply to Green4ever

    You can shorten it more:

     

    function getDate_Time() {
        var
            dTime = new Date(),
            hours = dTime.getHours(),
            minute = dTime.getMinutes(),
            period = ((hours > 12)?"PM":"AM"),
            dd = dTime.getDate(),
            mm = dTime.getMonth()+1,
            yyyy = dTime.getFullYear();
        hours = ((hours > 12) ? hours - 12 : hours);
        dd<10?dd='0'+dd:0;
        mm<10?mm='0'+mm:0;
        var time_Day = mm+'/'+dd+'/'+yyyy+" @ "+hours+":"+minute+" "+period;
        return time_Day;
    }
    

     

    --

    Marijan (tomaxxi)

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 15, 2012 1:13 AM   in reply to Marijan Tompa

    And even shorter:

     

    // ...
    hours > 12 && (hours-=12);
    dd < 10 && (dd='0'+dd);
    mm < 10 && (mm='0'+mm);
    // ...
    

     

    @+

    Marc

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 15, 2012 4:40 AM   in reply to Green4ever

    If you have a lot of conditions and some of them could be complex, do/while/false is the flattest and easiest-to-read method. You find this code pattern a LOT in the InDesign SDK.

     

    Harbs

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 15, 2012 5:53 AM   in reply to Harbs.

    Until I started writing plugins I could not understand why do / while code was used. It really is the best method when you have conditions that rely on the success previous conditions.

     

    P.

     
    |
    Mark as:
  • John Hawkinson
    5,572 posts
    Jun 25, 2009
    Currently Being Moderated
    Mar 15, 2012 6:29 PM   in reply to Harbs.

    Umm, what language are we talking about here? It looks like ExtendScript.

    If so, then when Harbs says:

    If you have a lot of conditions and some of them could be complex, do/while/false is the flattest and easiest-to-read method. You find this code pattern a LOT in the InDesign SDK.

    I really don't think so at all!

    It's a pattern that is not seen much outside of C++ and of the SDK, is I really wouldn't suggest it in JavaScript.

    Instead, I would just chain the ifs and cheat the indentation, like this:

     

    if (app.documents.length == 1){
        var inddDoc = app.documents.item(0);
    } else if (app.documents.length == 0){
        alert("Please open a document");
    } else {
        alert("More than one document is opened\rPlease close other documents");
    }
    

     

    You can have as many "else if" blocks as you like, before the final else.

    It's easy to read, makes sense, and is a very-established pattern.

     

    Also, of course, you should be using === not ==, unless you have a very good reason.

     
    |
    Mark as:
  • John Hawkinson
    5,572 posts
    Jun 25, 2009
    Currently Being Moderated
    Mar 15, 2012 6:32 PM   in reply to John Hawkinson

    Sorry, I left out one of the strongest reasons to avoid do { if / break / if / break ... / } while (false).

    It's easy to forget a 'break' and have your code go completely awry. It's much nicer when the language's syntax conventions encourage you to do the right thing.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 16, 2012 3:36 AM   in reply to John Hawkinson

    Horses for courses.

     

    If I have some conditions that cause a need to abort, I'll use if(condition)return; for each one. (no do/while/false)

     

    If I need to do something different for each case, I'll usually use a switch.

     

    switch (app.documents.length){

         case 0:

              alert("Please open a document");

              break;

         case 1:

              var inddDoc = app.documents.item(0);

              break;

         default:

               alert("More than one document is opened\rPlease close other documents");

              break;

    }

     

    If things are complex and I have just a few conditions I'll use if/else.

     

    If things are really complex, I'll use do/while/false.

     

    For me, the most important aspect of code is readability. Whatever fits the situation...

     

    Harbs

     
    |
    Mark as:
  • John Hawkinson
    5,572 posts
    Jun 25, 2009
    Currently Being Moderated
    Mar 19, 2012 12:23 AM   in reply to Green4ever

    Green4ever:

    var myValue1 = 1;
    myValue1 = ("000"+myValue1).slice(-3);

     

    Is there any other better way to achieve this.

    This code is not good for several reasons!

    Most importantly, it breaks for numbers bigger than 3 digits! That's horrible.

    Even if it was unlikely to happen in the original application, when you advertise it like this it's going to be repurposed and someone is going to have a nasty surprise some day! Not good! It's rare that this sort of code needs to run in a tight loop where perfect optimization and performance are more important than correctness. Take the time to do it right!

     

    Secondarily, you are using a single variable (myValue1) to hold two different kinds of objects, first an Number and later a String. That is usually not a good idea. It's not terrible, but it does tend to lead to confusion about what type the variable is at any given time, and string functions don't work well on numbers and vice versa. Much better to use two different variables.

     

    I'd probably take the first answer from http://stackoverflow.com/questions/2998784/how-to-output-integers-with -leading-zeros-in-javascript

    which suggests:

     

    function pad(num, size) {
        var s = num+"";
        while (s.length < size) s = "0" + s;
        return s;
    }
    


     
    |
    Mark as:
  • Currently Being Moderated
    Mar 19, 2012 12:26 AM   in reply to Green4ever

    There was a discussion on the forum a while back about this.

     

    slice() is probably the best way to go.

     

    You can generalize that with the following function (originally posted by Peter Kahrel):

     

    alert("myValue1 = " + pad(myValue1,3)+"\rmyValue2 = "+ pad(myValue2,3));
    function pad (num, len) {
        return ("0000000"+num).slice(-len);
    }
    

     

    Harbs

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 19, 2012 12:34 AM   in reply to John Hawkinson

    Personally, I like this answer from that discussion:

     

    function zfill(num, len) {return (Array(len).join("0") + num).slice(-len);}

     
    |
    Mark as:
  • John Hawkinson
    5,572 posts
    Jun 25, 2009
    Currently Being Moderated
    Mar 19, 2012 1:08 AM   in reply to Harbs.

    I agree that ithinc's answer with zfill() appears the most elegant. My inclination is to avoid the low-voted answers that look good because oftentimes they have subtle problems. This one looks OK to me, though.

     

    Of course, it's fairly disappointing to me that none of them properly handle negative numbers, or decimals, or NaN.  Bah!

     

    One probably doesn't care, but zfill() fails with big large numbers and small roundings, but pad() works ok:

     

    [04:03:49.850] pad(Number.MAX_VALUE,5)

    [04:03:49.852] "1.7976931348623157e+308"

    [04:03:54.122] zfill(Number.MAX_VALUE,5)

    [04:03:54.124] "e+308"

     

    If you try hard enough, maybe you can find a case where zfill() works and pad() fails? Or at least where it is faster?

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 19, 2012 1:48 AM   in reply to Harbs.

    @Harbs – a bit dangerous.

     

    One have to make sure that:

     

    len !< num.toString().length;
    

     

    Otherwise we possibly get truncated numbers on return.

     

    Uwe

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 19, 2012 5:33 AM   in reply to Laubender

    Good point.

     

    Of course this is all pretty silly unless you are writing a library for public consuption.

     

    For personal use, I'd just go with enough zeros as necessary and use a simple slice()...

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (1)