1

Let's say we have an analytic application (AppX) that allows the import and export of analytic files. We want to build some functionality into it to allow those files to be shared in an enterprise collaboration platform, however we use 2 different platforms, say Jive and Workplace.

While this is somewhat subjective, I'm looking to see if this model matches the convention for OO concepts?

1 - We have in interface CollaborationService defining methods that must be implemented in order to fulfill the full functionality.

2 - We have an abstract class DefaultCollaborationService implements CollaborationService that has some default implementation for some of the operations.

3 - We have a class WorkplaceCollaborationService extends DefaultCollaborationService and a class JiveCollaborationService extends DefaultCollaborationService that each have their own methods, which override those in the Default abstract class.

Or..

Is this better:

2 - abstract class DefaultCollaborationService - note, no link to the interface, so we don't have to implement everything

3 - class WorkplaceCollaborationService implements CollaborationService extends DefaultCollaborationService and class JiveCollaborationService implements CollaborationService extends DefaultCollaborationService

Or..

Is all of that not right, and you can advise a better method?

Wayneio
  • 3,466
  • 7
  • 42
  • 73

3 Answers3

1

This is on the edge of "opinionated", so lets focus on facts:

Option 1 (using the interface on your abstract base) class should be preferred: the whole purpose of this class is to provide implementation for some of the methods of your interface. You see, when the interface changes, you probably want that the compiler tells you that you have to look into the implementation in your base class.

And keep in mind: you don't have to implement all methods - you can still leave those abstract that can't be implemented on this level.

Beyond that, your approach seems reasonable.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 2
    I agree. Even for the naming, it would be confusing to have a class `DefaultCollaborationService` that does not implement an existing interface `CollaborationService`. I would probably go for `AbstractCollaborationService` though, I'd expect `Default` to provide a fully working implementation. – daniu Aug 23 '17 at 11:18
1

Let's look at an entire pattern, for a needed implementation and an offered service.

class Use1 extends Base
    @Override protected onA(X x) { }
    @Override protected onB(X x) { }

class Use2 extends Base
    @Override protected onA(X x) { }
    @Override protected onB(X x) { }

abstract class Base implements Api
    abstract protected onA(X x); // Requirement
    abstract protected onB(X x);
    public final a () { onA(x); } // Service
    public final b () { onB(x); }

interface Api
    public final a ();
    public final b ();

The first approach best fits this. But what is abstract class and interface varies today with default methods.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

If you are looking for an Object-Oriented solution, that is normally concerned about the "things" your business domain is about. The main problem I have with both proposed solutions, is that it hardly reflects anything about the problem you describe in the first paragraph.

So, let's see what your problem domain consists of: Analytic files, Jive, Workplace, and you mention "Platform" as an abstraction of the latter two. Those are the "things" mentioned right in the first paragraph.

Okay, so what are the "responsibilities" (the business functions) we need to take care of? You mention "sharing", so let's go with that.

Let's put all of those together:

public interface AnalyticFile {
    void shareTo(Platform platform);
}

public interface Platform {
    void share(byte[] data); // Whatever data is necessary
}

public final class Jive implements Platform {
    ...
}

public final class Workplace implements Platform {
    ...
}

And for the actual question you asked:

  • Always go for an interface if you want to define common functionality
  • Try to avoid "default" or "base" implementations, even with interfaces. That is not what inheritance is for. That is, it is not for sharing code, it is for expressing relations between classes.
Robert Bräutigam
  • 7,514
  • 1
  • 20
  • 38