Lesson Tuesday

In the previous lesson, we wrote and tested the business logic for our leap year application. We know our program is successfully demonstrating all necessary behaviors because all of our specifications are passing! Additionally, because we made sure to implement the least amount of code to make each spec pass, and refactor along the way, we have clean, easy-to-read code. Perfect!

Now that our business logic is in place, let's include additional user interface logic.

Business Before User Interface

In your level 2 course you will learn how to write coded, automated tests to assist in the BDD process. When these tools are available we will not write user interface logic until all basic back-end logic is present and passes specs.

Because we're testing manually in Intro to Programming, we had to begin with basic HTML and user interface logic to see our results. This is absolutely alright for now, just know that user interface logic should not be written until after business logic is complete in your level 2 course.

User Interface

As mentioned, we simply created the bare minimum user interface to allow us to manually test our application. Now that all necessary business logic is present, and passes all of our tests, let's add more.

We'll spruce up the output section of our page (the result div) so that we can present the user with a descriptive message instead of a terse true or false:

leap-year.html
<!DOCTYPE html>
<html>
  <head>
    <link href="css/bootstrap.css" rel="stylesheet" type="text/css">
    <link href="css/styles.css" rel="stylesheet" type="text/css">
    <script src="js/jquery-1.12.0.js"></script>
    <script src="js/scripts.js"></script>
    <title>Leap year detector</title>
  </head>
  <body>
    <div class="container">
      <h1>Leap year detector</h1>

      <form id="leap-year">
        <div class="form-group">
          <label for="year">Enter a year and find out if it's a leap year:</label>
          <input id="year" type="text">
        </div>

        <button type="submit" class="btn">Find out!</button>
      </form>

      <div id="result">
        <p><span class="year"></span> is <span class="not"></span> a leap year.</p>
      </div>
    </div>
  </body>
</html>

We'll add CSS to hide the div that will display the result until the evaluation is completed:

css/styles.css
#result {
  display: none;
}

Then, we'll update our user interface logic to appropriately fill the spans in our HTML based on the value of result:

js/scripts.js
// business logic
var leapYear = function(year) {
  if ((year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0)) {
    return true;
  } else {
    return false;
  }
};

// user interface logic
$(document).ready(function() {
  $("form#leap-year").submit(function(event) {
    event.preventDefault();
    var year = parseInt($("input#year").val());
    var result = leapYear(year);

    $(".year").text(year);

    if (!result) {                 // same as writing if (result === false)
      $(".not").text("not");
    } else {
      $(".not").text("");
    }

    $("#result").show();
  });
});

In the code above, we do the following:

  • Add the contents of the year variable into a span with the class year.
  • If the result variable is false we set the text of the not span to "not", so that our page will read "is not a leap year".
  • If the result variable is true we instead empty thenot span, so that our page will read "is a leap year".
  • Finally, we show our entire result div so that the user can see their results.

Separation of Logic

It is important to understand why this code belongs in user interface logic. We could theoretically just have our business logic return a formatted string that said "____ is a leap year", or "_____ is NOT a leap year", but this seriously mixes up business and user interface logics. After all, we're displaying our results in sentence format for the user's sake. It's therefore user interface logic.

Additionally, what if we later wanted to change the message containing the user's results? We would have to modify the business logic to change the display! This may not seem like a big deal in such a small app, but imagine doing something similar in an application with thousands, even millions of lines of code! You'd have to unravel countless lines of back-end logic just to change the way something is displayed to the user.

Focus on developing good habits early on, even if they seem like overkill for these smaller projects. Not only will this make it easier to navigate your own code as our projects grow in size and complexity, but it will make it easier for other developers to collaborate with you, and is considered far more professional.

Always keep your business and user interface logic separate. Follow the BDD process to clearly outline your program's intended behaviors. Focus on one behavior at a time. And write the minimum code to make each spec pass. Developing these habits now will make tackling the complex applications you'll soon build far easier!

Terminology

Business logic: The code responsible for handling the evaluation and manipulation of data; does not require any user interface.

User interface logic: The code responsible for the interaction between the user and the application; handles tasks such as event listening, user input forms, DOM manipulation, display and styling.

Sample code

leap-year.html
<!DOCTYPE html>
<html>
  <head>
    <link href="css/bootstrap.css" rel="stylesheet" type="text/css">
    <link href="css/styles.css" rel="stylesheet" type="text/css">
    <script src="js/jquery-1.12.0.js"></script>
    <script src="js/scripts.js"></script>
    <title>Leap year detector</title>
  </head>
  <body>
    <div class="container">
      <h1>Leap year detector</h1>

      <form id="leap-year">
        <div class="form-group">
          <label for="year">Enter a year and find out if it's a leap year:</label>
          <input id="year" type="text">
        </div>

        <button type="submit" class="btn">Find out!</button>
      </form>

      <div id="result">
        <p><span class="year"></span> is <span class="not"></span> a leap year.</p>
      </div>
    </div>
  </body>
</html>
css/styles.css
#result {
  display: none;
}
js/scripts.js
var leapYear = function(year) {
  if ((year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0)) {
    return true;
  } else {
    return false;
  }
};

$(document).ready(function() {
  $("form#leap-year").submit(function(event) {
    event.preventDefault();
    var year = parseInt($("input#year").val());
    var result = leapYear(year);

    $(".year").text(year);

    if (!result) {                 // same as writing if (result === false)
      $(".not").text("not");
    } else {
      $(".not").text("");
    }

    $("#result").show();
  });
});