La base de code sur laquelle je travaille utilise fréquemment des variables d'instance pour partager des données entre diverses méthodes triviales. Le développeur d'origine est catégorique sur le fait que cela respecte les meilleures pratiques énoncées dans le livre de l'oncle Bob / Robert Martin sur le code propre : "La première règle en matière de fonctions est qu'elles doivent être petites." et "Le nombre idéal d'arguments pour une fonction est zéro (niladique). (...) Les arguments sont difficiles. Ils prennent beaucoup de puissance conceptuelle."
Un exemple:
public class SomeBusinessProcess {
@Inject private Router router;
@Inject private ServiceClient serviceClient;
@Inject private CryptoService cryptoService;
private byte[] encodedData;
private EncryptionInfo encryptionInfo;
private EncryptedObject payloadOfResponse;
private URI destinationURI;
public EncryptedResponse process(EncryptedRequest encryptedRequest) {
checkNotNull(encryptedRequest);
getEncodedData(encryptedRequest);
getEncryptionInfo();
getDestinationURI();
passRequestToServiceClient();
return cryptoService.encryptResponse(payloadOfResponse);
}
private void getEncodedData(EncryptedRequest encryptedRequest) {
encodedData = cryptoService.decryptRequest(encryptedRequest, byte[].class);
}
private void getEncryptionInfo() {
encryptionInfo = cryptoService.getEncryptionInfoForDefaultClient();
}
private void getDestinationURI() {
destinationURI = router.getDestination().getUri();
}
private void passRequestToServiceClient() {
payloadOfResponse = serviceClient.handle(destinationURI, encodedData, encryptionInfo);
}
}
Je reformulerais cela en utilisant les variables locales suivantes:
public class SomeBusinessProcess {
@Inject private Router router;
@Inject private ServiceClient serviceClient;
@Inject private CryptoService cryptoService;
public EncryptedResponse process(EncryptedRequest encryptedRequest) {
checkNotNull(encryptedRequest);
byte[] encodedData = cryptoService.decryptRequest(encryptedRequest, byte[].class);
EncryptionInfo encryptionInfo = cryptoService.getEncryptionInfoForDefaultClient();
URI destinationURI = router.getDestination().getUri();
EncryptedObject payloadOfResponse = serviceClient.handle(destinationURI, encodedData,
encryptionInfo);
return cryptoService.encryptResponse(payloadOfResponse);
}
}
Ceci est plus court, élimine le couplage de données implicite entre les différentes méthodes triviales et limite les portées variables au minimum requis. Pourtant, malgré ces avantages, je n'arrive toujours pas à convaincre le développeur initial que cette refactorisation est justifiée, car elle semble contredire les pratiques d'Oncle Bob mentionnées ci-dessus.
D'où mes questions: Quelle est la raison objective, scientifique, de privilégier les variables locales aux variables d'instance? Je n'arrive pas à mettre le doigt dessus. Mon intuition me dit que les couplages cachés sont mauvais et qu’une portée étroite vaut mieux qu’une large. Mais quelle est la science pour sauvegarder cela?
Et inversement, cette refactorisation a-t-elle des inconvénients que j'ai peut-être négligés?