# Pragmatic programmer Ch9 - Ch12 ###### tags: `The Pragmatic Programmer` # Ch9: DRY—The Evils of Duplication **25 min** - It’s about when you forget one of your duplicated code. - (1) DUPLICATION IN CODE - If you find need to change more than one place for new requirement, that is a DIY violation. - Not All Code Duplication Is Knowledge Duplication - *validate_age() and validate_quantity()* - Happens to have same validation rules. That’s a coincidence, not a duplication. - *Product and Order list page* - Use composition - (2) DUPLICATION IN DOCUMENTATION - Redundant comments as duplication of code - DRY Violations in Data (why here?) ```jsx class Line { constractor { this.x: number; this.y: number; this.length: number; } } ``` - *length should be a function calculate the distance between two points but not a constant.* - Whenever a module exposes a data structure, you’re coupling all the code that uses that structure to the implementation of that module. Where possible, always use accessor functions to read and write the attributes of objects. It will make it easier to add functionality in the future. (Meyer’s Uniform Access principle) ```jsx <ProductCard product={product} /> <ProductCard productBase={productBase} /> <ProductCard image={product.image} title={product.title} subtitle={product.subtitle} /> ``` - (3) REPRESENTATIONAL DUPLICATION - Inevitable but able to be mitigated - (1) Duplication Across Internal APIs - Store and share all your APIs in a central repository - Share api interfaces between frontend and backend (node.js): Mono-repo - (2) Duplication Across External APIs - Import api definition from resources like OpenAPI - (3) Duplication with Data Sources (pending for confirming the meaning here) - (4) INTERDEVELOPER DUPLICATION - Two currency formatted in our project (both in directory Utils but hard to find.) Find this issue via code review. - Forster an environment where it’s easier to find and reuse existing stuff than to write it yourself. # Ch10: Orthogonality (decoupling) **35 min** - What is orthogonality - A nonorthogonal system: Helicopter controlling - Benefits - eliminate effects between unrelated things - gain productivity - (a) Changes are localized, so development time and testing time are reduced. - (b) promotes reuse. - (c) easy to combine two orthogonal components - reduce risk - (a) Diseased sections of code are isolated. - (b) less fragile when make changes (restricted to that area.) - (c) be better tested - (d) You will not be as tightly tied to a particular vendor, product, or platform, *(Exp: module wrapper: moment())* ```jsx export const getFormatedDate = () => dayjs().someMethod(); // dayjs ``` - Implementations - (1) Design - Interface, abstract, layer - Avoid global data - Every time your code references global data, it ties itself into the other components that share that data. => may try to pass the “context” to the code - (2) Toolkits and libraries - keep it isolated (encapsulation) - (3) Testing - An orthogonally designed and implemented system is easier to test. Because the interactions between the system’s components are formalized and limited. - Mock too many context: Do you have to import a large percentage of the rest of the system’s code? - How localized the fix is? Do you change just one module, or are the changes scattered throughout the entire system? - Q&A - Consider the difference between tools which have a graphical user interface and small but combinable command-line utilities used at shell prompts. Which set is more orthogonal, and why? Which is easier to use for exactly the purpose for which it was intended? Which set is easier to combine with other tools to meet new challenges? Which set is easier to learn? - C++ supports multiple inheritance, and Java allows a class to implement multiple interfaces. Ruby has mixins. What impact does using these facilities have on orthogonality? Is there a difference in impact between using multiple inheritance and multiple interfaces? Is there a difference between using delegation and using inheritance? - You’re asked to read a file a line at a time. For each line, you have to split it into fields. Which of the following sets of pseudo class definitions is likely to be more orthogonal? ```jsx const foo1 = (file) => { file.forEach((line) => newLine ) } const foo2 = (line) => { return newLine } ``` - What are the differences in orthogonality between object- oriented and functional languages? Are these differences inherent in the languages themselves, or just in the way people use them? # Ch11: Reversibility **10 min** - The mistake lies in assuming that any decision is cast in stone— and in not preparing for the contingencies that might arise. - *Search option alerts* ```jsx const ruleMap = { [optionA]: [ruleA, ruleB], [optionB]: [ruleC], [optionC]: [ruleB], } const checkInput = (ruleMap, curOption, inputValue) => ({ isInvalid: boolean; failCheck: enum Rule; }) switch (failCheck) { case RuleA: showAlert(Modal.X); case RuleB: showAlert(Modal.Y); } ``` - Hide third-party APIs behind your own abstraction layers. # Ch12: Tracer Bullets **10 min** - CODE THAT GLOWS IN THE DARK - TDD, MVP: prioritize your development - Benefits - Users get to see something working early - Developers build a structure to work in (a context to follow) - TRACER CODE VS PROTOTYPING - Prototyping generates disposable code. Tracer code is lean but complete, and forms part of the skeleton of the final system.