As a rule, files should contain a single logical compilation unit. By“logical” I mean a class, trait or object. One exception to thisguideline is for classes or traits which have companion objects.Companion objects should be grouped with their corresponding class ortrait in the same file. These files should be named according to theclass, trait or object they contain:
package com.novell.coolness
class Inbox { ... }
// companion object
object Inbox { ... }
These compilation units should be placed within a file namedInbox.scala
within the com/novell/coolness
directory. In short, theJava file naming and positioning conventions should be preferred,despite the fact that Scala allows for greater flexibility in thisregard.
Multi-Unit Files
Despite what was said above, there are some important situations whichwarrant the inclusion of multiple compilation units within a singlefile. One common example is that of a sealed trait and severalsub-classes (often emulating the ADT language feature available infunctional languages):
sealed trait Option[+A]
case class Some[A](a: A) extends Option[A]
case object None extends Option[Nothing]
Because of the nature of sealed superclasses (and traits), all subtypesmust be included in the same file. Thus, such a situation definitelyqualifies as an instance where the preference for single-unit filesshould be ignored.
Another case is when multiple classes logically form a single, cohesivegroup, sharing concepts to the point where maintenance is greatly servedby containing them within a single file. These situations are harder topredict than the aforementioned sealed supertype exception. Generallyspeaking, if it is easier to perform long-term maintenance anddevelopment on several units in a single file rather than spread acrossmultiple, then such an organizational strategy should be preferred forthese classes. However, keep in mind that when multiple units arecontained within a single file, it is often more difficult to findspecific units when it comes time to make changes.
All multi-unit files should be given camelCase names with a lower-casefirst letter. This is a very important convention. It differentiatesmulti- from single-unit files, greatly easing the process of findingdeclarations. These filenames may be based upon a significant type whichthey contain (e.g. option.scala
for the example above), or may bedescriptive of the logical property shared by all units within (e.g.ast.scala
).