mardi 5 juin 2018

Is grouping multiple @Service and @Repository classes into wrappers an anti-pattern?

Question is a bit rhetorical. I've had an argument with my colleagues regarding the following pattern:

@Component
public class MetaService {

    public static UserService userService;
    public static GroupService groupService;   
    public static PermissionService permissionService;            
    // ...more fields

    @Autowired
    public MetaService(UserService userService,
                       GroupService groupService
                       PermissionService permissionService) {

        MetaService.userService = userService;
        MetaService.groupService = groupService;
        MetaService.permissionService = permissionService;           
    }
}

Basically, MetaService is an entry point/wrapper for multiple Spring beans @Service classes. And there's one more similar MetaDao wrapper for @Repository beans class:

@Component
public class MetaDao {

    public static UserDao userDao;
    public static GroupDao groupDao;
    public static PermissionDao permissionDao;
    // ...more fields   

    @Autowired
    public MetaDao(UserDao userDao,
                   GroupDao groupDao,
                   PermissionDao permissionDao) {

        MetaDao.userDao = userDao;
        MetaDao.groupDao = groupDao;
        MetaDao.permissionDao = permissionDao;
    }
}

The idea of having such a Meta class is to reduce code base within @RestController and @Service classes, by providing concise API to call @Service and @Repository methods, for example:

@RestController
public class UserController {

    @PostMapping
    public UserCreateResponse createUser(UserCreateRequest request) {
        MetaService.userService.createAndReturn(userEntity);
        // other service calls
    }
}

In other words, this is an alternative of having @Autowired fields/constructors for each @Service within each @Controller etc. In my opinion this approach greatly reduces boilerplate repetitive code a lot.

Well, my colleagues are saying that: such an approach making the code harder to understand/maintain, since combining @Service components in one place hides dependency model of other components which use them. In other words, if there were fields declared for UserController class. It would've been easier to quickly find out which components UserController depends upon. In addition, it's harder to mock such dependencies doing unit testing. And the most important that such approach is super-anti-pattern. Whereas I can agree with mocking part, everything else seems ridiculous to me.

Question is, is this truly an anti-pattern in any way?

Thank you.

Aucun commentaire:

Enregistrer un commentaire