8

I have a WifiComponent in my Camera in my client application. It's responsible for handling the Wifi-related functionality of the Camera. The Camera represents a real world camera.

This WifiComponent can either be enabled (in which case I can do things with it, like checking connection status and scanning) or disabled (in which case you can't do anything with it at all, other than asking whether it's enabled).

When creating a Camera in my client application, I ask the camera whether its WifiComponent is enabled. Then I construct the appropriate subclass of WifiComponent, either WifiComponentImpl or NullWifiComponent.

Implementing the supportedWifiTypes() and wifiScan() methods are easy. The NullWifiComponent doesn't support any types, is instantly done with scanning and finds no results.

But now I have to implement a bool connect(WifiNetwork network, String password) method. I want to say that I failed to connect... But I don't even support the WifiEncryptionType provided in the WifiNetwork! The real implementation throws an IllegalArgumentException if you pass it an unsupported WifiEncryptionType wifi network.

Do I...

  • Throw IllegalArgumentException, because I don't support the WifiEncryptionType requested?
  • Silently fail to connect (return false), no matter what's provided?

Generalized question:

If the real implementation fulfills a contract, and part of this contract is to throw exceptions for certain inputs, should a null-implementation prioritize its neutrality or the contract?

5
  • From a strictly logical POV, you could say that since you have no camera, your camera does not reject the WifiEncriptionType so it should not throw the IllegalArgumentException. So, I do not think not throwing it would be a breach of contract.
    – SJuan76
    Commented Nov 17, 2014 at 15:26
  • I do have a Camera, it just doesn't support Wifi via my API, either because it's not implemented on the Camera in the device API or because the Camera really doesn't have a Wifi adapter. I get your point though.
    – Pimgd
    Commented Nov 17, 2014 at 15:30
  • Never break a class's contract. Your ability to reason about what a program does depends on every component doing what it says it does. Sometimes you need to change the contract or the overall design to do what you want, but never break the contract.
    – Doval
    Commented Nov 17, 2014 at 15:56
  • 1
    But why you can't just fulfill the contract to cover the situation of disabled wifi? Just throw some WifiDisabledException (say, extending IllegalStateException) in this case. This will allow the client code to recognize such situation and respond to it correctly (e.g. with proper indication).
    – lorus
    Commented Nov 17, 2014 at 16:19
  • @lorus I hadn't thought of that.
    – Pimgd
    Commented Nov 17, 2014 at 16:21

1 Answer 1

4

As the null-implementation is supposed to be a drop-in replacement for the full-functional implementation, the null-implementation should fully adhere to the interface that it implements.

If the WifiComponent interface specifies that connect() throws an exception if it gets invoked with an unsupported WifiEncryptionType, then that is exactly what your null-implementation should do, especially if the application must use the same WifiComponent interface to learn which WifiEncryptionTypes are supported.

If the list of supported WifiEncryptionTypes doesn't come from your null-implementation, then your null-implementation should only throw an exception if a functional implementation is also required to throw it.

If the WifiComponent interface doesn't specify that an exception must be thrown, then it is better to assume the value would be acceptable to a functional implementation and report a generic connection failure (return false).

3
  • I'm allowed to modify the interface of WifiComponent, but I'm looking for a balance between not being hard to work with and providing errors the moment you do something that can only go wrong. I think throwing the exception would be the way to go because it's developer error to pass in a unsupported encryption type, and use of the null-object pattern is to simplify null handling, not simplifying contract use.
    – Pimgd
    Commented Nov 17, 2014 at 15:42
  • @pimgd I agree with you here. It's clearly a program logic error if an encryption type is specified that didn't come from the list of supported types, so throwing the exception is definitely the best option.
    – Jules
    Commented Nov 17, 2014 at 16:03
  • @Pimgd: If WifiComponent isn't set in stone yet, I would recommend that you first define a sensible contract for it and then create your null-implementation with the absolute absolute minimum functionality that doesn't violate the contract you have set down. Commented Nov 17, 2014 at 16:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.