These are the general style qualities that we expect your web pages to have in order to receive full credit. Certainly it is possible to write good code that violates these guidelines, and you may feel free to contact us if you are unclear about or disagree with some of them. But we do expect you to follow these rules (unless there is an error in this document). In most professional work environments you are expected to follow that company's style standards. Learning to carefully obey a style guide, and writing code with a group of other developers where the style is consistent among them, are valuable job skills.
This document is a work in progress.
Any guidelines written here are in addition to what is mentioned in the given assignment's spec, so you are responsible for reading that spec and following its instructions.
Last updated Mon 2013/04/04
indenting: Increase your indentation by one increment (one tab, or four spaces, etc., consistently) every time you open a new block-level element, and decrease it once each time you close a block element.
line breaks: Place a line break after every block element. Do not place more than one block element on the same line.
<!-- bad -->
<p>Hello, how are you</p> <p>I am fine</p>
<!-- good -->
<p>Hello, how are you</p>
<p>I am fine</p>
long lines: We permit long lines, but never begin a block element past character index 100 on a given line. When any line is longer than 100 characters and you need to begin a new block element, break it into two lines by pressing Enter after a token and resuming on the next line.
blank lines: Place a blank line between sections of the page and between large elements containing a lot of content.
elements: Do not place whitespace between a tag's < brace and the element name.
< p >
<p>
self-closing tags: End them with a space, followed by />
.
<br>
<br />
choosing semantic tags: Choose appropriate tags that represent the semantic meaning of the content.
For example, do not use a <p>
tag around something that is not a paragraph, or do not use a <h4>
unless you have already previously used h1-h3
for three other more important levels of headings, or do not use a blockquote
just because you want some non-quote content to be indented to the right.
closing tags: You should close ALL tags, unless they are self-closing.
For example, every <p>
should have a corresponding </p>
, and every <li>
should have a corresponding </li>
.
Note that the HTML5 validator does not require this, but we do.
<p>first paragraph <p>second paragraph <ul> <li>first item <li>second item <li>third item </ul>
<p>first paragraph</p> <p>second paragraph</p> <ul> <li>first item</li> <li>second item</li> <li>third item</li> </ul>
nesting: Close tags in the opposite order in which they were opened.
Always nest every inline element inside of a block element.
(For example, don't just put an <a>
tag directly inside the body
; instead, place it inside a p
or li
or other block-level element.
presentational tags: Do not ever use deprecated tags whose meaning is entirely based on their appearance, such as b
, i
, u
, big
, small
, center
, or font
. (Use CSS instead to achieve such an appearance.)
attributes: Do not place a space between an attribute's name, the equals sign, and its value. Enclose the value in " " quotes, not bare, and not in ' ' apostrophes.
<a href = 'foo.html'>
<a href="foo.html">
boolean attributes: For attributes that are essentially boolean flags, set them equal to themselves.
<input type="text" disabled />
<input type="text" disabled="disabled" />
img
tag alt
attribute: Every img
tag must have an alt
attribute so that it can be understood by visually impaired users.
<img src="kittens.jpg" />
<img src="kittens.jpg" alt="a long cat" />
names: When giving an element an id
or class
, give it a descriptive name, such as mainheading
or announcements
.
Avoid one-letter names like x
or c
.
capitalization: Always favor lowercase, for elements, for attributes and their values, for classes and ids. Multi-word names for classes and ids should simply concatenate the words in lowercase without any in-between character (such as _) and without capitalization of the next word.
<h1 id="first_heading"> <P Class="importantReminder">
<h1 id="firstheading"> <p class="importantreminder">
class vs. id: Choose appropriately between classes and ids.
If an element belongs to a general category that can include multiple elements, use a class
.
If it is a unique part of the page that deserved to be named on its own, use an id
.
class-itis and id-itis: Do not over-use classes and ids on elements that do not need them.
If an equivalent style can be described cleanly using a CSS context selector such as .announcements li > strong
rather than a class or id, consider doing that instead.
A class or id is still more appropriate than a context selector if the context is very complicated or not really related to the styling.
tables for layout: Do not use HTML table
tags to lay out the contents of a web page.
For example, it is inappropriate to use a table
to divide the page's main content sections into columns, or to get a sidebar or navigation bar, etc.
Instead, use div
and other related tags along with the CSS box model and the float
property as appropriate.
See Chapter 4 of the Web Programming Step by Step textbook for examples.
inline css styles: Should never be used.
All CSS styles should be specified within a .css file and never as part of an HTML tag with the style
attribute.
whitespace: Place a line break after a { or }, and between each property declaration. Place spaces between selectors and { }. Place a space after a colon or a comma. Place a semicolon after every property declaration.
p,h1{color:red; font-family:serif; font-size:16pt;} a {text-decoration:none}
a { text-decoration: none; } h1, p { color: red; font-family: serif; font-size: 16pt; }
property order: Alphabetize the order of the properties of every style rule, always. As much as is reasonable, also alphabetize the order of selectors in a rule that contains more than one selector (like with h1
and p
below).
p, h1 { font-size: 16pt; text-decoration: underline; font-family: serif; color: red; }
h1, p { color: red; font-family: serif; font-size: 16pt; text-decoration: underline; }
minimize redundant CSS: If you repeat the same styles two or more times, and the styles are related in some way, find a way to remove the redundant code so that it appears only once. For example, place it into a common style rule that is used in both places. Note that not every common style should be combined; if two completely unrelated tags happen to share a style attribute (such as both being bold), this does not necessarily mean that they should be combined. A good example of when styles should be combined is if a site has a common font or color scheme that is used on several elements. The style should be written once and used throughout the page so it can be changed easily later if needed.
p { font-family: "Comic Sans MS", sans-serif; } h1 { font-family: "Comic Sans MS", sans-serif; }
h1, p { font-family: "Comic Sans MS", sans-serif; }
avoid unnecessary CSS rules: If a rule is not ever used in the page, remove it from your CSS file.
"vendor prefixed" CSS rules: Some CSS3 properties have browser-specific versions with prefixes like -webkit-
and -moz-
. Do not use these vendor-specific properties in your homework assignments unless you are specifically granted permission to do so.
div { -webkit-border-radius: 10px; }
div { border-radius: 10px; }
HTML in .php files: All HTML content that is inside of .php files is subject to the HTML style guide posted on this web site.
HTML validation: All HTML pages sent as output from a PHP file should pass the HTML validator. Choose the "View Source" option in your browser to get the HTML output, then copy/paste this into the validator.
switching between PHP and HTML modes: Try to minimize the number of unnecessary switches between PHP mode and HTML output mode.
In particular you should never switch modes and then immediately switch back again, back to back, such as ?> <?php
or <?php ?> <?php
.
expression blocks: Expression blocks should be used to inject PHP variables and values into HTML output. You should never call a PHP function from within an expression block, unless that function returns a value you want to print.
blank lines: Place a blank line before each mode switch from PHP mode to HTML mode.
Also place blank lines before or after functions and between complex sections of code.
(Of course, PHP expression blocks in <?= ... ?>
do not require blank lines around them.)
Never place more than one PHP statement on the same line.
indentation and whitespace: Increase your indentation by one increment (one tab, or four spaces, etc., consistently) every time you open a new left curly brace {
, and decrease the indent on each right curly brace }
. Also indent by one increment on each opening tag and decrease it on each closing tag. Therefore your PHP and HTML blocks should have a mixed indentation shared between the two of them, such as:
<div> <ul> <?php $max = 10; for ($i = 0; $i < $max; $i++) { ?> <li> There are <?= $i ?> bottles of beer on the wall.</li> <?php } ?> </ul> </div>The indentation shown in class examples (opening and closing PHP blocks at the same level of indentation) is also acceptable.
condensed whitespace: It is acceptable to enter-and-exit PHP mode on the same line, but only for an individual statement such as an if/else or loop header, or a single function call. If you use this condensed syntax, it is acceptable to omit blank lines around the mode switch.
<ul> <?php for ($i = 0; $i < 10; $i++) { ?> <li> There are <?= $i ?> bottles of beer on the wall. </li> <?php } ?> </ul>
long lines: Lines of pure PHP code (in PHP mode) should not exceed 100 characters in length. Lines of HTML content inside a PHP file (in HTML mode) are subject to the HTML section of the style guide in terms of line length.
print
/ echo
statements:
They should never be used in our assignments.
Instead, mode-switch into HTML output mode and write the content you want to display.
commenting placement/contents: Every PHP file should have a descriptive comment header at the top, written in your own words. Every function must have a comment header describing the function's behavior and parameters/return as appropriate. Non-trivial or complex sections of code (such as a piece of code that reads and processes an input file) should also have a brief comment explaining the code's purpose.
comment syntax:
Be sure to choose the right comment syntax.
Many students try to use HTML-style <!-- ... -->
comments in their PHP code files.
If the comments are about HTML content/output, then that comment syntax is appropriate.
But if you are commenting about PHP code, such as the purpose of a function or complex section of code, you should favor PHP-style #
or //
or /* ... */
comment syntax.
As a general rule, most of your comments should use the PHP syntax except for occasional ones that are specifically about HTML output tags.
variable "declarations": PHP has no concept of "declaring" a variable without initializing it. A statement such as the following is useless and should not be included in your code.
# bad
$employees; # these statements do nothing;
$todays_date; # they do not actually declare variables
names: When declaring a variable or function, give it a descriptive name, such as $students
or $ostrich_count
.
Avoid one-letter names like $x
or $c
.
capitalization: Name variables and functions in lowercase, with underscores to separate words, such as $ostrich_count
or compute_student_grade
.
If a variable serves as a de-facto constant, name it in uppercase, such as $INTEREST_RATE
.
function placement: Place all of your functions at the very top or bottom of your PHP file, never in the middle of the page.
global
keyword vs. function parameters/return:
You should never use the global
keyword, which allows functions to have access to global variables.
Instead, pass parameters to the function and/or return a value from the function.
# bad
$students = 4;
$money = 2;
process_classroom();
...
function process_classroom() {
global $students;
global $money;
print($students);
$money = 5;
}
# good
$students = 4;
$money = 2;
$money = process_classroom($students);
...
function process_classroom($stud) {
print($stud);
return 5;
}
referring to array elements: If your code processes an array where each element has a specific unique meaning, such as when exploding the tokens of a line of an input file, you should unpack that array into individual variables and avoid referring to array elements by their indexes as much as possible.
The reason to give them variable names is because the names are more descriptive and understandable than just using numeric indexes.
One convenient way to unpack an array into variables is to use the list
function.
# bad
$tokens = explode(":", $line);
if ($tokens[4] > $tokens[2] && $tokens[3] != "quit") {
...
}
# good
list($name, $id, $age, $action, $maxage) = explode(":", $line);
if ($maxage > $age && $action != "quit") {
...
}
It is sometimes okay to refer to elements of a super-global array, such as $_GET
or $_COOKIE
. The indexes of an associative array are strings, which are often more descriptive names than numeric array indexes.
But if you use the value from the super-global several times, you should still pull it out into a variable.
# bad
if (strlen($_POST["studentname"]) >= 5 &&
$_POST["studentname"] != "guest") {
...
}
# good
$name = $_POST["studentname"];
if (strlen($name) >= 5 && $name != "guest") {
...
}
superglobals are read-only:
The super-global arrays like $_GET
, $_POST
, and $_SERVER
should be considered read-only.
You should not store new values in them or modify existing values in them as a way of avoiding using regular local variables.
(The $_SESSION
superglobal array is an exception to this rule, if the assignment involves managing user login sessions.
It is meant to be written into directly by your code.)
redundancy:
You should work hard to reduce the amount of redundant PHP code in your programs.
This includes several kinds of redundancy elimination, such as moving repeated code into a loop, creating a function containing redundant code, or include
-ing a shared page of common HTML and/or PHP content.
save expensive call results in a variable: If you are calling an expensive function and using its result multiple times, save that result in a variable rather than having to call the function multiple times.
# bad
if (strlen(file_get_contents("foo.txt")) >= 0 &&
file_get_contents("foo.txt") != "hello") {
$text = strtolower(file_get_contents("foo.txt"));
}
# good
$text = file_get_contents("foo.txt");
if (strlen($text) >= 0 && $text != "hello") {
$text = strtolower($text);
}
if/else factoring: Move common code out of if/else
statements so that it is not repeated.
# bad
if ($x < $y) {
foo();
$x++;
print("hi");
} else {
foo();
$y++;
print("hi");
}
# good
foo();
if ($x < $y) {
$x++;
} else {
$y++;
}
print("hi");
for vs while: Use a for
or foreach
loop when the number of repetitions is known (definite); use a while
loop when the number of repetitions is unknown (indefinite).
break and continue: In general, you should avoid using the break
or continue
statements in loops unless absolutely necessary.
if/else patterns: When using if/else
statements, properly choose between various if
and else
patterns depending on whether the conditions are related to each other. Avoid redundant or unnecessary if
tests.
# bad
if ($grade >= 90) {
print("You got an A!");
}
if ($grade >= 80 && $grade < 90) {
print("You got a B!");
}
if ($grade >= 70 && $grade < 80) {
print("You got a C!");
}
...
# good
if ($grade >= 90) {
print("You got an A!");
} else if ($grade >= 80) {
print("You got a B!");
} else if ($grade >= 70) {
print("You got a C!");
}
...
boolean zen 1: If you have an if/else
statement that returns a boolean value based on a test, just directly return the test's result instead.
# bad
if ($score1 == $score2) {
return TRUE;
} else {
return FALSE;
}
# good
return $score1 == $score2;
boolean zen 2: Don't ever test whether a boolean
value is ==
or !=
to TRUE
or FALSE
.
# bad
if ($x == TRUE) {
...
} else if ($x != TRUE) {
...
}
# good
if ($x) {
...
} else {
...
}
filtering rows with WHERE
:
Queries should properly filter out rows that are not of interest to your code.
For example, if you are looking for cities with a large population,
you might choose to fetch all cities and loop over them in your code, displaying only the ones with large population.
Instead, you should rely on the database to filter out the rows using a proper WHERE
clause.
-- bad
SELECT * FROM cities;
-- good
SELECT * FROM cities WHERE population > 500000;
filtering rows with LIMIT
:
If you are only interested in a small number of results of your query, use a LIMIT
clause to ensure that your query only returns that many rows.
For example, if you wanted the 3 cities with the highest population in the entire database:
-- bad
SELECT * FROM cities ORDER BY population DESC;
-- good
SELECT * FROM cities ORDER BY population DESC LIMIT 3;
filtering columns with SELECT
:
If you are only interested in certain columns from your query, use a SELECT
clause that lists only the columns of interest.
This saves the database some work and memory over always selecting *
.
For example, if you wanted only the names and populations of the 3 cities with the highest population in the entire database:
-- bad
SELECT * FROM cities ORDER BY population DESC LIMIT 3;
-- good
SELECT name, population FROM cities ORDER BY population DESC LIMIT 3;
line breaks in long queries: If your query is more than ~80-100 characters in length, split it into multiple lines. You can do this in bare SQL or also in PHP, because PHP allows bare line breaks within a string.
-- bad
SELECT name, population, district FROM cities WHERE population > 500000 ORDER BY district, population, name DESC LIMIT 3;
-- good SELECT name, population, district FROM cities WHERE population > 500000 ORDER BY district, population, name DESC LIMIT 3; # PHP query $rows = $db->query("SELECT name, population, district FROM cities WHERE population > 500000 ORDER BY district, population, name DESC LIMIT 3");
proper JOIN
... ON
condition:
If your query uses data from multiple tables, use one or more JOIN
clauses to connect them.
Always join properly by relating unique keys from one table with those of another in your JOIN
... ON
condition.
Any other filters or constraints on the data that are not related to connecting keys of joined tables should go in the WHERE
clause.
-- bad
SELECT c.name
FROM courses c
JOIN grades g ON g.course_id = c.id
JOIN students bart ON bart.name = 'Bart'
WHERE g.student_id = bart.id;
-- good
SELECT c.name
FROM courses c
JOIN grades g ON g.course_id = c.id
JOIN students bart ON g.student_id = bart.id
WHERE bart.name = 'Bart';
JOIN
... ON
vs. FROM
/WHERE
:
It is possible to write an equivalent query with a FROM
and WHERE
clause that is equivalent to a JOIN
but does not use JOIN
syntax.
For the purposes of this course, such a query would be considered poor style and should be avoided.
-- bad
SELECT c.name
FROM courses c, grades g, students s
WHERE bart.name = 'Bart'
AND g.student_id = bart.id
AND g.course_id = c.id;
-- good
SELECT c.name
FROM courses c
JOIN grades g ON g.course_id = c.id
JOIN students bart ON g.student_id = bart.id
WHERE bart.name = 'Bart';
quoting inserted parameters:
To avoid SQL injection and security risks, any SQL query that inserts user input into the query string as a parameter must properly SQL-encode that parameter using a function such as PDO's quote
method.
$student = $_GET["student"]; $rows = $db->query("SELECT c.name FROM courses c JOIN grades g ON g.course_id = c.id JOIN students bart ON g.student_id = bart.id WHERE bart.name = '$student');
$student = $_GET["student"]; $student = $db->quote($student); $rows = $db->query("SELECT c.name FROM courses c JOIN grades g ON g.course_id = c.id JOIN students bart ON g.student_id = bart.id WHERE bart.name = $student);
commenting a query:
Any program that performs a SQL query should contain a brief comment next to that query indicating the meaning and purpose of the query.
The comment can be in SQL syntax (using the --
prefix at the start of the line) but more likely should be in the syntax of the programming language containing the query, such as PHP.
-- retrieves the names of all courses Bart Simpson has taken
SELECT c.name
FROM courses c
JOIN grades g ON g.course_id = c.id
JOIN students bart ON g.student_id = bart.id
WHERE bart.name = 'Bart';
# query to retrieve the names of all courses Bart Simpson has taken
$rows = $db->query("SELECT c.name
FROM courses c
JOIN grades g ON g.course_id = c.id
JOIN students bart ON g.student_id = bart.id
WHERE bart.name = 'Bart');
frameworks (e.g. jQuery): Please follow any restrictions in your assignment spec about the use of external JavaScript libraries such as jQuery. If the spec forbids using such libraries, do not link to them or use them in your code. These libraries can be very useful and powerful, but in a course setting, sometimes the assignment is intended to be solved without the use of these tools.
unobtrusive JavaScript: Always use unobtrusive JavaScript to keep all JavaScript commands entirely out of your HTML code and entirely inside your JavaScript file. The only JavaScript-related change to your HTML file is to link to your JS file using a script
tag. No onclick
, onchange
, onmouseover
, etc. handlers should ever be declared in your HTML files.
<!-- bad (HTML) -->
<button onclick="foo();">Click Me</button>
// bad (JS)
function foo() {
alert("You clicked the button.");
}
<!-- good (HTML) -->
<button id="clickme">Click Me</button>
// good (JS)
window.onload = function() {
document.getElementById("clickme").onclick = foo;
};
function foo() {
alert("You clicked the button.");
}
use strict: Always write a "use strict";
declaration at the top of your JS file to tell the browser to enable strict syntax checking of your JavaScript code.
JSLint: All of your JS files must pass the provided JSLint tool with zero errors. JSLint "warnings" or "notices" are less serious messages; it is okay to have these in your code.
module pattern: Always use the "module pattern" of wrapping your JS file's code inside an anonymous function that is immediately invoked, to get rid of global variables.
// bad
var x = 3;
var y = 4;
function f() {
x++;
}
// good
(function() {
"use strict";
var x = 3;
var y = 4;
function f() {
x++;
}
})();
minimize global and module-global variables: Avoid global variables as much as possible. If you use the module pattern, your code should declare 0 global variables. Even when using the module pattern, you should try to minimize the number of "module-global" variables that are declared at the outermost scope within your anonymous wrapper function.
// global variables: avoid these at all costs var globalBad = 123; // bad var globalBad2 = 456; // bad (function() { "use strict"; // module-global variables: some are okay, but don't over-use them var x = 7; var y = 8; function f() { // local variables: these are great! var z = 9; } })();
DOM objects as globals: Do not store DOM element objects, such as those returned by the document.getElementById
or document.querySelectorAll
functions, into global or module-global variables. Every time that you need them in a function, call the appropriate "get" function locally.
// bad
var inputBox = document.getElementById("passwordbox");
function f1() {
inputBox.value = "giraffe";
}
function f2() {
inputBox.value = "horse";
}
// good function f1() { var inputBox = document.getElementById("passwordbox"); inputBox.value = "giraffe"; } function f2() { var inputBox = document.getElementById("passwordbox"); inputBox.value = "horse"; } // alternative function f1() { document.getElementById("passwordbox").value = "giraffe"; } function f2() { document.getElementById("passwordbox").value = "horse"; }
other global variable hacks:
Some students try other bizarre hacks to basically achieve global variables.
For example, you can stuff various variables and values as dynamically created fields inside global DOM objects such as the document
object, or you can store anything into the global localStorage
array.
In general such trickery should be avoided, and global DOM objects should not be abused as a way around declaring global variables.
anonymous functions: Anonymous functions are useful and expressive in some cases where a function's name is meaningless and cumbersome, such as an initial window.onload
handler. But over-using anonymous functions leads to code that is too heavily nested and has too few names to guide the programmer, so over-use of anonymous functions should be avoided. In general, give names to your functions unless the name is truly useless and meaningless.
// bad
window.onload = function() {
myButton.onclick = function() {
setTimeout(function() {
alert("hi!");
}, 1000);
};
}
// good
window.onload = function() {
myButton.onclick = myButtonClick;
}
function myButtonClick() {
setTimeout(displayHiMessage, 1000);
}
function displayHiMessage() {
alert("hi!");
}
setting styles in JS code: If you are setting several styles on a DOM object in JS code, instead declare a class in your CSS file and use the JS code to apply that class to the DOM object. This helps keep most of the style decisions in your CSS file where they belong and out of your JS code.
// bad (JS)
myButton.style.border = "2px dotted green";
myButton.style.color = "red";
myButton.style.fontSize = "20pt";
myButton.style.fontWeight = "bold";
myButton.style.textDecoration = "underline";
/* good (CSS) */ button.urgent { border: 2px dotted green; color: red; font-size: 20pt; font-weight: bold; text-decoration: underline; } // good (JS) myButton.className = "urgent";
semicolons: JavaScript often still works if semicolons are omitted, using complex logic called automatic semicolon insertion (ASI). But you should not rely on this and should always insert semicolons wherever you end a complete statement of code.
// bad
var x = 3
var y = 4
function foo() {
alert("hi!");
}
window.onload = function() {
x++
foo()
}
// good
var x = 3;
var y = 4;
function foo() {
alert("hi!");
}
window.onload = function() {
x++;
foo();
};
indenting: Increase your indentation by one increment on each brace {
, and decrease it once on each closing brace }
.
line breaks: Place a line break after every {
. Do not place more than one statement on the same line.
// bad
var x = 3; var y = 4; x++;
if (a == b) { foo(); }
long lines: When any line is longer than 100 characters, break it into two lines by pressing Enter after an operator and resuming on the next line. Indent the trailing second part of the line by two increments (e.g. two tabs). For example:
var result = reallyLongFunctionOne() + reallyLongFunctionTwo() + reallyLongFunctionThree() + reallyLongFunctionFour(); var result2 = reallyLongFunction(parameterOne, parameterTwo, parameterThree, parameterFour, parameterFive, parameterSix);
expressions: Place a space between operators and their operands.
var x = (a + b) * c / d + foo();
blank lines: Place a blank line between functions and between groups of statements.
function foo() {
...
}
// this blank line here
function bar() {
...
}
names: Give variables descriptive names, such as firstName
or homeworkScore
.
Avoid one-letter names like x
or c
, except for loop counter variables such as i
.
capitalization: Name variables and functions with camel-casing likeThis
, name classes with Pascal casing LikeThis
, and name unchanging "constant" variables in uppercase LIKE_THIS
.
scope: Declare variables in the narrowest possible scope.
For example, if a variable is used only inside a specific if
statement, declare it inside that if
statement rather than at the top of the function or at the top of the class.
constants: If a particular constant value is used frequently in your code, declare it as a module-global "constant" variable in uppercase, and always refer to the constant in the rest of your code rather than referring to the corresponding value.
var DRINKING_AGE = 21;
for vs while: Use a for
loop when the number of repetitions is known (definite); use a while
loop when the number of repetitions is unknown (indefinite).
// repeat exactly size/2 times for (var i = 0; i < size / 2; i++) { ... } // repeat until the user clicks OK while (!confirm("Are you sure?")) { ... }
break and continue: In general, you should avoid using the break
or continue
statements in loops unless absolutely necessary.
if/else patterns: When using if/else
statements, properly choose between various if
and else
patterns depending on whether the conditions are related to each other. Avoid redundant or unnecessary if
tests.
// bad
if (grade >= 90) {
alert("You got an A!");
}
if (grade >= 80 && grade < 90) {
alert("You got a B!");
}
if (grade >= 70 && grade < 80) {
alert("You got a C!");
}
...
// good
if (grade >= 90) {
alert("You got an A!");
} else if (grade >= 80) {
alert("You got a B!");
} else if (grade >= 70) {
alert("You got a C!");
}
...
boolean zen 1: If you have an if/else
statement that returns a boolean value based on a test, just directly return the test's result instead.
// bad
if (score1 == score2) {
return true;
} else {
return false;
}
// good
return score1 == score2;
boolean zen 2: Don't ever test whether a boolean
value is ==
or !=
to true
or false
.
// bad
if (x == true) {
...
} else if (x != true) {
...
}
// good
if (x) {
...
} else {
...
}
exception handling: We don't use exceptions really in JS in this material.
So in general you should avoid try/catch
statements because this is not how we intend you to solve the problems.
But if you do need to use one, don't ever catch an exception with an empty catch
block.
// bad
try {
foo();
bar();
} catch (npe) {}
minimize redundant code: If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once. For example, place it into a helper function that is called from both places. If the repeated code is nearly but not entirely the same, try making your helper function accept a parameter to represent the differing part.
// bad
foo();
x = 10;
y++;
...
foo();
x = 15;
y++;
// good
helper(10);
helper(15);
...
function helper(newX) {
foo();
x = newX;
y++;
}
if/else factoring: Move common code out of if/else
statements so that it is not repeated.
// bad
if (x < y) {
foo();
x++;
alert("hi");
} else {
foo();
y++;
alert("hi");
}
// good
foo();
if (x < y) {
x++;
} else {
y++;
}
alert("hi");
function structure: If you have a single function that is very long, break it apart into smaller sub-functions. The definition of "very long" is vague, but let's say a function longer than 20-30 lines is pushing it. If you try to describe the function's purpose and find yourself using the word "and" a lot, that probably means the function does too many things and should be split into sub-functions.
save expensive call results in a variable: If you are calling an expensive function and using its result multiple times, save that result in a variable rather than having to call the function multiple times.
// bad
if (list.indexOf("abc") >= 0) {
list.remove(list.indexOf("abc"));
}
// good
var index = list.indexOf("abc");
if (index >= 0) {
list.remove(index);
}
Usage: When explicitly allowed by the homework specification, you can use jQuery, but we expect your Javascript to be written in the style of the jQuery framework. There are many many bad resources for jQuery so be careful how you Google, below are the best style practices for the most common jQuery actions, if you have style questions on other features feel free to post on the message board.
Function calls: They SHOULD be chained when possible, most jQuery calls return the original object so they can be chained appropriately. Chained method calls should be on their own line for readability
// bad
var obj = $("#selected").callOne();
obj = obj.callTwo();
obj = obj.callThree();
obj = obj.callFour();
// good
var obj = $("#selected").callOne()
.callTwo()
.callThree()
.callFour();
Global functions: When calling a global function (e.g. post
, ajax
)you should call
the $
object instead of the jQuery
object.
// bad
jQuery.globalFunction();
// good
$.globalFunction();
Document onload: When using jQuery it is incorrect to specify listeners directly on the window
or document
object. Instead you should use the ready
event listener. Note that for page loads you
should always use ready
and not load
// bad
window.onload = pageReadyHandler;
// good
$(document).ready(pageReadyHandler);
CSS properties: All CSS properties should be accessed and set via the css()
method
Nested selectors: It is better to use find
than to nest when possible, this is because
the sizzle engine that is internal to jQuery can optimize these calls more.
// bad
var children = $("#overallDiv .subClass");
// good
var children = $("#overallDiv").find(".subClass");
Manipulating page content: If jQuery provides a method to manipulate a value or attribute it should be used instead of manually manipulating things. Here is a non-exhaustive list of examples:
html()
instead of innerHTML
append()
to add it to the pagetext()
instead of attributes like textContent
val()
instead of the value
attributeAvoid looping when possible: Most jQuery result objects can apply calls to every value in the returned set and this should be used instead of looping over the results
// bad
var results = $('.findMe');
for(var i = 0; i < results.length; i++) {
results.css({ "color" : "red" });
}
// good - jQuery knows to apply it to everything
$('.findMe').css({ "color" : "red" });
Attaching events: jQuery provides a number of named event methods like click()
or mouseover()
,
when attaching events to objects these should be preferred over manual bindings. If no named method exists the bind()
method should
be used.
Detaching events: To detach you must use the unbind()
method, no other method will completely unregister your
event handlers and this may cause adverse side effects.
AJAX requests: You should use the specific $.get
and $.post
methods when possible, falling back
to $.ajax
when the request type is dynamically determined. In addition all parameters should be sent via a data object instead
of directly in the url
// bad
$.ajax({
url : "service.php?param1=data1¶m2=data2",
type : "GET"
...
})
// good
$.get({
url : "service.php",
data : {
param1 : data1,
param2 : data2
}
...
})
Usage: When explicitly allowed by the homework specification, you can use Prototype, but we expect your Javascript to be written in the style of the Prototype framework. Below are the best style practices for the most common Prototype actions, if you have style questions on other features feel free to post on the message board.
Querying for ids: You should use the provided $
object instead of document.getElementById
Querying with css selectors: You should use the provided $$
object instead of document.querySelector[All]
Querying for form controls: You should use the provided $F
when querying for form controls
Manipulating content: Instead of looping over a result set form Prototype to apply a function, you should take advantage of
the special invoke
function that is added to result sets.
// bad
var results = $$('.findMe');
for(var i = 0; i < results.length; i++) {
results.hide();
}
// good
$$('.findMe').invoke('hide')
AJAX requests: Ajax requests should be sent using the Ajax.Request
object instead of the XMLHttpRequest
.
Responses will be automatically decoded by this library so you won't need functions like JSON.parse
Animations: Any animations should be done via the Effects
object that is part of prototype. More complex animations
should use the extended library scriptaculous
file header: Place a descriptive comment heading on the top of every file describing that file's purpose. Assume that the reader of your comments is an intelligent programmer but not someone who has seen this assignment before. Your comment header should include at least your name, course/section, and a brief description of the assignment. If the assignment asks you to submit multiple files, each file's comment header should describe that file/class and its main purpose in the program.
function headers: Place a comment heading on each function you declare. The heading should describe the function's behavior.
parameters/return: If your function accepts parameters, briefly describe their purpose and meaning. If your function returns a value, briefly describe what it returns.
inline comments: Inside the interiors of your various functions, if you have sections of code that are lengthy or complex or non-trivial, place a small amount of inline comments near these lines of complex code describing what they are doing.
implementation details: Comment headers at the top of a function or class should describe the function's behavior, but not great detail about how it is implemented. Do not mention language-specific details like the fact that the function uses a if/else
statement, that the function declares an array, that the function loops over a collection and counts various elements, etc.
wording: Your comment headers should be written in complete sentences, and should be written in your own words, not copied from other sources (such as copied verbatim from the homework spec document).
commented-out code: It is considered bad style to turn in a program with chunks of code "commented out". It's fine to comment out code as you are working on a program, but if the program is done and such code is not needed, just remove it.