Evite anomalias DD

5

Eu tenho esse problema chamado pelo PMD (analisador de código estático) com mais frequência do que gostaria, e gostaria de saber como alguém com mais experiência do que eu o escreveria. Meu código é funcional, mas acho-o deselegante, então quero saber como outros programadores escreveriam essa peça.

O caso é, em uma petição de rede / IO, posso ou não obter um resultado, mas meu método pai não é à prova de nulo, então eu sempre tenho que retornar alguma coisa. Eu também não gosto de vários retornos em um método.

public String getBingLocation(Coordinate... data)
{
    String response = "Not Retrieved";
    final Coordinate location = data[0];
    JSONObject locationData;
    try {
        locationData = NetworkManager.getJSONResult(ApiFormatter
                .generateBingMapsReverseGeocodingURL(location.Latitude, location.Longitude));
        if (null != locationData) {
            final String address = this.getAddressFromJSONObject(locationData);
            response = address;
        }
    } catch (final ClientProtocolException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        return response;
    } catch (final JSONException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        return response;
    } catch (final IOException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        return response;
    } finally {
        location.Street = response;
    }
    return response;
}

Outro exemplo:

public static Object loadObject(final String fileName, final Context context) {
    Object object = null;
    try {
        ObjectInputStream objectInputStream = null;
        try {
            final FileInputStream fileStream = context.openFileInput(fileName);
            objectInputStream = new ObjectInputStream(fileStream);
            object = objectInputStream.readObject();
        } catch (final ClassNotFoundException catchException) {
            LoggerFactory.consoleLogger().printStackTrace(catchException);
        } catch (final ClassCastException catchException) {
            LoggerFactory.consoleLogger().printStackTrace(catchException);
        } catch (final Exception catchException) {
            LoggerFactory.consoleLogger().printStackTrace(catchException);
        } finally {
            if (objectInputStream != null) {
                objectInputStream.close();
            }
        }
    } catch (final IOException catchException) {
        LoggerFactory.consoleLogger().printStackTrace(catchException);
    }
    return object;
}
    
por MLProgrammer-CiM 01.02.2013 / 10:55
fonte

2 respostas

4

Parte do problema é que suas funções têm mais de uma responsabilidade. Ambos estão recebendo um resultado e lidando com erros. Você também está ficando desnecessariamente desligado tentando evitar vários pontos de retorno, o que é uma prática vestigial da programação em C, onde pode causar vazamentos de memória. Você deve usar vários retornos se esclarecer seu código, especialmente em funções curtas. Eu também estou supondo que o seu código de log está se repetindo em todo o lugar. Se você separar essas preocupações e tentar evitar se repetir, você terá algo assim:

public JSONObject getLoggedJSONResult(String api)
{
    try {
        return NetworkManager.getJSONResult(api);
    } catch (final ClientProtocolException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
    } catch (final JSONException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
    } catch (final IOException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
    }

    return null;
}

public String getBingLocation(Coordinate... data)
{
    final Coordinate location = data[0];

    JSONObject locationData = getLoggedJSONResult(
       ApiFormatter.generateBingMapsReverseGeocodingURL(
          location.Latitude, location.Longitude));

    if (null == locationData) {
        return "Not Retrieved";
    } else {
        return this.getAddressFromJSONObject(locationData);
    }
}

Como princípio geral, a maioria das anomalias DD pode ser corrigida dividindo a função. É principalmente uma questão de descobrir onde dividir isso.

Seu segundo exemplo é mais complicado. Esse tipo de situação é por que as declarações try-with-resources foram inventadas. Você pode usar um retorno antecipado para eliminar a anomalia de DD em object , mas não conseguirá fazer muito com objectInputStream sem tentar usar recursos.

    
por 05.02.2013 / 19:50
fonte
0

Quanto ao seu primeiro exemplo, eu escreveria assim:

public String getBingLocation(Coordinate... data)
{
    String response;
    final Coordinate location = data[0];
    JSONObject locationData;
    try {
        locationData = NetworkManager.getJSONResult(ApiFormatter
                .generateBingMapsReverseGeocodingURL(location.Latitude, location.Longitude));
        if (null != locationData) {
            final String address = this.getAddressFromJSONObject(locationData);
            response = address;
        } else {
            response = "Not Retrieved";
        }
    } catch (final ClientProtocolException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        response = "Not Retrieved";
    } catch (final JSONException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        response = "Not Retrieved";
    } catch (final IOException e) {
        LoggerFactory.consoleLogger().printStackTrace(e);
        response = "Not Retrieved";
    } finally {
        location.Street = response;
    }
    return response;
}

A idéia principal é evitar substituir um valor sem lê-lo (isso significa que uma atribuição é inútil porque nunca foi lida).

Uma solução é ter uma única instrução de retorno e retornar uma variável não inicializada. Em seguida, percorra todo o caminho possível e verifique se um valor é sempre atribuído e não mais de uma vez.

    
por 05.02.2013 / 15:42
fonte

Tags