A base de código em que estou trabalhando frequentemente usa variáveis de instância para compartilhar dados entre vários métodos triviais. O desenvolvedor original está convencido de que isso segue as melhores práticas declaradas no livro Código Limpo do tio Bob / Robert Martin: "A primeira regra das funções é que elas devem ser pequenas". e "O número ideal de argumentos para uma função é zero (niládico). (...) Os argumentos são difíceis. Eles exigem muito poder conceitual".
Um exemplo:
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);
}
}
Eu refatoraria isso da seguinte maneira usando variáveis locais:
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);
}
}
Isso é mais curto, elimina o acoplamento implícito de dados entre os vários métodos triviais e limita os escopos das variáveis ao mínimo necessário. Apesar desses benefícios, ainda não consigo convencer o desenvolvedor original de que essa refatoração é justificada, pois parece contradizer as práticas do tio Bob mencionadas acima.
Daí minhas perguntas: qual é o objetivo, a justificativa científica de favorecer variáveis locais sobre variáveis de instância? Eu não consigo colocar o dedo nele. Minha intuição me diz que os acoplamentos ocultos são ruins e que um escopo estreito é melhor que um amplo. Mas qual é a ciência para apoiar isso?
E, inversamente, há alguma desvantagem nessa refatoração que eu possivelmente tenha esquecido?