28

Suppose I have a trait in Scala

trait Connection {

  def init(name: String)
  def dispose
}

And I want to create a class which implements it. But I want to name it as Connection also:

class Connection extends Connection {
  // ....
 }

It's not going to work. Of course, I could name trait something differently, but it turned out that the naming convention in Scala says that I should name trait as ordinary classes, meaning without any prefix, which I would use in C# (IConnection where IConnection would be the interface).

And in this particular case the name of Connection for the class and the trait is more suitable.

Or did I miss something in Scala's naming convention?

Alan Coromano
  • 24,958
  • 53
  • 135
  • 205

4 Answers4

18

The fact that you are extracting a general API into a Connection trait itself implies that it'll have multiple specific implementations. Those implementations will of course be related to some more specific entities, e.g. a MySQL or an H2 database.

There are several approaches to your problem depending on the chosen architecture of your app:

  1. If you keep the specific implementations in the same namespace you get:

    • myApp.Connection

    • myApp.MySqlConnection

    • myApp.H2Connection

  2. But the above is actually discouraged due to redundancy in names (the *Connection part) and introduction of a new package is recommended, e.g.:

    • myApp.Connection

    • myApp.connections.MySql

    • myApp.connections.H2

    or

    • myApp.Connection

    • myApp.Connection.MySql

    • myApp.Connection.H2

    if you choose to place the specific implemntation in a companion object of Connection.

  3. In more advanced approaches to architecture you will end up with specific implementations having private packages:

    • myApp.Connection

    • myApp.mySql.Connection

    • myApp.h2.Connection

    And even here although you have the Connection name clashing it's easily solvable due to types being located in different packages by using qualified references (myApp.Connection) or qualified imports:

    import myApp.{Connection => GeneralConnection} //or IConnection if you insist
    
Nikita Volkov
  • 42,792
  • 11
  • 94
  • 169
  • 3
    I think option 1 is the most common in practice. Option 2 is confusing when you're reading code. – sksamuel Jun 15 '13 at 10:44
  • 1
    @monkjack That's right; It may feel like repeating the same information but on the other hand you can't expect all the developers to have all the package context of all the types in their head – AlexG Jun 18 '15 at 15:19
11

It's not a convention but something used in the scala.collection is the suffix Like used in traits:

  • SeqLike: A template trait for sequences of type Seq[A].
  • MapLike: A template trait for maps, which associate keys with values.

And so on.

I guess it's their way to say Rectangle/Rectangular where this relation (Seq/SeqLike) does not have a clear naming.

8

In Martin Odersky's book there is a sample with a class Rectangle that extends a trait Rectangular and a class Rational that extends a trait Ordered. So the pattern seems here to be to use an adjective for the trait name an a subject for the class name. So in your case it would be "class Connection extends Connected". At least I like this more than "class ConnectionImpl extends Connection".

OlliP
  • 1,545
  • 11
  • 22
5

The common practice for naming class that implements some interface/trait is to add Impl as postfix (and don't add any prefixes/postfixes to interface/trait):

class ConnectionImpl extends Connection {
  // ....
}

Why? Because in good code you write functions against interfaces, so you wont polute your functions with thoose I's:

def sendThings(conn: Connection) {


}

versus

def sendThings(conn: IConnection) {


}

If you have multiple implementations, this, of course should be Connection trait, HttpConnection class1, JdbcConnection class2.

Community
  • 1
  • 1
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • 4
    `HttpUtilImpl`, `UserImpl`, `CarImpl`...? that is, I should add `Impl` to each class name in my code, even if there is no trait with the similar name? Not reasonable at all. – Alan Coromano Jun 15 '13 at 10:05
  • 1
    @MariusKavansky nope, only if there is *trait and one class* situation and they do not differ in names. – om-nom-nom Jun 15 '13 at 10:07
  • that's the same thing. as I said in my question, I could name the trait (or the class) differently, but I didn't want to do that. – Alan Coromano Jun 15 '13 at 10:17
  • 4
    In his book Martin Odersky has a sample of a trait Rectangular where a class Rectangle extends the trait Rectangular. I like this Rectangle->Rectangular naming pair. What I would like to have is a naming convention that is a generalisation of Rectangle->Rectangular. But that is hard to find. To me the solution with Impl is ugly. I also didn't like it in the Java world. – OlliP Aug 08 '13 at 14:27
  • +1 for the link and adding extra affixes to "private/hidden" part of code rather than to "public". – æ-ra-code Nov 30 '13 at 15:50
  • I don't like Impl too, but sometimes very difficult to find equivalents of "Rectangle->Rectangular" kind, or "legal" name of class may be too much verbose. Of course, both cases are smells of bad understanding of domain... – æ-ra-code Nov 30 '13 at 16:09