There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies; the other way is to make it so complicated that there are no obvious deficiencies. (C.A.R. Hoare)
A computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute. (The Structure and Interpretation of Computer Programs, H. Abelson, G. Sussman and J. Sussman, 1985.)
Programming IS NOT (just) about coding a program that seem to solve a given problem for the case you have thought about, it IS about creating a SCALABLE program that take into account as many situations as possible and delivers good/helpful error messages for all the different kinds of bad input that the user can enter. Scalable implies READABLE (clear, concise, consistent in following conventions) and MODULAR (as in "one function per task" and "no more than 30 lines per function" and "no more than 10 lines outside functions"; modularization also helps readability and re-usability). It should be remembered that the initial development of a program is usually a small fraction of the time and cost that is spent on it (later maintenances and extensions is where most of the time is spent, even when good programming languages are used and good programming methodologies are followed).
Interpreted languages such as Javascript
encourage beginners to do (quick and) dirty programming, hence unreadable,
unscalable, unmaintainable, bug-filled and hard-to-debug programs.
It is therefore necessary to counter that by following as many
programming conventions as possible. This document details some
conventions/rules that you must follow
(click here for a MINIMAL checklist of
bad programming practices).
You are strongly encouraged to complement this list by additional rules
(consistent with those in the checklist) and follow them systematically
(for example, if you define object classes, try to follow the
JavaBeans conventions).
The rules below will HELP YOU design and debug your programs since they are
minimal ways to achieve better clarity, conciseness and modularity. Because of these
underlying notions, you should have no difficulty to remember them, and you will have
NO difficulty if (as you should) you apply them systematically whenever you write any
line of code.
If you do not understand a rule, ask about it but do not ignore it!
NEVER start your programs from scratch (THE most basic rule of programming).
In the context of this course, this entails the following:
1) test ALL the examples that you are given, 2) select the programs that you
think you can re-use, 3) copy these programs in your directory to make sure
they work in your directory, 4) correct these programs whenever they do not comply
with the programming rules below, 5) test them again after this correction,
6) begin to modify these programs (progressivelly, incrementally) to achieve
your goals.
Each line should not be more than 70 characters long: anyone should be able to print your documents in a 12-point font without problem or view them without using the horizontal scroll bar (the existence of this scroll bar in Notepad is a very easy-to-spot indication that some of your lines are too long).
Each HTML/Javascript/... structure (e.g., if/loop/...) should be
properly indented. However, you do not need to (and should not) indent the
direct sub-elements of the HTML tag (e.g., HEAD and BODY) nor their direct
sub-elements (e.g., STYLE, SCRIPT, P, H1 ...H5). Use two white characters (2 spaces)
for each level of indentation.
Never use tabulations (tabs) for the indentation. Some of the reasons are:
(i) tabulations are often changed or corrupted when a file is copied
from one machine/editor to another, (ii) the created indentation
is most often too large. More generally, do not use tabulations in any
program or documention.
Use one space before and after a single '=' used for an equality test
(as in " if (n = 2) then "). Use no space before '=' it when
it is used for an assignment (as in " n= 2 "). When an assignment is used
within a test (as in "if ((n= 2)) then " or "if (!(n= 2)) then "), put a
space after the '=' and use two sets of parenthesis. When an assignment is
used outside a test, you are allowed not to put a space after the '='.
When a procedure has parameters, do not put a space before the
the '(' for a procedure call but put it for the procedure declaration.
This convention will ease your search/debugging a lot.
More generally, be explicit. For example, do not leave an "else" implicit
(see example below).
If within an If-Then-Else statement, one of the two blocks is much
shorter that the other, it should be presented first (hence, a block doing
some about error detection should be presented first).
When using block delimiters, align them vertically if they are not on the
same line.
Do not waste spaces, the more compact the code, the more code you can see and
compare at a glance (i.e., without scrolling), which is extremely important
for understanding and debugging purposes.
And of course, declare and initialize all your variables. Give their types
within comments unless the type is clear from the name of the variable or
the way it is initialised (e.g., names ending by "Name" or "Str" should be
strings). The name of a boolean variable/function should begin by "is" or "has".
Here are some examples to illustrate these rules. (Study the last example carefully).
The indentation that should be used in any programming case can be derived from
the aboe rules and these examples. However, some students need to see a longer
list of examples to understand the rules. So,
click here for a longer list of case-by-case examples.
Example not to follow | Example to follow |
---|---|
<table> <tr><td>cell 1</td> <td>cell 2</td> </tr> </table> |
<table> <tr><td>cell 1</td> <td>cell 2</td> </tr> </table> |
sub someSubroutineName dim a a = 8 while a > 1 a = a - 1 end while end sub |
sub someSubroutineName dim a a= 8 while a > 1 a= a - 1 end while end sub |
function someFct(someNumber) { if(result = someNumber + 1) { prErr ('Some error message'); return result; } if(someNumber ==0) { result = 1; } return result; } |
/*int*/function someFct (/*int*/someNumber) { /*int*/result= 0; if (someNumber==0) result= 1; else if ((result= someNumber + 1)) { prErr('Some error message'); return result; } return result; } |
Use subroutines as often as possible in order to make your code more modular and its various components explicit. If you have a piece of code that is more than 10 lines long (within a program or a documentation), or a piece of code (even two lines long) that is used at different place in you programs(s) or documenttion(s), encapsulate it into one or more subroutines (no subroutine should be more than 15-lines long). If a subroutine has parameters, indicate their types in one way or another, e.g. using comments if you have too; for example in VBscript:
function minimumInteger (number1, number2) '(integer, integer) -> integerThen, put a 1-line comment before the subroutine. Also put a 1-line comment before a loop when it is difficult to understand. - if you use a piece of code more than 3 lines long at different places in your program(s), you must wrap it into a Perl subroutine (putting files collecting Perl subroutines into a directory named "fct" is an option);
A file name must not include any space (that creates problems when handling them via scripts). A file/variable/procedure name must follow the InterCap style, as in "thisIsAgoodName". Only the name of a global variable should begin by an uppercase. Do not use an abbreviation in the name of a file, variable or subroutine (however, if in the text of an assignment, I give you a name which is an abbreviation, you should of course use it as such). Use explicit (and therefore relatively long) names for your variables and subroutines.
A file/variable/procedure name should follow an object-oriented style whenever it is easy to do so (it most often is). With object-oriented languages (e.g., Javascript), this means embedding variables/methods within objects (structures) and then using the "." operator to access these variables/methods. For non-object-oriented languages (e.g., VBScript, Perl), this means doing so implicitely by using a '_' whenever you would have used a '.', as in "user_name", "user_name_set", "user_name_read", "uset_name_write". As these examples show, you should try to name/end your procedures/methods by "set", "read" and "write". Instead of "read"/"write" and specifying a file as a parameter, you can use "get"/"put" if the "input"/"output" is the keyboard/screen.
The name of an HTML form element should end by "Input" for an Input
element of type Text or Password. It should end by "Hidden" for an
Input element of type Hidden. It should end by "Choice" for an Input
element of type Radio. It should end by "Selection" for a Select element.
Examples: "addressInput", "passwordInput", "transmissionChoice".
These HTML form element namving conventions must be followed in the programs
of the tutorials, class tests and final examination. However, you are allowed
not to follow them in the programs of the two assessments.
Each file must have a header which includes your student name and number.
Never send me a Word document when you can send me a text document.
For each assignment the documentation should be in a text file named "doc.txt" (not "Doc.txt", nor "doc.txt.rtf", etc.).
Your programs must work without syntax errors or any other error
that appears in the browser when you enable "error notification"
(see under the menus "Tools - Internet Options ... - Advanced"; you should
always have the option "Display a notification about every script error"
enabled and the option "Disable script debugging" disabled).
In your final version of a program, the
debugging traces must not appear when the program is executed (to do
that, the traditional way is to test a global variable
DebugLevel
before each command printing traces; when the
variable is equal to 0, no trace is displayed).
Do not use an interface generator (HTML edit, ...). Use emacs. It will allow you to efficiently swap buffers and divide the window to see the buffers one below the other or side-by-side. Like Notepad, it will also allow you to open many windows and put them wherever you want (not just in a restricted area with lots of useless menus taking a lot of space) and thus will permit you to have your browser and your editor opened side-by side. Hence, you will not have to constantly swap windows and use your memory. Your development and debugging time will be greatly reduced. Furthermore, interface generators produce lots of unnecessary and badly indented code. You are supposed to know HTML and hence not need an interface generator. Using a simple text editor will lead you to write much cleaner HTML. Reminder: you will be penalised if I see you using something else than Xemacs, or see that your HTML has not been created manually. When you have a problem and ask for my help, you MUST have (i) a readable and modular code respecting the rules above and below, (ii) traces showing which subroutines is called, (iii) the browser on the left side of the screen and the editor of the executed program on the right side of the screen.
Each input data must be validated both client-side (i.e. by the client's browser, using some Javascript or client-side VBscript code) and server-side.
Never use instructions to transfer/redirect a program to another (e.g. the instructions Request.transfer and Request.redirect in VBscript and the instruction "redirect" in a CGI header) since this makes the program hard to understand, maintain and debug. Use subroutines instead.
Begin each HTML document by:
<html> <head><title>Document title/purpose here</title> <meta name="Author" content="your name, student ID and URL of your home page here"> <!-- URL: main URL of this HTML document here -->
Regarding interfaces:
- do not use frames, images, movies, animations (scrolling text,
etc.);
- do not let the user choose IDs when adding records
(IDs should be generated via the use of autoNumber);
- do not force the user to know the IDs of records or Web pages: give hyperlinks or
buttons to avoid that;
- do not force the user to enter all the values of a record, only
the values that are absolutely required;
- check the user's inputs, both client-side and server-side;
- do not force the user to re-enter values in case of input error or
unfound records (hence, client-side, do not erase the values, and
server-side, present these values again);
- more generally, do not force the user to navigate or enter values
when it is possible to avoid it (an example is at http://www.phmartin.info/ip2/interfaceExample.html);
- never use the POST parameter encoding method during development and testing (i.e., until
after its evaluation), use GET instead since it
eases debugging, testing, programmatic re-use and also user's navigation
to previous pages; then,
for the cases when the form/query
is more for an order (typically, a payment or a subscription) than for a question (a search),
you may wish to convert some of the GET into POST.