Home » Best Practices » How to Write a IF Statement that determine a value

How to Write a IF Statement that determine a value

Pretty much a basic case if you have done some programming. How to write a IF statement is an agnostic problem when it’s to assign one or multiple variables to be used. There is two patterns that I often see. The first one assign the variable or property directly.

if (/*what ever*/) {
    this.icon = "icon1";
}
else {
    this.icon = "icon2";
}

The second approach set the value into a temporary, scoped, variable and at the end of the IF assign the value to the field/property.

var iconType = "";
if (/*what ever*/) {
    iconType  = "icon1";
}
else {
    iconType  = "icon2";
}
this.icon = iconType ;

These two examples could be that instead of assigning to this.icon would be that we call this.featureMethod(icon). Like the two examples above, in the first approach, you would see the method twice, while on the second approach you would assign the value into a variable and have the method call once at the end. The first approach is appealing because you do not have to assign a temporary variable. However, we have code duplication that doesn’t seem to bother most people. The real problem is in code maintenance. If the method that needs to be invoked change it’s signature, you have two places to change instead of 1. If the IF become with more condition (else if) you will have to call the method (or assign field/property) few more times instead of just keeping a single call. These two argumentation leans in favor of the second approach and there is more. The second approach is cleaner in term of figuring out what is going on. The first approach is taking a decision and executing at the same time. If you look at the method, you cannot have a clear view of what is happening. From top to bottom you have multiple sections that do a condition check + action. Thus, the second approach is cleaner. We could even break down the code into two distinct part: arrange and act. We could refactor the method into 2 sub-methods which one determines the values to be used and the second that set values or calls methods.

I am bringing that point because the first approach seems to be taken with the argument that it’s the same as the second one. The real justification is that the first one is taking 2 lines of code less, hence faster to type which make it an easy default choice. If you are using the first approach, I suggest that you try for few times the second approach. You will see the benefits slowly when working and modifying that code again in the future.

here is an example of 3 temporary variables

function getMyLink(threshold: number) {
    // Default
    let url: string = "http://aboveHundred.com";
    let className: string = "default";
    let padding: number = 0;
    // Logics
    if (threshold <= 0) {
        url = "http://underOrZero.com";
        className = "dark-theme";
        padding = 100;
    }
    else if (threshold > 0 && threshold < 100) {
        url = "http://betweenZeroAndHundred.com";
        className = "light-theme";
        padding = 200;
    }
    // Assignments
    this.url = url;
    this.className = className;
    this.padding = padding;
}

If the next iteration of changes in the code requires to change one of the assignment to other variable, we have a single place to change. If instead of assigning we need to return something, we also have a single place to change.

function getMyLink(threshold: number) {
    // Default
    let url: string = "http://aboveHundred.com";
    let className: string = "default";
    let padding: number = 0;
    // Logics
    if (threshold <= 0) {
        url = "http://underOrZero.com";
        className = "dark-theme";
        padding = 100;
    }
    else if (threshold > 0 && threshold < 100) {
        url = "http://betweenZeroAndHundred.com";
        className = "light-theme";
        padding = 200;
    }
    // Now we return
    return `<a href="${url}" class="${className}" style="padding:${padding}">Click Here</a>`;
}

In term of flexibility, you may have to define these variables but the code is structured to be well resistant to future changes. Also, when a function requires a lot of assignation, it is often a case that the method will be long. It means that it’s even harder to have an idea of what is going on if assignations are done all over the function. I strongly believe that while assigning a long list of variables can be cumbersome that assigning them directly to several places reduce the readability and introduce more error (like forgetting one assignment in a specific case which keep an old assignment).

There are pros and cons in both, but the one I illustrate has more pros than cons in my opinion.

To recap about the advantage of having to assign values and then calling or assigning:

  • Remove code duplication
  • Easier refactoring since only one signature to change
  • Clearer readability of what happen into a method
  • Allow faster refactoring into smaller methods

If you like my article, think to buy my annual book, professionally edited by a proofreader. directly from me or on Amazon. I also wrote a TypeScript book called Holistic TypeScript

7 Responses so far.

  1. nico says:

    this.icon = /*what ever*/? “icon1” : “icon2”;

    • This is a shorthand that is totally acceptable if you have only a single value to set with a IF/ELSE only condition.

      However, I often see this kind of structure not growing well. Often, they tend to get more complex or to have imbricated ternary operator which make it shorter but harder to read. They often are repeated with almost the same condition few lines apart to assign many variables as well.

      The article targetted the scenario of assigning directly in multiple places (could be more than a single IF and else) against using a variable and assigning once. However, thanks for the mention. I should probably write something the pros and the cons of the ternary operator.

      • nico says:

        Indeed your way of doing it can apply to more than one variable. But does it really grow well?
        If you have 5 values to set, you have to create 5 temporary variables
        var iconType = “”;
        long var2 = 0;
        string var3 = “default “;
        string var 4 = “x”;
        float var5 = 1;

        then after your test and processing you have to do 5 allocations?
        The number of lines grows quickly.

        If this processing is just a small part of your method then it may make sense to have the added readability. But if you try and keep your methods small, you are probably already focusing on the processing of those 5 variables, therefore going through the code inside the if/else statement shouldn’t be too much of a distraction?

        • Hi Nico,

          Thank you for your time. I appreciate your perspective.

          To illustrate my point here is an example with 3 temporary variables

          function getMyLink(threshold: number) {
              // Default
              let url: string = "http://aboveHundred.com";
              let className: string = "default";
              let padding: number = 0;
              // Logics
              if (threshold <= 0) {
                  url = "http://underOrZero.com";
                  className = "dark-theme";
                  padding = 100;
              }
              else if (threshold > 0 && threshold < 100) {
                  url = "http://betweenZeroAndHundred.com";
                  className = "light-theme";
                  padding = 200;
              }
              // Assignments
              this.url = url;
              this.className = className;
              this.padding = padding;
          }
          

          If the next iteration require to change one of the assignment to other variable I have a single place to change. If instead of assigning I need to return something, I also have a single place to change.

          function getMyLink(threshold: number) {
              // Default
              let url: string = "http://aboveHundred.com";
              let className: string = "default";
              let padding: number = 0;
              // Logics
              if (threshold <= 0) {
                  url = "http://underOrZero.com";
                  className = "dark-theme";
                  padding = 100;
              }
              else if (threshold > 0 && threshold < 100) {
                  url = "http://betweenZeroAndHundred.com";
                  className = "light-theme";
                  padding = 200;
              }
              // Now we return
              return `<a href="${url}" class="${className}" style="padding:${padding}">Click Here</a>`;
          }
          

          In term of flexibility, you may have to define these variables but the code is structured to be well resistent to future changes.

          Also, when a function requires a lot of assignation, it is often a case that the method will be long. It means that it’s even harder to have an idea of what is going on if assignations are done all over the function. I strongly believe that while assigning a long list of variables can be cumbersome that assigning them directly to several places reduce the readability and introduce more error (like forgetting one assignment in a specific case which keep an old assignment).

          There are pros and cons in both, but the one I illustrate has more pros than cons in my opinion.

          • nico says:

            I think this is a great example, it illustrates your point better than your original example.

      • nico says:

        Just as I’m coding something I noticed that I use your pattern quite often, but I guess for another reason. I’m trying to avoid mistakes, and make it easy to make a change the code without introducing a bug.

        The idea is that processing can take any “path” inside the test cases, taking either a short simple route or a more complex one. Whenever you stop processing or avoid going to inside a if statement/loop, your current value stands. You do only a single assignment at the end, which is less error-prone.

        double? result = null;
        if( conditionA)
        {
        foreach( …)
        {
        if(TryParse)
        {
        result = X;
        continue;
        }
        else
        result = max(res, …)
        }
        }
        else if( conditionB)
        {
        }
        else
        {
        }
        myObj.Result = result;

        So I guess I do agree with you when the processing is more than a simple if/else

        • Hello Nico, we both wrote at the same time 🙂 Your last message is aligned with the response I gave to you in your previous responses. By the way, I like the code you just posted. To me, it is clear and less error-prone to do the way you wrote.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.