{"id":"debugging-names-comments","slug":"names-and-comments","title":"Names and comments","text":"When you read your own code, you tend to see what you *meant* to write, not what's actually there. That's why a bug can sit in plain sight while you read over it again and again.\n\nTwo habits make code easier to read, both for others and for you next week.\n\n### Names that say what a value is\n\nCompare these two versions of the same calculation:\n\n```java\nint a = 3;\nint b = 250;\nint c = a * b;\nSystem.out.println(c);\n```\n\n```output\n750\n```\n\n```java\nint tickets = 3;\nint priceInCents = 250;\nint totalInCents = tickets * priceInCents;\nSystem.out.println(totalInCents);\n```\n\n```output\n750\n```\n\nBoth work, but only the second one tells you what it does. A wrong line such as `int totalInCents = tickets + priceInCents;` stands out when the names make sense, and hides easily among `a`, `b` and `c`. Short names are fine where the meaning is obvious, such as `i` for a loop counter.\n\n### Comments that explain why\n\nYou met comments in module 1: `//` runs to the end of the line, and `/*` runs until `*/`. Java skips them, so they're written for people:\n\n```java\n/* Prices are kept in cents,\n   so no rounding happens. */\nint priceInCents = 250;\n// A discount of 10 percent on orders of 4 or more\nint tickets = 4;\nif (tickets >= 4) {\n    priceInCents = priceInCents * 90 / 100;\n}\nSystem.out.println(tickets * priceInCents);\n```\n\n```output\n900\n```\n\nGood comments say what the code can't: why it's written this way, or what a rule means. A comment that repeats the code (`// adds one to count` above `count++;`) adds nothing, and a comment that no longer matches the code is worse than none.\n\nA comment that states a rule is also a debugging aid: when the code and the comment above it disagree, one of them is wrong, and you've found where to look.\n","task":"In this ticket program, one line doesn't do what the comment above it says. Find it and fix the code (the comments are right). With the input `5` it prints:\n\n```\nTotal: 5200 cents\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int tickets = Integer.valueOf(scanner.nextLine());\n        int priceInCents = 1250;\n        // Groups of 5 or more get 20 percent off each ticket\n        if (tickets > 5) {\n            priceInCents = priceInCents * 80 / 100;\n        }\n        // A booking fee of 200 cents is added once per order\n        int totalInCents = tickets * priceInCents + 200;\n        System.out.println(\"Total: \" + totalInCents + \" cents\");\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int tickets = Integer.valueOf(scanner.nextLine());\n        int priceInCents = 1250;\n        // Groups of 5 or more get 20 percent off each ticket\n        if (tickets >= 5) {\n            priceInCents = priceInCents * 80 / 100;\n        }\n        // A booking fee of 200 cents is added once per order\n        int totalInCents = tickets * priceInCents + 200;\n        System.out.println(\"Total: \" + totalInCents + \" cents\");\n    }\n}\n","hints":["Read each comment, then check the line under it against it, for a group of exactly 5.","\"5 or more\" includes 5: the condition should be `tickets >= 5`."],"tests":[{"name":"Test 1","stdin":"5\n","expect":"Total: 5200 cents","hidden":false},{"name":"Test 2","stdin":"4\n","expect":"Total: 5200 cents","hidden":true},{"name":"Test 3","stdin":"6\n","expect":"Total: 6200 cents","hidden":true},{"name":"Test 4","stdin":"1\n","expect":"Total: 1450 cents","hidden":true}],"require":[],"forbid":[],"more":[{"task":"This program works, but its names hide what it does. It reads a distance in kilometers and a time in minutes, and prints the average speed in kilometers per hour. Rename the variables `a`, `b` and `c` to names that say what they hold (the output must stay the same). With the input `42` and `210` it prints:\n\n```\nAverage speed: 12.0 km/h\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        double a = Double.valueOf(scanner.nextLine());\n        double b = Double.valueOf(scanner.nextLine());\n        double c = a / (b / 60);\n        System.out.println(\"Average speed: \" + c + \" km/h\");\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        double kilometers = Double.valueOf(scanner.nextLine());\n        double minutes = Double.valueOf(scanner.nextLine());\n        double kilometersPerHour = kilometers / (minutes / 60);\n        System.out.println(\"Average speed: \" + kilometersPerHour + \" km/h\");\n    }\n}\n","hints":["`a` is the distance, `b` the time in minutes, and `c` the speed. Change every place a name is used, not only where it's declared.","For example `kilometers`, `minutes` and `kilometersPerHour`."],"tests":[{"name":"Test 1","stdin":"42\n210\n","expect":"Average speed: 12.0 km/h","hidden":false},{"name":"Test 2","stdin":"10\n30\n","expect":"Average speed: 20.0 km/h","hidden":true}],"require":[],"forbid":[{"pattern":"\\b(double|int)\\s+[a-z]\\s*=","message":"Give every variable a name of more than one letter that says what it holds."}]},{"task":"What does this program print? Watch for the comments.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        int lives = 3;\n        // lives = lives + 1;\n        System.out.println(\"Lives: \" + lives);\n        /* lives = 0;\n        System.out.println(\"Game over\"); */\n        lives--; // one hit\n        System.out.println(\"Lives: \" + lives);\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        int lives = 3;\n        // lives = lives + 1;\n        System.out.println(\"Lives: \" + lives);\n        /* lives = 0;\n        System.out.println(\"Game over\"); */\n        lives--; // one hit\n        System.out.println(\"Lives: \" + lives);\n    }\n}\n","hints":["Java skips everything after `//` on a line, and everything between `/*` and `*/`.","Only three statements run: the first print, `lives--;` and the last print."],"tests":[{"name":"Output","stdin":"","expect":"Lives: 3\nLives: 2","hidden":false}],"require":[],"forbid":[],"lines":["Lives: 3","Lives: 2"]}]}