Scala Style Guide

Code is both communication with computers and people. The effectiveness of the first is easily assessed with unit tests while the second is a matter of elegance and clarity. For CSIS 430, elegant code style is primarily assessed with the following criteria:


White Space


Indentation

Code must have proper, consistent indentation. For CSIS 430, this means using spaces instead of tabs. Either 2, 3, or 4 spaces should be used to for indentation.

An example of good indentation:

def sum(values: Iterable[Int]): Int =
{
   var total = 0

   for(value <- values)
   {
      total += value
   }

   total
}

An example of bad indentation:

def sum(values: Iterable[Int]): Int =
{
      var total = 0

   for(value <- values)
   {
   total += value
   }

 total
}

Empty Lines

Large blocks of code need to broken up with empty lines. Ideally, lines accomplishing the same purpose should be grouped together.

A good example of using empty lines:

//compute the mean of the squares
val total = values.map(v => v * v).sum
val meanSquared = total / values.size

//compute the mean of the absolute values
val absTotal = values.map(v => Math.abs(v)).sum
val absMean = absTotal / values.size

An example of not using empty lines:

//compute the mean of the squares
val total = values.map(v => v * v).sum
val meanSquared = total / values.size
//compute the mean of the absolute values
val absTotal = values.map(v => Math.abs(v)).sum
val absMean = absTotal / values.size

Spacing

Operators and type declarations need appropriate white space.

An example of good spacing:

def max(values: Iterable[Int]): Int =            
{
   var largest: Int = values.head

   for(current <- values)
   {
      if(current > largest)
      {
         largest = current
      }
   }

   largest
}

An example of the lack of proper spacing:

def max(values:Iterable[Int]):Int =            
{
   var largest:Int=values.head

   for(current<-values)
   {
      if(current> largest)
      {
         largest =current
      }
   }

   largest
}

One Way In, One Way Out

Each function, method, or block of code (anything with curly braces) should only have way in and one way out. The goal is to make code that is as easy to follow as possible, which means it should be as linear as possible. For example, break and continue statements should not be used as well as multiple return statements per function/method. The exception to multiple return statements are recursive functions since the return statements help mark the base and recursive cases.


Modularity

Functions and methods more than a "screen" in length should be split up into multiple smaller functions. A "screen" is about 40 to 50 lines in length. This includes white space and comments.


No Redundancy

This goes hand-in-hand with modularity. A program should not have non-trivial duplicate lines of code. The need to repeat logic implies that a new function or method should be created.


Comments

Every non-trivial block of code should have a comment explaining at least what it is doing and ideally why it is doing it. This includes each case of if statements, loops, functions, methods, class definitions, trait definitions, modules, and extended sections of logic. For function, methods, and module/trait/class definitions, follow ScalaDoc conventions.

An example of good comments:

/**
* Finds the largest value in the collection of Ints
* @param values a collection of Ints to find the max of
* @return the max value of the collection
*/
def max(values: Iterable[Int]): Int =            
{
   //use the "first" value of the collection as the first value for largest
   var largest: Int = values.head

   //compare each value in the collection with the current largest
   //updating when a larger value is found
   for(current <- values)
   {
      //if the current value is larget then the largest so far,
      //update it
      if(current > largest)
      {
         largest = current
      }
   }

   largest
}

Good Variable Names

Variable names should be in camel case and be meaningful in their context. With the exception of indices and arguments to lambda functions, single-letter variable names should never be used. Generic and meaningless names such as temp, hashMap2, stuff, etc should never be used.


Never Use Global Variables

Global variables are anathema. Never use global variables. Never use class attributes or any else like they are global variables.


This page was last modified on 2021-03-17 at 20:16:04.

Copyright © 2018–2024 George Fox University. All rights reserved.