Interface naming conventions

4,025 views
Skip to first unread message

Cristian Garcia

unread,
Mar 22, 2015, 5:08:00 PM3/22/15
to mi...@dartlang.org
In Dart everything is a possible interface with is REALLY nice for testing purposes (e.g. creating mock for non-abstract classes). I have a use case in mind for "interfaces" (abstract classes) and has to do with TDD: first create an interface and a class is suppose to implement that interface, then create tests for that interface (where all tests will fail), complete the class to implement the interface. Using a factory constructor, the initial setup would be like this example
 
abstract class IUser 
{
    String name;

    factory IUser () => new User();

    void Register ();
}

class User
{
    //Implement later
}

Now, here I am using C# naming convention. On the bright side, its pretty clear what is happening, on the down side writing "IUser user" everywhere is not so nice. Another strategy would be to define "abstract class User" for the interface, and for the implementation: "class User_" or "class User_Impl" or "class UserImpl" or even just "class _User" (don't like that its private).

What should be the standard on this?

Justin Fagnani

unread,
Mar 22, 2015, 5:26:45 PM3/22/15
to General Dart Discussion

Like you point out, I find C# style interface names to be ugly and noisy. The best thing, IMO, is to just define the class, and let it also be used as the interface. If the implementation needs methods you don't want in the interface, then split it the implementation as FooImpl or _FooImpl. That's the style the cite libraries use.

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.

Lasse R.H. Nielsen

unread,
Mar 23, 2015, 6:36:00 AM3/23/15
to mi...@dartlang.org
I would definitely not use IUser in Dart. It's a symptom of the need to have separate class and interface but with the same meaning. If they could both be called User, then there is no need, and in Dart they can. 

There are basically two use-cases for an interface:
- As a common interface for interchangeable implementations. This is what Map, Set, List etc are.
- As a common supertype for a group of subclasses. That would be User, PrivilegedUser, ExternalUser, etc.

When possible, make the interface also be the default implementation. There is no need for an extra class, and it makes it easier for people who want to extend the default class to not have to find it. That makes sense when the default implementation is common to most implementations, which is generally the second use-case.

The one constraint that has made us not actually do that is that we have base classes with constructors that create specific implementations. For "List", the "List()" constructor can create two different types of lists, which means that it's a factory, which again means that List it's not a good class to use as a superclass - which is why we have a separate ListBase class with a useful generative constructor. We should not have made IterableBase different from Iterable, though. That was a bad case of trying to be consistent with List, even if List was a compromise design.

For a separate implementation class, I usually go for _User if it's private (no "Impl" - it's redundant to say that a non-abstract class is an implementation). For a public name, it depends on whether there is a visible characteristic of the implementation class that describes it relative to other possible implementations (LinkedHashMap is the default Map, but it's also a class on its own, same for LinkedHashSet and ListQueue). It's rare that the default class is public, different from the interface, and doesn't have a meaningful distinguishing characteristic (read: I can't think of a case).

/L

--
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

Cristian Garcia

unread,
Mar 23, 2015, 12:49:15 PM3/23/15
to mi...@dartlang.org
Lasse, you make good points. On one hand, since everything is an interface the default implementation could just be that interface,
resolving the naming problem and making it extendable. For what I need a could just do this

class UserServices
{
    Future<User> Login (String username, String password) => throw new UnimplementedError();
    Future<User> New () => throw new UnimplementedError();
    Future<User> Get (String id) => throw new UnimplementedError();
}

which is almost the same as defining an interface. The one thing that bugs me about that is loosing the factory constructor, to be honest
this is an approach I plan to take, I've not used it extensively, but the factory constructor looks extremely convenient. Also, I haven't been
able to extend a class that has a factory constructor, I get errors that I haven't been able to resolve.

Cristian Garcia

unread,
Mar 23, 2015, 12:53:46 PM3/23/15
to mi...@dartlang.org
Note: UserServices is like that because in TDD you have create the tests before writing actual code, not because its a good way of creating interfaces

Justin Fagnani

unread,
Mar 23, 2015, 1:18:28 PM3/23/15
to General Dart Discussion
Dart's very forgiving with respect to warnings an errors. You might try just leaving the methods unimplemented - you'll get a static warning, and a NoSuchMethodError() when you call them :)

On Mon, Mar 23, 2015 at 9:53 AM, Cristian Garcia <cgarc...@gmail.com> wrote:
Note: UserServices is like that because in TDD you have create the tests before writing actual code, not because its a good way of creating interfaces

--
Reply all
Reply to author
Forward
0 new messages