Question

The ISP says that the client should not depend on things what are not needed. As a solution small focusing interfaces (contracts) can be used:

interface RegisterUser {
  User register(String username);
}

class UserService implements RegisterUser,LockUser,FindUser,... {
  ...
}

class UserRegistrationClient {
  private RegisterUser registerUser;
  ...
}

new UserRegistrationClient(userService);

While this approach decouples client from unnecessary details, it brings some complexity in form of explosion of interfaces.

Similar effect can be achieved using lambdas:

class UserService {
  User register(String username) { ... }
  ...
}

class UserRegistrationClient {
  private Function<String,User> registerUser;
  ...
}

new UserRegistrationClient(
  username -> userService.register(username)
);
// or just:
new UserRegistrationClient(userService::register);

Is this a good approach or are there some design flaws I can't see?

Was it helpful?

Solution

Using lambdas / anonymous functions instead of interfaces with a single method (for dependency injection) is a standard approach. It is not a "good" or "bad" approach, it is an approach. And as almost any approach, it has benefits and drawbacks.

The benefits are mostly "less code" (or as you wrote, no "explosion of interfaces"). The drawbacks are less explictness / less typesafety. By using an interface, "registering service functions" get an explicit name (RegisterUser). Using lambdas will allow to inject any function into UserRegistrationClient which fits to the expected signature, not just derivations of RegisterUser.

What to choose depends on the specific situation, the specific requirements, and sometimes the specific taste of the programmer. It is pretty much the same decision whether one uses a string variable for something like a city name, or introducing a special type for city names, to distinguish them from other strings.

Licensed under: CC-BY-SA with attribution
scroll top