Baza kodów, nad którą pracuję, często używa zmiennych instancji do udostępniania danych między różnymi trywialnymi metodami. Pierwotny programista jest przekonany, że przestrzega najlepszych praktyk zawartych w książce Clean Code autorstwa Uncle Bob / Robert Martin: „Pierwszą zasadą funkcji jest to, że powinny być małe”. oraz „Idealna liczba argumentów dla funkcji wynosi zero (niladic). (...) Argumenty są trudne. Wymagają dużej mocy konceptualnej”.
Przykład:
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);
}
}
Zmieniłbym to na następujące, używając zmiennych lokalnych:
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);
}
}
Jest to krótsze, eliminuje niejawne sprzężenie danych między różnymi trywialnymi metodami i ogranicza zakresy zmiennych do wymaganego minimum. Jednak pomimo tych korzyści nadal nie wydaje mi się, aby przekonać pierwotnego programistę, że takie refaktoryzowanie jest uzasadnione, ponieważ wydaje się być sprzeczne z praktykami wuja Boba wspomnianymi powyżej.
Stąd moje pytania: jaki jest obiektywny, naukowy uzasadnienie faworyzowania zmiennych lokalnych nad zmiennymi instancji? Nie mogę po prostu położyć na tym palca. Moja intuicja mówi mi, że ukryte połączenia są złe i że wąski zakres jest lepszy niż szeroki. Ale jaka jest nauka, aby to poprzeć?
I odwrotnie, czy są jakieś wady tego refaktoryzacji, które prawdopodobnie przeoczyłem?