├── design-solid-principles.png ├── solid-ts4-interface-segregation-principle ├── IFax.ts ├── IScan.ts ├── IPrint.ts ├── IMultiFunction.ts ├── CanonPrinter.ts ├── index.ts ├── EpsonPrinterNScanner.ts └── XeroxMainCenter.ts ├── solid-ts5-dependency-inversion-principle ├── ProductRepository.ts ├── index.ts ├── ProductFactory.ts ├── DBProductRepository.ts └── ProductCatalog.ts ├── solid-ts2-open-closed-principle ├── CustomerProfile.ts ├── HomeInsuerenceProfile.ts ├── HealthInsuerenceProfile.ts ├── VehicleInsuerenceProfile.ts ├── index.ts └── InsuerencePremiumCalculator.ts ├── solid-ts3-liskov-subtitution-principle ├── Product.ts ├── index.ts ├── InHouseProduct.ts └── PricingUtils.ts ├── solid-ts1-singgle-principle-responsibility ├── TaxCalculator.ts ├── EmployeeRepository.ts └── index.ts └── README.md /design-solid-principles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zidniryi/design-solid-principles/HEAD/design-solid-principles.png -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/IFax.ts: -------------------------------------------------------------------------------- 1 | export interface IFax { 2 | fax(): void, 3 | faxInternet(): void 4 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/IScan.ts: -------------------------------------------------------------------------------- 1 | export interface IScan { 2 | scan(): void, 3 | scanPhoto(): void 4 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/IPrint.ts: -------------------------------------------------------------------------------- 1 | export interface IPrint { 2 | print(): void; 3 | getPrintSpoolDetail(): void 4 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/IMultiFunction.ts: -------------------------------------------------------------------------------- 1 | export interface IMultiFunction { 2 | fax(): void, 3 | faxInternet(): void 4 | } -------------------------------------------------------------------------------- /solid-ts5-dependency-inversion-principle/ProductRepository.ts: -------------------------------------------------------------------------------- 1 | export interface ProductRepository { 2 | getAllProductsName(): Array 3 | } -------------------------------------------------------------------------------- /solid-ts5-dependency-inversion-principle/index.ts: -------------------------------------------------------------------------------- 1 | import { ProductCatalog } from "./ProductCatalog"; 2 | 3 | const productCatalog = new ProductCatalog() 4 | console.log(productCatalog.getAllListsProducts()) -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/CustomerProfile.ts: -------------------------------------------------------------------------------- 1 | // The intrefcae or extentions we used for bridge the Closed class with Open Extention class 2 | export interface CustomerProfile { 3 | isLoyalCustomer(): boolean; 4 | } -------------------------------------------------------------------------------- /solid-ts3-liskov-subtitution-principle/Product.ts: -------------------------------------------------------------------------------- 1 | export class Product { 2 | // Initial discount product 3 | protected discount: number = 20 4 | // The general discount product 5 | public getDiscount(): number { 6 | return Number(this.discount) 7 | } 8 | } -------------------------------------------------------------------------------- /solid-ts5-dependency-inversion-principle/ProductFactory.ts: -------------------------------------------------------------------------------- 1 | import { DBProductRepository } from "./DBProductRepository"; 2 | 3 | export class ProductFactory { 4 | [x: string]: any; 5 | 6 | public static create(): ProductFactory { 7 | return new DBProductRepository() 8 | } 9 | } -------------------------------------------------------------------------------- /solid-ts5-dependency-inversion-principle/DBProductRepository.ts: -------------------------------------------------------------------------------- 1 | import { ProductRepository } from "./ProductRepository" 2 | 3 | export class DBProductRepository implements ProductRepository { 4 | 5 | public getAllProductsName() { 6 | const dataList = ["soap", "shampo"] 7 | return dataList 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/HomeInsuerenceProfile.ts: -------------------------------------------------------------------------------- 1 | import { CustomerProfile } from "./CustomerProfile"; 2 | 3 | // You should modify here, the extentsion, when you add new type insurence usertype 4 | export class HomeInsuerenceProfile implements CustomerProfile { 5 | public isLoyalCustomer() { 6 | return false 7 | } 8 | } -------------------------------------------------------------------------------- /solid-ts5-dependency-inversion-principle/ProductCatalog.ts: -------------------------------------------------------------------------------- 1 | import { ProductFactory } from "./ProductFactory"; 2 | 3 | 4 | export class ProductCatalog { 5 | 6 | public getAllListsProducts() { 7 | const productRepository = ProductFactory.create() 8 | return productRepository.getAllProductsName() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/HealthInsuerenceProfile.ts: -------------------------------------------------------------------------------- 1 | import { CustomerProfile } from "./CustomerProfile"; 2 | 3 | // You should modify here, the extentsion, when you add new type insurence usertype 4 | export class HealthInsuerenceProfile implements CustomerProfile { 5 | public isLoyalCustomer(): boolean { 6 | return true 7 | } 8 | } -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/VehicleInsuerenceProfile.ts: -------------------------------------------------------------------------------- 1 | import { CustomerProfile } from "./CustomerProfile"; 2 | 3 | // You should modify here, the extentsion, when you add new type insurence usertype 4 | export class VehicleInsuerenceProfile implements CustomerProfile { 5 | public isLoyalCustomer(): boolean { 6 | return true 7 | } 8 | } -------------------------------------------------------------------------------- /solid-ts3-liskov-subtitution-principle/index.ts: -------------------------------------------------------------------------------- 1 | import { PricingUtils } from "./PricingUtils"; 2 | 3 | const pricingUtils = new PricingUtils() 4 | 5 | console.log(pricingUtils.getMappingDiscount()) 6 | 7 | /** 8 | * LISKOV need working code and correctness code 9 | * Subtitution should 10 | * Breaking the hierarchy 11 | * Not Ask, Tell 12 | */ -------------------------------------------------------------------------------- /solid-ts1-singgle-principle-responsibility/TaxCalculator.ts: -------------------------------------------------------------------------------- 1 | import { Employee } from "."; 2 | 3 | export class TaxCalculator { 4 | public calculateTaxes(employee: Employee) { 5 | if (employee.getEmployeeType() == "fulltime") { 6 | return (Number(employee.getEmployeeSalary()) * 10) / 100; 7 | } else { 8 | return (Number(employee.getEmployeeSalary()) * 5) / 100; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /solid-ts1-singgle-principle-responsibility/EmployeeRepository.ts: -------------------------------------------------------------------------------- 1 | import { Employee } from "."; 2 | 3 | export class EmployeeRepository { 4 | public saveData(employee: Employee) { 5 | // In real world you should separate in repository db 6 | // If in FE like for HTTP Request 7 | // If in BE saving to DB SQL 8 | // Log for run in index.ts 9 | console.log(employee, "Save TO DB"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /solid-ts3-liskov-subtitution-principle/InHouseProduct.ts: -------------------------------------------------------------------------------- 1 | import { Product } from "./Product"; 2 | 3 | export class InHouseProduct extends Product { 4 | 5 | // Override the discount inheritence 6 | override getDiscount() { 7 | this.applyDiscount() 8 | return this.discount 9 | } 10 | 11 | // Method if inhouse product 12 | public applyDiscount() { 13 | return this.discount = this.discount * 1.5; 14 | } 15 | } -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/index.ts: -------------------------------------------------------------------------------- 1 | import { InsuerencePremiumCalculator } from "./InsuerencePremiumCalculator"; 2 | import { VehicleInsuerenceProfile } from "./VehicleInsuerenceProfile"; 3 | 4 | const vechileInsuerenceProfile = new VehicleInsuerenceProfile() 5 | 6 | vechileInsuerenceProfile.isLoyalCustomer() 7 | const insuerencePremiumCalculator = new InsuerencePremiumCalculator() 8 | 9 | // We called it here 10 | console.log(insuerencePremiumCalculator.premiumUserCalculator(vechileInsuerenceProfile)) -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/CanonPrinter.ts: -------------------------------------------------------------------------------- 1 | import { IPrint } from "./IPrint"; 2 | 3 | export class CanonPrinter implements IPrint { 4 | print(): void { 5 | // Real world code should here 6 | // For sample we just print here 7 | console.log('Method not implemented. Print'); 8 | } 9 | 10 | getPrintSpoolDetail(): void { 11 | // Real world code should here 12 | // For sample we just print here 13 | console.log('Method not implemented. Print Detail'); 14 | } 15 | } -------------------------------------------------------------------------------- /solid-ts2-open-closed-principle/InsuerencePremiumCalculator.ts: -------------------------------------------------------------------------------- 1 | import { CustomerProfile } from "./CustomerProfile"; 2 | 3 | // This is Closed class we should modify this class 4 | // Just imagine like laptop you can add accesory like headphone, speaker, external keyboard but you can't allow to modify the processor 5 | export class InsuerencePremiumCalculator { 6 | 7 | public premiumUserCalculator(customer: CustomerProfile) { 8 | if (customer.isLoyalCustomer()) { 9 | return 20 10 | } 11 | return 0 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/index.ts: -------------------------------------------------------------------------------- 1 | import { CanonPrinter } from "./CanonPrinter"; 2 | import { EpsonPrinterNScanner } from "./EpsonPrinterNScanner"; 3 | import { XeroxMainCenter } from "./XeroxMainCenter"; 4 | 5 | /** 6 | * Interface Segregation 7 | * No method should force implement the method that is not use 8 | * Decople and only implements that method we need and we use 9 | */ 10 | const xeroxMainCenter = new XeroxMainCenter() 11 | const epsonPrinterNScanner = new EpsonPrinterNScanner() 12 | const canonPrinter = new CanonPrinter() 13 | 14 | xeroxMainCenter.faxInternet() 15 | epsonPrinterNScanner.scanPhoto() 16 | canonPrinter.print() -------------------------------------------------------------------------------- /solid-ts3-liskov-subtitution-principle/PricingUtils.ts: -------------------------------------------------------------------------------- 1 | import { InHouseProduct } from "./InHouseProduct"; 2 | import { Product } from "./Product"; 3 | 4 | export class PricingUtils { 5 | // Create 3 instance object 6 | p1 = new Product() 7 | p2 = new Product() 8 | p3 = new InHouseProduct() 9 | 10 | // Init array product 11 | productList: Array = [] 12 | 13 | constructor() { 14 | this.productList.push(this.p1) 15 | this.productList.push(this.p2) 16 | this.productList.push(this.p3) 17 | this.getMappingDiscount() 18 | } 19 | 20 | // Mapping the data 21 | getMappingDiscount() { 22 | return this.productList.map(itemProduct => { 23 | return itemProduct.getDiscount() 24 | }) 25 | } 26 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/EpsonPrinterNScanner.ts: -------------------------------------------------------------------------------- 1 | import { IPrint } from "./IPrint"; 2 | import { IScan } from "./IScan"; 3 | 4 | export class EpsonPrinterNScanner implements IPrint, IScan { 5 | 6 | print(): void { 7 | // Real world code should here 8 | // For sample we just print here 9 | console.log('Method not implemented. Print'); 10 | } 11 | 12 | getPrintSpoolDetail(): void { 13 | // Real world code should here 14 | // For sample we just print here 15 | console.log('Method not implemented. Print Detail'); 16 | } 17 | 18 | scan(): void { 19 | // Real world code should here 20 | // For sample we just print here 21 | console.log('Method not implemented. Scan'); 22 | } 23 | 24 | scanPhoto(): void { 25 | // Real world code should here 26 | // For sample we just print here 27 | console.log('Method not implemented. Scan Photo'); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /solid-ts4-interface-segregation-principle/XeroxMainCenter.ts: -------------------------------------------------------------------------------- 1 | import { IFax } from "./IFax"; 2 | import { IPrint } from "./IPrint"; 3 | import { IScan } from "./IScan"; 4 | 5 | export class XeroxMainCenter implements IPrint, IScan, IFax { 6 | 7 | print(): void { 8 | // Real world code should here 9 | // For sample we just print here 10 | console.log('Method not implemented. Print'); 11 | } 12 | 13 | getPrintSpoolDetail(): void { 14 | // Real world code should here 15 | // For sample we just print here 16 | console.log('Method not implemented. Print Detail'); 17 | } 18 | 19 | scan(): void { 20 | // Real world code should here 21 | // For sample we just print here 22 | console.log('Method not implemented. Scan'); 23 | } 24 | 25 | scanPhoto(): void { 26 | // Real world code should here 27 | // For sample we just print here 28 | console.log('Method not implemented. Scan Photo'); 29 | } 30 | 31 | fax(): void { 32 | // Real world code should here 33 | // For sample we just print here 34 | console.log('Method not implemented. Fax'); 35 | } 36 | 37 | faxInternet(): void { 38 | // Real world code should here 39 | // For sample we just print here 40 | console.log('Method not implemented. Fax With Internet'); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /solid-ts1-singgle-principle-responsibility/index.ts: -------------------------------------------------------------------------------- 1 | import { EmployeeRepository } from "./EmployeeRepository" 2 | import { TaxCalculator } from "./TaxCalculator" 3 | 4 | export class Employee { 5 | private employeeId?: string 6 | private employeeName?: string 7 | private employeeAddress?: string 8 | private employeeType?: string 9 | private employeeNumber?: number 10 | private employeeSalary?: number 11 | 12 | constructor() { 13 | this.setEmployeeId() 14 | this.setEmployeeName() 15 | this.setEmployeeAddress() 16 | this.setEmployeeType() 17 | this.setEmployeeNumber() 18 | this.setEmployeeSallary() 19 | } 20 | 21 | // Decouple in repository class (Coupling) 22 | public saveEmployeeData() { 23 | const employeeRepository = new EmployeeRepository(); 24 | return employeeRepository.saveData(this); 25 | } 26 | 27 | // Decouple in Tax Calculator Class (Cohesion) 28 | public calculateTaxEmployee() { 29 | return new TaxCalculator().calculateTaxes(this); 30 | } 31 | 32 | // For GET and SET it's not neceserry to create own class 33 | public getEmployeeId() { 34 | return this.employeeId 35 | } 36 | 37 | private setEmployeeId() { 38 | return this.employeeId = "11" 39 | } 40 | 41 | public getEmployeeName() { 42 | return this.employeeName 43 | } 44 | 45 | public setEmployeeName() { 46 | return this.employeeName = "John Doe" 47 | } 48 | 49 | public getEmployeeAdress() { 50 | return this.employeeAddress 51 | 52 | } 53 | 54 | public setEmployeeAddress() { 55 | return this.employeeAddress = "Jakarta" 56 | } 57 | 58 | public getEmployeeType() { 59 | return this.employeeType; 60 | 61 | } 62 | 63 | public setEmployeeType() { 64 | return this.employeeType = "fulltime" 65 | } 66 | 67 | public getEmployeeNumber() { 68 | return this.employeeNumber 69 | } 70 | 71 | public setEmployeeNumber() { 72 | return this.employeeNumber = 123455 73 | } 74 | 75 | public getEmployeeSalary() { 76 | return this.employeeSalary 77 | } 78 | 79 | public setEmployeeSallary() { 80 | return this.employeeSalary = 200000 81 | } 82 | } 83 | 84 | const employee = new Employee() 85 | console.log(employee.calculateTaxEmployee()) 86 | employee.saveEmployeeData() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design SOLID Principles 2 | 3 | Architectural Design SOLID Principles that are Easy to Understand and Apply 4 | 5 | ![Design SOLID Principles](/design-solid-principles.png) 6 | 7 | ## Question 8 | 9 | Before we do something it's good we make a question to ourselves, the possibility of something we will do. 10 | 11 | ### What is SOLID Principles? 12 | 13 | The SOLID Principles are five principles of Object-Oriented class design. They are a set of rules and best practices to follow while designing a class structure. 14 | 15 | ### Who should implement SOLID Principles? 16 | 17 | Every programmer/engineer who jumps into a project for the efficiency and effectiveness of the team in doing the project well 18 | 19 | ### When we should implement SOLID Principles? 20 | 21 | Every time we write our code, whether it's creating new features, improvements or enhancements, we must pay attention to aspects of the SOLID Principles. 22 | 23 | ### Why we used SOLID Principles? 24 | 25 | Because by using SOLID Principles we will create a code that is clean, easy to read, maintain, and has effectiveness and efficiency and will save time and effort for us as programmers or engineers and will save money for our company. 26 | 27 | Other benefits is the goal of the SOLID principles is to reduce dependencies so that we can change one area of software without impacting others. Additionally, they're intended to make designs easier to understand, maintain, and extend. 28 | 29 | ### How we implement SOLID Principles? 30 | 31 | To implement the SOLID Principles everything starts from habit and when we do it often it will be automatically programmed in us, and how, will be explained and given an example of the SOLID Principles project in this repo. 32 | 33 | ## Concepts of SOLID principles 34 | 35 | ### 1. Single-Responsibility Principle 36 | 37 | Single-responsibility Principle (SRP) states: 38 | 39 | A class should have one and only one reason to change, meaning that a class should have only one job. 40 | 41 | **Examples** 42 | 43 | ```typescript 44 | export class EmployeeRepository { 45 | public saveData(employee: Employee) { 46 | // In real world you should separate in repository db 47 | // If in FE like for HTTP Request 48 | // If in BE saving to DB SQL 49 | console.log(employee, "Save TO DB"); 50 | } 51 | } 52 | ``` 53 | 54 | ```typescript 55 | export class TaxCalculator { 56 | public calculateTaxes(employee: Employee) { 57 | if (employee.getEmployeeType() == "fulltime") { 58 | return (Number(employee.getEmployeeSalary()) * 10) / 100; 59 | } else { 60 | return (Number(employee.getEmployeeSalary()) * 5) / 100; 61 | } 62 | } 63 | } 64 | ``` 65 | 66 | **Explanation** 67 | We separate the saveData method into EmployeeRepository and we also separate the TaxCalculator cohesion with what the method or class does with only one responsibility. 68 | 69 | ### 2. Open-Closed Principle 70 | 71 | Open-closed Principle (OCP) states: 72 | 73 | Objects or entities should be open for extension but closed for modification. 74 | 75 | This means that a class should be extendable without modifying the class itself. 76 | 77 | **Examples** 78 | 79 | ```typescript 80 | // This is Closed class we should modify this class 81 | // Just imagine like laptop you can add accesory like headphone, speaker, external keyboard but you can't allow to modify the processor 82 | export class InsuerencePremiumCalculator { 83 | public premiumUserCalculator(customer: CustomerProfile) { 84 | if (customer.isLoyalCustomer()) { 85 | return 20; 86 | } 87 | return 0; 88 | } 89 | } 90 | ``` 91 | 92 | ```typescript 93 | // The intrefcae or extentions we used for bridge the Closed class with Open Extention class 94 | export interface CustomerProfile { 95 | isLoyalCustomer(): boolean; 96 | } 97 | ``` 98 | 99 | **Explanation** 100 | We create interfaces for all Users, so when a new User Type is added we don't need to change the source class library that we have. 101 | 102 | ### 3. Liskov Substitution Principle 103 | 104 | The Liskov Substitution Principle (LSP) states that objects of a superclass should be replaceable with objects of its subclasses without breaking the application. 105 | 106 | **Examples** 107 | 108 | ```typescript 109 | export class Product { 110 | // Initial discount product 111 | protected discount: number = 20; 112 | // The general discount product 113 | public getDiscount(): number { 114 | return Number(this.discount); 115 | } 116 | } 117 | ``` 118 | 119 | ```typescript 120 | export class InHouseProduct extends Product { 121 | // Override the discount inheritence 122 | override getDiscount() { 123 | this.applyDiscount(); 124 | return this.discount; 125 | } 126 | 127 | // Method if inhouse product 128 | public applyDiscount() { 129 | return (this.discount = this.discount * 1.5); 130 | } 131 | } 132 | ``` 133 | 134 | ```typescript 135 | import { PricingUtils } from "./PricingUtils"; 136 | 137 | const pricingUtils = new PricingUtils(); 138 | 139 | console.log(pricingUtils.getMappingDiscount()); 140 | 141 | /** 142 | * LISKOV need working code and correctness code 143 | * Subtitution should 144 | * Breaking the hierarchy 145 | * Not Ask, Tell 146 | */ 147 | ``` 148 | 149 | **Explanation** 150 | We override the get Discount method in the InHouse Product class to provide a different discount so that when we mapped it or called the method we created it doesn't break. 151 | 152 | ### 4. Interface Segregation Principle 153 | 154 | Interface Segregation Principle 155 | Interface segregation principle states: 156 | 157 | A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use. 158 | 159 | **Examples** 160 | 161 | ```typescript 162 | import { IFax } from "./IFax"; 163 | import { IPrint } from "./IPrint"; 164 | import { IScan } from "./IScan"; 165 | 166 | export class XeroxMainCenter implements IPrint, IScan, IFax { 167 | print(): void { 168 | // Real world code should here 169 | // For sample we just print here 170 | console.log("Method not implemented. Print"); 171 | } 172 | 173 | getPrintSpoolDetail(): void { 174 | // Real world code should here 175 | // For sample we just print here 176 | console.log("Method not implemented. Print Detail"); 177 | } 178 | 179 | scan(): void { 180 | // Real world code should here 181 | // For sample we just print here 182 | console.log("Method not implemented. Scan"); 183 | } 184 | 185 | scanPhoto(): void { 186 | // Real world code should here 187 | // For sample we just print here 188 | console.log("Method not implemented. Scan Photo"); 189 | } 190 | 191 | fax(): void { 192 | // Real world code should here 193 | // For sample we just print here 194 | console.log("Method not implemented. Fax"); 195 | } 196 | 197 | faxInternet(): void { 198 | // Real world code should here 199 | // For sample we just print here 200 | console.log("Method not implemented. Fax With Internet"); 201 | } 202 | } 203 | ``` 204 | 205 | ```typescript 206 | import { IPrint } from "./IPrint"; 207 | 208 | export class CanonPrinter implements IPrint { 209 | print(): void { 210 | // Real world code should here 211 | // For sample we just print here 212 | console.log("Method not implemented. Print"); 213 | } 214 | 215 | getPrintSpoolDetail(): void { 216 | // Real world code should here 217 | // For sample we just print here 218 | console.log("Method not implemented. Print Detail"); 219 | } 220 | } 221 | ``` 222 | 223 | **Explanation** 224 | We make the interface according to our needs, we can see that we implement IPrint, IScan, IFax Interfaces in the XeroxMainCenter class and we implement 1 IPrint Interface class in the CanonPrinter class because CanonPrinter can only and requires 1 class that needs to be implemented. 225 | 226 | ### 5. Dependency Inversion Principle 227 | 228 | Entities must depend on abstractions, not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions. This principle allows for decoupling. 229 | 230 | **Examples** 231 | 232 | ```typescript 233 | export class DBProductRepository implements ProductRepository { 234 | public getAllProductsName() { 235 | const dataList = ["soap", "shampo"]; 236 | return dataList; 237 | } 238 | } 239 | ``` 240 | 241 | ```typescript 242 | export interface ProductRepository { 243 | getAllProductsName(): Array; 244 | } 245 | ``` 246 | 247 | ```typescript 248 | export class ProductFactory { 249 | [x: string]: any; 250 | 251 | public static create(): ProductFactory { 252 | return new DBProductRepository(); 253 | } 254 | } 255 | ``` 256 | 257 | **Explanation** 258 | From the code above we can see that the DBProductRepository depends on the abstract Interface of the ProductRepository class which is then rewritten in the ProductFactory class so that it can be called ProductCatalog so it depends on abstractions. 259 | 260 | ### Benefits Of SOLID Principles 261 | 262 | 1. Clean: clean and standard code. 263 | 2. Maintainable: Manageable and easy for maintenance. 264 | 3. Scalable: Easy to refactor or change code. 265 | 4. Redundancy: Avoids redundant code. 266 | 5. Testable: Can be easily unit tested. 267 | 6. Readable: Easy and readable. 268 | 7. Independent: Reduce dependencies 269 | 8. Reusable: Reusable code 270 | 9. Saving time and money for the company 271 | 272 | ### Disadvantages Of SOLID Principles 273 | 274 | 1. To many small business entities (I.e. SRP) 275 | 2. Take more time for development in the begining. 276 | 277 | ### Playground 278 | 279 | To make it easier, if you want to run this repo project, it is already embedded and can be run directly without clone and install the Typscript environment on your computer. 280 | 281 | 1. https://replit.com/@zidniryi/solid-ts1-singgle-principle-responsibility#index.ts 282 | 2. https://replit.com/@zidniryi/solid-ts2-open-closed-principle 283 | 3. https://replit.com/@zidniryi/solid-ts3-liskov-subtitution-principle 284 | 4. https://replit.com/@zidniryi/solid-ts4-interface-segregation-principle 285 | 5. https://replit.com/@zidniryi/solid-ts5-dependency-inversion-principle 286 | 287 | ### Conclusion 288 | 289 | For the solid design of this repository you can be implemented in Other Programming Languages as per your requirement. You can try it with the Programming Language that you are currently fluent in, you can use PHP, JAVA, DART, KOTLIN and others. 290 | 291 | The author uses the Typescripts Programming Language to make it easier and can be run online, hopefully useful and helpful. 292 | --------------------------------------------------------------------------------