Interfaces, what if not all implementations use all methods?

I am new to programming against interfaces, and I try to make this the right tool for developing a test.

We currently have many manager classes that implement the CRUD interface. However, some managers still do not make updates, and some do not delete, some of them can never do it.


An exception is not implemented?

It's alright just

 throw new NotImplementedException() 

until the method is implemented, or even for the whole time, if it never does?

(obviously, with a source code comment telling the programmer "this method is not supposed to be used, for example, such as" male "," female "are never deleted)?


Split up?

Or should I split my CRUD interface into Creatable, Readable (Searchable), Updatable, and Deletable? Wouldn't that hurt the definition of my class?

 PersonManager implements Creatable<Person>, Updateable<Person>, Deletable<Person>, Searchable<Person> 

Split and merge?

Or do I need to combine some interfaces, such as all 4, in CRUD, and possibly some other combinations, such as Read + Update?

Maybe this will also create a load of interfaces, where you need to click on a large inheritance path to find out which interface implements all the necessary atomic interfaces for the current situation (do I need to read and create, so one of them implements two ?, and this can become much more complicated fast)

+7
source share
4 answers

IMO, for the middle stage, it's normal to use a NotImplementedException until you finish implementing it.

However, as a permanent solution - I think this is bad practice [in most cases].

Instead, I will create an interface that contains the behavior common to all classes, and use subinterfaces to group them for more specific behavior.

The idea is similar to the java standard SortedSet , which extends Set - we would not want to treat Set as a SortedSet and give a variable of this type a HashSet value, instead we use a sub-interface, SortedSet for this purpose.

+5
source

Typically, you would like to throw an UnsupportedOperationException , which is an exception at run time, explicitly indicating that the requested operation is not supported.

The presence of loads of interfaces will lead to too many files, and also if someone tries to look at them, they will be confused. Java documents do not help in such cases.

Splitting an interface makes sense if there are too many operations for one interface, and not all operations are logically connected.

To work with a database, it is rarely the case that you will have a basic operation that will be valid for most of the scenario.

+5
source

NotImplementedException does not mean that the class does not support this action. This means that it is not implemented, but it will be in the future.

Logically, all interface methods should be implemented and should work well. But if you leave it and write the application only for yourself, then you will recall this restriction. In the other hand, I would be angry that some developer implemented the interface and left it unrealized. Therefore, I do not think that you can leave the interface method not implemented only for future development.

My suggestion, rather, is to modify the interfaces and then use exceptions inside the implemented methods.

+1
source

Within frameworks that support covariance and contravariance, it can be very useful to separate the interfaces and then define some composite interfaces. For frameworks that do not offer such support (and even sometimes within frameworks), it is sometimes more useful to have an interface that includes methods that may or may not be supported by individual implementations (an implementation should throw an exception when trying unsupported actions); if someone does this, you need to include methods or properties by which the external code may ask what actions are supported without using any code that will throw an exception.

However, even when using interfaces where support for actions is optional, it is sometimes useful to define additional interfaces that ensure that some actions are available. A good way to do this might be an interface that inherits other interfaces without adding new members. If everything is done correctly, the only additional work that will be required on behalf of the implementation is to make sure that they have declared themselves the most applicable type. The situation for clients is somewhat more complicated: if the needs of clients can be adequately expressed in the type system, clients can avoid the need to check the type of runtime by requiring certain types. On the other hand, routines that transfer instances between clients can be complicated by some of the clients' requirements for a more specific type than the code transfer code would otherwise require.

0
source

All Articles