{"id":15355469,"url":"https://github.com/ittus/refactoring-summary-2nd-javascript","last_synced_at":"2026-01-25T09:34:07.786Z","repository":{"id":48444655,"uuid":"219493803","full_name":"ittus/Refactoring-summary-2nd-javascript","owner":"ittus","description":"Summary of \"Refactoring: Improving the Design of Existing Code (2nd Edition)\" by Martin Fowler","archived":false,"fork":false,"pushed_at":"2022-07-07T14:15:23.000Z","size":49,"stargazers_count":263,"open_issues_count":0,"forks_count":49,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-27T19:28:50.814Z","etag":null,"topics":["books","refactoring","software-engineering"],"latest_commit_sha":null,"homepage":"","language":null,"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/ittus.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}},"created_at":"2019-11-04T12:14:02.000Z","updated_at":"2025-02-11T16:29:20.000Z","dependencies_parsed_at":"2022-08-24T02:40:27.581Z","dependency_job_id":null,"html_url":"https://github.com/ittus/Refactoring-summary-2nd-javascript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ittus/Refactoring-summary-2nd-javascript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ittus%2FRefactoring-summary-2nd-javascript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ittus%2FRefactoring-summary-2nd-javascript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ittus%2FRefactoring-summary-2nd-javascript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ittus%2FRefactoring-summary-2nd-javascript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ittus","download_url":"https://codeload.github.com/ittus/Refactoring-summary-2nd-javascript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ittus%2FRefactoring-summary-2nd-javascript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28750875,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T09:00:19.176Z","status":"ssl_error","status_checked_at":"2026-01-25T09:00:04.131Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["books","refactoring","software-engineering"],"created_at":"2024-10-01T12:24:29.449Z","updated_at":"2026-01-25T09:34:07.770Z","avatar_url":"https://github.com/ittus.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"My personal notes while reading \"Refactoring: Improving the Design of Existing Code (2nd Edition)\" by Martin Fowler. It only contains some basic concept as my understanding. If you want to learn more, I highly recommend you should buy the book.\n\nIf you are the publisher and think this repository should not be public, please write me an email to vuminhthang [dot] cm [at] gmail [dot] com and I will make it private.\n\nHappy reading!\n\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Refactoring%20Book%20Summary\u0026url=https://github.com/ittus/Refactoring-summary-2nd-javascript\u0026hashtags=refactoring,javascript,software,developers)\n\n## 1. TABLE OF CONTENT\n- [1. TABLE OF CONTENT](#1-table-of-content)\n- [3. BAD SMELLS IN CODE](#3-bad-smells-in-code)\n  - [1. Mysterious name](#1-mysterious-name)\n  - [2. Duplicated code](#2-duplicated-code)\n  - [3. Long function](#3-long-function)\n  - [4. Long parameter list](#4-long-parameter-list)\n  - [5. Global data](#5-global-data)\n  - [6. Mutable data](#6-mutable-data)\n  - [7. Divergent change](#7-divergent-change)\n  - [8. Shotgun surgery](#8-shotgun-surgery)\n  - [9. Feature envy](#9-feature-envy)\n  - [10. Data clumps](#10-data-clumps)\n  - [11. Primittive Obsession](#11-primittive-obsession)\n  - [12. Repeated switches](#12-repeated-switches)\n  - [13. Loops](#13-loops)\n  - [14. Lazy element](#14-lazy-element)\n  - [15. Speculative generality](#15-speculative-generality)\n  - [16. Temporary field](#16-temporary-field)\n  - [17. Message chains](#17-message-chains)\n  - [18. Middle man](#18-middle-man)\n  - [19. Insider trading](#19-insider-trading)\n  - [20. Large class](#20-large-class)\n  - [21. Alternative Classes with Different Interfaces](#21-alternative-classes-with-different-interfaces)\n  - [22. Data class](#22-data-class)\n  - [23. Refused Bequest](#23-refused-bequest)\n  - [24. Comment](#24-comment)\n- [6. MOST COMMON SET OF REFACTORING](#6-most-common-set-of-refactoring)\n  - [1. Extract Function](#1-extract-function)\n  - [2. Inline Function](#2-inline-function)\n  - [3. Extract Variable](#3-extract-variable)\n  - [4. Inline Variable](#4-inline-variable)\n  - [5. Change Function Declaration](#5-change-function-declaration)\n  - [6. Encapsulate Variable](#6-encapsulate-variable)\n  - [7. Rename Variable](#7-rename-variable)\n  - [8. Introduce Parameter Object](#8-introduce-parameter-object)\n  - [9. Combine Functions Into Class](#9-combine-functions-into-class)\n  - [10. Combine Functions Into Transform](#10-combine-functions-into-transform)\n  - [11. Split Phase](#11-split-phase)\n- [7. ENCAPSULATION](#7-encapsulation)\n  - [1. Encapsulate Record](#1-encapsulate-record)\n  - [2. Encapsulate Collection](#2-encapsulate-collection)\n  - [3. Replace Primitive with Object](#3-replace-primitive-with-object)\n  - [4. Replace Temp with Query](#4-replace-temp-with-query)\n  - [5. Extract Class](#5-extract-class)\n  - [6. Inline Class](#6-inline-class)\n  - [7. Hide Delegate](#7-hide-delegate)\n  - [8. Remove Middle Man](#8-remove-middle-man)\n  - [9. Substitute Algorithm](#9-substitute-algorithm)\n- [8. MOVING FEATURES](#8-moving-features)\n  - [1. Move Function](#1-move-function)\n  - [2. Move Field](#2-move-field)\n  - [3. Move Statements into Function](#3-move-statements-into-function)\n  - [4. Move Statements To Callers](#4-move-statements-to-callers)\n  - [5. Replace Inline Code with Function Call](#5-replace-inline-code-with-function-call)\n  - [6. Slide Statements](#6-slide-statements)\n  - [7. Split Loop](#7-split-loop)\n  - [8. Replace Loop with Pipeline](#8-replace-loop-with-pipeline)\n  - [9. Remove Dead Code](#9-remove-dead-code)\n- [9. ORGANIZING DATA](#9-organizing-data)\n  - [1. Split Variable](#1-split-variable)\n  - [2. Rename Field](#2-rename-field)\n  - [3. Replace Derived Variable With Query](#3-replace-derived-variable-with-query)\n  - [4. Change Reference To Value](#4-change-reference-to-value)\n  - [5. Change Value To Reference](#5-change-value-to-reference)\n- [10. SIMPLIFYING CONDITIONAL LOGIC](#10-simplifying-conditional-logic)\n  - [1. Decompose Conditional](#1-decompose-conditional)\n  - [2. Consolidate Conditional Expression](#2-consolidate-conditional-expression)\n  - [3. Replace Nested Conditional with Guard Clauses](#3-replace-nested-conditional-with-guard-clauses)\n  - [4. Replace Conditional with Polymorphism](#4-replace-conditional-with-polymorphism)\n  - [5. Introduce Special Case](#5-introduce-special-case)\n  - [6. Introduce Assertion](#6-introduce-assertion)\n- [11. REFACTORING APIS](#11-refactoring-apis)\n  - [1. Separate Query from Modifier](#1-separate-query-from-modifier)\n  - [2. Parameterize Function](#2-parameterize-function)\n  - [3. Remove Flag Argument](#3-remove-flag-argument)\n  - [4. Preserve Whole Object](#4-preserve-whole-object)\n  - [5. Replace Parameter with Query](#5-replace-parameter-with-query)\n  - [6. Replace Query with Parameter](#6-replace-query-with-parameter)\n  - [7. Remove Setting Method](#7-remove-setting-method)\n  - [8. Replace Constructor with Factory Function](#8-replace-constructor-with-factory-function)\n  - [9. Replace Function with Command](#9-replace-function-with-command)\n  - [10. Replace Command with Function](#10-replace-command-with-function)\n- [12. DEALING WITH INHERITANCE](#12-dealing-with-inheritance)\n  - [1. Pull Up Method](#1-pull-up-method)\n  - [2. Pull Up Field](#2-pull-up-field)\n  - [3. Pull Up Constructor Body](#3-pull-up-constructor-body)\n  - [4. Push Down Method](#4-push-down-method)\n  - [5. Push Down Field](#5-push-down-field)\n  - [6. Replace Type Code with Subclasses](#6-replace-type-code-with-subclasses)\n  - [7. Remove Subclass](#7-remove-subclass)\n  - [8. Extract Superclass](#8-extract-superclass)\n  - [9. Collapse Hierarchy](#9-collapse-hierarchy)\n  - [10. Replace Subclass with Delegate](#10-replace-subclass-with-delegate)\n  - [11. Replace Superclass with Delegate](#11-replace-superclass-with-delegate)\n\n## 3. BAD SMELLS IN CODE\n\n### 1. Mysterious name\nName should clearly communicate what they do and how to use them\n\n### 2. Duplicated code\nSame code structure in more than one place\n\n### 3. Long function\nthe longer a function is, the more difficult it is to understand\n\n### 4. Long parameter list\nDifficult to understand and easily introduce bug\n\n### 5. Global data\nGlobal variable is difficult to track and debug\n\n### 6. Mutable data\nChanges to data can often lead to unexpected consequences and tricky bugs\n\n### 7. Divergent change\nOne module is changed in different ways for different reasons\n\n### 8. Shotgun surgery\nWhen every time you make a change, you have to make a lot of little edits to a lot of different classes\n\n### 9. Feature envy\nWhen a function in one module spends more time communicating with functions or data inside another module than it does within its own module\n\n### 10. Data clumps\nSame three or four data items together in lots of places\n\n### 11. Primittive Obsession\nUse primitive types instead of custom fundamental types\n\n### 12. Repeated switches\nSame conditional switching logic pops up in different places\n\n### 13. Loops\nUsing loops instead of first-class functions such as filter or map\n\n### 14. Lazy element\nA class, struct or function that isn't doing enough to pay for itself should be eliminated.\n\n### 15. Speculative generality\nAll sorts of hooks and special cases to handle things that aren’t required\n\n### 16. Temporary field\nAn instance variable that is set only in certain circumstances.\n\n### 17. Message chains\nWhen a client asks one object for another object, which the client then asks for yet another object...\n\n### 18. Middle man\nWhen an object delegates much of its functionality.\n\n### 19. Insider trading\nModules that whisper to each other by the coffee machine need to be separated by using Move Function and Move Field to reduce the need to chat.\n\n### 20. Large class\nA class is trying to do too much, it often shows up as too many fields\n\n### 21. Alternative Classes with Different Interfaces\nClasses with methods that look to similar.\n\n### 22. Data class\nClasses that have fields, getting and setting methods for the fields, and nothing else\n\n### 23. Refused Bequest\nSubclasses doesn't make uses of parents method\n\n### 24. Comment\nThe comments are there because the code is bad\n\n## 6. MOST COMMON SET OF REFACTORING\n\n### 1. Extract Function\nExtract fragment of code into its own function named after its purpose.\n\n```javascript\nfunction printOwing(invoice) {\n  printBanner()\n  let outstanding = calculateOutstanding()\n\n  // print details\n  console.log(`name: ${invoice.customer}`)\n  console.log(`amount: ${outstanding}`)\n}\n```\n\nto\n\n```javascript\nfunction printOwing(invoice) {\n  printBanner()\n  let outstanding = calculateOutstanding()\n  printDetails(outstanding)\n\n  function printDetails(outstanding) {\n    console.log(`name: ${invoice.customer}`)\n    console.log(`amount: ${outstanding}`)\n  }\n}\n```\n\n**Motivation**:\n- You know what's the code doing without reading the details\n- Short function is easier to read\n- Reduce comment\n\n### 2. Inline Function\nGet rid of the function when the body of the code is just as clear as the name\n\n```javascript\nfunction rating(aDriver) {\n  return moreThanFiveLateDeliveries(aDriver) ? 2 : 1\n}\nfunction moreThanFiveLateDeliveries(aDriver) {\n  return aDriver.numberOfLateDeliveries \u003e 5\n}\n```\n\nto\n\n```javascript\nfunction rating(aDriver) {\n  return aDriver.numberOfLateDeliveries \u003e 5 ? 2 : 1\n}\n```\n\n**Motivation**\n- When Indirection is needless (simple delegation) becomes irritating.\n- If group of methods are badly factored and grouping them makes it clearer\n\n### 3. Extract Variable\nAdd a name to an expression\n\n```javascript\n//price is base price ­ quantity discount + shipping\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100)\n```\n\nto\n\n```javascript\nconst basePrice = order.quantity * order.itemPrice\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemP\nconst shipping = Math.min(basePrice * 0.1, 100)\nreturn basePrice - quantityDiscount + shipping;\n```\n\n**Motivation**\n- Break down and name a part of a more complex piece of logic\n- Easier for debugging\n\n### 4. Inline Variable\nRemove variable which doesn't really communicate more than the expression itself.\n\n```javascript\nlet basePrice = anOrder.basePrice\nreturn (basePrice \u003e 1000)\n```\n\nto\n\n```javascript\nreturn anOrder.basePrice \u003e 1000\n```\n\n### 5. Change Function Declaration\nRename a function, change list of parameters\n\n```javascript\nfunction circum(radius) {...}\n```\n\nto\n\n```javascript\nfunction circumference(radius) {...}\n```\n\n**Motivation**\n- Easier to understand\n- Easier to reuse, sometime better encapsulation\n\n### 6. Encapsulate Variable\nEncapsulate a reference to some data structure\n\n```javascript\nlet defaultOwner = {firstName: \"Martin\", lastName: \"Fowler\"}\n```\n\nto\n\n```javascript\n// defaultOwner.js\nlet defaultOwnerData = {firstName: \"Martin\", lastName: \"Fowler\"}\nexport function defaultOwner() { return defaultOwnerData }\nexport function setDefaultOwner(arg) { defaultOwnerData = arg }\n```\n\n**Motivation**\n- Provide a clear point to monitor changes and use of the data, like validation.\n\n### 7. Rename Variable\nMake shared variable's name can self-explain\n\n```javascript\nlet a = height * width\n```\n\nto\n\n```javascript\nlet area = height * width\n```\n\n### 8. Introduce Parameter Object\nReplace groups of data items that regularly travel together with a single data structure\n\n```javascript\nfunction amountInvoiced(startDate, endDate) {}\nfunction amountReceived(startDate, endDate) {}\nfunction amountOverdue(startDate, endDate) {}\n```\n\nto\n\n```javascript\nfunction amountInvoiced(aDateRange) {}\nfunction amountReceived(aDateRange) {}\nfunction amountOverdue(aDateRange) {}\n```\n\n**Motivation**\n- Make explicit the relationship between the data items\n- Reduce the size of parameter list\n- Make code more consistent\n- Enable deeper changes to the code\n\n### 9. Combine Functions Into Class\nForm a class base on group of functions that operate closely on a common data\n\n```javascript\nfunction base(aReading) {}\nfunction taxableCharge(aReading) {}\nfunction calculateBaseCharge(aReading) {}\n```\n\nto\n\n```javascript\nclass Reading() {\n  base() {}\n  taxableCharge() {}\n  calculateBaseCharge() {}\n}\n```\n\n**Motivation**\n- Simplify function call by removing many arguments\n- Easier to pass object to other parts of the system\n\n### 10. Combine Functions Into Transform\nTakes the source data as input and calculates all the derivations, putting each derived value as a field in the output data\n\n```javascript\nfunction base(aReading) {}\nfunction taxableCharge(aReading) {}\n```\n\nto\n\n```javascript\nfunction enrichReading(argReading) {\n  const aReading = _.cloneDeep(argReading)\n  aReading.baseCharge = base(aReading)\n  aReading.taxableCharge = taxableCharge(aReading)\n  return aReading\n}\n```\n\n**Motivation**\n- Avoid duplication of logic\n\n### 11. Split Phase\nSplit code which do different things into separate modules\n\n```javascript\nconst orderData = orderString.split(/\\s+/)\nconst productPrice = priceList[orderData[0].split(\"-\")[1]]\nconst orderPrice = parseInt(orderData[1]) * productPrice\n```\n\nto\n\n```javascript\nconst orderRecord = parseOrder(orderString)\nconst orderPrice = price(orderRecord, priceList)\n\nfunction parseOrder(aString) {\n  const values = aString.split(/\\s+/)\n  return {\n    productID: values[0].split(\"-\")[1],\n    quantity: parseInt(values[1])\n  }\n}\nfunction price(order, priceList) {\n  return order.quantity * priceList[order.productID]\n}\n```\n\n**Motivation**\n- Make the different explicit, revealing the different in the code\n- Be able to deal with each module separately\n\n## 7. ENCAPSULATION\n\n### 1. Encapsulate Record\nCreate record (class) from object\n\n```javascript\norganization = {name: \"Acme gooseberries\", country: \"GB\"}\n```\n\nto\n\n```javascript\nclass Organization {\n  constructor(data) {\n    this._name = data.name\n    this._country = data.country\n  }\n\n  get name() { return this._name }\n  set name(arg) { this._name = arg }\n  get country() { retrun this._country }\n  set country(arg) { this._country = arg }\n}\n```\n\n**Motivation**\n- Hide what's stored and provide methods to get value\n- Easier to refactoring, for example: rename\n\n### 2. Encapsulate Collection\nA method returns a collection. Make it return a read-only view and provide add/remove methods\n\n```javascript\nclass Person {\n  get courses() { return this._courses }\n  set courses(aList) { this._courses = aList }\n}\n```\n\nto\n\n```javascript\nclass Person {\n  get courses() { return this._courses.slice() }\n  addCourse(aCourse) {}\n  removeCourse(aCourse)\n}\n```\n\n**Motivation**\n- Change to the collection should go through the owning class to prevent unexpected changes.\n- Prevent modification of the underlying collection for example: return a copy or read-only proxy instead of collection value\n\n### 3. Replace Primitive with Object\nCreate class for data\n\n```javascript\norders.filter(o =\u003e \"high\" === o.priority || \"rush\" === o.priority)\n```\n\nto\n\n```javascript\norders.filter(o =\u003e o.priority.higherThan(new Priority(\"normal\")))\n```\n\n**Motivation**\n- Encapsulate behaviour with data\n\n### 4. Replace Temp with Query\nExtract the assignment of the variable into a function\n\n```javascript\nconst basePrice = this._quantity * this._itemPrice\nif (basePrice \u003e 1000) {\n  return basePrice * 0.95\n} else {\n  return basePrice * 0.98\n}\n```\n\nto\n\n```javascript\nget basePrice() { return this._quantity * this._itemPrice }\n//...\nif (this.basePrice \u003e 1000) {\n  return this.basePrice * 0.95\n} else {\n  return this.basePrice * 0.98\n}\n```\n\n**Motivation**\n- Avoid duplicating the calculation logic in similar functions\n\n### 5. Extract Class\nExtract class base on a subset of data and a subset of methods\n\n```javascript\nclass Person {\n  get officeAreaCode() { return this._officeAreaCode }\n  get officeNumber() { return this._officeNumber }\n}\n```\n\nto\n\n```javascript\nclass Person {\n  get officeAreaCode() { return this._telephoneNumber.areaCode }\n  get officeNumber() { return this._telephoneNumber.number }\n}\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode }\n  get number() { return this._number }\n}\n```\n\n**Motivation**\n- Smaller class is easier to understand\n- Separate class's responsibility\n\n### 6. Inline Class\nMerge class if class isn't doing very much. Move its feature to another class then delete it.\n\n```javascript\nclass Person {\n  get officeAreaCode() { return this._telephoneNumber.areaCode }\n  get officeNumber() { return this._telephoneNumber.number }\n}\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode }\n  get number() { return this._number }\n}\n```\n\nto\n\n```javascript\nclass Person {\n  get officeAreaCode() { return this._officeAreaCode }\n  get officeNumber() { return this._officeNumber }\n}\n```\n\n**Motivation**\n- Class is no longer pulling its weight and shouldn’t be around any more\n- When want to refactor pair of classes. First Inline Class -\u003e Extract Class to make new separation\n\n### 7. Hide Delegate\nA client is calling a delegate class of an object, create methods on the server to hide the delegate.\n\n```javascript\nmanager = aPerson.department.manager\n```\n\nto\n\n```javascript\nmanager = aPerson.manager\n\nclass Person {\n  get manager() {\n    return this.department.manager\n  }\n}\n```\n\n**Motivation**\n- Client doesn't need to know and response to delegation's change\n- Better encapsulation\n\n### 8. Remove Middle Man\nClient call the delegate directly\n\n```javascript\nmanager = aPerson.manager\n\nclass Person {\n  get manager() {\n    return this.department.manager\n  }\n}\n```\n\nto\n\n```javascript\nmanager = aPerson.department.manager\n```\n\n**Motivation**\n- When there are too many delegating methods\n\n### 9. Substitute Algorithm\nReplace complicated algorithm with simpler algorithm\n\n```javascript\nfunction foundPerson(people) {\n  for (let i = 0; i \u003c people.lenth; i++) {\n    if (people[i] === \"Don\") {\n      return \"Don\"\n    }\n    if (people[i] === \"John\") {\n      return \"John\"\n    }\n    if (people[i] === \"Kent\") {\n      return \"Kent\"\n    }\n  }\n  return \"\"\n}\n```\n\nto\n\n```javascript\nfunction foundPerson(people) {\n  const candidates = [\"Don\", \"John\", \"Kent\"]\n  return people.find(p =\u003e candidates.includes(p)) || \"\"\n}\n```\n\n**Motivation**\n- Change to algorithm which make changes easier\n- The clearer algorithm is, the better.\n\n## 8. MOVING FEATURES\n\n### 1. Move Function\nMove a function when it references elements in other contexts more than the one it currently resides in\n\n```javascript\nclass Account {\n  get overdraftCharge() {}\n}\nclass AccountType {}\n```\n\nto\n\n```javascript\nclass Account {}\nclass AccountType {\n  get overdraftCharge() {}\n}\n```\n\n**Motivation**\n- Improve encapsulation, loose coupling\n\n### 2. Move Field\nMove field from once class to another\n\n```javascript\nclass Customer {\n  get plan() { return this._plan }\n  get discountRate() { return this._discountRate }\n}\n```\n\nto\n\n```javascript\nclass Customer {\n  get plan() { return this._plan }\n  get discountRate() { return this.plan.discountRate }\n}\n```\n\n**Motivation**\n- Pieces of data that are always passed to functions together are usually best put in a single record\n- If a change in one record causes a field in another record to change too, that’s a sign of a field in the wrong place\n\n### 3. Move Statements into Function\nWhen statement is a part of called functions (always go togeter), move it inside the function\n\n```javascript\nresult.push(`\u003cp\u003etitle: ${person.photo.title}\u003c/p\u003e`)\nresult.concat(photoData(person.photo))\n\nfunction photoData(aPhoto) {\n  return [\n    `\u003cp\u003elocation: ${aPhoto.location}\u003c/p\u003e`,\n    `\u003cp\u003edate: ${aPhoto.data.toDateString()}\u003c/p\u003e`\n  ]\n}\n```\n\nto\n\n```javascript\nresult.concat(photoData(person.photo))\n\nfunction photoData(aPhoto) {\n  return [\n    `\u003cp\u003etitle: ${aPhoto.title}\u003c/p\u003e`,\n    `\u003cp\u003elocation: ${aPhoto.location}\u003c/p\u003e`,\n    `\u003cp\u003edate: ${aPhoto.data.toDateString()}\u003c/p\u003e`\n  ]\n}\n```\n\n**Motivation**\n- Remove duplicated code\n\n### 4. Move Statements To Callers\n\n```javascript\nemitPhotoData(outStream, person.photo)\n\nfunction emitPhotoData(outStream, photo) {\n  outStream.write(`\u003cp\u003etitle: ${photo.title}\u003c/p\u003e\\n`)\n  outStream.write(`\u003cp\u003elocation: ${photo.location}\u003c/p\u003e\\n`)\n}\n```\n\nto\n\n```javascript\nemitPhotoData(outStream, person.photo)\noutStream.write(`\u003cp\u003elocation: ${photo.location}\u003c/p\u003e\\n`)\n\nfunction emitPhotoData(outStream, photo) {\n  outStream.write(`\u003cp\u003etitle: ${photo.title}\u003c/p\u003e\\n`)\n}\n```\n\n**Motivation**\n- When common behavior used in several places needs to vary in some of its call\n\n### 5. Replace Inline Code with Function Call\nReplace the inline code with a call to the existing function\n\n```javascript\nlet appliesToMass = false\nfor (const s of states) {\n  if (s === \"MA\") appliesToMass = true\n}\n```\n\n```javascript\nappliesToMass = states.includes(\"MA\")\n```\n\n**Motivation**\n- Remove duplication\n- Meaningful function name is easier to understand\n\n### 6. Slide Statements\nMove related code to near each other\n\n```javascript\nconst pricingPlan = retrievePricingPlan()\nconst order = retreiveOrder()\nlet charge\nconst chargePerUnit = pricingPlan.unit\n```\n\nto\n\n```javascript\nconst pricingPlan = retrievePricingPlan()\nconst chargePerUnit = pricingPlan.unit\nconst order = retreiveOrder()\nlet charge\n```\n\n**Motivation**\n- It makes code easier to understand and easier to extract function\n\n### 7. Split Loop\nSplit the loop which does two different things\n\n```javascript\nlet averageAge = 0\nlet totalSalary = 0\nfor (const p of people) {\n  averageAge += p.age\n  totalSalary += p.salary\n}\naverageAage = averageAge / people.length\n```\n\nto\n\n```javascript\nlet totalSalary = 0\nfor (const p of people) {\n  totalSalary += p.salary\n}\n\nlet averageAge = 0\nfor (const p of people) {\n  averageAge += p.age\n}\naverageAge = averageAge / people.length\n```\n\n**Motivation**\n- Easier to use\n- Easier to understand because each loop will do only 1 thing\n\n### 8. Replace Loop with Pipeline\nReplace loop with collection pipeline, like `map` or `filter`\n\n```javascript\nconst names = []\nfor (const i of input) {\n  if (i.job === \"programmer\") {\n    names.push(i.name)\n  }\n}\n```\n\nto\n\n```javascript\nconst names = input.filter(i =\u003e i.job === \"programmer\").\n                    map(i =\u003e i.name)\n```\n\n**Motivation**\n- Easier to understand the flow of data\n\n### 9. Remove Dead Code\n\n```javascript\nif (false) {\n  doSomethingThatUsedToMatter()\n}\n```\n\nto\n\n```javascript\n\n```\n\n**Motivation**\n- Easier and quicker for developer to understand the codebase\n\n\n## 9. ORGANIZING DATA\n\n### 1. Split Variable\nAny variable with more than one responsibility should be replaced with multiple variables, one for each responsibility\n\n```javascript\nlet temp = 2 * (height + width)\nconsole.log(temp)\ntemp = height * width\nconsole.log(temp)\n```\n\nto\n\n```javascript\nconst perimeter = 2 * (height + width)\nconsole.log(perimeter)\nconst area = height * width\nconsole.log(area)\n```\n\n**Motivation**\n- Easier to understand\n\n### 2. Rename Field\n\n```javascript\nclass Organization {\n  get name() {}\n}\n```\n\nto\n\n```javascript\nclass Organization {\n  get title() {}\n}\n```\n\n### 3. Replace Derived Variable With Query\nRemove anny variables which cloud be easily calculate\n\n```javascript\nget discountedTotal() { return this._discountedTotal }\nset discount(aNumber) {\n  const old = this._discount\n  this._discount = aNumber\n  this._discountedTotal += old - aNumber\n}\n```\n\nto\n\n```javascript\nget discountedTotal() { return this._baseTotal - this._discount }\nset discount() { this._discount = aNumber }\n```\n\n**Motivation**\n- Minimize scope of mutable data\n- A calculate makes it clearer what the meaning of data is\n\n### 4. Change Reference To Value\nTreat data as value. When update, replace entire inner object with a new one\n\n```javascript\nclass Product {\n  applyDiscount(arg) {\n    this._price.amount -= arg\n  }\n}\n```\n\nto\n\n```javascript\nclass Product {\n  applyDiscount(arg) {\n    this._price = new Money(this._price.amount - arg, this._price.currency)\n  }\n}\n```\n\n**Motivation**\n- Immutable data is easier to deal with\n\n### 5. Change Value To Reference\nWhen need to share an object in different place, or have duplicated objects\n\n```javascript\nlet customer = new Customer(customerData)\n```\n\nto\n\n```javascript\nlet customer = customerRepository.get(customerData.id)\n```\n\n**Motivation**\n- Update one reference is easier and more consistent than update multiple copies\n\n## 10. SIMPLIFYING CONDITIONAL LOGIC\n\n### 1. Decompose Conditional\nDecomposing condition and replacing each chunk of code with a function call\n```javascript\nif (!aDate.isBefore(plan.summerStart) \u0026\u0026 !aData.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge\n}\n```\n\nto\n\n```javascript\nif (summer()) {\n  charge = summerCharge()\n} else {\n  charge = regularCharge()\n}\n```\n\n**Motivation**\n- Clearer intention of what we're branching on\n\n### 2. Consolidate Conditional Expression\nConsolidate different condition check which the result action is same to a single condition check with single result\n\n```javascript\nif (anEmployee.seniority \u003c 2) return 0\nif (anEmployee.monthsDisabled \u003e 12) return 0;\nif (anEmployee.isPartTime) return 0\n```\n\nto\n\n```javascript\nif (isNotEligableForDisability()) return 0\n\nfunction isNotEligableForDisability() {\n   return ((anEmployee.seniority \u003c 2)\n    || (anEmployee.monthsDisabled \u003e 12)\n    || (anEmployee.isPartTime))\n}\n```\n\n**Motivation**\n- Often lead to Extract Function, which reveal intead of the code by function name\n- If conditions are not related, don't consolidate them\n\n### 3. Replace Nested Conditional with Guard Clauses\nIf condition is unusual condition, early return (Guard Clauses) and exist the function\n\n```javascript\nfunction getPayAmount() {\n  let result\n  if (isDead) {\n    result = deadAmount()\n  } else {\n    if (isSeparated) {\n      result = separatedAmount()\n    } else {\n      if (isRetired) {\n        result = retiredAmount()\n      } else {\n        result = normalPayAmount()\n      }\n    }\n  }\n  return result\n}\n```\n\nto\n\n```javascript\nfunction getPayAmount() {\n  if (isDead) return deadAmount()\n  if (isSeparated) return separatedAmount()\n  if (isRetired) return retiredAmount()\n  return normalPayAmount()\n}\n```\n\n**Motivation**\n- It shows conditional branch are normal or unusual\n\n### 4. Replace Conditional with Polymorphism\nUsing object oriented class instead of complex condition\n\n```javascript\nswitch (bird.type) {\n  case 'EuropeanSwallow':\n    return 'average'\n  case 'AfricanSwallow':\n    return bird.numberOfCoconuts \u003e 2 ? 'tired' : 'average'\n  case 'NorwegianBlueParrot':\n    return bird.voltage \u003e 100 ? 'scorched' : 'beautiful'\n  default:\n    return 'unknow'\n}\n```\n\nto\n\n```javascript\nclass EuropeanSwallow {\n  get plumage() {\n    return 'average'\n  }\n}\nclass AfricanSwallow {\n  get plumage() {\n    return this.numberOfCoconuts \u003e 2 ? 'tired' : 'average'\n  }\n}\nclass NorwegianBlueParrot {\n  get plumage() {\n    return this.voltage \u003e 100 ? 'scorched' : 'beautiful'\n  }\n}\n```\n\n**Motivation**\n- Make the separation more explicit\n\n### 5. Introduce Special Case\nBring special check case to a single place\n\n```javascript\nif (aCustomer === \"unknown\") {\n  customerName = \"occupant\"\n}\n```\n\nto\n\n```javascript\nclass UnknownCustomer {\n  get name() {\n    return \"occupant\"\n  }\n}\n```\n\n**Motivation**\n- Remove duplicate code\n- Easy to add additional behavior to special object\n\n### 6. Introduce Assertion\nMake the assumption explicit by writing an assertion\n\n```javascript\nif (this.discountRate) {\n  base = base - (this.discountRate * base)\n}\n```\n\nto\n\n```javascript\nassert(this.discountRate \u003e= 0)\nif (this.discountRate) {\n  base = base - (this.discountRate * base)\n}\n```\n\n**Motivation**\n- Reader can understand the assumption easily\n- Help in debugging\n\n## 11. REFACTORING APIS\n\n### 1. Separate Query from Modifier\nSeparate function that returns a value (query only) and function with side effects (example: modify data)\n\n```javascript\nfunction alertForMiscreant (people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms()\n      return \"Don\"\n    }\n    if (p === \"John\") {\n      setOffAlarms()\n      return \"John\"\n    }\n  }\n  return \"\"\n}\n```\n\nto\n\n```javascript\nfunction findMiscreant (people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      return \"Don\"\n    }\n    if (p === \"John\") {\n      return \"John\"\n    }\n  }\n  return \"\"\n}\nfunction alertForMiscreant (people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n**Motivation**\n- Immutable function (query only) is easy to test and reuse\n\n### 2. Parameterize Function\nCombine function with similar logic and different literal value\n\n```javascript\nfunction tenPercentRaise(aPerson) {\n  aPerson.salary = aPerson.salary.multiply(1.1)\n}\nfunction fivePercentRaise(aPerson) {\n  aPerson.salary = aPerson.salary.multiply(1.05)\n}\n```\n\nto\n\n```javascript\nfunction raise(aPerson, factor) {\n  aPerson.salary = aPerson.salary.multiply(1 + factor)\n}\n```\n\n**Motivation**\n- Increase usefulness of the function\n\n### 3. Remove Flag Argument\nRemove _literal_ flag argument by clear name functions\n\n```javascript\nfunction setDimension(name, value) {\n  if (name === 'height') {\n    this._height = value\n    return\n  }\n  if (name === 'width') {\n    this._width = value\n    return\n  }\n}\n```\n\nto\n\n```javascript\nfunction setHeight(value) { this._height = value }\nfunction setWidth(value) { this._width = value }\n```\n\n**Motivation**\n- Easy to read and understand code\n- Be careful if flag argument appears more than 1 time in the function, or is passed to further function\n\n### 4. Preserve Whole Object\nPassing whole object instead of multiple parameters\n\n```javascript\nconst low = aRoom.daysTempRange.low\nconst high = aRoom.daysTempRange.high\nif (aPlan.withinRange(low, high)) {}\n```\n\nto\n\n```javascript\nif (aPlan.withInRange(aRoom.daysTempRange)) {}\n```\n\n**Motivation**\n- Shorter parameter list\n- Don't need to add additional parameter if function needs more data in the future\n- Be careful if function and object are in different modules, which make tight coupling if we apply this refactor\n\n### 5. Replace Parameter with Query\n\n```javascript\navailableVacation(anEmployee, anEmployee.grade)\n\nfunction availableVacation(anEmployee, grade) {\n  // calculate vacation...\n}\n```\n\nto\n\n```javascript\navailableVacation(anEmployee)\n\nfunction availableVacation(anEmployee) {\n  const grade = anEmployee.grade\n  // calculate vacation...\n}\n```\n\n**Motivation**\n- Shorter list of parameters\n- Simpler work for the caller (because fewer parameters)\n- Be careful because it can increase function's dependency\n\n### 6. Replace Query with Parameter\nReplace internal reference with a parameter\n\n```javascript\ntargetTemperature(aPlan)\n\nfunction targetTemperature(aPlan) {\n  currentTemperature = thermostat.currentTemperature\n  // rest of function...\n}\n```\n\nto\n\n```javascript\ntargetTemperature(aPlan, thermostat.currentTemperature)\n\nfunction targetTemperature(aPlan, currentTemperature) {\n  // rest of function...\n}\n```\n\n**Motivation**\n- Reduce function's dependency\n- Create more pure functions\n\n### 7. Remove Setting Method\nMake a field immutable by removing setting method\n\n```javascript\nclass Person {\n  get name() {...}\n  set name(aString) {...}\n}\n```\n\nto\n\n```javascript\nclass Person {\n  get name() {...}\n}\n```\n\n### 8. Replace Constructor with Factory Function\n\n```javascript\nleadEngineer = new Employee(document.leadEngineer, 'E')\n```\n\nto\n\n```javascript\nleadEngineer = createEngineer(document.leadEngineer)\n```\n\n**Motivation**\n- You want to do more than simple construction when you create an object.\n\n\n### 9. Replace Function with Command\nEncapsulate function into its own object\n\n```javascript\nfunction score(candidate, medicalExam, scoringGuide) {\n  let result = 0\n  let healthLevel = 0\n  // long body code\n}\n```\n\nto\n\n```javascript\nclass Scorer {\n  constructor(candidate, medicalExam, scoringGuide) {\n    this._candidate = candidate\n    this._medicalExam = medicalExam\n    this._scoringGuide = scoringGuide\n  }\n\n  execute() {\n    this._result = 0\n    this._healthLevel = 0\n    // long body code\n  }\n}\n```\n\n**Motivation**\n- You want to add complimentary operation, such as undo\n- Can have richer lifecycle\n- Can build customization such as inheritance and hooks\n- Easily break down a complex function to simpler steps\n\n### 10. Replace Command with Function\n\n```javascript\nclass ChargeCalculator {\n  constructor (customer, usage){\n    this._customer = customer\n    this._usage = usage\n  }\n  execute() {\n    return this._customer.rate * this._usage\n  }\n}\n```\n\nto\n\n```javascript\nfunction charge(customer, usage) {\n  return customer.rate * usage\n}\n```\n\n**Motivation**\n- Function call is simpler than command object\n\n## 12. DEALING WITH INHERITANCE\n\n### 1. Pull Up Method\nMove similar methods in subclass to superclass\n\n```java\nclass Employee {...}\n\nclass Salesman extends Employee {\n  get name() {...}\n}\n\nclass Engineer extends Employee {\n  get name() {...}\n}\n```\n\nto\n\n```java\nclass Employee {\n  get name() {...}\n}\n\nclass Salesman extends Employee {...}\nclass Engineer extends Employee {...}\n```\n\n**Motivation**\n- Eliminate duplicate code in subclass\n- If two methods has similar workflow, consider using Template Method Pattern\n\n### 2. Pull Up Field\nPull up similar field to superclass to remove duplication\n\n```java\nclass Employee {...}\n\nclass Salesman extends Employee {\n  private String name;\n}\n\nclass Engineer extends Employee {\n  private String name;\n}\n```\n\nto\n\n```java\nclass Employee {\n  protected String name;\n}\n\nclass Salesman extends Employee {...}\nclass Engineer extends Employee {...}\n```\n\n### 3. Pull Up Constructor Body\nYou have constructors on subclasses with mostly identical bodies.\nCreate a superclass constructor; call this from the subclass methods\n\n```javascript\nclass Party {...}\n\nclass Employee extends Party {\n  constructor(name, id, monthlyCost) {\n    super()\n    this._id = id\n    this._name = name\n    this._monthlyCost = monthlyCost\n  }\n}\n```\n\nto\n\n```javascript\nclass Party {\n  constructor(name){\n    this._name = name\n  }\n}\n\nclass Employee extends Party {\n  constructor(name, id, monthlyCost) {\n    super(name)\n    this._id = id\n    this._monthlyCost = monthlyCost\n  }\n}\n```\n\n### 4. Push Down Method\nIf method is only relevant to one subclass, moving it from superclass to subclass\n\n```javascript\nclass Employee {\n  get quota {...}\n}\n\nclass Engineer extends Employee {...}\nclass Salesman extends Employee {...}\n```\n\nto\n\n```javascript\nclass Employee {...}\nclass Engineer extends Employee {...}\nclass Salesman extends Employee {\n  get quota {...}\n}\n```\n\n### 5. Push Down Field\nIf field is only used in one subclass, move it to those subclasses\n\n```java\nclass Employee {\n  private String quota;\n}\n\nclass Engineer extends Employee {...}\nclass Salesman extends Employee {...}\n```\n\nto\n\n```java\nclass Employee {...}\nclass Engineer extends Employee {...}\n\nclass Salesman extends Employee {\n  protected String quota;\n}\n```\n\n### 6. Replace Type Code with Subclasses\n\n```javascript\nfunction createEmployee(name, type) {\n  return new Employee(name, type)\n}\n```\n\nto\n\n```javascript\nfunction createEmployee(name, type) {\n  switch (type) {\n    case \"engineer\": return new Engineer(name)\n    case \"salesman\": return new Salesman(name)\n    case \"manager\":  return new Manager (name)\n  }\n}\n```\n\n**Motivation**\n- Easily to apply Replace Conditional with Polymorphism later\n- Execute different code depending on the value of a type\n\n### 7. Remove Subclass\nYou have subclasses do to little. Replace the subclass with a field in superclass.\n\n```javascript\nclass Person {\n  get genderCode() {return \"X\"}\n}\nclass Male extends Person {\n  get genderCode() {return \"M\"}\n}\nclass Female extends Person {\n  get genderCode() {return \"F\"}\n}\n```\n\nto\n\n```javascript\nclass Person {\n  get genderCode() {return this._genderCode}\n}\n```\n\n### 8. Extract Superclass\nIf 2 classes have similar behaviors, create superclass and move these behaviors to superclass\n\n```javascript\nclass Department {\n  get totalAnnualCost() {...}\n  get name() {...}\n  get headCount() {...}\n}\n\nclass Employee {\n  get annualCost() {...}\n  get name() {...}\n  get id() {...}\n}\n```\n\nto\n\n```javascript\nclass Party {\n  get name() {...}\n  get annualCost() {...}\n}\n\nclass Department extends Party {\n  get annualCost() {...}\n  get headCount() {...}\n}\n\nclass Employee extends Party {\n  get annualCost() {...}\n  get id() {...}\n}\n```\n\n**Motivation**\n- Remove duplication\n- Prepare for Replace Superclass with Delegate refactor\n\n### 9. Collapse Hierarchy\nMerge superclass and subclass when there are no longer different enough to keep them separate\n\n```javascript\nclass Employee {...}\nclass Salesman extends Employee {...}\n```\n\nto\n\n```javascript\nclass Employee {...}\n```\n\n### 10. Replace Subclass with Delegate\n\"Favor object composition over class inheritance\" (where composition is effectively the same as delegation\n\n```javascript\nclass Order {\n  get daysToShip() {\n    return this._warehouse.daysToShip\n  }\n}\n\nclass PriorityOrder extends Order {\n  get daysToShip() {\n    return this._priorityPlan.daysToShip\n  }\n}\n```\n\nto\n\n```javascript\nclass Order {\n  get daysToShip() {\n    return (this._priorityDelegate)\n      ? this._priorityDelegate.daysToShip\n      : this._warehouse.daysToShip\n  }\n}\n\nclass PriorityOrderDelegate {\n  get daysToShip() {\n    return this._priorityPlan.daysToShip\n  }\n}\n```\n\n**Motivation**\n- If there are more than 1 reason to vary something, inheritance is not enough\n- Inheritance introduce very close relationship\n\n### 11. Replace Superclass with Delegate\nIf functions of the superclass don’t make sense on the subclass, replace with with delegate\n\n```javascript\nclass List {...}\nclass Stack extends List {...}\n```\n\nto\n\n```javascript\nclass Stack {\n  constructor() {\n    this._storage = new List();\n  }\n}\nclass List {...}\n```\n\n**Motivation**\n- Easier to maintain code\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fittus%2Frefactoring-summary-2nd-javascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fittus%2Frefactoring-summary-2nd-javascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fittus%2Frefactoring-summary-2nd-javascript/lists"}