On this page:
8.1 Clarity of Code
8.2 Comments
8.3 The Very Basics
8.3.1 Names
8.3.2 Size of Functions and Methods
8.14.0.4

8 Programming Components🔗

18 September 2024

Questions?

5min

Where we are We have looked at:

It is time to look at the how components are made in a socially responsible manner. This is where 80% of socially responsible sw dev happens.

Meta-how: how do you write down the how—a translation of a part of your thoughts—so that the receiving sw dev can reconstruct what is necessary to understand, fix things, and make changes in general.

8.1 Clarity of Code🔗

5min

Factors involved:

Comments A typical response to “I don’t understand this code” is to say “we’ll add comments” or, to sound sophisticated, the sw dev may say “we’ll add documentation.” What does this mean?

Names One of the most basic and helpful changes to code is to use good names for interfaces, classes, fields, methods, parameters, and variables. How do we make names signal their role inside of code?

Data representations Choosing a weil-suited data representation is the most difficult step. It has implications for several other aspects, including names, comments, and methods. How do we pick good data representations?

Size of Units of Code, esp. Methods Conquering complexity means keeping units of code small so that they become easily comprehensible. Methods (or functions) are the most basic units of code. How do we keep them small enough? What is small?

8.2 Comments🔗

10-15min

Every programming language comes with a mechanism for adding comments to code. That does not tell us how to use this mechanism to convey important supplements to code.

Comments are almost always wrong. Out of sync.

Comments that translate code into English are obstacles, not helpful. Here is what I was taught:

    x = x + 1; // increase x by 1

One cure: write down comments that play a specific roles:

8.3 The Very Basics🔗

Three aspects of code influence comprehensibility of methods and functions: (use of) names; size of methods; conditionals.

8.3.1 Names🔗

10min

re-use the above example to address the issue of which parts go into a name, which into a purpose statement

if metric units matter, make it part of the name

if the exact location matters, ...

Give meaningful names to intermediate results:

    // represents a positioned square

    class SquareShape:

      Posn center;  // of `this` shape

      int width;    // in pixels of `this` shape

    

      // is `p` inside `this` square shape

      boolean onTarget(Posn p) {

        return

          this.isInside(

            Geometry.vectorFromTo(

              p,

              Geometry.shift(this.center,(width/2))));

      }

  

    // represents a positioned square

    class SquareShape:

      Posn center;  // of `this` shape

      int width;    // in pixels of `this` shape

    

      // is `p` inside `this` square shape

      boolean onTarget(Posn p) {

       int halfWidth  = width / 2;

       Posn nuOrigin = Geometry.shift(this.center,halfWidth);

       Posn pRelative2Center = Geometry.vectorFromTo(p,nuOrigin);

       return this.isInside(pRelative2Center);

     }

8.3.2 Size of Functions and Methods🔗

15-25min

Squeak is an implementation of a programming language like Java w/o types. Its core is 600,000 lines of code as of 2020. It is written in the Squeak itself. Guess how long the average method is?

Six (6) lines of code.

How did they achieve this? They followed the advice we start giving you in Fundamentals I:

or

Sample problem:

Develop a program that, given an input-file name and an output-file name, consumes the content of the input-file of JSOn values (up to 1K, only Strings, Numbers, Objects, and Arrays), turns them into numbers, and writes out the resulting sequence of numbers as a JSON array of corresponding strings to the output-file.

Each JSON value is turned into a number as follows:
  • strings – the number of chars in the string

  • numbers – easy

  • objects – the sum of the field values turned into numbers

  • arrays – the product of the values of its elements

Work through this, explain how each function stays small. Explain one more time how someone chose a data representation for JSON values

#; {PathString PathString -> Void}
; composite
(define (main in-file-name out-file-name)
  (define in      (read-in-file file-name))
  (define numbers (turn-into-numbers in))
  (define strings (as-strings numbers))
  (write-as-json-file strings out-file-name))
 
#; {PathString -> [Listof JSexpr]}
; atomic: use library
(define (read-in-file in) '[])
 
#; {[Listof String] PathString -> Void}
; atomic: use library
(define (write-as-json-file strings out-file-name) (void))
 
#; {[Listof JSexpr] -> [Listof Number]}
; use recursion to match structure JSexpr
(define (turn-into-numbers in) '[])
 
#; {[Listof Number] -> [Listof String]}
; use for loop (for/list (...) ..)
(define (as-strings numbers) '[])

Total: 35–60 mins