Programming Style Guide


It has been said that ``programs must be written for people to read, and only incidentally for machines to execute'' [SICP]. Moreover, consider that

Donald Knuth called his classic series The Art of Computer Programming. In his Turing Award Lecture, he explained that this title was a conscious choice---that what drew him to programming was ``the possibility of writing beautiful programs.''

Like architecture, programming has elements of both art and science. A program has to live up to mathematical truth in the same way that a building has to live up to the laws of physics. But the architect's aim is not simply to make a building that doesn't fall down. Almost always the real aim is to make something beautiful.

Many programmers feel, like Donald Knuth, that this is also the real aim of programming. Almost all Lisp hackers do. The spirit of Lisp hacking can be expressed in two sentences. Programming should be fun. Programs should be beautiful [ACL].

Therefore, as discussed in class, it is important to follow some guidelines for writing source code. Follow the guidelines below for all programming assignments. Note: we may evolve this set of guidelines as the course progresses and as we study additional languages.

Remember, assignments provide you with an opportunity to show us that you care enough to submit a professionally-prepared work. Practice good programming habits early and you will be rewarded with effective and efficient programs. Following this guide will improve the readability, writeabiliy, and maintainability of your programs and, therefore, reduce the likelihood of costly errors which will save you time in debugging. We will evaluate the style of your source code.
Universal Style Guidelines:
  • Do not allow any line of code to exceed 80 characters in length. Most text editors have an option to give you column position. Find an appropriate place to break long program statements to continue them on the following line. Break long character strings using string concatenation.

  • Indent code consistently. Some IDEs have an automatic indentation tool. For instance, in Dr. Racket there is a `Reindent All' function (nested within the Racket menu).

  • Do not use tabs anywhere in your code. For each level of indentation, use a fixed number of spaces (e.g., three). Tabs cause different amounts of horizontal spacing on different systems. By using spaces (and a fixed-width font), you guarantee your code will be properly indented for every system, editor, and printout.

  • Use descriptive, yet succinct, identifiers and use appropriate naming conventions. Remember, syntax should imply semantics.

  • Keep programs as modular as possible to foster better maintainability and re-use. No function should exceed 50 lines of code.

  • Utilize recursion, higher-order functions, and pattern-directed invocation to the fullest extent.

  • Verify, with the instructor, the permission to use any language feature not discussed in class by the instructor.


Functional Programming in Scheme, ML, or Haskell:
  • Follow The First Ten Commandments and The Next Ten Commandments [TSS] completely.

  • Begin each source file with the following comment header filled-in appropriately:
    ;;;;****************************************************************************
    ;;;;
    ;;;;      filename:  hw2.scm
    ;;;;
    ;;;;   description:  Implements the functions required for Homework #2
    ;;;;
    ;;;;        author:  First Last
    ;;;;      login id:  cps352.01
    ;;;;
    ;;;;         class:  CPS 352
    ;;;;    instructor:  Perugini
    ;;;;    assignment:  Homework #2
    ;;;;
    ;;;;      assigned:  January 17, 2015
    ;;;;           due:  January 24, 2015
    ;;;;
    ;;;;****************************************************************************
    
  • Adapt the above comment header for use with ML by replacing each occurrence of the string ;;;; with ( and the last asterisk on the last line with ).

  • Adapt the above comment header for use with Haskell by replacing each occurrence of the string ;;;; with --.

  • Precede every function with the following comment header explaining its purpose, the meaning of each parameter, precondition, postcondition, and the general strategy of its implementation, if applicable. Also indicate which problem the function addresses. For instance (in Scheme):
    ;;; purpose: To compute the factorial of a non-negative integer.
    ;;; Solves problem #3
    (define factorial
       (lambda (n)
          (cond
             ((zero? n) 1)
             (else (* n (factorial (- n 1)))))))
    
  • Scheme or COMMON LISP comment conventions [ACL]: use
    • four semicolons in a heading,
    • three in a description of a function or macro,
    • two to explain the line below, and
    • one when a comment is on the same line as the code it applies to
    • example:
      ;;;; Helper functions
      
      ;;; purpose: To compute the factorial of a non-negative integer.
      ;;; Solves problem #3
      (define factorial
         (lambda (n)
            (cond
               ;; base case
               ((zero? n) 1)
               (else (* n (factorial (- n 1))))))) ; inductive step
      
  • Avoid the of use imperative features other than the language's facilities for input and output.

  • Avoid statement blocks. Use let's instead as they do not run contrary to the spirit of functional programming. For more information, see pp. 106-107 of [EMPL] J.D. Ullman. Elements of ML Programming. Prentice Hall, ML97 edition, 1998.

  • Avoid the use of iteration. Use recursion.

  • Avoid side-effects, again, with the exception of input and output.

  • Where possible, use cons operator (cons in Scheme, :: in ML, or : in Haskell) instead of append (or @ in ML or ++ in Haskell). `It may not be obvious, but while it takes time proportional to the length of the first list to [append] lists, we can cons a head and tail in constant time' [EMLP]. For the details, see pp. 84-88 of [EMPL].

  • In Scheme, never use if in a program since if is just a specialized version of cond.


Logic Programming in PROLOG:
    Precede every predicate definition with the following comment header explaining its purpose, the meaning of each parameter, precondition, postcondition, and the general strategy of its implementation, if applicable. Also indicate which problem the function addresses. For instance,
    /******************************************************************************
    /
    / purpose: Predicate to compute the factorial of a non-negative integer
    /          given in its first argument and bind the result to its
    /          second argument.  Solves problem #5.
    /
    /*****************************************************************************/
    factorial(0, 1).
    factorial(X, Y) :- X > 0, Z is X-1, factorial(Z, M), Y is M*X.
    

Object-oriented Programming in Smalltalk:
  • Adapt the first comment header above for use with Smalltalk by replacing each occurrence of the string ;;;; with / and the last asterisk on the last line with /. When defining a class, include this comment header in the comment section of the Squeak System Browser.

  • Precede every user-defined method definition with the following comment header explaining its purpose, the meaning of each parameter, precondition, postcondition, and the general strategy of its implementation, if applicable. Also indicate which problem the function addresses. For instance,
    "*****************************************************************************"
    
    " purpose: Adds amount to the bank balance and adds a new entry to the        "
    "          history OrderedCollection by sending the balance message.          "
    "          Solves problem #2.                                                 "
    
    "*****************************************************************************"
    withdraw: amount
       amount > balance ifTrue: [^ self inform: 'sorry, not enough funds'].
       self balance: balance - amount.
    

  • Be consistent in your application of the above guidelines.

  • Overall, write your programs such that they are self-documenting. In other words, structure your code such that the program itself provides its own documentation. Self-documentation means using descriptive identifiers and a consistent, aligned format.


References

    [ACL] P. Graham. ANSI Common Lisp. Prentice Hall, Upper Saddle River, NJ, 1996.
    [EMLP] J.D. Ullman. Elements of ML Programming. Prentice Hall, Upper Saddle River, NJ, Second edition, 1997.
    [SICP] H. Abelson and G.J. Sussman. Structure and Interpretation of Computer Programs. MIT Press, Cambridge, MA, Second edition, 1996.
    [TSS] D.P. Friedman and M. Felleisen. The Seasoned Schemer. MIT Press, Cambridge, MA, 1996.

Return Home