[{"data":1,"prerenderedAt":3966},["ShallowReactive",2],{"writing-understand-and-use-solid-design-principles-with-typescript":3},{"id":4,"title":5,"body":6,"category":3951,"date":3952,"description":3953,"excerpt":3954,"extension":3955,"image":3956,"keywords":3957,"meta":3958,"navigation":165,"path":3959,"readingTime":3960,"seo":3961,"slug":3962,"stem":3963,"tags":3964,"__hash__":3965},"blog\u002Fblog\u002Funderstand-and-use-solid-design-principles-with-typescript.md","Understand and use SOLID Design Principles with TypeScript",{"type":7,"value":8,"toc":3940},"minimark",[9,18,23,28,31,35,43,50,53,57,70,76,110,113,118,124,127,465,472,475,996,1002,1023,1026,1031,1055,1059,1062,1068,1087,1198,1223,1591,1610,1617,1631,2045,2050,2069,2073,2089,2092,2098,2101,2436,2459,2462,2743,2747,2754,2757,2915,2935,3111,3128,3132,3139,3142,3145,3148,3156,3167,3437,3453,3460,3837,3850,3927,3930,3933,3936],[10,11,12,13,17],"p",{},"Yes, another take into explaining SOLID Design Principles. And yes, another blog post about making your code more maintainable and readable. But this time something is different - well, mostly nothing really is (",[14,15,16],"em",{},"you expected something here, didn't ya?",") except that it's just my perspective. A perspective gained from applying these principles in real life projects.",[19,20,22],"h2",{"id":21},"what-is-a-design-principle","What is a Design Principle?",[10,24,25],{},[14,26,27],{},"Software design principles are concerned with providing means to handle the complexity of the design process effectively. Effectively managing the complexity will not only reduce the effort needed for design but can also reduce the scope of introducing errors during design. Design Principles are standards used to organize and arrange the structural components of Software Engineering design. Methods in which these design principles are applied affect the expressive content and the working process from the start. Design principles help developers build-up common consensus about architectural knowledge, help people process with large-scale software engineering, help beginners avoid traps and pitfalls which have been detected by past experiences.",[10,29,30],{},"Reading the above definition might scare you if you are a beginner or confuse you if you are a seasoned developer. To explain in a concise and understandable way - the goal of a design principle is to make our software easier to understand, read, extend and maintain.",[19,32,34],{"id":33},"why-do-we-need-design-principles","Why do we need Design Principles",[10,36,37,38,42],{},"Imagine you are put into a position to work on a legacy codebase that didn't have proper code architecture and components within the projects are coupled together and you need to either fix some minor bug or extend the code with some functionality. You will find yourself jumping back and forth between individual components to understand how these individual components are coupled. Once you think you understood how the system is structured and how do these components behave (and are interconnected between each other), you start extending the codebase. But then again, while extending some of the things might not seem logical at first, so you have to adapt your mindset to follow the existing codebase, which will again force to you ",[39,40,41],"strong",{},"spend more time reading than writing code",".",[10,44,45,46,49],{},"These issues don't arise only on legacy codebases. Let's say you are working for a startup (or start one of your own), and you are in charge of a project. You start your project from a clean slate and you are in charge of its architecture and the whole development cycle. We all know that startups want to release new features and new products as fast as possible, so you end up spending less time thinking about the code structure and more about just building up new features. And this is okay if you have a ",[14,47,48],{},"short-term"," vision for your startup. But what happens if your startup gets enough steam and is in it for the long run? How much technical debt have you introduced and how much time and money is it going to cost you while trying to scale and maintain your codebase?",[10,51,52],{},"Implementing these design principles is not something you will waste extra time on. Once you understand their meaning and their usage, gain a little bit of real-life experience, they will be part of your development process - making you a better and more-seniorish-like developer.",[19,54,56],{"id":55},"what-does-solid-stand-for","What does SOLID stand for",[10,58,59,62,63,42],{},[39,60,61],{},"SOLID"," is an acronym for the first five object-oriented design (OOD) principles by Robert C. Martin, popularly known as ",[64,65,69],"a",{"href":66,"rel":67},"https:\u002F\u002Ftwitter.com\u002FUncleBob",[68],"nofollow","@UncleBob",[10,71,72,73,75],{},"The following 5 concepts make up our ",[39,74,61],{}," principles:",[77,78,79,86,92,98,104],"ol",{},[80,81,82,85],"li",{},[39,83,84],{},"S","ingle Responsibility",[80,87,88,91],{},[39,89,90],{},"O","pen\u002FClosed",[80,93,94,97],{},[39,95,96],{},"L","iskov Substitution",[80,99,100,103],{},[39,101,102],{},"I","nterface Segregation",[80,105,106,109],{},[39,107,108],{},"D","ependency Inversion",[10,111,112],{},"While some of these words may sound daunting, they can be easily understood with some simple code examples. In the following sections, we'll take a deep dive into what each of these principles means, along with a quick TypeScript example to illustrate each one.",[114,115,117],"h3",{"id":116},"single-responsibility-principle-srp","Single Responsibility Principle (SRP)",[10,119,120,123],{},[39,121,122],{},"The SRP requires that a class should have only one reason to change."," A class that follows this principle performs just a few related tasks. You don’t need to limit your thinking to classes when considering the SRP. You can apply the principle to methods or modules, ensuring that they do just one thing and therefore have just one reason to change.",[10,125,126],{},"Let's look at an example where we violate SRP:",[128,129,134],"pre",{"className":130,"code":131,"language":132,"meta":133,"style":133},"language-ts shiki shiki-themes github-light github-dark","import axios from \"axios\";\n\nclass User {\n  private emailServiceUrl = `emailService.example\u002Fapi`;\n  private email: string;\n  private name: string;\n\n  constructor(name: string, email: string) {\n    this.name = name;\n    this.email = email;\n  }\n\n  sendGreetingEmail() {\n    const { name, email, emailServiceUrl } = this;\n    const body = `Hey ${name}. Welcome to our app!`;\n\n    return axios(emailServiceUrl, {\n      data: {\n        email,\n        body,\n      },\n    });\n  }\n}\n\nconst user = new User(\"John\", \"email@example.com\");\nuser.sendGreetingEmail();\n","ts","",[135,136,137,160,167,180,198,215,229,234,263,278,291,297,302,311,341,361,366,378,384,390,396,402,408,413,419,424,453],"code",{"__ignoreMap":133},[138,139,142,146,150,153,157],"span",{"class":140,"line":141},"line",1,[138,143,145],{"class":144},"szBVR","import",[138,147,149],{"class":148},"sVt8B"," axios ",[138,151,152],{"class":144},"from",[138,154,156],{"class":155},"sZZnC"," \"axios\"",[138,158,159],{"class":148},";\n",[138,161,163],{"class":140,"line":162},2,[138,164,166],{"emptyLinePlaceholder":165},true,"\n",[138,168,170,173,177],{"class":140,"line":169},3,[138,171,172],{"class":144},"class",[138,174,176],{"class":175},"sScJk"," User",[138,178,179],{"class":148}," {\n",[138,181,183,186,190,193,196],{"class":140,"line":182},4,[138,184,185],{"class":144},"  private",[138,187,189],{"class":188},"s4XuR"," emailServiceUrl",[138,191,192],{"class":144}," =",[138,194,195],{"class":155}," `emailService.example\u002Fapi`",[138,197,159],{"class":148},[138,199,201,203,206,209,213],{"class":140,"line":200},5,[138,202,185],{"class":144},[138,204,205],{"class":188}," email",[138,207,208],{"class":144},":",[138,210,212],{"class":211},"sj4cs"," string",[138,214,159],{"class":148},[138,216,218,220,223,225,227],{"class":140,"line":217},6,[138,219,185],{"class":144},[138,221,222],{"class":188}," name",[138,224,208],{"class":144},[138,226,212],{"class":211},[138,228,159],{"class":148},[138,230,232],{"class":140,"line":231},7,[138,233,166],{"emptyLinePlaceholder":165},[138,235,237,240,243,246,248,250,253,256,258,260],{"class":140,"line":236},8,[138,238,239],{"class":144},"  constructor",[138,241,242],{"class":148},"(",[138,244,245],{"class":188},"name",[138,247,208],{"class":144},[138,249,212],{"class":211},[138,251,252],{"class":148},", ",[138,254,255],{"class":188},"email",[138,257,208],{"class":144},[138,259,212],{"class":211},[138,261,262],{"class":148},") {\n",[138,264,266,269,272,275],{"class":140,"line":265},9,[138,267,268],{"class":211},"    this",[138,270,271],{"class":148},".name ",[138,273,274],{"class":144},"=",[138,276,277],{"class":148}," name;\n",[138,279,281,283,286,288],{"class":140,"line":280},10,[138,282,268],{"class":211},[138,284,285],{"class":148},".email ",[138,287,274],{"class":144},[138,289,290],{"class":148}," email;\n",[138,292,294],{"class":140,"line":293},11,[138,295,296],{"class":148},"  }\n",[138,298,300],{"class":140,"line":299},12,[138,301,166],{"emptyLinePlaceholder":165},[138,303,305,308],{"class":140,"line":304},13,[138,306,307],{"class":175},"  sendGreetingEmail",[138,309,310],{"class":148},"() {\n",[138,312,314,317,320,322,324,326,328,331,334,336,339],{"class":140,"line":313},14,[138,315,316],{"class":144},"    const",[138,318,319],{"class":148}," { ",[138,321,245],{"class":211},[138,323,252],{"class":148},[138,325,255],{"class":211},[138,327,252],{"class":148},[138,329,330],{"class":211},"emailServiceUrl",[138,332,333],{"class":148}," } ",[138,335,274],{"class":144},[138,337,338],{"class":211}," this",[138,340,159],{"class":148},[138,342,344,346,349,351,354,356,359],{"class":140,"line":343},15,[138,345,316],{"class":144},[138,347,348],{"class":211}," body",[138,350,192],{"class":144},[138,352,353],{"class":155}," `Hey ${",[138,355,245],{"class":148},[138,357,358],{"class":155},"}. Welcome to our app!`",[138,360,159],{"class":148},[138,362,364],{"class":140,"line":363},16,[138,365,166],{"emptyLinePlaceholder":165},[138,367,369,372,375],{"class":140,"line":368},17,[138,370,371],{"class":144},"    return",[138,373,374],{"class":175}," axios",[138,376,377],{"class":148},"(emailServiceUrl, {\n",[138,379,381],{"class":140,"line":380},18,[138,382,383],{"class":148},"      data: {\n",[138,385,387],{"class":140,"line":386},19,[138,388,389],{"class":148},"        email,\n",[138,391,393],{"class":140,"line":392},20,[138,394,395],{"class":148},"        body,\n",[138,397,399],{"class":140,"line":398},21,[138,400,401],{"class":148},"      },\n",[138,403,405],{"class":140,"line":404},22,[138,406,407],{"class":148},"    });\n",[138,409,411],{"class":140,"line":410},23,[138,412,296],{"class":148},[138,414,416],{"class":140,"line":415},24,[138,417,418],{"class":148},"}\n",[138,420,422],{"class":140,"line":421},25,[138,423,166],{"emptyLinePlaceholder":165},[138,425,427,430,433,435,438,440,442,445,447,450],{"class":140,"line":426},26,[138,428,429],{"class":144},"const",[138,431,432],{"class":211}," user",[138,434,192],{"class":144},[138,436,437],{"class":144}," new",[138,439,176],{"class":175},[138,441,242],{"class":148},[138,443,444],{"class":155},"\"John\"",[138,446,252],{"class":148},[138,448,449],{"class":155},"\"email@example.com\"",[138,451,452],{"class":148},");\n",[138,454,456,459,462],{"class":140,"line":455},27,[138,457,458],{"class":148},"user.",[138,460,461],{"class":175},"sendGreetingEmail",[138,463,464],{"class":148},"();\n",[10,466,467,468,471],{},"As you can see in the example above, this ",[135,469,470],{},"User"," class is responsible for many things. It contains user details, sending a welcome email, contains the email service url, constructs and sends the email message. Think of the code smells here. Why would the user need to know about which email service to use? Why would the user need to handle sending a welcome email?",[10,473,474],{},"Let's refactor the above example to conform to SRP, so each class has only one reason to change.",[128,476,478],{"className":130,"code":477,"language":132,"meta":133,"style":133},"import axios from \"axios\";\n\nclass EmailClient {\n  private endpoint = `emailService.example\u002Fapi`;\n\n  public send(to: string, body: any) {\n    const { endpoint } = this;\n\n    return axios(endpoint, {\n      data: {\n        email: to,\n        body,\n      },\n    });\n  }\n}\n\nclass User {\n  private email: string;\n  private name: string;\n\n  constructor(name: string, email: string) {\n    this.name = name;\n    this.email = email;\n  }\n\n  getName(): string {\n    return this.name;\n  }\n\n  getEmail(): string {\n    return this.email;\n  }\n}\n\nclass WelcomeUserService {\n  private emailService: EmailClient;\n\n  constructor() {\n    this.emailService = new EmailClient();\n  }\n\n  public handle(user: User) {\n    const name = user.getName();\n    const email = user.getEmail();\n    const body = `Hey ${name}. Welcome to our app!`;\n\n    return this.emailService.send(email, body);\n  }\n}\n\nconst welcomeUserService = new WelcomeUserService();\nconst user = new User(\"John\", \"email@example.com\");\n\nwelcomeUserService.handle(user);\n",[135,479,480,492,496,505,518,522,551,568,572,581,585,590,594,598,602,606,610,614,622,634,646,650,672,682,692,696,700,714,724,729,734,748,758,763,768,773,783,797,802,809,825,830,835,854,871,887,904,909,925,930,935,940,956,979,984],{"__ignoreMap":133},[138,481,482,484,486,488,490],{"class":140,"line":141},[138,483,145],{"class":144},[138,485,149],{"class":148},[138,487,152],{"class":144},[138,489,156],{"class":155},[138,491,159],{"class":148},[138,493,494],{"class":140,"line":162},[138,495,166],{"emptyLinePlaceholder":165},[138,497,498,500,503],{"class":140,"line":169},[138,499,172],{"class":144},[138,501,502],{"class":175}," EmailClient",[138,504,179],{"class":148},[138,506,507,509,512,514,516],{"class":140,"line":182},[138,508,185],{"class":144},[138,510,511],{"class":188}," endpoint",[138,513,192],{"class":144},[138,515,195],{"class":155},[138,517,159],{"class":148},[138,519,520],{"class":140,"line":200},[138,521,166],{"emptyLinePlaceholder":165},[138,523,524,527,530,532,535,537,539,541,544,546,549],{"class":140,"line":217},[138,525,526],{"class":144},"  public",[138,528,529],{"class":175}," send",[138,531,242],{"class":148},[138,533,534],{"class":188},"to",[138,536,208],{"class":144},[138,538,212],{"class":211},[138,540,252],{"class":148},[138,542,543],{"class":188},"body",[138,545,208],{"class":144},[138,547,548],{"class":211}," any",[138,550,262],{"class":148},[138,552,553,555,557,560,562,564,566],{"class":140,"line":231},[138,554,316],{"class":144},[138,556,319],{"class":148},[138,558,559],{"class":211},"endpoint",[138,561,333],{"class":148},[138,563,274],{"class":144},[138,565,338],{"class":211},[138,567,159],{"class":148},[138,569,570],{"class":140,"line":236},[138,571,166],{"emptyLinePlaceholder":165},[138,573,574,576,578],{"class":140,"line":265},[138,575,371],{"class":144},[138,577,374],{"class":175},[138,579,580],{"class":148},"(endpoint, {\n",[138,582,583],{"class":140,"line":280},[138,584,383],{"class":148},[138,586,587],{"class":140,"line":293},[138,588,589],{"class":148},"        email: to,\n",[138,591,592],{"class":140,"line":299},[138,593,395],{"class":148},[138,595,596],{"class":140,"line":304},[138,597,401],{"class":148},[138,599,600],{"class":140,"line":313},[138,601,407],{"class":148},[138,603,604],{"class":140,"line":343},[138,605,296],{"class":148},[138,607,608],{"class":140,"line":363},[138,609,418],{"class":148},[138,611,612],{"class":140,"line":368},[138,613,166],{"emptyLinePlaceholder":165},[138,615,616,618,620],{"class":140,"line":380},[138,617,172],{"class":144},[138,619,176],{"class":175},[138,621,179],{"class":148},[138,623,624,626,628,630,632],{"class":140,"line":386},[138,625,185],{"class":144},[138,627,205],{"class":188},[138,629,208],{"class":144},[138,631,212],{"class":211},[138,633,159],{"class":148},[138,635,636,638,640,642,644],{"class":140,"line":392},[138,637,185],{"class":144},[138,639,222],{"class":188},[138,641,208],{"class":144},[138,643,212],{"class":211},[138,645,159],{"class":148},[138,647,648],{"class":140,"line":398},[138,649,166],{"emptyLinePlaceholder":165},[138,651,652,654,656,658,660,662,664,666,668,670],{"class":140,"line":404},[138,653,239],{"class":144},[138,655,242],{"class":148},[138,657,245],{"class":188},[138,659,208],{"class":144},[138,661,212],{"class":211},[138,663,252],{"class":148},[138,665,255],{"class":188},[138,667,208],{"class":144},[138,669,212],{"class":211},[138,671,262],{"class":148},[138,673,674,676,678,680],{"class":140,"line":410},[138,675,268],{"class":211},[138,677,271],{"class":148},[138,679,274],{"class":144},[138,681,277],{"class":148},[138,683,684,686,688,690],{"class":140,"line":415},[138,685,268],{"class":211},[138,687,285],{"class":148},[138,689,274],{"class":144},[138,691,290],{"class":148},[138,693,694],{"class":140,"line":421},[138,695,296],{"class":148},[138,697,698],{"class":140,"line":426},[138,699,166],{"emptyLinePlaceholder":165},[138,701,702,705,708,710,712],{"class":140,"line":455},[138,703,704],{"class":175},"  getName",[138,706,707],{"class":148},"()",[138,709,208],{"class":144},[138,711,212],{"class":211},[138,713,179],{"class":148},[138,715,717,719,721],{"class":140,"line":716},28,[138,718,371],{"class":144},[138,720,338],{"class":211},[138,722,723],{"class":148},".name;\n",[138,725,727],{"class":140,"line":726},29,[138,728,296],{"class":148},[138,730,732],{"class":140,"line":731},30,[138,733,166],{"emptyLinePlaceholder":165},[138,735,737,740,742,744,746],{"class":140,"line":736},31,[138,738,739],{"class":175},"  getEmail",[138,741,707],{"class":148},[138,743,208],{"class":144},[138,745,212],{"class":211},[138,747,179],{"class":148},[138,749,751,753,755],{"class":140,"line":750},32,[138,752,371],{"class":144},[138,754,338],{"class":211},[138,756,757],{"class":148},".email;\n",[138,759,761],{"class":140,"line":760},33,[138,762,296],{"class":148},[138,764,766],{"class":140,"line":765},34,[138,767,418],{"class":148},[138,769,771],{"class":140,"line":770},35,[138,772,166],{"emptyLinePlaceholder":165},[138,774,776,778,781],{"class":140,"line":775},36,[138,777,172],{"class":144},[138,779,780],{"class":175}," WelcomeUserService",[138,782,179],{"class":148},[138,784,786,788,791,793,795],{"class":140,"line":785},37,[138,787,185],{"class":144},[138,789,790],{"class":188}," emailService",[138,792,208],{"class":144},[138,794,502],{"class":175},[138,796,159],{"class":148},[138,798,800],{"class":140,"line":799},38,[138,801,166],{"emptyLinePlaceholder":165},[138,803,805,807],{"class":140,"line":804},39,[138,806,239],{"class":144},[138,808,310],{"class":148},[138,810,812,814,817,819,821,823],{"class":140,"line":811},40,[138,813,268],{"class":211},[138,815,816],{"class":148},".emailService ",[138,818,274],{"class":144},[138,820,437],{"class":144},[138,822,502],{"class":175},[138,824,464],{"class":148},[138,826,828],{"class":140,"line":827},41,[138,829,296],{"class":148},[138,831,833],{"class":140,"line":832},42,[138,834,166],{"emptyLinePlaceholder":165},[138,836,838,840,843,845,848,850,852],{"class":140,"line":837},43,[138,839,526],{"class":144},[138,841,842],{"class":175}," handle",[138,844,242],{"class":148},[138,846,847],{"class":188},"user",[138,849,208],{"class":144},[138,851,176],{"class":175},[138,853,262],{"class":148},[138,855,857,859,861,863,866,869],{"class":140,"line":856},44,[138,858,316],{"class":144},[138,860,222],{"class":211},[138,862,192],{"class":144},[138,864,865],{"class":148}," user.",[138,867,868],{"class":175},"getName",[138,870,464],{"class":148},[138,872,874,876,878,880,882,885],{"class":140,"line":873},45,[138,875,316],{"class":144},[138,877,205],{"class":211},[138,879,192],{"class":144},[138,881,865],{"class":148},[138,883,884],{"class":175},"getEmail",[138,886,464],{"class":148},[138,888,890,892,894,896,898,900,902],{"class":140,"line":889},46,[138,891,316],{"class":144},[138,893,348],{"class":211},[138,895,192],{"class":144},[138,897,353],{"class":155},[138,899,245],{"class":148},[138,901,358],{"class":155},[138,903,159],{"class":148},[138,905,907],{"class":140,"line":906},47,[138,908,166],{"emptyLinePlaceholder":165},[138,910,912,914,916,919,922],{"class":140,"line":911},48,[138,913,371],{"class":144},[138,915,338],{"class":211},[138,917,918],{"class":148},".emailService.",[138,920,921],{"class":175},"send",[138,923,924],{"class":148},"(email, body);\n",[138,926,928],{"class":140,"line":927},49,[138,929,296],{"class":148},[138,931,933],{"class":140,"line":932},50,[138,934,418],{"class":148},[138,936,938],{"class":140,"line":937},51,[138,939,166],{"emptyLinePlaceholder":165},[138,941,943,945,948,950,952,954],{"class":140,"line":942},52,[138,944,429],{"class":144},[138,946,947],{"class":211}," welcomeUserService",[138,949,192],{"class":144},[138,951,437],{"class":144},[138,953,780],{"class":175},[138,955,464],{"class":148},[138,957,959,961,963,965,967,969,971,973,975,977],{"class":140,"line":958},53,[138,960,429],{"class":144},[138,962,432],{"class":211},[138,964,192],{"class":144},[138,966,437],{"class":144},[138,968,176],{"class":175},[138,970,242],{"class":148},[138,972,444],{"class":155},[138,974,252],{"class":148},[138,976,449],{"class":155},[138,978,452],{"class":148},[138,980,982],{"class":140,"line":981},54,[138,983,166],{"emptyLinePlaceholder":165},[138,985,987,990,993],{"class":140,"line":986},55,[138,988,989],{"class":148},"welcomeUserService.",[138,991,992],{"class":175},"handle",[138,994,995],{"class":148},"(user);\n",[10,997,998,999],{},"When you compare the two code snippets, the refactored one is longer. ",[39,1000,1001],{},"So let's address this before deep-diving into the refactor. Yes, the refactored code is a bit longer but that doesn't mean that you will lose more time writing this code. In fact, you will save time in the long run when you go back reading and trying to understand your code. So it's a tradeoff, and a tradeoff that you should be more than happy to make.",[10,1003,1004,1005,1007,1008,1010,1011,1014,1015,1018,1019,1022],{},"After we refactored our ",[135,1006,470],{}," class we ended up having three classes. Now, the ",[135,1009,470],{}," class is only responsible for keeping the user details - SRP achieved. But what happened with the other functionality? We extracted that functionality to separate classes. We have an ",[135,1012,1013],{},"EmailClient"," class, that is responsible for sending out emails (",[14,1016,1017],{},"any kind of emails, not just welcome emails","). Now we have a class that we can reuse now only for our users but throughout our application. The ",[135,1020,1021],{},"WelcomeUserService"," class handles sending out an email to the user when he joins our app. It is responsible for generating the body for the email and sending out the email.",[10,1024,1025],{},"There we have it. We refactored one class that doesn't follow SRP to three classes that do. Extending any of these classes will be easier now because they are not tightly coupled.",[10,1027,1028],{},[39,1029,1030],{},"How to notice code that needs to be refactored using SRP",[1032,1033,1034,1037,1047],"ul",{},[80,1035,1036],{},"Prefixed functions that should be extracted to their own class,",[80,1038,1039,1040,1042,1043,1046],{},"Mixing separate entities into one class (ex. encapsulating",[135,1041,470],{}," and ",[135,1044,1045],{},"UserRole"," into one class)",[80,1048,1049,1050,1042,1052,1046],{},"Mixing separate concerns into one class (ex. encapsulating ",[135,1051,470],{},[135,1053,1054],{},"AuthService",[114,1056,1058],{"id":1057},"openclosed-principle-ocp","Open\u002FClosed Principle (OCP)",[10,1060,1061],{},"People usually stop reading and trying to understand the rest of the SOLID principles after going through SRP because they feel intimidated by the definitions and names of the remaining principles, but don't give up just yet!",[10,1063,1064,1067],{},[39,1065,1066],{},"The OCP requires that a class (other entities as well - functions, modules) should be open for extension but closed for modification."," This principle can be confusing at the beginning because its name is counterintuitive, but once you understand it, it's the principle that will save you the most time in terms of development in the future. Its goal is to get your application to a stable state, a state where the application's core can never be broken.",[10,1069,1070,1071,1074,1075,1078,1079,1082,1083,1086],{},"Imagine we have an ",[14,1072,1073],{},"e-commerce"," application that needs to handle different payment methods. In the beginning, lets say we have a ",[135,1076,1077],{},"Checkout"," class that has a ",[135,1080,1081],{},"process"," method that processes a ",[135,1084,1085],{},"Cart"," using the payment method the user selected.",[128,1088,1090],{"className":130,"code":1089,"language":132,"meta":133,"style":133},"class Payment {\n  creditCard(cart: Cart) {\n    \u002F\u002F handle payment using credit card\n  }\n}\n\nclass Checkout {\n  private cart: Cart;\n\n  process() {\n    new Payment().creditCard(this.cart);\n  }\n}\n",[135,1091,1092,1101,1118,1124,1128,1132,1136,1145,1158,1162,1169,1190,1194],{"__ignoreMap":133},[138,1093,1094,1096,1099],{"class":140,"line":141},[138,1095,172],{"class":144},[138,1097,1098],{"class":175}," Payment",[138,1100,179],{"class":148},[138,1102,1103,1106,1108,1111,1113,1116],{"class":140,"line":162},[138,1104,1105],{"class":175},"  creditCard",[138,1107,242],{"class":148},[138,1109,1110],{"class":188},"cart",[138,1112,208],{"class":144},[138,1114,1115],{"class":175}," Cart",[138,1117,262],{"class":148},[138,1119,1120],{"class":140,"line":169},[138,1121,1123],{"class":1122},"sJ8bj","    \u002F\u002F handle payment using credit card\n",[138,1125,1126],{"class":140,"line":182},[138,1127,296],{"class":148},[138,1129,1130],{"class":140,"line":200},[138,1131,418],{"class":148},[138,1133,1134],{"class":140,"line":217},[138,1135,166],{"emptyLinePlaceholder":165},[138,1137,1138,1140,1143],{"class":140,"line":231},[138,1139,172],{"class":144},[138,1141,1142],{"class":175}," Checkout",[138,1144,179],{"class":148},[138,1146,1147,1149,1152,1154,1156],{"class":140,"line":236},[138,1148,185],{"class":144},[138,1150,1151],{"class":188}," cart",[138,1153,208],{"class":144},[138,1155,1115],{"class":175},[138,1157,159],{"class":148},[138,1159,1160],{"class":140,"line":265},[138,1161,166],{"emptyLinePlaceholder":165},[138,1163,1164,1167],{"class":140,"line":280},[138,1165,1166],{"class":175},"  process",[138,1168,310],{"class":148},[138,1170,1171,1174,1176,1179,1182,1184,1187],{"class":140,"line":293},[138,1172,1173],{"class":144},"    new",[138,1175,1098],{"class":175},[138,1177,1178],{"class":148},"().",[138,1180,1181],{"class":175},"creditCard",[138,1183,242],{"class":148},[138,1185,1186],{"class":211},"this",[138,1188,1189],{"class":148},".cart);\n",[138,1191,1192],{"class":140,"line":299},[138,1193,296],{"class":148},[138,1195,1196],{"class":140,"line":304},[138,1197,418],{"class":148},[10,1199,1200,1201,1204,1205,1208,1209,1211,1212,1214,1215,1218,1219,1222],{},"But, what if we want to add more payment methods - PayPal, Coupons, Bank Transfer, etc. They all have different underlying implementations, so we have to implement separate methods within our ",[135,1202,1203],{},"Payment"," class for each of these payment methods. Now, we have to add ",[135,1206,1207],{},"if"," statements within our ",[135,1210,1081],{}," method within the ",[135,1213,1077],{}," class to handle different cases. So, if we decide to add another payment method, we have to ",[39,1216,1217],{},"modify"," our ****existing implementation to add another ",[135,1220,1221],{},"else if"," statement to handle this case. Considering this principle it means that our code design is bad and we should consider another approach.",[128,1224,1226],{"className":130,"code":1225,"language":132,"meta":133,"style":133},"class Payment {\n  private cart: Cart;\n\n  constructor(cart: Cart) {\n    this.cart = cart;\n  }\n\n  creditCard() {\n    \u002F\u002F handle payment using credit card\n  }\n\n  payPal() {\n    \u002F\u002F handle payment using paypal\n  }\n\n  bankTransfer() {\n    \u002F\u002F handle payment using bank transfer\n  }\n\n  coupon() {\n    \u002F\u002F handle payment using bank transfer\n  }\n}\n\nclass Checkout {\n  private cart: Cart;\n\n  constructor(cart: Cart) {\n    this.cart = cart;\n  }\n\n  process() {\n    const paymentMethod = request().get(\"payment_method\"); \u002F\u002F getting user's selection\n    const payment = new Payment(this.card);\n\n    if (paymentMethod === \"credit-card\") {\n      payment.creditCard();\n    } else if (paymentMethod === \"paypal\") {\n      payment.paypal();\n    } else if (paymentMethod === \"bank-transfer\") {\n      payment.bankTransfer();\n    } else {\n      payment.coupon();\n    }\n  }\n}\n",[135,1227,1228,1236,1248,1252,1266,1278,1282,1286,1292,1296,1300,1304,1311,1316,1320,1324,1331,1336,1340,1344,1351,1355,1359,1363,1367,1375,1387,1391,1405,1415,1419,1423,1429,1457,1477,1481,1497,1506,1526,1535,1552,1561,1569,1578,1583,1587],{"__ignoreMap":133},[138,1229,1230,1232,1234],{"class":140,"line":141},[138,1231,172],{"class":144},[138,1233,1098],{"class":175},[138,1235,179],{"class":148},[138,1237,1238,1240,1242,1244,1246],{"class":140,"line":162},[138,1239,185],{"class":144},[138,1241,1151],{"class":188},[138,1243,208],{"class":144},[138,1245,1115],{"class":175},[138,1247,159],{"class":148},[138,1249,1250],{"class":140,"line":169},[138,1251,166],{"emptyLinePlaceholder":165},[138,1253,1254,1256,1258,1260,1262,1264],{"class":140,"line":182},[138,1255,239],{"class":144},[138,1257,242],{"class":148},[138,1259,1110],{"class":188},[138,1261,208],{"class":144},[138,1263,1115],{"class":175},[138,1265,262],{"class":148},[138,1267,1268,1270,1273,1275],{"class":140,"line":200},[138,1269,268],{"class":211},[138,1271,1272],{"class":148},".cart ",[138,1274,274],{"class":144},[138,1276,1277],{"class":148}," cart;\n",[138,1279,1280],{"class":140,"line":217},[138,1281,296],{"class":148},[138,1283,1284],{"class":140,"line":231},[138,1285,166],{"emptyLinePlaceholder":165},[138,1287,1288,1290],{"class":140,"line":236},[138,1289,1105],{"class":175},[138,1291,310],{"class":148},[138,1293,1294],{"class":140,"line":265},[138,1295,1123],{"class":1122},[138,1297,1298],{"class":140,"line":280},[138,1299,296],{"class":148},[138,1301,1302],{"class":140,"line":293},[138,1303,166],{"emptyLinePlaceholder":165},[138,1305,1306,1309],{"class":140,"line":299},[138,1307,1308],{"class":175},"  payPal",[138,1310,310],{"class":148},[138,1312,1313],{"class":140,"line":304},[138,1314,1315],{"class":1122},"    \u002F\u002F handle payment using paypal\n",[138,1317,1318],{"class":140,"line":313},[138,1319,296],{"class":148},[138,1321,1322],{"class":140,"line":343},[138,1323,166],{"emptyLinePlaceholder":165},[138,1325,1326,1329],{"class":140,"line":363},[138,1327,1328],{"class":175},"  bankTransfer",[138,1330,310],{"class":148},[138,1332,1333],{"class":140,"line":368},[138,1334,1335],{"class":1122},"    \u002F\u002F handle payment using bank transfer\n",[138,1337,1338],{"class":140,"line":380},[138,1339,296],{"class":148},[138,1341,1342],{"class":140,"line":386},[138,1343,166],{"emptyLinePlaceholder":165},[138,1345,1346,1349],{"class":140,"line":392},[138,1347,1348],{"class":175},"  coupon",[138,1350,310],{"class":148},[138,1352,1353],{"class":140,"line":398},[138,1354,1335],{"class":1122},[138,1356,1357],{"class":140,"line":404},[138,1358,296],{"class":148},[138,1360,1361],{"class":140,"line":410},[138,1362,418],{"class":148},[138,1364,1365],{"class":140,"line":415},[138,1366,166],{"emptyLinePlaceholder":165},[138,1368,1369,1371,1373],{"class":140,"line":421},[138,1370,172],{"class":144},[138,1372,1142],{"class":175},[138,1374,179],{"class":148},[138,1376,1377,1379,1381,1383,1385],{"class":140,"line":426},[138,1378,185],{"class":144},[138,1380,1151],{"class":188},[138,1382,208],{"class":144},[138,1384,1115],{"class":175},[138,1386,159],{"class":148},[138,1388,1389],{"class":140,"line":455},[138,1390,166],{"emptyLinePlaceholder":165},[138,1392,1393,1395,1397,1399,1401,1403],{"class":140,"line":716},[138,1394,239],{"class":144},[138,1396,242],{"class":148},[138,1398,1110],{"class":188},[138,1400,208],{"class":144},[138,1402,1115],{"class":175},[138,1404,262],{"class":148},[138,1406,1407,1409,1411,1413],{"class":140,"line":726},[138,1408,268],{"class":211},[138,1410,1272],{"class":148},[138,1412,274],{"class":144},[138,1414,1277],{"class":148},[138,1416,1417],{"class":140,"line":731},[138,1418,296],{"class":148},[138,1420,1421],{"class":140,"line":736},[138,1422,166],{"emptyLinePlaceholder":165},[138,1424,1425,1427],{"class":140,"line":750},[138,1426,1166],{"class":175},[138,1428,310],{"class":148},[138,1430,1431,1433,1436,1438,1441,1443,1446,1448,1451,1454],{"class":140,"line":760},[138,1432,316],{"class":144},[138,1434,1435],{"class":211}," paymentMethod",[138,1437,192],{"class":144},[138,1439,1440],{"class":175}," request",[138,1442,1178],{"class":148},[138,1444,1445],{"class":175},"get",[138,1447,242],{"class":148},[138,1449,1450],{"class":155},"\"payment_method\"",[138,1452,1453],{"class":148},"); ",[138,1455,1456],{"class":1122},"\u002F\u002F getting user's selection\n",[138,1458,1459,1461,1464,1466,1468,1470,1472,1474],{"class":140,"line":765},[138,1460,316],{"class":144},[138,1462,1463],{"class":211}," payment",[138,1465,192],{"class":144},[138,1467,437],{"class":144},[138,1469,1098],{"class":175},[138,1471,242],{"class":148},[138,1473,1186],{"class":211},[138,1475,1476],{"class":148},".card);\n",[138,1478,1479],{"class":140,"line":770},[138,1480,166],{"emptyLinePlaceholder":165},[138,1482,1483,1486,1489,1492,1495],{"class":140,"line":775},[138,1484,1485],{"class":144},"    if",[138,1487,1488],{"class":148}," (paymentMethod ",[138,1490,1491],{"class":144},"===",[138,1493,1494],{"class":155}," \"credit-card\"",[138,1496,262],{"class":148},[138,1498,1499,1502,1504],{"class":140,"line":785},[138,1500,1501],{"class":148},"      payment.",[138,1503,1181],{"class":175},[138,1505,464],{"class":148},[138,1507,1508,1511,1514,1517,1519,1521,1524],{"class":140,"line":799},[138,1509,1510],{"class":148},"    } ",[138,1512,1513],{"class":144},"else",[138,1515,1516],{"class":144}," if",[138,1518,1488],{"class":148},[138,1520,1491],{"class":144},[138,1522,1523],{"class":155}," \"paypal\"",[138,1525,262],{"class":148},[138,1527,1528,1530,1533],{"class":140,"line":804},[138,1529,1501],{"class":148},[138,1531,1532],{"class":175},"paypal",[138,1534,464],{"class":148},[138,1536,1537,1539,1541,1543,1545,1547,1550],{"class":140,"line":811},[138,1538,1510],{"class":148},[138,1540,1513],{"class":144},[138,1542,1516],{"class":144},[138,1544,1488],{"class":148},[138,1546,1491],{"class":144},[138,1548,1549],{"class":155}," \"bank-transfer\"",[138,1551,262],{"class":148},[138,1553,1554,1556,1559],{"class":140,"line":827},[138,1555,1501],{"class":148},[138,1557,1558],{"class":175},"bankTransfer",[138,1560,464],{"class":148},[138,1562,1563,1565,1567],{"class":140,"line":832},[138,1564,1510],{"class":148},[138,1566,1513],{"class":144},[138,1568,179],{"class":148},[138,1570,1571,1573,1576],{"class":140,"line":837},[138,1572,1501],{"class":148},[138,1574,1575],{"class":175},"coupon",[138,1577,464],{"class":148},[138,1579,1580],{"class":140,"line":856},[138,1581,1582],{"class":148},"    }\n",[138,1584,1585],{"class":140,"line":873},[138,1586,296],{"class":148},[138,1588,1589],{"class":140,"line":889},[138,1590,418],{"class":148},[10,1592,1593,1594,1596,1597,1599,1600,1602,1603,1605,1606,1609],{},"What would happen if we need to add another payment method? We would have to change the ",[135,1595,1081],{}," method in the ",[135,1598,1077],{}," class and include another ",[135,1601,1221],{}," statement in the ",[135,1604,1081],{}," method which violates the ",[14,1607,1608],{},"closed for modification"," part of this principle. This calls for a code design change.",[10,1611,1612,1613,1616],{},"To refactor this code and satisfy the requirements of the principle, we can use the ",[39,1614,1615],{},"Factory Pattern",". The Factory pattern is a creational pattern that allows us to create different instances of a class on runtime (more about the Factory Pattern can be found online). This means that we don't have to care about which method is going to be called because a proper class instance will be instantiated on runtime based on the client's selection.",[10,1618,1619,1620,1623,1624,1627,1628,1630],{},"Knowing this, let's refactor the example above to follow the requirements of OCP. We can define an interface and define classes for each of the payments that extend that interface and implement its methods. We will also define a ",[135,1621,1622],{},"PayableFactory"," class that instantiates our desired ",[135,1625,1626],{},"Payable"," instance and we use that in the checkout. That way, the ",[135,1629,1077],{}," class is not going to be modified in case we need to add another payment method and is compliant with the requirements of OCP.",[128,1632,1634],{"className":130,"code":1633,"language":132,"meta":133,"style":133},"interface Payable {\n  pay(cart: Cart);\n}\n\nclass BankTransfer implements Payable {\n  pay(cart: Cart) {\n    \u002F\u002F Handle bank transfer payment\n  }\n}\n\nclass CreditCard implements Payable {\n  pay(cart: Cart) {\n    \u002F\u002F Handle credit card payment\n  }\n}\n\nclass PayPal implements Payable {\n  pay(cart: Cart) {\n    \u002F\u002F Handle PayPal payment\n  }\n}\n\nclass PayableFactory {\n  static make(type: string) {\n    if(paymentMethod === 'credit-card') {\n      return new CreditCard();\n    } else if (paymentMethod === 'paypal') {\n      return new PayPal();\n    } else (paymentMethod === 'bank-transfer') {\n      return new BankTransfer();\n  }\n}\n\nclass Checkout {\n  private cart: Cart;\n\n  constructor(cart: Cart) {\n    this.cart = cart;\n  }\n\n  process() {\n    const paymentMethod = request().get('payment_method') \u002F\u002F getting user's selection\n    const paymentFactory = new PaymentFactory(paymentMethod);\n\n    paymentFactory.pay(cart);\n  }\n}\n",[135,1635,1636,1646,1661,1665,1669,1683,1697,1702,1706,1710,1714,1727,1741,1746,1750,1754,1758,1771,1785,1790,1794,1798,1802,1811,1830,1844,1855,1872,1882,1897,1907,1911,1915,1919,1927,1939,1943,1957,1967,1971,1975,1981,2005,2022,2026,2037,2041],{"__ignoreMap":133},[138,1637,1638,1641,1644],{"class":140,"line":141},[138,1639,1640],{"class":144},"interface",[138,1642,1643],{"class":175}," Payable",[138,1645,179],{"class":148},[138,1647,1648,1651,1653,1655,1657,1659],{"class":140,"line":162},[138,1649,1650],{"class":175},"  pay",[138,1652,242],{"class":148},[138,1654,1110],{"class":188},[138,1656,208],{"class":144},[138,1658,1115],{"class":175},[138,1660,452],{"class":148},[138,1662,1663],{"class":140,"line":169},[138,1664,418],{"class":148},[138,1666,1667],{"class":140,"line":182},[138,1668,166],{"emptyLinePlaceholder":165},[138,1670,1671,1673,1676,1679,1681],{"class":140,"line":200},[138,1672,172],{"class":144},[138,1674,1675],{"class":175}," BankTransfer",[138,1677,1678],{"class":144}," implements",[138,1680,1643],{"class":175},[138,1682,179],{"class":148},[138,1684,1685,1687,1689,1691,1693,1695],{"class":140,"line":217},[138,1686,1650],{"class":175},[138,1688,242],{"class":148},[138,1690,1110],{"class":188},[138,1692,208],{"class":144},[138,1694,1115],{"class":175},[138,1696,262],{"class":148},[138,1698,1699],{"class":140,"line":231},[138,1700,1701],{"class":1122},"    \u002F\u002F Handle bank transfer payment\n",[138,1703,1704],{"class":140,"line":236},[138,1705,296],{"class":148},[138,1707,1708],{"class":140,"line":265},[138,1709,418],{"class":148},[138,1711,1712],{"class":140,"line":280},[138,1713,166],{"emptyLinePlaceholder":165},[138,1715,1716,1718,1721,1723,1725],{"class":140,"line":293},[138,1717,172],{"class":144},[138,1719,1720],{"class":175}," CreditCard",[138,1722,1678],{"class":144},[138,1724,1643],{"class":175},[138,1726,179],{"class":148},[138,1728,1729,1731,1733,1735,1737,1739],{"class":140,"line":299},[138,1730,1650],{"class":175},[138,1732,242],{"class":148},[138,1734,1110],{"class":188},[138,1736,208],{"class":144},[138,1738,1115],{"class":175},[138,1740,262],{"class":148},[138,1742,1743],{"class":140,"line":304},[138,1744,1745],{"class":1122},"    \u002F\u002F Handle credit card payment\n",[138,1747,1748],{"class":140,"line":313},[138,1749,296],{"class":148},[138,1751,1752],{"class":140,"line":343},[138,1753,418],{"class":148},[138,1755,1756],{"class":140,"line":363},[138,1757,166],{"emptyLinePlaceholder":165},[138,1759,1760,1762,1765,1767,1769],{"class":140,"line":368},[138,1761,172],{"class":144},[138,1763,1764],{"class":175}," PayPal",[138,1766,1678],{"class":144},[138,1768,1643],{"class":175},[138,1770,179],{"class":148},[138,1772,1773,1775,1777,1779,1781,1783],{"class":140,"line":380},[138,1774,1650],{"class":175},[138,1776,242],{"class":148},[138,1778,1110],{"class":188},[138,1780,208],{"class":144},[138,1782,1115],{"class":175},[138,1784,262],{"class":148},[138,1786,1787],{"class":140,"line":386},[138,1788,1789],{"class":1122},"    \u002F\u002F Handle PayPal payment\n",[138,1791,1792],{"class":140,"line":392},[138,1793,296],{"class":148},[138,1795,1796],{"class":140,"line":398},[138,1797,418],{"class":148},[138,1799,1800],{"class":140,"line":404},[138,1801,166],{"emptyLinePlaceholder":165},[138,1803,1804,1806,1809],{"class":140,"line":410},[138,1805,172],{"class":144},[138,1807,1808],{"class":175}," PayableFactory",[138,1810,179],{"class":148},[138,1812,1813,1816,1819,1821,1824,1826,1828],{"class":140,"line":415},[138,1814,1815],{"class":144},"  static",[138,1817,1818],{"class":175}," make",[138,1820,242],{"class":148},[138,1822,1823],{"class":188},"type",[138,1825,208],{"class":144},[138,1827,212],{"class":211},[138,1829,262],{"class":148},[138,1831,1832,1834,1837,1839,1842],{"class":140,"line":421},[138,1833,1485],{"class":144},[138,1835,1836],{"class":148},"(paymentMethod ",[138,1838,1491],{"class":144},[138,1840,1841],{"class":155}," 'credit-card'",[138,1843,262],{"class":148},[138,1845,1846,1849,1851,1853],{"class":140,"line":426},[138,1847,1848],{"class":144},"      return",[138,1850,437],{"class":144},[138,1852,1720],{"class":175},[138,1854,464],{"class":148},[138,1856,1857,1859,1861,1863,1865,1867,1870],{"class":140,"line":455},[138,1858,1510],{"class":148},[138,1860,1513],{"class":144},[138,1862,1516],{"class":144},[138,1864,1488],{"class":148},[138,1866,1491],{"class":144},[138,1868,1869],{"class":155}," 'paypal'",[138,1871,262],{"class":148},[138,1873,1874,1876,1878,1880],{"class":140,"line":716},[138,1875,1848],{"class":144},[138,1877,437],{"class":144},[138,1879,1764],{"class":175},[138,1881,464],{"class":148},[138,1883,1884,1886,1888,1890,1892,1895],{"class":140,"line":726},[138,1885,1510],{"class":148},[138,1887,1513],{"class":144},[138,1889,1488],{"class":148},[138,1891,1491],{"class":144},[138,1893,1894],{"class":155}," 'bank-transfer'",[138,1896,262],{"class":148},[138,1898,1899,1901,1903,1905],{"class":140,"line":731},[138,1900,1848],{"class":144},[138,1902,437],{"class":144},[138,1904,1675],{"class":175},[138,1906,464],{"class":148},[138,1908,1909],{"class":140,"line":736},[138,1910,296],{"class":148},[138,1912,1913],{"class":140,"line":750},[138,1914,418],{"class":148},[138,1916,1917],{"class":140,"line":760},[138,1918,166],{"emptyLinePlaceholder":165},[138,1920,1921,1923,1925],{"class":140,"line":765},[138,1922,172],{"class":144},[138,1924,1142],{"class":175},[138,1926,179],{"class":148},[138,1928,1929,1931,1933,1935,1937],{"class":140,"line":770},[138,1930,185],{"class":144},[138,1932,1151],{"class":188},[138,1934,208],{"class":144},[138,1936,1115],{"class":175},[138,1938,159],{"class":148},[138,1940,1941],{"class":140,"line":775},[138,1942,166],{"emptyLinePlaceholder":165},[138,1944,1945,1947,1949,1951,1953,1955],{"class":140,"line":785},[138,1946,239],{"class":144},[138,1948,242],{"class":148},[138,1950,1110],{"class":188},[138,1952,208],{"class":144},[138,1954,1115],{"class":175},[138,1956,262],{"class":148},[138,1958,1959,1961,1963,1965],{"class":140,"line":799},[138,1960,268],{"class":211},[138,1962,1272],{"class":148},[138,1964,274],{"class":144},[138,1966,1277],{"class":148},[138,1968,1969],{"class":140,"line":804},[138,1970,296],{"class":148},[138,1972,1973],{"class":140,"line":811},[138,1974,166],{"emptyLinePlaceholder":165},[138,1976,1977,1979],{"class":140,"line":827},[138,1978,1166],{"class":175},[138,1980,310],{"class":148},[138,1982,1983,1985,1987,1989,1991,1993,1995,1997,2000,2003],{"class":140,"line":832},[138,1984,316],{"class":144},[138,1986,1435],{"class":211},[138,1988,192],{"class":144},[138,1990,1440],{"class":175},[138,1992,1178],{"class":148},[138,1994,1445],{"class":175},[138,1996,242],{"class":148},[138,1998,1999],{"class":155},"'payment_method'",[138,2001,2002],{"class":148},") ",[138,2004,1456],{"class":1122},[138,2006,2007,2009,2012,2014,2016,2019],{"class":140,"line":837},[138,2008,316],{"class":144},[138,2010,2011],{"class":211}," paymentFactory",[138,2013,192],{"class":144},[138,2015,437],{"class":144},[138,2017,2018],{"class":175}," PaymentFactory",[138,2020,2021],{"class":148},"(paymentMethod);\n",[138,2023,2024],{"class":140,"line":856},[138,2025,166],{"emptyLinePlaceholder":165},[138,2027,2028,2031,2034],{"class":140,"line":873},[138,2029,2030],{"class":148},"    paymentFactory.",[138,2032,2033],{"class":175},"pay",[138,2035,2036],{"class":148},"(cart);\n",[138,2038,2039],{"class":140,"line":889},[138,2040,296],{"class":148},[138,2042,2043],{"class":140,"line":906},[138,2044,418],{"class":148},[10,2046,2047],{},[39,2048,2049],{},"How to notice code that needs to be refactored using OCP",[1032,2051,2052,2063,2066],{},[80,2053,2054,2055,2057,2058,2057,2060,2062],{},"Conditional Code - a lot of ",[135,2056,1207],{}," ",[135,2059,1221],{},[135,2061,1513],{}," statements,",[80,2064,2065],{},"Multiple unit tests due to multiple execution paths,",[80,2067,2068],{},"Violation of the Single Responsibility Principle,",[114,2070,2072],{"id":2071},"liskov-substitution-principle","Liskov Substitution Principle",[10,2074,2075,2078,2079,2082,2083,2088],{},[39,2076,2077],{},"LSP states that"," r",[39,2080,2081],{},"eplacing an instance of a class with its child class should not produce any negative side effects."," This rule, introduced by ",[64,2084,2087],{"href":2085,"rel":2086},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBarbara_Liskov",[68],"Barbara Liskov",", ensures us that changing one part of our system does not break other parts. To make this principle less confusing, we will break it down into multiple parts.",[10,2090,2091],{},"The first thing we notice for LSP is that its main focus is class inheritance. Let’s implement a straightforward and vivid example of how we can break the above principle (this time using a meme as a starting point).",[10,2093,2094],{},[2095,2096],"img",{"alt":2072,"src":2097},"\u002Fimages\u002Fposts\u002Fduck-liskov.jpg",[10,2099,2100],{},"Let's translate the meme into valid OOP code.",[128,2102,2104],{"className":130,"code":2103,"language":132,"meta":133,"style":133},"abstract class Duck {\n  quack(): string {\n    return 'The duck is quacking';\n  },\n\n  fly(): string {\n    return 'The duck is flying';\n  },\n\n  swim(): string {\n    return 'The duck is swimming';\n  }\n}\n\nclass RubberDuck extends Duck {\n  quack(): string {\n    person = new Person();\n\n    if(!person.squeezesDuck(this)) {\n      throw new Error('The rubber duck cannot swim on its own');\n    }\n\n    return 'The duck is quacking';\n  }\n\n  fly() {\n    throw new Error('The rubber duck cannot fly');\n  }\n\n  swim(): string {\n    person = new Person();\n\n    if(!person.throwDuckInBath(this)) {\n      throw new Error('The rubber duck cannot swim on its own');\n    }\n\n    return 'The duck is swimming';\n  }\n}\n",[135,2105,2106,2119,2132,2141,2146,2150,2163,2172,2176,2180,2193,2202,2206,2210,2214,2228,2240,2254,2258,2280,2297,2301,2305,2313,2317,2321,2327,2343,2347,2351,2363,2375,2379,2398,2412,2416,2420,2428,2432],{"__ignoreMap":133},[138,2107,2108,2111,2114,2117],{"class":140,"line":141},[138,2109,2110],{"class":144},"abstract",[138,2112,2113],{"class":144}," class",[138,2115,2116],{"class":175}," Duck",[138,2118,179],{"class":148},[138,2120,2121,2124,2126,2128,2130],{"class":140,"line":162},[138,2122,2123],{"class":175},"  quack",[138,2125,707],{"class":148},[138,2127,208],{"class":144},[138,2129,212],{"class":211},[138,2131,179],{"class":148},[138,2133,2134,2136,2139],{"class":140,"line":169},[138,2135,371],{"class":144},[138,2137,2138],{"class":155}," 'The duck is quacking'",[138,2140,159],{"class":148},[138,2142,2143],{"class":140,"line":182},[138,2144,2145],{"class":148},"  },\n",[138,2147,2148],{"class":140,"line":200},[138,2149,166],{"emptyLinePlaceholder":165},[138,2151,2152,2155,2157,2159,2161],{"class":140,"line":217},[138,2153,2154],{"class":175},"  fly",[138,2156,707],{"class":148},[138,2158,208],{"class":144},[138,2160,212],{"class":211},[138,2162,179],{"class":148},[138,2164,2165,2167,2170],{"class":140,"line":231},[138,2166,371],{"class":144},[138,2168,2169],{"class":155}," 'The duck is flying'",[138,2171,159],{"class":148},[138,2173,2174],{"class":140,"line":236},[138,2175,2145],{"class":148},[138,2177,2178],{"class":140,"line":265},[138,2179,166],{"emptyLinePlaceholder":165},[138,2181,2182,2185,2187,2189,2191],{"class":140,"line":280},[138,2183,2184],{"class":175},"  swim",[138,2186,707],{"class":148},[138,2188,208],{"class":144},[138,2190,212],{"class":211},[138,2192,179],{"class":148},[138,2194,2195,2197,2200],{"class":140,"line":293},[138,2196,371],{"class":144},[138,2198,2199],{"class":155}," 'The duck is swimming'",[138,2201,159],{"class":148},[138,2203,2204],{"class":140,"line":299},[138,2205,296],{"class":148},[138,2207,2208],{"class":140,"line":304},[138,2209,418],{"class":148},[138,2211,2212],{"class":140,"line":313},[138,2213,166],{"emptyLinePlaceholder":165},[138,2215,2216,2218,2221,2224,2226],{"class":140,"line":343},[138,2217,172],{"class":144},[138,2219,2220],{"class":175}," RubberDuck",[138,2222,2223],{"class":144}," extends",[138,2225,2116],{"class":175},[138,2227,179],{"class":148},[138,2229,2230,2232,2234,2236,2238],{"class":140,"line":363},[138,2231,2123],{"class":175},[138,2233,707],{"class":148},[138,2235,208],{"class":144},[138,2237,212],{"class":211},[138,2239,179],{"class":148},[138,2241,2242,2245,2247,2249,2252],{"class":140,"line":368},[138,2243,2244],{"class":148},"    person ",[138,2246,274],{"class":144},[138,2248,437],{"class":144},[138,2250,2251],{"class":175}," Person",[138,2253,464],{"class":148},[138,2255,2256],{"class":140,"line":380},[138,2257,166],{"emptyLinePlaceholder":165},[138,2259,2260,2262,2264,2267,2270,2273,2275,2277],{"class":140,"line":386},[138,2261,1485],{"class":144},[138,2263,242],{"class":148},[138,2265,2266],{"class":144},"!",[138,2268,2269],{"class":148},"person.",[138,2271,2272],{"class":175},"squeezesDuck",[138,2274,242],{"class":148},[138,2276,1186],{"class":211},[138,2278,2279],{"class":148},")) {\n",[138,2281,2282,2285,2287,2290,2292,2295],{"class":140,"line":392},[138,2283,2284],{"class":144},"      throw",[138,2286,437],{"class":144},[138,2288,2289],{"class":175}," Error",[138,2291,242],{"class":148},[138,2293,2294],{"class":155},"'The rubber duck cannot swim on its own'",[138,2296,452],{"class":148},[138,2298,2299],{"class":140,"line":398},[138,2300,1582],{"class":148},[138,2302,2303],{"class":140,"line":404},[138,2304,166],{"emptyLinePlaceholder":165},[138,2306,2307,2309,2311],{"class":140,"line":410},[138,2308,371],{"class":144},[138,2310,2138],{"class":155},[138,2312,159],{"class":148},[138,2314,2315],{"class":140,"line":415},[138,2316,296],{"class":148},[138,2318,2319],{"class":140,"line":421},[138,2320,166],{"emptyLinePlaceholder":165},[138,2322,2323,2325],{"class":140,"line":426},[138,2324,2154],{"class":175},[138,2326,310],{"class":148},[138,2328,2329,2332,2334,2336,2338,2341],{"class":140,"line":455},[138,2330,2331],{"class":144},"    throw",[138,2333,437],{"class":144},[138,2335,2289],{"class":175},[138,2337,242],{"class":148},[138,2339,2340],{"class":155},"'The rubber duck cannot fly'",[138,2342,452],{"class":148},[138,2344,2345],{"class":140,"line":716},[138,2346,296],{"class":148},[138,2348,2349],{"class":140,"line":726},[138,2350,166],{"emptyLinePlaceholder":165},[138,2352,2353,2355,2357,2359,2361],{"class":140,"line":731},[138,2354,2184],{"class":175},[138,2356,707],{"class":148},[138,2358,208],{"class":144},[138,2360,212],{"class":211},[138,2362,179],{"class":148},[138,2364,2365,2367,2369,2371,2373],{"class":140,"line":736},[138,2366,2244],{"class":148},[138,2368,274],{"class":144},[138,2370,437],{"class":144},[138,2372,2251],{"class":175},[138,2374,464],{"class":148},[138,2376,2377],{"class":140,"line":750},[138,2378,166],{"emptyLinePlaceholder":165},[138,2380,2381,2383,2385,2387,2389,2392,2394,2396],{"class":140,"line":760},[138,2382,1485],{"class":144},[138,2384,242],{"class":148},[138,2386,2266],{"class":144},[138,2388,2269],{"class":148},[138,2390,2391],{"class":175},"throwDuckInBath",[138,2393,242],{"class":148},[138,2395,1186],{"class":211},[138,2397,2279],{"class":148},[138,2399,2400,2402,2404,2406,2408,2410],{"class":140,"line":765},[138,2401,2284],{"class":144},[138,2403,437],{"class":144},[138,2405,2289],{"class":175},[138,2407,242],{"class":148},[138,2409,2294],{"class":155},[138,2411,452],{"class":148},[138,2413,2414],{"class":140,"line":770},[138,2415,1582],{"class":148},[138,2417,2418],{"class":140,"line":775},[138,2419,166],{"emptyLinePlaceholder":165},[138,2421,2422,2424,2426],{"class":140,"line":785},[138,2423,371],{"class":144},[138,2425,2199],{"class":155},[138,2427,159],{"class":148},[138,2429,2430],{"class":140,"line":799},[138,2431,296],{"class":148},[138,2433,2434],{"class":140,"line":804},[138,2435,418],{"class":148},[10,2437,2438,2439,2442,2443,2446,2447,1211,2450,2452,2453,2455,2456,2458],{},"Notice how we are changing every method of the ",[135,2440,2441],{},"abstract class Duck"," in our concrete class ",[135,2444,2445],{},"RubberDuck",". This is the first clue that we are violating LSP. The second clue is the ",[135,2448,2449],{},"fly",[135,2451,2445],{}," class. It just throws an Error. This means that if we have an instance of the ",[135,2454,2445],{}," somewhere within our app and we want to call the ",[135,2457,2449],{}," method on that instance our app will fail every time, which is a signal of a bad code design.",[10,2460,2461],{},"The way we can resolve this bad code design and follow LSP is coding by contract instead of extending an abstract class. This means that our class will implement only the contracts needed for its implementation.",[128,2463,2465],{"className":130,"code":2464,"language":132,"meta":133,"style":133},"interface QuackableInterface {\n  swim(): string;\n}\n\ninterface FlyableInterface {\n  fly(): string;\n}\n\ninterface SwimmableInterface {\n  swim(): string;\n}\n\nclass RubberDuck implements QuackableInterface, SwimmableInterface {\n  quack(): string {\n    person = new Person();\n\n    if (!person.squeezesDuck(this)) {\n      throw new Error(\"The rubber duck cannot swim on its own\");\n    }\n\n    return \"The duck is quacking\";\n  }\n\n  swim(): string {\n    person = new Person();\n\n    if (!person.throwDuckInBath(this)) {\n      throw new Error(\"The rubber duck cannot swim on its own\");\n    }\n\n    return \"The duck is swimming\";\n  }\n}\n",[135,2466,2467,2476,2488,2492,2496,2505,2517,2521,2525,2534,2546,2550,2554,2571,2583,2595,2599,2618,2633,2637,2641,2650,2654,2658,2670,2682,2686,2704,2718,2722,2726,2735,2739],{"__ignoreMap":133},[138,2468,2469,2471,2474],{"class":140,"line":141},[138,2470,1640],{"class":144},[138,2472,2473],{"class":175}," QuackableInterface",[138,2475,179],{"class":148},[138,2477,2478,2480,2482,2484,2486],{"class":140,"line":162},[138,2479,2184],{"class":175},[138,2481,707],{"class":148},[138,2483,208],{"class":144},[138,2485,212],{"class":211},[138,2487,159],{"class":148},[138,2489,2490],{"class":140,"line":169},[138,2491,418],{"class":148},[138,2493,2494],{"class":140,"line":182},[138,2495,166],{"emptyLinePlaceholder":165},[138,2497,2498,2500,2503],{"class":140,"line":200},[138,2499,1640],{"class":144},[138,2501,2502],{"class":175}," FlyableInterface",[138,2504,179],{"class":148},[138,2506,2507,2509,2511,2513,2515],{"class":140,"line":217},[138,2508,2154],{"class":175},[138,2510,707],{"class":148},[138,2512,208],{"class":144},[138,2514,212],{"class":211},[138,2516,159],{"class":148},[138,2518,2519],{"class":140,"line":231},[138,2520,418],{"class":148},[138,2522,2523],{"class":140,"line":236},[138,2524,166],{"emptyLinePlaceholder":165},[138,2526,2527,2529,2532],{"class":140,"line":265},[138,2528,1640],{"class":144},[138,2530,2531],{"class":175}," SwimmableInterface",[138,2533,179],{"class":148},[138,2535,2536,2538,2540,2542,2544],{"class":140,"line":280},[138,2537,2184],{"class":175},[138,2539,707],{"class":148},[138,2541,208],{"class":144},[138,2543,212],{"class":211},[138,2545,159],{"class":148},[138,2547,2548],{"class":140,"line":293},[138,2549,418],{"class":148},[138,2551,2552],{"class":140,"line":299},[138,2553,166],{"emptyLinePlaceholder":165},[138,2555,2556,2558,2560,2562,2564,2566,2569],{"class":140,"line":304},[138,2557,172],{"class":144},[138,2559,2220],{"class":175},[138,2561,1678],{"class":144},[138,2563,2473],{"class":175},[138,2565,252],{"class":148},[138,2567,2568],{"class":175},"SwimmableInterface",[138,2570,179],{"class":148},[138,2572,2573,2575,2577,2579,2581],{"class":140,"line":313},[138,2574,2123],{"class":175},[138,2576,707],{"class":148},[138,2578,208],{"class":144},[138,2580,212],{"class":211},[138,2582,179],{"class":148},[138,2584,2585,2587,2589,2591,2593],{"class":140,"line":343},[138,2586,2244],{"class":148},[138,2588,274],{"class":144},[138,2590,437],{"class":144},[138,2592,2251],{"class":175},[138,2594,464],{"class":148},[138,2596,2597],{"class":140,"line":363},[138,2598,166],{"emptyLinePlaceholder":165},[138,2600,2601,2603,2606,2608,2610,2612,2614,2616],{"class":140,"line":368},[138,2602,1485],{"class":144},[138,2604,2605],{"class":148}," (",[138,2607,2266],{"class":144},[138,2609,2269],{"class":148},[138,2611,2272],{"class":175},[138,2613,242],{"class":148},[138,2615,1186],{"class":211},[138,2617,2279],{"class":148},[138,2619,2620,2622,2624,2626,2628,2631],{"class":140,"line":380},[138,2621,2284],{"class":144},[138,2623,437],{"class":144},[138,2625,2289],{"class":175},[138,2627,242],{"class":148},[138,2629,2630],{"class":155},"\"The rubber duck cannot swim on its own\"",[138,2632,452],{"class":148},[138,2634,2635],{"class":140,"line":386},[138,2636,1582],{"class":148},[138,2638,2639],{"class":140,"line":392},[138,2640,166],{"emptyLinePlaceholder":165},[138,2642,2643,2645,2648],{"class":140,"line":398},[138,2644,371],{"class":144},[138,2646,2647],{"class":155}," \"The duck is quacking\"",[138,2649,159],{"class":148},[138,2651,2652],{"class":140,"line":404},[138,2653,296],{"class":148},[138,2655,2656],{"class":140,"line":410},[138,2657,166],{"emptyLinePlaceholder":165},[138,2659,2660,2662,2664,2666,2668],{"class":140,"line":415},[138,2661,2184],{"class":175},[138,2663,707],{"class":148},[138,2665,208],{"class":144},[138,2667,212],{"class":211},[138,2669,179],{"class":148},[138,2671,2672,2674,2676,2678,2680],{"class":140,"line":421},[138,2673,2244],{"class":148},[138,2675,274],{"class":144},[138,2677,437],{"class":144},[138,2679,2251],{"class":175},[138,2681,464],{"class":148},[138,2683,2684],{"class":140,"line":426},[138,2685,166],{"emptyLinePlaceholder":165},[138,2687,2688,2690,2692,2694,2696,2698,2700,2702],{"class":140,"line":455},[138,2689,1485],{"class":144},[138,2691,2605],{"class":148},[138,2693,2266],{"class":144},[138,2695,2269],{"class":148},[138,2697,2391],{"class":175},[138,2699,242],{"class":148},[138,2701,1186],{"class":211},[138,2703,2279],{"class":148},[138,2705,2706,2708,2710,2712,2714,2716],{"class":140,"line":716},[138,2707,2284],{"class":144},[138,2709,437],{"class":144},[138,2711,2289],{"class":175},[138,2713,242],{"class":148},[138,2715,2630],{"class":155},[138,2717,452],{"class":148},[138,2719,2720],{"class":140,"line":726},[138,2721,1582],{"class":148},[138,2723,2724],{"class":140,"line":731},[138,2725,166],{"emptyLinePlaceholder":165},[138,2727,2728,2730,2733],{"class":140,"line":736},[138,2729,371],{"class":144},[138,2731,2732],{"class":155}," \"The duck is swimming\"",[138,2734,159],{"class":148},[138,2736,2737],{"class":140,"line":750},[138,2738,296],{"class":148},[138,2740,2741],{"class":140,"line":760},[138,2742,418],{"class":148},[114,2744,2746],{"id":2745},"interface-segregation-principle","Interface Segregation Principle",[10,2748,2749,2750,2753],{},"It is quite common to find that an interface is in essence just a description of an entire class. ISP states that ",[39,2751,2752],{},"we should write a series of smaller and more specific interfaces"," that are implemented by the class. Each interface provides a single behavior. It's also important to mention that an instance (or a method) should never be dependent on methods it doesn't use.",[10,2755,2756],{},"Let's see through an example of what does this means.",[128,2758,2760],{"className":130,"code":2759,"language":132,"meta":133,"style":133},"class Subscriber {\n  subscribe() {\n    \u002F\u002F\n  }\n\n  unsubscribe() {\n    \u002F\u002F\n  }\n\n  getNotifyEmail() {\n    \u002F\u002F\n  }\n}\n\nclass Notification {\n  send(subscriber: Subscriber, message: string) {\n    \u002F\u002F imagine we already have some EmailClient service\n    const emailClient = new EmailClient();\n\n    emailClient.send(subscriber.getNotifyEmail(), message);\n  }\n}\n",[135,2761,2762,2771,2778,2783,2787,2791,2798,2802,2806,2810,2817,2821,2825,2829,2833,2842,2867,2872,2887,2891,2907,2911],{"__ignoreMap":133},[138,2763,2764,2766,2769],{"class":140,"line":141},[138,2765,172],{"class":144},[138,2767,2768],{"class":175}," Subscriber",[138,2770,179],{"class":148},[138,2772,2773,2776],{"class":140,"line":162},[138,2774,2775],{"class":175},"  subscribe",[138,2777,310],{"class":148},[138,2779,2780],{"class":140,"line":169},[138,2781,2782],{"class":1122},"    \u002F\u002F\n",[138,2784,2785],{"class":140,"line":182},[138,2786,296],{"class":148},[138,2788,2789],{"class":140,"line":200},[138,2790,166],{"emptyLinePlaceholder":165},[138,2792,2793,2796],{"class":140,"line":217},[138,2794,2795],{"class":175},"  unsubscribe",[138,2797,310],{"class":148},[138,2799,2800],{"class":140,"line":231},[138,2801,2782],{"class":1122},[138,2803,2804],{"class":140,"line":236},[138,2805,296],{"class":148},[138,2807,2808],{"class":140,"line":265},[138,2809,166],{"emptyLinePlaceholder":165},[138,2811,2812,2815],{"class":140,"line":280},[138,2813,2814],{"class":175},"  getNotifyEmail",[138,2816,310],{"class":148},[138,2818,2819],{"class":140,"line":293},[138,2820,2782],{"class":1122},[138,2822,2823],{"class":140,"line":299},[138,2824,296],{"class":148},[138,2826,2827],{"class":140,"line":304},[138,2828,418],{"class":148},[138,2830,2831],{"class":140,"line":313},[138,2832,166],{"emptyLinePlaceholder":165},[138,2834,2835,2837,2840],{"class":140,"line":343},[138,2836,172],{"class":144},[138,2838,2839],{"class":175}," Notification",[138,2841,179],{"class":148},[138,2843,2844,2847,2849,2852,2854,2856,2858,2861,2863,2865],{"class":140,"line":363},[138,2845,2846],{"class":175},"  send",[138,2848,242],{"class":148},[138,2850,2851],{"class":188},"subscriber",[138,2853,208],{"class":144},[138,2855,2768],{"class":175},[138,2857,252],{"class":148},[138,2859,2860],{"class":188},"message",[138,2862,208],{"class":144},[138,2864,212],{"class":211},[138,2866,262],{"class":148},[138,2868,2869],{"class":140,"line":368},[138,2870,2871],{"class":1122},"    \u002F\u002F imagine we already have some EmailClient service\n",[138,2873,2874,2876,2879,2881,2883,2885],{"class":140,"line":380},[138,2875,316],{"class":144},[138,2877,2878],{"class":211}," emailClient",[138,2880,192],{"class":144},[138,2882,437],{"class":144},[138,2884,502],{"class":175},[138,2886,464],{"class":148},[138,2888,2889],{"class":140,"line":386},[138,2890,166],{"emptyLinePlaceholder":165},[138,2892,2893,2896,2898,2901,2904],{"class":140,"line":392},[138,2894,2895],{"class":148},"    emailClient.",[138,2897,921],{"class":175},[138,2899,2900],{"class":148},"(subscriber.",[138,2902,2903],{"class":175},"getNotifyEmail",[138,2905,2906],{"class":148},"(), message);\n",[138,2908,2909],{"class":140,"line":398},[138,2910,296],{"class":148},[138,2912,2913],{"class":140,"line":404},[138,2914,418],{"class":148},[10,2916,2917,2918,2920,2921,2924,2925,2928,2929,2931,2932,2934],{},"Notice here that if the implementation of the ",[135,2919,2903],{}," in the ",[135,2922,2923],{},"Subscriber"," class changes, our ",[135,2926,2927],{},"Notification"," class will need to change as well even though they are not dependant on each other. To comply with the ISP, we can create an interface that implements the ",[135,2930,2903],{}," and have the ",[135,2933,2923],{}," class implement that interface:",[128,2936,2938],{"className":130,"code":2937,"language":132,"meta":133,"style":133},"interface NotifiableInterface {\n  getNotifyEmail(): string;\n}\n\nclass Subscriber implements NotifiableInterface {\n  subscribe() {\n    \u002F\u002F\n  }\n\n  unsubscribe() {\n    \u002F\u002F\n  }\n\n  getNotifyEmail() {\n    \u002F\u002F\n  }\n}\n\nclass Notification {\n  send(subscriber: NotifiableInterface, message: string) {\n    \u002F\u002F imagine we already have some EmailClient service\n    const emailClient = new EmailClient();\n\n    emailClient.send(subscriber.getNotifyEmail(), message);\n  }\n}\n",[135,2939,2940,2949,2961,2965,2969,2981,2987,2991,2995,2999,3005,3009,3013,3017,3023,3027,3031,3035,3039,3047,3069,3073,3087,3091,3103,3107],{"__ignoreMap":133},[138,2941,2942,2944,2947],{"class":140,"line":141},[138,2943,1640],{"class":144},[138,2945,2946],{"class":175}," NotifiableInterface",[138,2948,179],{"class":148},[138,2950,2951,2953,2955,2957,2959],{"class":140,"line":162},[138,2952,2814],{"class":175},[138,2954,707],{"class":148},[138,2956,208],{"class":144},[138,2958,212],{"class":211},[138,2960,159],{"class":148},[138,2962,2963],{"class":140,"line":169},[138,2964,418],{"class":148},[138,2966,2967],{"class":140,"line":182},[138,2968,166],{"emptyLinePlaceholder":165},[138,2970,2971,2973,2975,2977,2979],{"class":140,"line":200},[138,2972,172],{"class":144},[138,2974,2768],{"class":175},[138,2976,1678],{"class":144},[138,2978,2946],{"class":175},[138,2980,179],{"class":148},[138,2982,2983,2985],{"class":140,"line":217},[138,2984,2775],{"class":175},[138,2986,310],{"class":148},[138,2988,2989],{"class":140,"line":231},[138,2990,2782],{"class":1122},[138,2992,2993],{"class":140,"line":236},[138,2994,296],{"class":148},[138,2996,2997],{"class":140,"line":265},[138,2998,166],{"emptyLinePlaceholder":165},[138,3000,3001,3003],{"class":140,"line":280},[138,3002,2795],{"class":175},[138,3004,310],{"class":148},[138,3006,3007],{"class":140,"line":293},[138,3008,2782],{"class":1122},[138,3010,3011],{"class":140,"line":299},[138,3012,296],{"class":148},[138,3014,3015],{"class":140,"line":304},[138,3016,166],{"emptyLinePlaceholder":165},[138,3018,3019,3021],{"class":140,"line":313},[138,3020,2814],{"class":175},[138,3022,310],{"class":148},[138,3024,3025],{"class":140,"line":343},[138,3026,2782],{"class":1122},[138,3028,3029],{"class":140,"line":363},[138,3030,296],{"class":148},[138,3032,3033],{"class":140,"line":368},[138,3034,418],{"class":148},[138,3036,3037],{"class":140,"line":380},[138,3038,166],{"emptyLinePlaceholder":165},[138,3040,3041,3043,3045],{"class":140,"line":386},[138,3042,172],{"class":144},[138,3044,2839],{"class":175},[138,3046,179],{"class":148},[138,3048,3049,3051,3053,3055,3057,3059,3061,3063,3065,3067],{"class":140,"line":392},[138,3050,2846],{"class":175},[138,3052,242],{"class":148},[138,3054,2851],{"class":188},[138,3056,208],{"class":144},[138,3058,2946],{"class":175},[138,3060,252],{"class":148},[138,3062,2860],{"class":188},[138,3064,208],{"class":144},[138,3066,212],{"class":211},[138,3068,262],{"class":148},[138,3070,3071],{"class":140,"line":398},[138,3072,2871],{"class":1122},[138,3074,3075,3077,3079,3081,3083,3085],{"class":140,"line":404},[138,3076,316],{"class":144},[138,3078,2878],{"class":211},[138,3080,192],{"class":144},[138,3082,437],{"class":144},[138,3084,502],{"class":175},[138,3086,464],{"class":148},[138,3088,3089],{"class":140,"line":410},[138,3090,166],{"emptyLinePlaceholder":165},[138,3092,3093,3095,3097,3099,3101],{"class":140,"line":415},[138,3094,2895],{"class":148},[138,3096,921],{"class":175},[138,3098,2900],{"class":148},[138,3100,2903],{"class":175},[138,3102,2906],{"class":148},[138,3104,3105],{"class":140,"line":421},[138,3106,296],{"class":148},[138,3108,3109],{"class":140,"line":426},[138,3110,418],{"class":148},[10,3112,3113,3114,1211,3116,3118,3119,3121,3122,2920,3124,3127],{},"Now, our ",[135,3115,921],{},[135,3117,2927],{}," class doesn't depend on the whole ",[135,3120,2923],{}," method and only depends on the particular method ",[135,3123,2903],{},[135,3125,3126],{},"NotifiableInterface"," interface.",[114,3129,3131],{"id":3130},"dependency-inversion-principle","Dependency Inversion Principle",[10,3133,3134,3135,3138],{},"This is the last one, I promise. The core of DIP is that ",[39,3136,3137],{},"high-level modules should not depend on the low-level modules. Instead, both of them should depend on abstractions."," This definition is way too abstract and technical, so let's break it down with examples and simplified explanations.",[10,3140,3141],{},"Let's see a real-life example of DIP. Let's say you want to charge your laptop. You can do that using your power supply adapter by plugging it into the wall socket. We don't dig a hole in the wall to find the wirings and plug the adapter directly into our power supply grid.",[10,3143,3144],{},"To translate the metaphor above coding-wise, our interface is the socket, and it provides us with the means (functions\u002Fclasses\u002Fmodules) to achieve the desired outcome. This means that we don't depend on a concrete implementation but we depend on abstractions. The most common example to take that implement DIP are database engines. You don't care what happens under the hood, what you care about is that the abstraction provided you enough functions to read and manipulate your data.",[10,3146,3147],{},"Other benefits that this principle offers:",[1032,3149,3150,3153],{},[80,3151,3152],{},"Easy testing and clear boundaries of dependencies.",[80,3154,3155],{},"Low coupling, allowing for varying implementations or business requirements changing but the contract between modules remains the same.",[10,3157,3158,3159,3162,3163,3166],{},"Let's see this principle through an example. Let's build a ",[135,3160,3161],{},"SignupService"," that uses an ",[135,3164,3165],{},"HttpClient"," as a data source.",[128,3168,3170],{"className":130,"code":3169,"language":132,"meta":133,"style":133},"\u002F\u002F classes\u002FHttpClient.ts\nimport axios from \"axios\";\n\nexport default {\n  createUser: async (user: User) => {\n    return axios.post(\u002F* ... *\u002F);\n  },\n\n  getUserByEmail: async (email: string) => {\n    return axios.get(\u002F* ... *\u002F);\n  },\n};\n\n\u002F\u002F services\u002FSignupService.ts\nimport HttpClient from \"classes\u002FHttpClient\"; \u002F\u002F ❌ the domain depends on a concretion\n\nexport async function signup(email: string, password: string) {\n  const existingUser = await HttpClient.getUserByEmail(email);\n\n  if (existingUser) {\n    throw new Error(\"Email already used\");\n  }\n\n  return HttpClient.createUser({ email, password });\n}\n",[135,3171,3172,3177,3189,3193,3203,3229,3246,3250,3254,3277,3291,3295,3300,3304,3309,3327,3331,3363,3385,3389,3397,3412,3416,3420,3433],{"__ignoreMap":133},[138,3173,3174],{"class":140,"line":141},[138,3175,3176],{"class":1122},"\u002F\u002F classes\u002FHttpClient.ts\n",[138,3178,3179,3181,3183,3185,3187],{"class":140,"line":162},[138,3180,145],{"class":144},[138,3182,149],{"class":148},[138,3184,152],{"class":144},[138,3186,156],{"class":155},[138,3188,159],{"class":148},[138,3190,3191],{"class":140,"line":169},[138,3192,166],{"emptyLinePlaceholder":165},[138,3194,3195,3198,3201],{"class":140,"line":182},[138,3196,3197],{"class":144},"export",[138,3199,3200],{"class":144}," default",[138,3202,179],{"class":148},[138,3204,3205,3208,3211,3214,3216,3218,3220,3222,3224,3227],{"class":140,"line":200},[138,3206,3207],{"class":175},"  createUser",[138,3209,3210],{"class":148},": ",[138,3212,3213],{"class":144},"async",[138,3215,2605],{"class":148},[138,3217,847],{"class":188},[138,3219,208],{"class":144},[138,3221,176],{"class":175},[138,3223,2002],{"class":148},[138,3225,3226],{"class":144},"=>",[138,3228,179],{"class":148},[138,3230,3231,3233,3236,3239,3241,3244],{"class":140,"line":217},[138,3232,371],{"class":144},[138,3234,3235],{"class":148}," axios.",[138,3237,3238],{"class":175},"post",[138,3240,242],{"class":148},[138,3242,3243],{"class":1122},"\u002F* ... *\u002F",[138,3245,452],{"class":148},[138,3247,3248],{"class":140,"line":231},[138,3249,2145],{"class":148},[138,3251,3252],{"class":140,"line":236},[138,3253,166],{"emptyLinePlaceholder":165},[138,3255,3256,3259,3261,3263,3265,3267,3269,3271,3273,3275],{"class":140,"line":265},[138,3257,3258],{"class":175},"  getUserByEmail",[138,3260,3210],{"class":148},[138,3262,3213],{"class":144},[138,3264,2605],{"class":148},[138,3266,255],{"class":188},[138,3268,208],{"class":144},[138,3270,212],{"class":211},[138,3272,2002],{"class":148},[138,3274,3226],{"class":144},[138,3276,179],{"class":148},[138,3278,3279,3281,3283,3285,3287,3289],{"class":140,"line":280},[138,3280,371],{"class":144},[138,3282,3235],{"class":148},[138,3284,1445],{"class":175},[138,3286,242],{"class":148},[138,3288,3243],{"class":1122},[138,3290,452],{"class":148},[138,3292,3293],{"class":140,"line":293},[138,3294,2145],{"class":148},[138,3296,3297],{"class":140,"line":299},[138,3298,3299],{"class":148},"};\n",[138,3301,3302],{"class":140,"line":304},[138,3303,166],{"emptyLinePlaceholder":165},[138,3305,3306],{"class":140,"line":313},[138,3307,3308],{"class":1122},"\u002F\u002F services\u002FSignupService.ts\n",[138,3310,3311,3313,3316,3318,3321,3324],{"class":140,"line":343},[138,3312,145],{"class":144},[138,3314,3315],{"class":148}," HttpClient ",[138,3317,152],{"class":144},[138,3319,3320],{"class":155}," \"classes\u002FHttpClient\"",[138,3322,3323],{"class":148},"; ",[138,3325,3326],{"class":1122},"\u002F\u002F ❌ the domain depends on a concretion\n",[138,3328,3329],{"class":140,"line":363},[138,3330,166],{"emptyLinePlaceholder":165},[138,3332,3333,3335,3338,3341,3344,3346,3348,3350,3352,3354,3357,3359,3361],{"class":140,"line":368},[138,3334,3197],{"class":144},[138,3336,3337],{"class":144}," async",[138,3339,3340],{"class":144}," function",[138,3342,3343],{"class":175}," signup",[138,3345,242],{"class":148},[138,3347,255],{"class":188},[138,3349,208],{"class":144},[138,3351,212],{"class":211},[138,3353,252],{"class":148},[138,3355,3356],{"class":188},"password",[138,3358,208],{"class":144},[138,3360,212],{"class":211},[138,3362,262],{"class":148},[138,3364,3365,3368,3371,3373,3376,3379,3382],{"class":140,"line":380},[138,3366,3367],{"class":144},"  const",[138,3369,3370],{"class":211}," existingUser",[138,3372,192],{"class":144},[138,3374,3375],{"class":144}," await",[138,3377,3378],{"class":148}," HttpClient.",[138,3380,3381],{"class":175},"getUserByEmail",[138,3383,3384],{"class":148},"(email);\n",[138,3386,3387],{"class":140,"line":386},[138,3388,166],{"emptyLinePlaceholder":165},[138,3390,3391,3394],{"class":140,"line":392},[138,3392,3393],{"class":144},"  if",[138,3395,3396],{"class":148}," (existingUser) {\n",[138,3398,3399,3401,3403,3405,3407,3410],{"class":140,"line":398},[138,3400,2331],{"class":144},[138,3402,437],{"class":144},[138,3404,2289],{"class":175},[138,3406,242],{"class":148},[138,3408,3409],{"class":155},"\"Email already used\"",[138,3411,452],{"class":148},[138,3413,3414],{"class":140,"line":404},[138,3415,296],{"class":148},[138,3417,3418],{"class":140,"line":410},[138,3419,166],{"emptyLinePlaceholder":165},[138,3421,3422,3425,3427,3430],{"class":140,"line":415},[138,3423,3424],{"class":144},"  return",[138,3426,3378],{"class":148},[138,3428,3429],{"class":175},"createUser",[138,3431,3432],{"class":148},"({ email, password });\n",[138,3434,3435],{"class":140,"line":421},[138,3436,418],{"class":148},[10,3438,3439,3440],{},"This isn't ideal. We have just created a dependency from our domain to an implementation detail (HTTP) - crossing an architectural boundary and thus violating the Dependency rule. Furthermore, ",[39,3441,3442,3443,3446,3447,3449,3450,3452],{},"because ",[135,3444,3445],{},"signup"," is coupled with ",[135,3448,3165],{},", ",[135,3451,3445],{}," it can't be unit tested.",[10,3454,3455,3456,1042,3458,42],{},"Let's reimplement it with dependency inversion this time! We're going to start by decoupling ",[135,3457,3161],{},[135,3459,3165],{},[128,3461,3463],{"className":130,"code":3462,"language":132,"meta":133,"style":133},"\u002F\u002F contracts\u002FApiClient.ts\nexport interface ApiClient {\n  createUser: (user: User) => Promise\u003Cvoid>;\n  getUserByEmail: (email: string) => Promise\u003CUser>;\n}\n\n\u002F\u002F classes\u002FHttpClient.ts\nimport axios from \"axios\";\nimport ApiClient from \"contracts\u002FApiClient\";\n\nexport function HttpClient(): ApiClient {\n  return {\n    createUser: async (user: User) => {\n      return axios.post(\u002F* ... *\u002F);\n    },\n    getUserByEmail: async (email: string) => {\n      return axios.get(\u002F* ... *\u002F);\n    },\n  };\n}\n\n\u002F\u002F services\u002FSignupService.ts\nimport ApiClient from \"contracts\u002FApiClient\"; \u002F\u002F ✅ the domain depends on an abstraction\n\nexport function SignupService(client: ApiClient) {\n  return async (email: string, password: string) => {\n    const existingUser = await client.getUserByEmail(email);\n\n    if (existingUser) {\n      throw new Error(\"Email already used\");\n    }\n\n    return client.createUser({ email, password });\n  };\n}\n",[135,3464,3465,3470,3482,3512,3538,3542,3546,3550,3562,3576,3580,3597,3603,3626,3640,3645,3668,3682,3686,3691,3695,3699,3703,3718,3722,3742,3770,3787,3791,3797,3811,3815,3819,3829,3833],{"__ignoreMap":133},[138,3466,3467],{"class":140,"line":141},[138,3468,3469],{"class":1122},"\u002F\u002F contracts\u002FApiClient.ts\n",[138,3471,3472,3474,3477,3480],{"class":140,"line":162},[138,3473,3197],{"class":144},[138,3475,3476],{"class":144}," interface",[138,3478,3479],{"class":175}," ApiClient",[138,3481,179],{"class":148},[138,3483,3484,3486,3488,3490,3492,3494,3496,3498,3500,3503,3506,3509],{"class":140,"line":169},[138,3485,3207],{"class":175},[138,3487,208],{"class":144},[138,3489,2605],{"class":148},[138,3491,847],{"class":188},[138,3493,208],{"class":144},[138,3495,176],{"class":175},[138,3497,2002],{"class":148},[138,3499,3226],{"class":144},[138,3501,3502],{"class":175}," Promise",[138,3504,3505],{"class":148},"\u003C",[138,3507,3508],{"class":211},"void",[138,3510,3511],{"class":148},">;\n",[138,3513,3514,3516,3518,3520,3522,3524,3526,3528,3530,3532,3534,3536],{"class":140,"line":182},[138,3515,3258],{"class":175},[138,3517,208],{"class":144},[138,3519,2605],{"class":148},[138,3521,255],{"class":188},[138,3523,208],{"class":144},[138,3525,212],{"class":211},[138,3527,2002],{"class":148},[138,3529,3226],{"class":144},[138,3531,3502],{"class":175},[138,3533,3505],{"class":148},[138,3535,470],{"class":175},[138,3537,3511],{"class":148},[138,3539,3540],{"class":140,"line":200},[138,3541,418],{"class":148},[138,3543,3544],{"class":140,"line":217},[138,3545,166],{"emptyLinePlaceholder":165},[138,3547,3548],{"class":140,"line":231},[138,3549,3176],{"class":1122},[138,3551,3552,3554,3556,3558,3560],{"class":140,"line":236},[138,3553,145],{"class":144},[138,3555,149],{"class":148},[138,3557,152],{"class":144},[138,3559,156],{"class":155},[138,3561,159],{"class":148},[138,3563,3564,3566,3569,3571,3574],{"class":140,"line":265},[138,3565,145],{"class":144},[138,3567,3568],{"class":148}," ApiClient ",[138,3570,152],{"class":144},[138,3572,3573],{"class":155}," \"contracts\u002FApiClient\"",[138,3575,159],{"class":148},[138,3577,3578],{"class":140,"line":280},[138,3579,166],{"emptyLinePlaceholder":165},[138,3581,3582,3584,3586,3589,3591,3593,3595],{"class":140,"line":293},[138,3583,3197],{"class":144},[138,3585,3340],{"class":144},[138,3587,3588],{"class":175}," HttpClient",[138,3590,707],{"class":148},[138,3592,208],{"class":144},[138,3594,3479],{"class":175},[138,3596,179],{"class":148},[138,3598,3599,3601],{"class":140,"line":299},[138,3600,3424],{"class":144},[138,3602,179],{"class":148},[138,3604,3605,3608,3610,3612,3614,3616,3618,3620,3622,3624],{"class":140,"line":304},[138,3606,3607],{"class":175},"    createUser",[138,3609,3210],{"class":148},[138,3611,3213],{"class":144},[138,3613,2605],{"class":148},[138,3615,847],{"class":188},[138,3617,208],{"class":144},[138,3619,176],{"class":175},[138,3621,2002],{"class":148},[138,3623,3226],{"class":144},[138,3625,179],{"class":148},[138,3627,3628,3630,3632,3634,3636,3638],{"class":140,"line":313},[138,3629,1848],{"class":144},[138,3631,3235],{"class":148},[138,3633,3238],{"class":175},[138,3635,242],{"class":148},[138,3637,3243],{"class":1122},[138,3639,452],{"class":148},[138,3641,3642],{"class":140,"line":343},[138,3643,3644],{"class":148},"    },\n",[138,3646,3647,3650,3652,3654,3656,3658,3660,3662,3664,3666],{"class":140,"line":363},[138,3648,3649],{"class":175},"    getUserByEmail",[138,3651,3210],{"class":148},[138,3653,3213],{"class":144},[138,3655,2605],{"class":148},[138,3657,255],{"class":188},[138,3659,208],{"class":144},[138,3661,212],{"class":211},[138,3663,2002],{"class":148},[138,3665,3226],{"class":144},[138,3667,179],{"class":148},[138,3669,3670,3672,3674,3676,3678,3680],{"class":140,"line":368},[138,3671,1848],{"class":144},[138,3673,3235],{"class":148},[138,3675,1445],{"class":175},[138,3677,242],{"class":148},[138,3679,3243],{"class":1122},[138,3681,452],{"class":148},[138,3683,3684],{"class":140,"line":380},[138,3685,3644],{"class":148},[138,3687,3688],{"class":140,"line":386},[138,3689,3690],{"class":148},"  };\n",[138,3692,3693],{"class":140,"line":392},[138,3694,418],{"class":148},[138,3696,3697],{"class":140,"line":398},[138,3698,166],{"emptyLinePlaceholder":165},[138,3700,3701],{"class":140,"line":404},[138,3702,3308],{"class":1122},[138,3704,3705,3707,3709,3711,3713,3715],{"class":140,"line":410},[138,3706,145],{"class":144},[138,3708,3568],{"class":148},[138,3710,152],{"class":144},[138,3712,3573],{"class":155},[138,3714,3323],{"class":148},[138,3716,3717],{"class":1122},"\u002F\u002F ✅ the domain depends on an abstraction\n",[138,3719,3720],{"class":140,"line":415},[138,3721,166],{"emptyLinePlaceholder":165},[138,3723,3724,3726,3728,3731,3733,3736,3738,3740],{"class":140,"line":421},[138,3725,3197],{"class":144},[138,3727,3340],{"class":144},[138,3729,3730],{"class":175}," SignupService",[138,3732,242],{"class":148},[138,3734,3735],{"class":188},"client",[138,3737,208],{"class":144},[138,3739,3479],{"class":175},[138,3741,262],{"class":148},[138,3743,3744,3746,3748,3750,3752,3754,3756,3758,3760,3762,3764,3766,3768],{"class":140,"line":426},[138,3745,3424],{"class":144},[138,3747,3337],{"class":144},[138,3749,2605],{"class":148},[138,3751,255],{"class":188},[138,3753,208],{"class":144},[138,3755,212],{"class":211},[138,3757,252],{"class":148},[138,3759,3356],{"class":188},[138,3761,208],{"class":144},[138,3763,212],{"class":211},[138,3765,2002],{"class":148},[138,3767,3226],{"class":144},[138,3769,179],{"class":148},[138,3771,3772,3774,3776,3778,3780,3783,3785],{"class":140,"line":455},[138,3773,316],{"class":144},[138,3775,3370],{"class":211},[138,3777,192],{"class":144},[138,3779,3375],{"class":144},[138,3781,3782],{"class":148}," client.",[138,3784,3381],{"class":175},[138,3786,3384],{"class":148},[138,3788,3789],{"class":140,"line":716},[138,3790,166],{"emptyLinePlaceholder":165},[138,3792,3793,3795],{"class":140,"line":726},[138,3794,1485],{"class":144},[138,3796,3396],{"class":148},[138,3798,3799,3801,3803,3805,3807,3809],{"class":140,"line":731},[138,3800,2284],{"class":144},[138,3802,437],{"class":144},[138,3804,2289],{"class":175},[138,3806,242],{"class":148},[138,3808,3409],{"class":155},[138,3810,452],{"class":148},[138,3812,3813],{"class":140,"line":736},[138,3814,1582],{"class":148},[138,3816,3817],{"class":140,"line":750},[138,3818,166],{"emptyLinePlaceholder":165},[138,3820,3821,3823,3825,3827],{"class":140,"line":760},[138,3822,371],{"class":144},[138,3824,3782],{"class":148},[138,3826,3429],{"class":175},[138,3828,3432],{"class":148},[138,3830,3831],{"class":140,"line":765},[138,3832,3690],{"class":148},[138,3834,3835],{"class":140,"line":770},[138,3836,418],{"class":148},[10,3838,3839,3840,3842,3843,3846,3847,3849],{},"With the power of dependency inversion, our ",[135,3841,3161],{}," can now use any ",[135,3844,3845],{},"ApiClient",". Let's inject our ",[135,3848,3165],{}," for now.",[128,3851,3853],{"className":130,"code":3852,"language":132,"meta":133,"style":133},"\u002F\u002F index.ts\nimport SignupService from \"services\u002Fsignup\";\nimport HttpClient from \"classes\u002FHttpClient\";\n\nconst signup = SignupService(HttpClient());\n\nsignup(\"bojan@example.com\", \"password\");\n",[135,3854,3855,3860,3874,3886,3890,3907,3911],{"__ignoreMap":133},[138,3856,3857],{"class":140,"line":141},[138,3858,3859],{"class":1122},"\u002F\u002F index.ts\n",[138,3861,3862,3864,3867,3869,3872],{"class":140,"line":162},[138,3863,145],{"class":144},[138,3865,3866],{"class":148}," SignupService ",[138,3868,152],{"class":144},[138,3870,3871],{"class":155}," \"services\u002Fsignup\"",[138,3873,159],{"class":148},[138,3875,3876,3878,3880,3882,3884],{"class":140,"line":169},[138,3877,145],{"class":144},[138,3879,3315],{"class":148},[138,3881,152],{"class":144},[138,3883,3320],{"class":155},[138,3885,159],{"class":148},[138,3887,3888],{"class":140,"line":182},[138,3889,166],{"emptyLinePlaceholder":165},[138,3891,3892,3894,3896,3898,3900,3902,3904],{"class":140,"line":200},[138,3893,429],{"class":144},[138,3895,3343],{"class":211},[138,3897,192],{"class":144},[138,3899,3730],{"class":175},[138,3901,242],{"class":148},[138,3903,3165],{"class":175},[138,3905,3906],{"class":148},"());\n",[138,3908,3909],{"class":140,"line":217},[138,3910,166],{"emptyLinePlaceholder":165},[138,3912,3913,3915,3917,3920,3922,3925],{"class":140,"line":231},[138,3914,3445],{"class":175},[138,3916,242],{"class":148},[138,3918,3919],{"class":155},"\"bojan@example.com\"",[138,3921,252],{"class":148},[138,3923,3924],{"class":155},"\"password\"",[138,3926,452],{"class":148},[3928,3929],"hr",{},[10,3931,3932],{},"And there you have it. I know it has been a long article, but I wanted to share my knowledge about this particular topic for a long time.",[10,3934,3935],{},"Wish everyone a happy, productive, successful and healthy New Year & Merry Christmas!",[3937,3938,3939],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":133,"searchDepth":162,"depth":162,"links":3941},[3942,3943,3944],{"id":21,"depth":162,"text":22},{"id":33,"depth":162,"text":34},{"id":55,"depth":162,"text":56,"children":3945},[3946,3947,3948,3949,3950],{"id":116,"depth":169,"text":117},{"id":1057,"depth":169,"text":1058},{"id":2071,"depth":169,"text":2072},{"id":2745,"depth":169,"text":2746},{"id":3130,"depth":169,"text":3131},"TypeScript","2020\u002F12\u002F26","Yes, another take into explaining SOLID Design Principles. And yes, another blog post about making your code more maintainable and readable. But this time something is different - well, mostly nothing really is (you expected something here, didn't ya?) except that it's just my perspective. A perspective gained from applying these principles in real life projects.",null,"md","\u002Fimages\u002Fsolid-ts.jpg","typescript, design patters, solid, solid design principles, single responsibility principle, open close principle, liskov substitution principle, dependency inversion principle, interface segregation principle",{},"\u002Fblog\u002Funderstand-and-use-solid-design-principles-with-typescript","☕️☕️ 19 min read",{"title":5,"description":3953},"understand-and-use-solid-design-principles-with-typescript","blog\u002Funderstand-and-use-solid-design-principles-with-typescript","solid, typescript, design patterns","exK7fI-uA5IXl6sv5uvrn9lmCvwjMYdH-j6KdtUp8GU",1774945272080]