Acronyms should be treated as normal words:

  1. maxId

instead of:

  1. XHTML
  2. maxID

Underscores in names (_) are not actually forbidden by thecompiler, but are strongly discouraged as they havespecial meaning within the Scala syntax. (But see belowfor exceptions.)

Classes should be named in upper camel case:

  1. class MyFairLady

This mimics the Java naming convention for classes.

Sometimes traits and classes as well as their members are used to describeformats, documentation or protocols and generate/derive them. In these cases it is desirable to be close to a 1:1 relation to the output formatand the naming conventions don’t apply. In this case, they should only be usedfor that specific purpose and not throughout the rest of the code.

Objects

Object names are like class names (upper camel case).

An exception is when mimicking a package or function.This isn’t common. Example:

  1. object ast {
  2. sealed trait Expr
  3. case class Plus(e1: Expr, e2: Expr) extends Expr
  4. ...
  5. }
  6. object inc {
  7. def apply(x: Int): Int = x + 1
  8. }

Scala packages should follow the Java package naming conventions:

  1. // wrong!
  2. package coolness
  3. // right! puts only coolness._ in scope
  4. package com.novell.coolness
  5. // right! puts both novell._ and coolness._ in scope
  6. package com.novell
  7. package coolness
  8. // right, for package object com.novell.coolness
  9. package com.novell
  10. /**
  11. * Provides classes related to coolness
  12. */
  13. package object coolness {
  14. }

It is occasionally necessary to fully-qualify imports usingroot. For example if another net is in scope, thento access net.liftweb we must write e.g.:

  1. import _root_.net.liftweb._

Do not overuse root. In general, nested package resolves are agood thing and very helpful in reducing import clutter. Using rootnot only negates their benefit, but also introduces extra clutter in andof itself.

Methods

Textual (alphabetic) names for methods should be in lower camel case:

  1. def myFairMethod = ...

This section is not a comprehensive guide to idiomatic method naming in Scala.Further information may be found in the method invocation section.

  • For accessors of properties, the name of the method should be thename of the property.
  • In some instances, it is acceptable to prepend “is” on a booleanaccessor (e.g. isEmpty). This should only be the case when nocorresponding mutator is provided. Please note that the convention of appending “” to booleanaccessors is non-standard and not used outside of the Liftframework.
  • For mutators, the name of the method should be the name of theproperty with “_=” appended. As long as a corresponding accessorwith that particular property name is defined on the enclosing type,this convention will enable a call-site mutation syntax whichmirrors assignment. Note that this is not just a convention but arequirement of the language.

Unfortunately, these conventions fall afoul of the Java conventionto name the private fields encapsulated by accessors and mutatorsaccording to the property they represent. For example:

  1. public class Company {
  2. private String name;
  3. public String getName() {
  4. return name;
  5. }
  6. public void setName(String name) {
  7. this.name = name;
  8. }
  9. }

In Scala, there is no distinction between fields and methods. In fact,fields are completely named and controlled by the compiler. If we wantedto adopt the Java convention of bean getters/setters in Scala, this is arather simple encoding:

  1. class Company {
  2. private var _name: String = _
  3. def name = _name
  4. def name_=(name: String) {
  5. _name = name
  6. }
  7. }

While Hungarian notation is terribly ugly, it does have the advantage ofdisambiguating the name variable without cluttering the identifier.The underscore is in the prefix position rather than the suffix to avoidany danger of mistakenly typing name instead of name_. With heavyuse of Scala’s type inference, such a mistake could potentially lead toa very confusing error.

Note that the Java getter/setter paradigm was often used to work around alack of first class support for Properties and bindings. In Scala, thereare libraries that support properties and bindings. The convention is touse an immutable reference to a property class that contains its owngetter and setter. For example:

  1. class Company {
  2. val string: Property[String] = Property("Initial Value")

Unlike Ruby, Scala attaches significance to whether or not a method isdeclared with parentheses (only applicable to methods ofarity-0). For example:

  1. def foo1() = ...

These are different methods at compile-time. While foo1 can be calledwith or without the parentheses, foo2 may not be called _with_parentheses.

Thus, it is actually quite important that proper guidelines be observedregarding when it is appropriate to declare a method without parenthesesand when it is not.

Methods which act as accessors of any sort (either encapsulating a fieldor a logical property) should be declared without parentheses exceptif they have side effects. While Ruby and Lift use a ! to indicatethis, the usage of parens is preferred (please note that fluid APIs andinternal domain-specific languages have a tendency to break theguidelines given below for the sake of syntax. Such exceptions shouldnot be considered a violation so much as a time when these rules do notapply. In a DSL, syntax should be paramount over convention).

Further, the callsite should follow the declaration; if declared withparentheses, call with parentheses. While there is temptation to save afew characters, if you follow this guideline, your code will be _much_more readable and maintainable.

  1. // doesn't change state, call as birthdate
  2. def birthdate = firstName
  3. // updates our internal state, call as age()
  4. def age() = {
  5. _age = updateAge(birthdate)
  6. _age
  7. }

Avoid! Despite the degree to which Scala facilitates this area of APIdesign, the definition of methods with symbolic names should not beundertaken lightly, particularly when the symbols itself arenon-standard (for example, >>#>>). As a general rule, symbolic methodnames have two valid use-cases:

  • Domain-specific languages (e.g. actor1 ! Msg)
  • Logically mathematical operations (e.g. a + b or )

In the former case, symbolic method names may be used with impunity solong as the syntax is actually beneficial. However, in the course ofstandard API design, symbolic method names should be strictly reservedfor purely-functional operations. Thus, it is acceptable to define a>>= method for joining two monads, but it is not acceptable to definea << method for writing to an output stream. The former ismathematically well-defined and side-effect free, while the latter isneither of these.

As a general rule, symbolic method names should be well-understood andself documenting in nature. The rule of thumb is as follows: if you needto explain what the method does, then it should have a real, descriptivename rather than a symbols. There are some very rare cases where it isacceptable to invent new symbolic method names. Odds are, your API isnot one of those cases!

The definition of methods with symbolic names should be considered anadvanced feature in Scala, to be used only by those most well-versed inits pitfalls. Without care, excessive use of symbolic method names caneasily transform even the simplest code into symbolic soup.

  1. object Container {
  2. val MyConstant = ...
  3. }

The value: Pi in scala.math package is another example of such a constant.

Method, Value and variable names should be in lower camel case:

  1. val myValue = ...
  2. def myMethod = ...
  3. var myVariable

Type Parameters (generics)

For simple type parameters, a single upper-case letter (from the Englishalphabet) should be used, starting with A (this is different than theJava convention of starting with T). For example:

If the type parameter has a more specific meaning, a descriptive nameshould be used, following the class naming conventions (as opposed to anall-uppercase style):

  1. // Right
  2. class Map[Key, Value] {
  3. def get(key: Key): Value
  4. def put(key: Key, value: Value): Unit
  5. }
  6. // Wrong; don't use all-caps
  7. class Map[KEY, VALUE] {
  8. def get(key: KEY): VALUE
  9. def put(key: KEY, value: VALUE): Unit
  10. }

If the scope of the type parameter is small enough, a mnemonic can beused in place of a longer, descriptive name:

  1. class Map[K, V] {
  2. def get(key: K): V
  3. def put(key: K, value: V): Unit
  4. }

Higher-kinds are theoretically no different from regular type parameters(except that their) is at least=> rather than simply *). The naming conventions are generallysimilar, however it is preferred to use a descriptive name rather than asingle letter, for clarity:

  1. class HigherOrderMap[Key[_], Value[_]] { ... }

The single letter form is (sometimes) acceptable for fundamental conceptsused throughout a codebase, such as F[] for Functor and M[] forMonad.

In such cases, the fundamental concept should be something well knownand understood to the team, or have tertiary evidence, such as thefollowing:

  1. def doSomething[M[_]: Monad](m: M[Int]) = ...

Here, the type bound : Monad offers the necessary evidence to informthe reader that M[_] is the type of the Monad.

Annotations, such as @volatile should be in lower camel case:

  1. class cloneable extends StaticAnnotation

This convention is used throughout the Scala library, even though it isnot consistent with Java annotation naming.

Note: This convention applied even when using type aliases onannotations. For example, when using JDBC:

  1. type id = javax.persistence.Id @annotation.target.field
  2. @id

Special Note on Brevity

Because of Scala’s roots in the functional languages, it is quite normalfor local names to be very short:

  1. def add(a: Int, b: Int) = a + b

This convention only applies to parameters of very simple methods (andlocal fields for very simply classes); everything in the publicinterface should be descriptive. Also note that the names of argumentsare now part of the public API of a class, since users can use namedparameters in method calls.