Repeating code in the same method

3

I have a method that generates some information. As I was in a hurry to deliver, I did and I sent. Well, it turns out, that looking at the code more carefully, I realized how crappy it is. It was made to meet a specification and as it was changed it had to change the code. The current rule is as follows: I have a method that handles files from FarmInterna . The same goes for FarmExterna . It turns out that I now need to create two folders folders before FarmInterna folder. Homologation and Production . In each folder ( Homologacao e Producao ) there should be two folders: FarmInterna and FarmExterna . I'm going to talk only about FarmInterna, which will also be valid for Externa. The same files that I generate in path: ...Homolagacao/FarmInterna/web/... are the same for: ...Producao/FarmInterna/web/... . This made my code extremely ugly and inelegant. How do I not to duplicate the code as it is? Is there any pattern for this? Below my code. Where there is the H letter refers to Homolagation and

production.

private void CriaPastaFarmInterna()
        {
            string novo_path_H  = caminho_original + @"\Destino\Temp\Homologacao\FarmInterna\web";
            string novo_path_P  = caminho_original + @"\Destino\Temp\Producao\FarmInterna\web";
            string path_files   = caminho_original + @"\Destino\Temp";

            DirectoryInfo dirInfoH = new DirectoryInfo(novo_path_H);
            DirectoryInfo dirInfoP = new DirectoryInfo(novo_path_P);

            int indice = 1;

            if (dirInfoH.Exists == false)
                Directory.CreateDirectory(novo_path_H);

            if (dirInfoP.Exists == false)
                Directory.CreateDirectory(novo_path_P);

            List<String> myFiles = Directory.GetFiles(caminho_original + @"\Destino\Temp\web", "*.*", SearchOption.AllDirectories).ToList();

            List<String> myDirectoriesH = Directory.GetDirectories(caminho_original + @"\Destino\Temp\web").ToList();
            List<String> myDirectoriesP = Directory.GetDirectories(caminho_original + @"\Destino\Temp\web").ToList();

            var diretorios_H = myDirectoriesH.Where(d => !d.Contains("FarmInterna"));
            var diretorios_P = myDirectoriesP.Where(d => !d.Contains("FarmInterna"));

            try
            {
                foreach (string file in myFiles)
                {
                    FileInfo mFile = new FileInfo(file);
                    string newFileH = novo_path_H + (file.Replace(caminho_original + @"\Destino\Temp\web", ""));
                    string newFileP = novo_path_P + (file.Replace(caminho_original + @"\Destino\Temp\web", ""));

                    if (!Directory.Exists(newFileH))
                        Directory.CreateDirectory(Path.GetDirectoryName(newFileH));

                    if (!Directory.Exists(newFileP))
                        Directory.CreateDirectory(Path.GetDirectoryName(newFileP));

                    if (new FileInfo(newFileH).Exists == false)
                        mFile.CopyTo(newFileH);

                    if (new FileInfo(newFileP).Exists == false)
                        mFile.CopyTo(newFileP);
                }

                RenomearWebConfig(novo_path_H, "H");
                RenomearWebConfig(novo_path_P, "P");
            }
            catch(Exception ex)
            {}
        }
    
asked by anonymous 25.05.2016 / 18:34

3 answers

4

Refactoring for duplicate code is quite simple:

  • 2) Scroll through the code of the original method by moving each duplicate line into the new method. You see: moving! It is not copying and pasting, it is cutting and pasting. Choose a pattern of lines to move; for example: move to the new method lines that treat "homologation" , leaving the lines that treat production in the original method.

  • 3) Lines that structure execution (conditions, loops, try-catch ...) are eventually not duplicated - these you copy to the new method instead of moving.

  • 4) The rows moved to the new method will not compile because they need variables that do not exist in that context. Declare each of these non-existent variables as parameters of this new method. Now the new method already compiles.

  • 5) In the new method's code, replace the constants and literals that are unique to each run in order to make the lines using these constants and literals generic.

  • 6) Rescan the original method and replace the lines that have already been replicated in the new method by calling this new method, passing the parameters as required by it (in this case, the parameters referring to "production").

  • )
  • li>

Ready. Now you have the original method generating the arguments needed to be passed in the two calls to the new method.

This step-by-step is generic and can be used for any refactoring of this type.

Tip: If you're willing, add the Zero Step at the top of the list, which is a unit test covering functionality that will ensure that it continues to produce the same results after refactoring.

Following this step-by-step, the code looks like this:

private void CriaPastaFarmInternaEExterna()
{
    string novo_path_H = caminho_original + @"\Destino\Temp\Homologacao\FarmInterna\web";
    string novo_path_P = caminho_original + @"\Destino\Temp\Producao\FarmInterna\web";

    List<String> myFiles = Directory.GetFiles(caminho_original + @"\Destino\Temp\web", "*.*", SearchOption.AllDirectories).ToList();

    CriaPastaFarm(novo_path_H, myFiles, "H");
    CriaPastaFarm(novo_path_P, myFiles, "P");
}

private void CriaPastaFarm(string novo_path, IEnumerable<string> files, string ambiente)
{
    DirectoryInfo dirInfo = new DirectoryInfo(novo_path);

    if (dirInfo.Exists == false)
        Directory.CreateDirectory(novo_path);

    List<String> myDirectories = Directory.GetDirectories(caminho_original + @"\Destino\Temp\web").ToList();
    var diretorios = myDirectories.Where(d => !d.Contains("FarmInterna"));

    foreach (string file in files)
    {
        FileInfo mFile = new FileInfo(file);
        string newFile = novo_path + (file.Replace(caminho_original + @"\Destino\Temp\web", ""));

        if (!Directory.Exists(newFile))
            Directory.CreateDirectory(Path.GetDirectoryName(newFile));

        if (new FileInfo(newFile).Exists == false)
            mFile.CopyTo(newFile);
    }
    RenomearWebConfig(novo_path, ambiente);
}

Note: I left out the index and path_files variables that were not being used. I also left out try-catch because the way you used it, cleaning up the exception could cause problems.

Obs2: There are a number of things that can be improved, such as replacing an enum and "P" in order to increase the expressiveness of the code; replace the (condição == false) comparison with the negation of the condition, (!condição) , which is more usual; delete the file path repeats ( @ "\ Destination \ Temp \ web" ); etc.

    
25.05.2016 / 19:45
0

Friend, center the repeated code in a new method, and call this method 2 times passing the parameters that change the behavior of the program.

private void CriaPastaFarmInterna()
        {
            NovoMetodo(caminho_original + @"\Destino\Temp\Homologacao\FarmInterna\web", 'H');
            NovoMetodo(caminho_original + @"\Destino\Temp\Producao\FarmInterna\web", 'P');


}

private void NovoMetodo(string novoPath, char letra) {

    DirectoryInfo dirInfo = new DirectoryInfo(novoPath);    

    if (dirInfo.Exists == false)
                Directory.CreateDirectory(novoPath);

    List<String> myFiles = Directory.GetFiles(caminho_original + @"\Destino\Temp\web", "*.*", SearchOption.AllDirectories).ToList();

    List<String> myDirectories = Directory.GetDirectories(caminho_original + @"\Destino\Temp\web").ToList();

    var diretorios = myDirectories.Where(d => !d.Contains("FarmInterna"));

    try
    {
        foreach (string file in myFiles)
        {
            FileInfo mFile = new FileInfo(file);
            string newFile = novoPath + (file.Replace(caminho_original + @"\Destino\Temp\web", ""));

            if (!Directory.Exists(newFile))
                Directory.CreateDirectory(Path.GetDirectoryName(newFile));


            if (new FileInfo(newFile).Exists == false)
                mFile.CopyTo(newFile);

        }

        RenomearWebConfig(novoPath, letra);
    }
    catch(Exception ex)
    {}

}
    
25.05.2016 / 19:09
0

You can try as follows:

private void CriaPastaFarmInterna(string oldPath, string newPath)
{
    var oldDirectory = new DirectoryInfo(oldPath);
    var newDirectory = new DirectoryInfo(newPath);

    if (!oldDirectory.Exists)
        return false;       

    if (!diretorio.Exists)
        diretorio.Create();

    for (var subDirectory in oldDirectory.GetDirectories())
    {
        CriaPastaFarmInterna(subDirectory.FullName, newPath + @"\" + subDirectory.Name)
    }

    for (var oldFile in oldDirectory.GetFiles())
    {
        var newFile = new FileInfo(newDirectory.FullName + @"\" + oldFile.Name);
        if (!newFile.Exists)
            oldFile.CopyTo(newFile.FullName)
    }
}

private void CriaPastaFarmInterna()
{
    string oldPath   = caminho_original + @"\Destino\Temp\Web";
    string newPathH  = caminho_original + @"\Destino\Temp\Homologacao\FarmInterna\web";
    string newPathP  = caminho_original + @"\Destino\Temp\Producao\FarmInterna\web";

    try
    {
        CriaPastaFarmInterna(oldPath, newPathH);
        CriaPastaFarmInterna(oldPath, newPathP);

        RenomearWebConfig(novo_path_H, "H");
        RenomearWebConfig(novo_path_P, "P");
    }
    catch(Exception ex)
    {           

    }
}
    
25.05.2016 / 19:10