{"id":20216961,"url":"https://github.com/danilobandeira29/refactoring","last_synced_at":"2025-03-03T11:25:14.188Z","repository":{"id":123063445,"uuid":"415337629","full_name":"danilobandeira29/refactoring","owner":"danilobandeira29","description":"notes of patterns to refactor code following the book \"Refactoring\" by Martin Fowler ","archived":false,"fork":false,"pushed_at":"2021-12-25T16:22:48.000Z","size":742,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-13T22:19:04.046Z","etag":null,"topics":["design-patterns","refactor","refactoring"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danilobandeira29.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-09T14:50:15.000Z","updated_at":"2024-10-16T18:34:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"0e85951b-15fe-4f9b-bf3a-2c8857fb2ac9","html_url":"https://github.com/danilobandeira29/refactoring","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danilobandeira29%2Frefactoring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danilobandeira29%2Frefactoring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danilobandeira29%2Frefactoring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danilobandeira29%2Frefactoring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danilobandeira29","download_url":"https://codeload.github.com/danilobandeira29/refactoring/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241654259,"owners_count":19997829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["design-patterns","refactor","refactoring"],"created_at":"2024-11-14T06:31:13.519Z","updated_at":"2025-03-03T11:25:14.147Z","avatar_url":"https://github.com/danilobandeira29.png","language":"TypeScript","readme":"# Notes on _Refactoring_ by Martin Fowler\n\n## Basic Refactorings\n* [Extract Function (134)](#extract-function-134)\n* [Inline Function (144)](#inline-function-144)\n* [Extract Variable (147)](#extract-variable-147)\n* [Inline Variable (152)](#inline-variable-152)\n* [Change Function Declaration (153)](#change-function-declaration-153)\n* [Encapsulate Variable (160)](#encapsulate-variable-160)\n* [Rename Variable (165)](#rename-variable-165)\n* [Introduce Parameter Object (168)](#introduce-parameter-object-168)\n* [Combine Functions into Class (172)](#combine-functions-into-class-172)\n* [Combine Functions into Transform (177)](#combine-functions-into-transform-177)\n* [Split Phase (183)](#split-phase-183)\n\n## Encapsulation\n* [Encapsulate Record (190)](#encapsulate-record-190)\n* [Encapsulate Collection (198)](#encapsulate-collection-198)\n* [Replace Primitive with Object (203)](#replace-primitive-with-object-203)\n* [Replace Temp with Query (207)](#replace-temp-with-query-207)\n* [Extract Class (211)](#extract-class-211)\n* [Inline Class (215)](#inline-class-215)\n* [Hide Delegate (218)](#hide-delegate-218)\n* [Remove Middle Man (220)](#remove-middle-man-220)\n* [Substitute Algorithm (223)](#substitute-algorithm-223)\n\n## Moving Features\n* [Move Function (225)](#move-function-225)\n* [Move Field (235)](#move-field-235)\n* [Move Statements into Function (241)](#move-statements-into-function-241)\n* [Move Statements to Callers (245)](#move-statements-to-callers-245)\n* [Replace Inline Code with Function Call (251)](#replace-inline-code-with-function-call-251)\n* [Slide Statements (252)](#slide-statements-252)\n* [Split Loop (257)](#split-loop-257)\n* [Replace Loop with Pipeline(261)](#replace-loop-with-pipeline-261)\n* [Remove Dead Code(267)](#remove-dead-code-267)\n\n## Organizing Data\n* [Split Variable(269)](#split-variable-269)\n* [Rename Field(273)](#rename-field-273)\n* [Replace Derived Variable with Query(277)](#replace-derived-variable-with-query-277)\n* [Change Reference to Value(281)](#change-reference-to-value-281)\n* [Change Value to Reference(284)](#change-value-to-reference-284)\n\n## Simplifying Conditional Logic\n* [Decompose Conditional(288)](#decompose-conditional-288)\n* [Consolidate Conditional Expression(291)](#consolidate-conditional-expression-291)\n* [Replace Nested Conditional with Guard Clauses(294)](#replace-nested-conditional-with-guard-clauses-294)\n* [Replace Conditional with Polymorphism(299)](#replace-conditional-with-polymorphism-299)\n* [Introduce Special Case(318)](#introduce-special-case-318)\n* [Introduce Assertion(333)](#introduce-assertion-333)\n\n## Refactoring APIs\n* [Separate Query from Modifier(337)](#separate-query-from-modifier-337)\n* [Parameterize Function(340)](#parameterize-function-340)\n* [Remove Flag Argument(344)](#remove-flag-argument-344)\n* [Preserve Whole Object(349)](#preserve-whole-object-349)\n* [Replace Parameter with Query(354)](#replace-parameter-with-query-354)\n* [Replace Query with Parameter(357)](#replace-query-with-parameter-357)\n* [Remove Setting Method(361)](#remove-setting-method-361)\n* [Replace Constructor with Factory Function(363)](#replace-constructor-with-factory-function-363)\n* [Replace Function with Command(366)](#replace-function-with-command-366)\n* [Replace Command with Function(373)](#replace-command-with-function-373)\n\n## Dealing with Inheritance \n* [Pull Up Method(378)](#pull-up-method-378)\n* [Pull Up Field(381)](#pull-up-field-381)\n* [Pull Up Constructor Body(383)](#pull-up-constructor-body-383)\n* [Push Down Method(387)](#push-down-method-387)\n* [Push Down Field(388)](#push-down-field-388)\n* [Replace Type Code with Subclasses(389)](#replace-type-code-with-subclasses-389)\n* [Remove Subclass(397)](#remove-subclass-397)\n* [Extract Superclass(402)](#extract-superclass-402)\n* [Collapse Hierarchy(408)](#collapse-hierarchy-408)\n* [Replace Subclass with Delegate(409)](#replace-subclass-with-delegate-409)\n* [Replace Superclass with Delegate(429)](#replace-superclass-with-delegate-429)\n\n### Extract Function (134)\nUse quando funções são longas. Código usado mais do que uma vez merece a sua própria função.\nSe voce investe tempo para tentar entender o que um bloco de código faz, transforme-o numa função com um nome que descreva o seu comportamento.\n\n[Back to Top](#basic-refactorings)\n\n### Inline Function (144)\nOposto do _Extract Function_. Utilizar quando o corpo da função consegue descrever o seu próprio comportamento.\nExcelente quando existem muitas chamadas indiretas de função(uma função que chama outra, onde o corpo da segunda já descreve o comportamento).\nEm alguns casos, é interessante utilizar o _Inline Function_ para se ter uma visão melhor do que acontece, para posteriormente\naplicar _Extract Function_ com mais cuidado, evitando tantas delegações indiretas e desnecessárias.\n\n### Extract Variable (147)\nExistem expressões que são complexas e muito difíceis de entender. Para esses casos, é interessante dividir em pequenas as expressões\nque sejam mais fácil de ler. Dessa forma, é possível dar nomes descritivos para essas pequenas expressões.\nCaso o sentido seja apenas no contexto de uma função, então utilizar _Extract Variable_ é uma boa solução.\nPorém, em casos onde o contexto é mais amplo(além da função que a expressão se encontra), é mais interessante disponibilizar em forma de função\n_Extract Function_.\n\n[Back to Top](#basic-refactorings)\n\n### Inline Variable (152)\nUtilizar quando o nome da variável não diz nada além do que a própria expressão.\n\n### Change Function Declaration (153)\nTambém conhecido como _Rename Function_, _Rename Method_, _Add Parameter_, _Remove Parameter_, _Change Signature_.\n\nBons nomes são essenciais para entendimento do sistema de forma fácil. Se possuo um nome descritivo, não tenho a necessidade\nde olhar o corpo da função. Porém, o nome de uma Função ou Método, na grande maioria das vezes, não é o melhor na primeira declaração.\n\nMuito útil para diminuir o acoplamento entre módulos, onde uma função ou método muitas vezes não é necessário ter conhecimento\nda interface de um objeto. Por exemplo, se tiver uma função para formatar o número de telefone de uma pessoa, onde tal função\naceita uma pessoa como parâmetro, não poderei usá-la para formatar o número de telefone de uma empresa.\n\n[Back to Top](#basic-refactorings)\n\n### Encapsulate Variable (160)\nDados, diferentemente de funções, são difíceis de alterar ou refatorar caso o seu escopo seja amplo.\n\nNo caso de uma função antiga,\né possível migra-la mantendo-a intacta como uma função de encaminhamento (o cliente continua a chamar a função antiga, que chama a função nova).\n\nNo caso de dados(variáveis), o ideal é ter funções que servem como encapsulamento, tanto de acesso como de atualização para manipulação.\n\n O encapsulamento garante um controle sobre os dados, como eles podem ou não serem alterados. Ademais, transforma a difícil tarefa \nde reorganizar dados na tarefa mais simples de reorganizar funções, utilizando _Change Function Declaration_, por exemplo.\n\n[Back to Top](#basic-refactorings)\n\n### Rename Variable (165)\nBons nomes são essenciais para o entendimento do software sem gerar muito esforço. Utilizar para que o código se autodescreva.\nNão irei conseguir criar bons nomes de primeira tentativa. Ademais, a variável acaba a receber outro nome como consequência\ndas mudanças nas necessidades dos meus usuários.\n\nO nome de uma variável deve refletir o tamanho do seu escopo. Se ela está inserida numa função de 2 linhas, então posso ter\numa letra como nome. Caso o seu escopo seja mais amplo, devo utilizar um nome mais descritivo.\n\n[Back to Top](#basic-refactorings)\n\n### Introduce Parameter Object (168)\nExistem dados que aparecerem em grupo, onde ao chamar um é necessário chamar outro, por exemplo,\n_startDate_ e _endDate_. Ao aplicar _Introduce Parameter Object_, eles farão parte do mesmo objeto ou classe, \ntornando esse relacionamento explicito,\ne assim diminuindo a quantidade de parâmetros das funções que os chamam.\n\nO real benefício é que isso me permite criar comportamentos comuns nesses dados, \npor exemplo, _isBetween_, criando uma abstração que simplifica a compreensão do meu domínio.\n\n[Back to Top](#basic-refactorings)\n\n### Combine Functions into Class (172)\nUtilizar quando funções compartilham o mesmo corpo comum de dados (em geral, passados como argumentos da chamada de função).\n\nUsar uma classe deixa o ambiente comum compartilhado por essas funções mais explicito, permite simplificar as chamadas de \nfunção dentro do objeto por meio da remoção de vários argumentos, já que usarão variáveis de instância.\n\n[Back to Top](#basic-refactorings)\n\n### Combine Functions into Transform (177)\nUtilizar quando funções compartilham o mesmo corpo comum de dados (em geral, passados como argumentos da chamada de função).\n\nA partir disso, criar uma função pura, que irá pegar o corpo comum, fazer uma _deep copy_, alterar as propriedades dessa cópia\n(transformar ou enriquecer com dados calculados) e devolver para o _client_ com os valores atualizados, sem alterar o corpo original.\n\nDessa forma todos os lugares que transformam um objeto de entrada para gerar novos valores estão num único lugar.\n\n[Back to Top](#basic-refactorings)\n\n### Split Phase (183)\nUtilizar quando uma função faz mais de uma coisa.\n\nPor exemplo, uma função que faz parse e calcula os valores de um pedido.\nDividir em duas fases, onde a primeira fase irá fazer o parse da estrutura, \ne a segunda fase irá fazer os cálculos. A segunda fase irá receber os \nparâmetros necessários, seguido de uma estrutura de dados intermediária que fará a troca de dados entre a primeira e a segunda fase.\n\n[Back to Top](#basic-refactorings)\n\n### Encapsulate Record (190)\nEstrutura de dados exemplo:\n```js\nconst range = { start: 1, end: 5 };\n//ou\nconst range = { start: 1, length: 5 };\n//ou\nconst range = { end:5, length: 5 };\n```\nFowler prefere objetos a estrutura de dados quando trabalha com dados mutáveis, pois assim é possível expor\napenas os comportamentos, um para cada valor acima, por exemplo. Além disso, o _client_ de um objeto não saberá a estrutura interna \nnem como a lógica de cálculo está implementada, possibilitando assim fazer alterações mais facilmente.\n\n[Back to Top](#encapsulation)\n\n### Encapsulate Collection (198)\nCaso especial do _Encapsulate Record_.\n\nSegundo Fowler, é mais fácil manter dados mutáveis encapsulados, pois, o rastreio das alterações na estrutura se torna explícito.\n\nMuitas vezes, os _getters_ de uma _coleção_ subjacente de uma Classe(_Encapsulated Record_) devolve diretamente o seu estado, sendo possível modificar \ne manipular sem que o _Encapsulated Record_ possa intervir, quebrando o encapsulamento e dificultando a depuração caso ocorra bugs (ou se os desenvolvedores não tiverem conhecimento sobre a estrutura).\n\nO ideal, é devolver uma cópia da coleção e oferecer ao _client_ métodos para manipulação da _coleção_ a partir do _Encapsulated Record_(métodos _add_, _remove_ e _access_).\n\n[Back to Top](#encapsulation)\n\n### Replace Primitive with Object (203)\nNas etapas iniciais do desenvolvimento de software, tomamos a decisão de representar valores como tipo primitivo, \nexemplo: string para representar CPF. À medida que o software evoluí, esses valores não serão mais simples. \nUm CPF pode ser representado sem ou com formatação, ter necessidade de validar e afins. E isso pode acabar com duplicação na lógica.\n(O mesmo vale para telefone, date range entre outros).\n\nO ideal é encapsular esses valores para que, futuramente, possam ser adicionados comportamentos.\n\n[Back to Top](#encapsulation)\n\n### Replace Temp with Query (207)\nVariáveis temporárias são usadas para capturar o valor de um código de modo a referenciá-lo mais tarde numa função, além \nde explicar o significado da expressão.\n\nUtilizar uma função ao invés de variável temporária, dando mais sentido num contexto mais amplo, além de permitir quebrar \numa função longa em pequenas.\n\nCaso a variável seja atribuída várias vezes, todas as atribuições devem ser extraídas e colocadas na consulta.\n\nEssa refatoração funciona melhor em classe, pois existe um contexto compartilhado para os métodos extraídos. Fora de \numa classe, pode correr o risco de ter muitos parâmetros numa função de nível mais alto, perdendo boa parte das vantagens \nde usar uma função.\n\n[Back to Top](#encapsulation)\n\n### Extract Class (211)\nUma Classe deve ser uma abstração nítida, deve lidar apenas com algumas responsabilidades claras.\nUma Classe cresce e acaba ficando cheias de responsabilidades, pois você julga não ser necessária outra classe.\n\nUm bom sinal de que uma Classe deve ser dividida em outra(s) é quando um subconjunto dos dados e um subconjunto dos métodos\nparecem formar um conjunto. Outro sinal é quando um subconjunto de dados mudam juntos.\n\n[Back to Top](#encapsulation)\n\n### Inline Class (215)\nÀs vezes, uma Classe extraída não vale mais a pena, ela não deveria existir. Isso é resultado de mover responsabilidade \nde uma Classe original, tornando-a vazia.\n\nOutro motivo para utilizar _Inline Class_ é quando tenho que refatorar duas classes em outro par de Classes com uma alocação\ndiferente de recursos. O mais fácil é utilizar _Inline Class_ para juntar ambas, e então usar _Extract Class_ para fazer \na nova separação.\n\nEsta é a abordagem genérica para reorganizar o código: às vezes, é mais fácil mover elementos, um de cada vez, de um contexto para outro;\noutras vezes, porém, é melhor usar _Inline Class_ para reunir os contextos e depois usar _Extract Class_ para separar em \nelementos diferentes.\n\n[Back to Top](#encapsulation)\n\n### Hide Delegate (218)\nO segredo para um bom design modular é o encapsulamento. Um encapsulamento significa que módulos precisam saber menos \nsobre outras partes do sistema. Logo, quando houver mudanças num módulo, menos módulos precisarão ter conhecimento sobre elas.\n\nExemplo: \n\nSe temos 4 clientes A, B, C e D, onde todos consomem o método _getManager_ da Classe _Department_ que está na Classe\n_Person_. Se a interface de _Department_ mudar, todos os clientes saberão e deverão mudar junto a ele. _Person_ pode \nesconder a delegação simplesmente chamando o método que se faz necessário em todos os clientes de _Department_. Em outras\npalavras, alguns métodos de _Person_ irão encapsular as chamadas para os métodos de _Department_.\n\nDessa forma, caso _Department_ mude a sua interface, o impacto será apenas em _Person_.\n\n[Back to Top](#encapsulation)\n\n### Remove Middle Man (220)\nCertamente existem vantagens em utilizar o _Hide Delegate_, porém, a sua desvantagem é que, sempre que um cliente precisar\nde um método do objeto delegado, o _middle man_ precisará implementar um método simples.\n\n[Back to Top](#encapsulation)\n\n### Substitute Algorithm (223)\nExistem muitas formas de fazer uma mesma tarefa. Algumas são mais fáceis que outras. Se eu achar uma maneira mais simples\nde fazer algo, substituirei o modo mais complicado pelo modo mais claro. \n\nExemplo: utilizar uma _library_ ao invés de utilizar uma implementação complexa.\n\n[Back to Top](#encapsulation)\n\n### Move Function (225)\nUm bom motivo para mover funções é quando ela referencia mais elementos de outros contextos do que do contexto em que se\nencontra no momento. Dessa forma, outras partes do software serão menos independentes dos detalhes desse módulo.\n\n[Back to Top](#moving-features)\n\n### Move Field (235)\nSempre crie estruturas de dados com um bom design orientado ao domínio(DDD), pois geralmente isso ajuda a criar boas \nestruturas de dados.\n\nUse essa refatoração sempre que possuir estruturas de dados com defeitos. \nOu quando perceber que tem sempre que passar um campo de um registro quando passa outro registro para uma função. \nÉ melhor que porções de dados que são sempre passados em conjunto estejam num único registro para que o seu relacionamento \nesteja claro.\n\n[Back to Top](#moving-features)\n\n### Move Statements into Function (241)\nRemover duplicação é uma das melhores regras gerais de um código saudável. Se você ver o mesmo código executado\nsempre que chamar uma função, mova o código executado para dentro da função. Assim, quaisquer modificações futuras serão\nfeitas num só lugar e usadas em todos os lugares que o chamam.\n\n[Back to Top](#moving-features)\n\n### Move Statements to Callers (245)\nAs funções devem ter apenas uma responsabilidade, mas com o tempo acabam crescendo e ficando com duas ou mais\nresponsabilidades.\n\nUse quando uma função for chamada em vários lugares e variar em algumas delas. O código que varia deve ser \nextraído da função e ser utilizado diretamente em quem chama.\n\n[Back to Top](#moving-features)\n\n### Replace Inline Code with Function Call (251)\nSimilar o _Move Statements into Function_, mas sem uma função preexistente.\n\nUse para substituir um código _inline_ por uma chamada de função. Dessa forma, é possível dar um nome para a função que \nexplique o seu _propósito_ e não o seu _funcionamento_.\n\n[Back to Top](#moving-features)\n\n### Slide Statements (252)\nUm código torna-se mais fácil de entender se todos os elementos relacionados aparecem juntos. Logo, é ideal para observar \nestruturas de dados e onde elas são manipuladas, facilitando o meu entendimento.\n\nGeralmente utilizado como passo preparatório para outra refatoração como, por exemplo, _Extract Function_.\n\nTome cuidado ao mover códigos que possam ter efeitos colaterais. Para evitar isso, é interessante aplicar\no _Command-Query Separation_, dessa forma qualquer função que devolva um valor está livre de efeitos colaterais.\nCaso não tenha tanto controle sobre o código, criar testes robustos que possibilitem capturar falhas.\n\n[Back to Top](#moving-features)\n\n### Split Loop (257)\nMuitas vezes fazemos mais de uma tarefa num loop. Dessa forma, sempre que for necessário modificar uma dessas tarefas teremos\nque entender ambas.\n\nUtilize para separar responsabilidades. Também pode ser usado como forma preparatória para outras refatorações, \npor exemplo, _Extract Function_.\n\n[Back to Top](#moving-features)\n\n### Replace Loop with Pipeline (261)\nUtilize _Collection Pipelines_(`map`, `filter` e afins) para maior legibilidade na manipulação de coleção de objetos. \n\n[Back to Top](#moving-features)\n\n### Remove Dead Code (267)\nRemover o código que não é utilizado. Não deixar o código como comentário. Dessa forma, evita outros\nprogramadores a lerem um código que não possuí nenhum efeito.\n\n[Back to Top](#moving-features)\n\n### Split Variable (269)\nVariável que recebe valor mais de uma vez é sinal que possuí mais que uma responsabilidade no método. Qualquer variável\ncom mais de uma responsabilidade deve ser substituída por diversas variáveis, uma para cada responsabilidade.\n\nVariável acumuladora tem apenas uma responsabilidade, então não se encaixa nessa refatoração.\n\n[Back to Top](#organizing-data)\n\n### Rename Field (273)\nNomes são importantes, principalmente se são nomes de campos de um objeto(_record_) amplamente utilizado.\n\nUtilize sempre que precisar de um bom nome para refletir o real significado de um campo.\n\n[Back to Top](#organizing-data)\n\n### Replace Derived Variable with Query (277)\nUtilize quando o _uso_ da variável está distante dos locais em que ela pode sofrer mutação. Ao invés de ter uma variável que\nseja acumuladora, prefira fazer o cálculo sob demanda. Dessa forma, torna-se mais fácil rastrear os valores da variável.\n\n[Back to Top](#organizing-data)\n\n### Change Reference to Value (281)\nFowler defende que, de modo geral, é mais fácil trabalhar com dados imutáveis, pois é possível passar o objeto para \ndiferentes contextos sem se preocupar que o seu valor seja alterado. \n\nCaso precise que o objeto seja manipulado e observado\npor diferentes contextos, é melhor trata-lo como referência, ou seja, aplicar _Change Value to Reference_.\n\n[Back to Top](#organizing-data)\n\n### Change Value to Reference (284)\nInversa de _Change Reference to Value_. \n\nUtilize quando precisar manipular algum objeto que é compartilhado entre diferentes contextos. Assim, haverá apenas uma \nreferência de uma entidade sendo tratada por todos os contextos necessários, ao invés de ter vários _Value Object_ \nespalhados por contextos do qual iriam gerar inconsistência.\n\n[Back to Top](#organizing-data)\n\n### Decompose Conditional (288)\nCaso especial de _Extract Function_.\n\nUtilize quando existirem condicionais complexas. Transforme o parâmetro do `if` numa chamada de função que revela a sua \nintenção. Faça isso para cada ramificação, e para o corpo de cada uma delas. No final de tudo, saberá _o que acontece_ e o _por que_.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Consolidate Conditional Expression (291)\nUtilize quando houver condicionais em que cada verificação difere, porém, a ação resultante é a mesma.\n\nAo aplicar essa refatoração, é possível usar _Extract Function_. Dessa forma, saberá o _por que acontece_ ao invés de _como acontece_.\n\nNão utilizar caso as verificações tiverem uma ação resultante diferente.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Replace Nested Conditional with Guard Clauses (294)\nSegundo Fowler, as expressões condicionais se apresentam em dois estilos. No primeiro, os dois ramos da condicional fazem parte do _happy path_.\nNo segundo, um ramo é o _happy path_ enquanto os demais são incomuns(exceções).\n\nUtilize quando houver condicionais aninhadas e complexas. Dessa forma, será possível diminuir a complexidade ciclomática,\nfacilitando observar o _happy path_ da função.\n\nÉ possível aplicar _Guard Clause_ com a simples inversão das condicionais. Em alguns casos, basta ter um retorno imediato, sem a necessidade\nde inversão da condicional. Em todos os casos, começar pela condicional mais externa.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Replace Conditional with Polymorphism (299)\nUtilizar quando tiver condicionais complexas, que se repetem em diversas partes do código para gerar algum valor com base num tipo.\n\nExistem casos onde a implementação base ficará na superclasse, por ser o caso mais comum ou o mais simples, então a variação ficará por conta da subclasse. \nEm outros casos, todas as condicionais variam e não existe um caso base, logo, toda a implementação ficará na subclasse.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Introduce Special Case (318)\nUtilizar quando tiver condicional que busca por um valor específico, que acaba sendo repetida em diversos clientes. Por exemplo, verificar por _null_ em alguma propriedade de um objeto. \nAo invés de retornar _null_, deve ser retornado um objeto literal que represente o _null_, onde possuí os seus próprios métodos para valores _default_.\n\n_Special Case Object_ são sempre _Value Object_ e, dessa forma, devem ser sempre imutáveis, mesmo que os objetos que eles estejam substituindo não sejam. \nCaso seja um objeto literal(objeto javascript, por exemplo), devo utilizar o _Object.freeze_ para lhe tornar imutável.\n\nEssa refatoração também é chamada de _Null Object Pattern_, porém, para Fowler, esse _pattern_ é um caso especial do _Special Case_.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Introduce Assertion (333)\nUtilize como último recurso para debug.\n\nUma falha numa asserção sinaliza um erro do programador, além disso, comunica-o sobre o estado em que se supõe que esteja o programa\nno respectivo ponto de execução. Asserções não devem afetar a execução de um sistema, ou seja, o programa deve funcionar da mesma maneira com ou sem elas.\n\nUm código autotestável reduz a importância das asserções na depuração.\n\n[Back to Top](#simplifying-conditional-logic)\n\n### Separate Query from Modifier (337)\nSegundo Fowler, funções que não possuem efeitos colaterais podem ser chamadas diversas vezes e serem inseridas em outras funções facilmente. Uma regra mencionada por ele é que:\na função que devolve um valor não deve ter efeitos colaterais observáveis(_command-query separation_).\n\nEm casos de _cache_, onde é alterado o estado do objeto, a mudança não é observável, por isso essa refatoração não deve ser aplicada.\n\n[Back to Top](#refactoring-apis)\n\n### Parameterize Function (340)\nUtilize quando existirem funções que possuem uma lógica muita parecida que difere apenas nos seus valores literais. \nDessa forma, a função irá atender a diversos casos, pois poderá ser usada com diferentes valores.\n\n[Back to Top](#refactoring-apis)\n\n### Remove Flag Argument (344)\nUtilizar uma flag como argumento para decidir qual fluxo a função deve seguir sinaliza que a função faz mais de uma coisa.\n\nAplique juntamente _Decompose Conditional_ para criar funções explícitas, que revelem a quem chama a sua verdadeira intenção.\n\n[Back to Top](#refactoring-apis)\n\n### Preserve Whole Object (349)\nSegundo Fowler, ao trabalhar com parâmetros de funções que recebem valores derivados, é melhor ter o registro completo e deixar o corpo da função tratar da derivação.\nDessa forma, será mais fácil caso queira pegar outros valores do mesmo registro no futuro.\n\nAlém disso, Fowler defende que o principal motivo para não fazer essa refatoração é não querer depender do objeto completo, porém, \nisso é sinal de que a lógica deve ser movida para o próprio objeto completo.\n\n[Back to Top](#refactoring-apis)\n\n### Replace Parameter with Query (354)\nInversa de _Replace Query with Parameter_.\n\n\"Se uma chamada de função passar um valor que a função possa facilmente determinar por conta própria, essa é uma forma de duplicação.\".\nIsso faz com que quem chama a função tenha que determinar o parâmetro, quando poderia estar livre dessa tarefa, sendo essa a responsabilidade do corpo da função.\n\nO motivo mais comum para evitar essa refatoração é se com a remoção do parâmetro a função tenha uma dependência indesejada no seu corpo.\n\n[Back to Top](#refactoring-apis)\n\n### Replace Query with Parameter (357)\nInversa de _Replace Parameter with Query_.\n\nUtilize quando tiver a necessidade de remover do corpo da função uma dependência indesejada. Dessa forma, quem chama a função recebe a responsabilidade de fornecer o valor que antes era interno.\n\nAplicando essa refatoração tenho a possibilidade de criar funções puras(transparência referencial), ou seja, sempre que eu chamar essa função passando os mesmos valores de parâmetros, terei o mesmo resultado.\nE com isso facilito os testes e a compreensão do módulo.\n\n[Back to Top](#refactoring-apis)\n\n### Remove Setting Method (361)\nUtilizar quando não faz sentido alterar o valor de um campo após a instanciação. \nCaso algum cliente precise \"alterar\" o valor de um campo que antes era feito com um setter(e agora é imutável), ele deverá instanciar um novo objeto.\n\n[Back to Top](#refactoring-apis)\n\n### Replace Constructor with Factory Function (363)\nO método `constructor` em muitas linguagens orientadas a objeto possuem limitações onde, por exemplo, não é possível retornar uma subclasse. A função de factory serve para tirar algumas dessas limitações.\nUtilize quando precisar criar diferentes objetos. \n\n[Back to Top](#refactoring-apis)\n\n### Replace Function with Command (366)\nInversa de _Replace Command with Function_.\n\nUtilizar quando necessitar quebrar uma função grande e complexa em pequena e simples. \nCom isso, será criado um `objeto de comando`(como Fowler chama), onde o seu propósito será requisição e execução. Um `objeto de comando` contém estado e realiza operações como `execute` e `undo`,\nalém de ganhar mais flexibilidade, pois permitirá uso de _inheritance_(herança) e _hooks_.\n\n[Back to Top](#refactoring-apis)\n\n### Replace Command with Function (373)\nInversa de _Replace Function with Command_.\n\nUtilizar quando o _Command_ executar algo pequeno e simples. Uma função já é o suficiente para realizar tal tarefa. \n\n[Back to Top](#refactoring-apis)\n\n### Pull Up Method (378)\nInversa de _Push Down Method_.\n\nUtilizar quando subclasses possuem duplicação no código. O ideal em casos de herança é que comportamento em comum fique na _superclass_,\nenquanto os detalhes fiquem na _subclass_.\n\nExistem casos onde esta refatoração é antecedida por outras, como _Parameterize Function_ quando duas funções são muitos parecidas e ao serem alteradas serão \nessencialmente a mesma função, ou _Pull Up Field_ quando o corpo da função duplicada referenciar um campo da _subclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Pull Up Field (381)\nInversa de _Push Down Field_.\n\nUtilizar quando subclasses possuem duplicação nos campos.\n\nAo aplicar esta refatoração as duplicações são reduzidas de duas formas, tanto no campo quanto nos métodos que utilizam esse campo, \npois serão movidos para a _superclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Pull Up Constructor Body (383)\nSemelhante a _Pull Up Method_.\n\nUtilizar quando possuir comportamento em comum no construtor das subclasses. Chamar o `super()`(JavaScript) e jogar a duplicação na _superclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Push Down Method (387)\nInversa de _Pull Up Method_.\n\nUtilizar quando um método de uma _superclass_ for relevante apenas para uma _subclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Push Down Field (388)\nInversa de _Pull Up Field_.\n\nUtilizar quando um campo de uma _superclass_ for relevante apenas para uma _subclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Replace Type Code with Subclasses (389)\nInversa de _Remove Subclass_.\n\nUtilizar quando tiver uma propriedade que classifica o \"tipo\" de um _item_, como código de tipo de _employee_(_engineer_, _manager_, _salesman_).\n\nExiste um caso especial onde não posso utilizar _subclasses_(herança direta) se o código de tipo for mutável ou se precisar do código de tipo para outras tarefas.\nNesse caso, devo utilizar herança indireta.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Remove Subclass (397)\nInversa de _Replace Type Code with Subclasses_.\n\nSubclasses são úteis quando precisar de diferentes objetos, por exemplo, _employee_(_engineer_, _manager_, _salesman_), e/ou comportamento polimórfico.\nEntretanto, em alguns casos uma _subclass_ não faz muito e não valerá a pena tê-la.\n\nUtilize para remover _subclass_, e substitui-la com um campo na _superclass_.\n\nUma dica valiosa dada por Fowler é: `sempre que quero mudar o modo de representar algo, procuro primeiro encapsular a representação atual a fim\nde minimizar o impacto em qualquer código de cliente.`\n\n[Back to Top](#dealing-with-inheritance)\n\n### Extract Superclass (402)\nUtilizar quando classes fizerem tarefas parecidas, aplicar herança para extrair as semelhanças e inseri-las em uma _superclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Collapse Hierarchy (408)\nUtilizar quando uma _subclass_ não for mais tão diferente da _superclass_, então combine-as numa única classe.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Replace Subclass with Delegate (409)\nSegundo Fowler, uma das desvantagens de utilizar herança é que ela pode só ser usada uma vez, num único eixo de variação.\nExemplo: posso variar comportamento das pessoas de acordo a categoria idade e o nível de renda, \npoderei ter subclasses para jovens e idosos, ou para ricos e pobres, mas não para ambos.\nOutra desvantagem de herança é que existirá um relacionamento íntimo entre as classes, então qualquer \nalteração na _superclass_ poderá causar erros nas _subclasses_. É possível resolver ambos os problemas com delegação. \n\nFowler também diz que essa refatoração é basicamente `Composition over inheritance`(_gang of four_) onde delegação é o mesmo que `composition`.\nE finaliza com a frase de efeito: `Prefira uma mistura criteriosa de composição e herança a usar somente uma delas`.\n\n[Back to Top](#dealing-with-inheritance)\n\n### Replace Superclass with Delegate (429)\nAlém de usar todas as funções da _superclass_, também deve ser verdade que toda instância da _subclass_ é uma instância da _superclass_,\ne ela deve ser um objeto válido em todos os casos em que estivermos usando a _superclass_.\n\nSe as funções da _superclass_ não fazem sentido na _subclass_, é sinal de que não deveria utilizar herança para ter funcionalidades da _superclass_.\nNesse caso, o mais interessante seria instanciar a _superclass_ dentro da _subclass_ e criar métodos de delegação, dessa forma,\nserá possível utilizar alguns dos métodos da _superclass_ que se fazem necessários na _subclass_.\n\n[Back to Top](#dealing-with-inheritance)\n\nInspirado por: https://gist.github.com/cs-cordero/3799f26699bdecdb286fd719f08122af\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanilobandeira29%2Frefactoring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanilobandeira29%2Frefactoring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanilobandeira29%2Frefactoring/lists"}