├── .github └── workflows │ ├── markdown-link-check.json │ └── markdown-link-check.yml ├── .prettierrc └── README.md /.github/workflows/markdown-link-check.json: -------------------------------------------------------------------------------- 1 | { 2 | "aliveStatusCodes": [0, 200, 429], 3 | "httpHeaders": [ 4 | { 5 | "urls": ["http"], 6 | "headers": { 7 | "User-Agent": "Chrome/124.0.0.0" 8 | } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/markdown-link-check.yml: -------------------------------------------------------------------------------- 1 | name: Check Markdown links 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | schedule: 8 | # Run every Tuesday at 3:00 AM (See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07) 9 | - cron: "0 3 * * 2" 10 | 11 | jobs: 12 | markdown-link-check: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@master 16 | - uses: gaurav-nelson/github-action-markdown-link-check@v1 17 | with: 18 | config-file: ".github/workflows/markdown-link-check.json" 19 | use-quiet-mode: "yes" 20 | use-verbose-mode: "yes" 21 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "proseWrap": "always", 3 | "printWidth": 80 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programming Principles 2 | 3 | Every programmer benefits from understanding programming principles and design 4 | patterns. This overview is a reference for myself, and maybe it is of help to 5 | you during design, discussion, or review. The list is incomplete, and sometimes 6 | trade-offs need to be made between conflicting principles. However, higher 7 | ranked principles usually beat lower ranked ones. 8 | 9 | The list was inspired by [The Principles of Good Programming][1]. I've added a 10 | bit more reasoning, details, and links to further resources. [Let me know][2] if 11 | you have any feedback or suggestions for improvement! 12 | 13 | ## Contents 14 | 15 | ### Generic 16 | 17 | - [KISS][3] 18 | - [YAGNI][4] 19 | - [Do The Simplest Thing That Could Possibly Work][5] 20 | - [Separation of Concerns][6] 21 | - [Code For The Maintainer][7] 22 | - [Avoid Premature Optimization][8] 23 | - [Optimize for Deletion][9] 24 | - [Keep things DRY][10] 25 | - [Boy Scout Rule][11] 26 | 27 | ### Relationships between modules, classes, components, entities 28 | 29 | - [Connascence][12] 30 | - [Minimise Coupling][13] 31 | - [Law of Demeter][14] 32 | - [Composition Over Inheritance][15] 33 | - [Orthogonality][16] 34 | - [Robustness Principle][17] 35 | - [Inversion of Control][18] 36 | 37 | ### Modules, classes, components, entities 38 | 39 | - [Maximise Cohesion][19] 40 | - [Liskov Substitution Principle][20] 41 | - [Open/Closed Principle][21] 42 | - [Single Responsibility Principle][22] 43 | - [Hide Implementation Details][23] 44 | - [Curly's Law][24] 45 | - [Encapsulate What Changes][25] 46 | - [Interface Segregation Principle][26] 47 | - [Command Query Separation][27] 48 | - [Dependency Inversion Principle][28] 49 | - [SOLID][29] 50 | 51 | ### Test 52 | 53 | - [FIRST principles of testing][30] 54 | - [Arrange, Act, Assert][31] 55 | 56 | ## KISS 57 | 58 | **Keep It Simple, Stupid**: most systems work and are understood better if they 59 | are kept simple rather than made complex. 60 | 61 | Why 62 | 63 | - Less code takes less time to write, has less bugs, and is easier to modify. 64 | - Simplicity is the ultimate sophistication. 65 | - It seems that perfection is reached not when there is nothing left to add, but 66 | when there is nothing left to take away. 67 | 68 | Resources 69 | 70 | - [KISS principle (wikipedia.org)][32] 71 | - [Keep It Simple Stupid (KISS) (principles-wiki.net)][33] 72 | - [Cognitive Load is what matters (github.com)][34] 73 | - [The Limits of Human Cognitive Capacities in Programming and Their Impact on 74 | Code Readability (florian-kraemer.net)][35] 75 | - [Simplicity is An Advantage but Sadly Complexity Sells Better 76 | (eugeneyan.com)][36] 77 | - [What Makes Code Hard To Read: Visual Patterns of Complexity 78 | (seeinglogic.com)][37] 79 | 80 | ## YAGNI 81 | 82 | **You Aren't Gonna Need It**: don't implement something until it is necessary. 83 | 84 | Why 85 | 86 | - Any work that's only used for a feature that's needed tomorrow, means losing 87 | effort from features that need to be done for the current iteration. 88 | - It leads to code bloat; the software becomes larger and more complicated. 89 | 90 | How 91 | 92 | - Always implement things when you actually need them, never when you just 93 | foresee that you need them. 94 | 95 | Resources 96 | 97 | - [You Arent Gonna Need It (wiki.c2.com)][38] 98 | - [You’re NOT gonna need it! (ronjeffries.com)][39] 99 | - [You aren't gonna need it (wikipedia.org)][40] 100 | 101 | ## Do The Simplest Thing That Could Possibly Work 102 | 103 | Why 104 | 105 | - Real progress against the real problem is maximized if we just work on what 106 | the problem really is. 107 | 108 | How 109 | 110 | - Ask yourself: "What is the simplest thing that could possibly work?" 111 | 112 | Resources 113 | 114 | - [Do The Simplest Thing That Could Possibly Work (wiki.c2.com)][41] 115 | 116 | ## Separation of Concerns 117 | 118 | Separation of concerns is a design principle for separating a computer program 119 | into distinct sections, such that each section addresses a separate concern. For 120 | example, the business logic and the user interface of an application are 121 | separate concerns. Changing the user interface should not require changes to the 122 | business logic and vice versa. 123 | 124 | Quoting [Edsger W. Dijkstra][42] (1974): 125 | 126 | > It is what I sometimes have called "the separation of concerns", which, even 127 | > if not perfectly possible, is yet the only available technique for effective 128 | > ordering of one's thoughts, that I know of. This is what I mean by "focusing 129 | > one's attention upon some aspect": it does not mean ignoring the other 130 | > aspects, it is just doing justice to the fact that from this aspect's point of 131 | > view, the other is irrelevant. 132 | 133 | Why 134 | 135 | - Simplify development and maintenance of software applications. 136 | - When concerns are well-separated, individual sections can be reused, as well 137 | as developed and updated independently. 138 | 139 | How 140 | 141 | - Break program functionality into separate modules that overlap as little as 142 | possible. 143 | 144 | Resources 145 | 146 | - [Separation of Concerns (wikipedia.org)][43] 147 | 148 | ## Code For The Maintainer 149 | 150 | Why 151 | 152 | - Maintenance is by far the most expensive phase of any project. 153 | 154 | How 155 | 156 | - _Be_ the maintainer. 157 | - Always code as if the person who ends up maintaining your code is a violent 158 | psychopath who knows where you live. 159 | - Always code and comment in such a way that if someone a few notches junior 160 | picks up the code, they will take pleasure in reading and learning from it. 161 | - [Don't make me think][44]. 162 | - Use the [Principle of Least Astonishment][45]. 163 | 164 | Resources 165 | 166 | - [Code For The Maintainer (wiki.c2.com)][46] 167 | - [The Noble Art of Maintenance Programming (blog.codinghorror.com)][47] 168 | 169 | ## Avoid Premature Optimization 170 | 171 | Quoting [Donald Knuth][48]: 172 | 173 | > Programmers waste enormous amounts of time thinking about, or worrying about, 174 | > the speed of non-critical parts of their programs, and these attempts at 175 | > efficiency actually have a strong negative impact when debugging and 176 | > maintenance are considered. We should forget about small efficiencies, say 177 | > about 97% of the time: premature optimization is the root of all evil. Yet we 178 | > should not pass up our opportunities in that critical 3%. 179 | 180 | Understanding what is and isn’t "premature" is critical. 181 | 182 | Why 183 | 184 | - It is unknown upfront where the bottlenecks will be. 185 | - After optimization, it might be harder to read and thus maintain. 186 | 187 | How 188 | 189 | - [Make It Work Make It Right Make It Fast (wiki.c2.com)][49] 190 | - Don't optimize until you need to, and only after profiling you discover a 191 | bottleneck to optimise. 192 | 193 | Resources 194 | 195 | - [Program optimization (wikipedia.org)][50] 196 | - [Premature Optimization (wiki.c2.com)][51] 197 | 198 | ## Optimize for Deletion 199 | 200 | Why 201 | 202 | Code should be optimized for change. Code that's easy to delete is easy to 203 | replace or change. 204 | 205 | How 206 | 207 | Don't try to predict future changes today, instead focus on deletable and 208 | rewriteable code. 209 | 210 | Principles such as [separation of concerns][6], [low coupling][13] and the 211 | [Single Responsibility Principle][22] result in increased deletability. In 212 | general, high modularity helps to increase deletability of individual parts. 213 | 214 | Resources 215 | 216 | - [The art of destroying software (youtube.com)][52] 217 | - [Optimize for Deletion (work.stevegrossi.com)][53] 218 | - [Deletability (kellysutton.com)][54] 219 | - [Write code that is easy to delete, not easy to extend.][55] 220 | 221 | ## Keep things DRY 222 | 223 | **Don't Repeat Yourself**: Every piece of knowledge must have a single, 224 | unambiguous, authoritative representation within a system. 225 | 226 | Each significant piece of functionality in a program should be implemented in 227 | just one place in the source code. Where similar functions are carried out by 228 | distinct pieces of code, it is generally beneficial to combine them into one by 229 | abstracting out the varying parts. 230 | 231 | Why 232 | 233 | - Duplication (inadvertent or purposeful duplication) can lead to maintenance 234 | nightmares, poor factoring, and logical contradictions. 235 | - A modification of any single element of a system does not require a change in 236 | other logically unrelated elements. 237 | - Additionally, elements that are logically related all change predictably and 238 | uniformly, and are thus kept in sync. 239 | 240 | How 241 | 242 | - Put business rules, long expressions, if statements, math formulas, metadata, 243 | etc. in only one place. 244 | - Identify the single, definitive source of every piece of knowledge used in 245 | your system, and then use that source to generate applicable instances of that 246 | knowledge (code, documentation, tests, etc). 247 | - Apply the [Rule of three][56]. 248 | 249 | Resources 250 | 251 | - [Dont Repeat Yourself (wiki.c2.com)][57] 252 | - [Don't repeat yourself (wikipedia.org)][58] 253 | - [DRY Principle: Its Benefit and Cost with Examples (thevaluable.dev)][59] 254 | 255 | Related 256 | 257 | - [Abstraction principle (wikipedia.org)][60] 258 | - [Once And Only Once (wiki.c2.com)][61] is a subset of DRY (also referred to as 259 | the goal of refactoring). 260 | - [Single Source of Truth (wikipedia.org)][62] 261 | - A violation of DRY is [WET][63] (Write Everything Twice) 262 | - [Be careful with the code metric "duplicated lines" 263 | (rachelcarmena.github.io)][64] 264 | 265 | ## Boy Scout Rule 266 | 267 | The Boy Scouts of America have a simple rule that we can apply to our 268 | profession: "Leave the campground cleaner than you found it". The boy scout rule 269 | states that we should always leave the code cleaner than we found it. 270 | 271 | Why 272 | 273 | - When making changes to an existing codebase the code quality tends to degrade, 274 | accumulating technical debt. Following the boy scout rule, we should mind the 275 | quality with each commit. Technical debt is resisted by continuous 276 | refactoring, no matter how small. 277 | 278 | How 279 | 280 | - With each commit make sure it does not degrade the codebase quality. 281 | - Any time someone sees some code that isn't as clear as it should be, they 282 | should take the opportunity to fix it right there and then. 283 | 284 | Resources 285 | 286 | - [Opportunistic Refactoring (martinfowler.com)][65] 287 | 288 | ## Connascence 289 | 290 | Connascence is a software quality metric that describes different levels and 291 | dimensions of coupling. Two components are connascent if a change in one would 292 | require a change in the other as well. Lower connascence means higher code 293 | quality. 294 | 295 | Why 296 | 297 | - Reducing connascence will reduce the cost of change for a software system. 298 | - Arguably one of the most important benefits of connascence is that it gives 299 | developers a vocabulary to talk about different types of coupling. 300 | 301 | How 302 | 303 | - Each instance of connascence in a codebase is considered on 3 separate axes: 304 | strength, degree and locality. 305 | - It provides a system for comparing different types of dependency. 306 | 307 | Resources 308 | 309 | - [Connascence (connascence.io)][66] 310 | - [Connascence (wikipedia.org)][67] 311 | 312 | ## Minimise Coupling 313 | 314 | Coupling between modules or components is their degree of mutual 315 | interdependence; lower coupling is better. In other words, coupling is the 316 | probability that code unit "B" will "break" after an unknown change to code unit 317 | "A". 318 | 319 | Why 320 | 321 | - A change in one module usually forces a ripple effect of changes in other 322 | modules. 323 | - Assembly of modules might require more effort and/or time due to the increased 324 | inter-module dependency. 325 | - A particular module might be harder to reuse and/or test because dependent 326 | modules must be included. 327 | - Developers might be afraid to change code because they aren't sure what might 328 | be affected. 329 | 330 | How 331 | 332 | - Eliminate, minimise, and reduce complexity of necessary relationships. 333 | - By hiding implementation details, coupling is reduced. 334 | - Apply the [Law of Demeter][14]. 335 | 336 | Resources 337 | 338 | - [Coupling (wikipedia.org)][68] 339 | - [Coupling And Cohesion (wiki.c2.com)][69] 340 | 341 | ## Law of Demeter 342 | 343 | Don't talk to strangers. 344 | 345 | Why 346 | 347 | - It usually tightens coupling 348 | - It might reveal too much implementation details 349 | 350 | How 351 | 352 | A method of an object may only call methods of: 353 | 354 | 1. The object itself. 355 | 2. An argument of the method. 356 | 3. Any object created within the method. 357 | 4. Any direct properties/fields of the object. 358 | 359 | Resources 360 | 361 | - [Law of Demeter (wikipedia.org)][70] 362 | - [The Law of Demeter Is Not A Dot Counting Exercise (haacked.com)][71] 363 | 364 | ## Composition Over Inheritance 365 | 366 | It is better to compose what an object can do than extend what it is. Compose 367 | when there is a "has a" (or "uses a") relationship, inherit when "is a". 368 | 369 | Why 370 | 371 | - Less coupling between classes. 372 | - Using inheritance, subclasses easily make assumptions, and break [LSP][72]. 373 | - Increase flexibility: accommodate future requirements changes, otherwise 374 | requiring restructuring of business-domain classes in the inheritance model. 375 | - Avoid problems often associated with relatively minor changes to an 376 | inheritance-based model including several generations of classes. 377 | 378 | How 379 | 380 | - Identify system object behaviors in separate interfaces, instead of creating a 381 | hierarchical relationship to distribute behaviors among business-domain 382 | classes via inheritance. 383 | - Test for [LSP][72] to decide when to inherit. 384 | 385 | Resources 386 | 387 | - [Composition over inheritance (wikipedia.org)][73] 388 | - [Favor Composition Over Inheritance (docs.microsoft.com)][74] 389 | 390 | ## Orthogonality 391 | 392 | > The basic idea of orthogonality is that things that are not related 393 | > conceptually should not be related in the system. 394 | 395 | Source: [Be Orthogonal][75] 396 | 397 | > It is associated with simplicity; the more orthogonal the design, the fewer 398 | > exceptions. This makes it easier to learn, read and write programs in a 399 | > programming language. The meaning of an orthogonal feature is independent of 400 | > context; the key parameters are symmetry and consistency. 401 | 402 | Source: [Orthogonality (wikipedia.org)][76] 403 | 404 | ## Robustness Principle 405 | 406 | > Be conservative in what you do, be liberal in what you accept from others 407 | 408 | Collaborating services depend on each others interfaces. Often the interfaces 409 | need to evolve causing the other end to receive unspecified data. A naive 410 | implementation refuses to collaborate if the received data does not strictly 411 | follow the specification. A more sophisticated implementation will still work 412 | ignoring the data it does not recognize. 413 | 414 | Why 415 | 416 | - Ensure that a provider can make changes to support new demands, while causing 417 | minimal breakage to their existing clients. 418 | 419 | How 420 | 421 | - Code that sends commands or data to other programs or machines should conform 422 | completely to the specifications, but code that receives input should accept 423 | non-conformant input as long as the meaning is clear. 424 | 425 | Resources 426 | 427 | - [Robustness Principle (wikipedia.org)][77] 428 | - [Tolerant Reader (martinfowler.com)][78] 429 | 430 | ## Inversion of Control 431 | 432 | IoC inverts the flow of control. It's also known as the Hollywood Principle, 433 | "Don't call us, we'll call you". A design principle in which custom-written 434 | portions of a computer program receive the flow of control from a generic 435 | framework. It carries the strong connotation that the reusable code and the 436 | problem-specific code are developed independently even though they operate 437 | together in an application. 438 | 439 | Why 440 | 441 | - Increase modularity of the program and make it extensible. 442 | - To decouple the execution of a task from implementation. 443 | - To focus a module on the task it is designed for. 444 | - To free modules from assumptions about other systems and instead rely on 445 | contracts. 446 | - To prevent side effects when replacing a module. 447 | 448 | How 449 | 450 | - Using Factory pattern 451 | - Using Service Locator pattern 452 | - Using Dependency Injection 453 | - Using contextualized lookup 454 | - Using Template Method pattern 455 | - Using Strategy pattern 456 | 457 | Resources 458 | 459 | - [Inversion of Control (wikipedia.org)][79] 460 | - [Inversion of Control Containers and the Dependency Injection pattern 461 | (martinfowler.com)][80] 462 | 463 | ## Maximise Cohesion 464 | 465 | Cohesion of a single module or component is the degree to which its 466 | responsibilities form a meaningful unit. Higher cohesion is better. 467 | 468 | Why 469 | 470 | - Reduced module complexity 471 | - Increased system maintainability, because logical changes in the domain affect 472 | fewer modules, and because changes in one module require fewer changes in 473 | other modules. 474 | - Increased module reusability, because application developers will find the 475 | component they need more easily among the cohesive set of operations provided 476 | by the module. 477 | 478 | How 479 | 480 | - Group related functionalities sharing a single responsibility (e.g. in a 481 | module or class). 482 | 483 | Resources 484 | 485 | - [Cohesion (wikipedia.org)][81] 486 | - [Coupling And Cohesion (wiki.c2.com)][69] 487 | 488 | ## Liskov Substitution Principle 489 | 490 | The LSP is all about expected behavior of objects: 491 | 492 | > Objects in a program should be replaceable with instances of their subtypes 493 | > without altering the correctness of that program. 494 | 495 | **LSP** is the L in [SOLID][29]. 496 | 497 | Resources 498 | 499 | - [Liskov substitution principle (wikipedia.org)][82] 500 | - [The Liskov Substitution Principle Explained (reflectoring.io)][83] 501 | 502 | ## Open/Closed Principle 503 | 504 | Software entities (e.g. classes) should be open for extension, but closed for 505 | modification. Such an entity can allow its behavior to be modified, without 506 | altering its source code. 507 | 508 | **Open/Closed** is the O in [SOLID][29]. 509 | 510 | Why 511 | 512 | - Improve maintainability and stability by minimizing changes to existing code. 513 | 514 | How 515 | 516 | - Write classes that can be extended (as opposed to classes that can be 517 | modified). 518 | - Expose only the moving parts that need to change, hide everything else. 519 | 520 | Resources 521 | 522 | - [Open Closed Principle (wikipedia.org)][84] 523 | - [The Open Closed Principle (blog.cleancoder.com)][85] 524 | 525 | ## Single Responsibility Principle 526 | 527 | A class should never have more than one reason to change. 528 | 529 | Long version: Every class should have a single responsibility, and that 530 | responsibility should be entirely encapsulated by the class. Responsibility can 531 | be defined as a reason to change, so a class or module should have one, and only 532 | one, reason to change. 533 | 534 | **SRP** is the S in [SOLID][29]. 535 | 536 | Why 537 | 538 | - Maintainability: changes should be necessary only in one module or class. 539 | 540 | How 541 | 542 | - Apply [Curly's Law][86]. 543 | 544 | Resources 545 | 546 | - [Single responsibility principle (wikipedia.org)][87] 547 | 548 | ## Hide Implementation Details 549 | 550 | A software module hides information (i.e. implementation details) by providing 551 | an interface, and not leak any unnecessary information. 552 | 553 | Why 554 | 555 | - When the implementation changes, the interface clients are using does not have 556 | to change. 557 | 558 | How 559 | 560 | - Minimize accessibility of classes and members. 561 | - Don’t expose member data in public. 562 | - Avoid putting private implementation details into a class’s interface. 563 | - Decrease coupling to hide more implementation details. 564 | 565 | Resources 566 | 567 | - [Information hiding (wikipedia.org)][88] 568 | 569 | ## Curly's Law 570 | 571 | Curly's Law is about choosing a single, clearly defined goal for any particular 572 | bit of code: Do One Thing. 573 | 574 | - [Curly's Law: Do One Thing (blog.codinghorror.com)][89] 575 | - [The Rule of One or Curly’s Law (grsmentor.com)][90] 576 | 577 | ## Encapsulate What Changes 578 | 579 | A good design identifies the hotspots that are most likely to change and 580 | encapsulates them behind an interface. When an anticipated change then occurs, 581 | the modifications are kept local. 582 | 583 | Why 584 | 585 | - To minimize required modifications when a change occurs. 586 | 587 | How 588 | 589 | - Encapsulate the concept that varies behind an interface. 590 | - Possibly separate the varying concept into its own module. 591 | 592 | Resources 593 | 594 | - [Encapsulate the Concept that Varies (principles-wiki.net)][91] 595 | - [Encapsulate What Varies (blogs.msdn.microsoft.com)][92] 596 | - [Information hiding (wikipedia.org)][88] 597 | 598 | ## Interface Segregation Principle 599 | 600 | Reduce fat interfaces into multiple smaller and more specific client specific 601 | interfaces. An interface should be more dependent on the code that calls it than 602 | the code that implements it. 603 | 604 | **ISP** is the I in [SOLID][29]. 605 | 606 | Why 607 | 608 | - Keep a system decoupled and thus easier to refactor, change, and redeploy. 609 | 610 | How 611 | 612 | - Avoid fat interfaces. Classes should never have to implement methods that 613 | violate the [Single responsibility principle][22]. 614 | 615 | Resources 616 | 617 | - [Interface segregation principle (wikipedia.org)][93] 618 | 619 | ## Command Query Separation 620 | 621 | The Command Query Separation principle states that each method should be either 622 | a command that performs an action, or a query that returns data to the caller 623 | but not both. Asking a question should not modify the answer. 624 | 625 | With this principle applied the programmer can code with much more confidence. 626 | The query methods can be used anywhere and in any order since they do not mutate 627 | the state. With commands one has to be more careful. 628 | 629 | Why 630 | 631 | - By clearly separating methods into queries and commands the programmer can 632 | code with additional confidence without knowing each method's implementation 633 | details. 634 | 635 | How 636 | 637 | - Implement each method as either a query or a command 638 | - Apply naming convention to method names that implies whether the method is a 639 | query or a command 640 | 641 | Resources 642 | 643 | - [Command Query Separation (wikipedia.org)][94] 644 | - [Command Query Separation (martinfowler.com)][95] 645 | 646 | ## Dependency Inversion Principle 647 | 648 | Dependency Inversion is the strategy of depending upon interfaces or abstract 649 | functions and classes rather than upon concrete functions and classes. Simply 650 | put, when components of our system have dependencies, we don’t want to directly 651 | inject a component’s dependency into another. Instead, we should use a level of 652 | abstraction between them. 653 | 654 | **DIP** is the D in [SOLID][29]. 655 | 656 | Why 657 | 658 | - By decoupling the high-level modules from the low-level modules, the 659 | high-level modules become more reusable and maintainable. 660 | - Facilitates unit testing by allowing the use of mock objects, enabling 661 | isolated testing of modules. 662 | - Reduces the risk of breaking the system when changes are made. 663 | - Allows adding new implementations without changing the existing code, 664 | enhancing the system's extensibility. 665 | - Concrete classes change frequently, while abstractions and interfaces change 666 | much less. 667 | 668 | How 669 | 670 | - Define interfaces to capture behavior and use them to define the dependencies 671 | of a class. 672 | - Depends on abstractions, not on concretions. 673 | - Using patterns like Factory, Service Locator, and Dependency Injection. 674 | - Use the [Inversion of Control][18] principle. 675 | 676 | Resources 677 | 678 | - [SOLID — Dependency Inversion Principle][96] 679 | - [Dependency inversion principle (wikipedia.org)][97] 680 | - [System Design: Dependency Inversion Principle][98] 681 | 682 | ## SOLID 683 | 684 | A subset of programming principles: 685 | 686 | - [Single Responsibility Principle][22] 687 | - [Open/Closed Principle][21] 688 | - [Liskov Substitution Principle][20] 689 | - [Interface Segregation Principle][26] 690 | - [Dependency Inversion Principle][28] 691 | 692 | ## FIRST principles of testing 693 | 694 | The FIRST testing principles mean that tests should be Fast, Isolated, 695 | Repeatable, Self-validating and Timely. 696 | 697 | Resources 698 | 699 | - [F.I.R.S.T.][99] 700 | 701 | ## Arrange, Act, Assert 702 | 703 | The 3A's are a pattern to arrange and format code in unit tests. _Arrange_ all 704 | necessary preconditions and inputs. _Act_ on the object or method under test. 705 | _Assert_ that the expected results have occurred. 706 | 707 | Resources 708 | 709 | - [Arrange Act Assert (wiki.c2.com)][100] 710 | - [3A - Arrange, Act, Assert (xp123.com)][101] 711 | 712 | [1]: https://www.artima.com/weblogs/viewpost.jsp?thread=331531 713 | [2]: https://github.com/webpro/programming-principles/issues 714 | [3]: #kiss 715 | [4]: #yagni 716 | [5]: #do-the-simplest-thing-that-could-possibly-work 717 | [6]: #separation-of-concerns 718 | [7]: #code-for-the-maintainer 719 | [8]: #avoid-premature-optimization 720 | [9]: #optimize-for-deletion 721 | [10]: #keep-things-dry 722 | [11]: #boy-scout-rule 723 | [12]: #connascence 724 | [13]: #minimise-coupling 725 | [14]: #law-of-demeter 726 | [15]: #composition-over-inheritance 727 | [16]: #orthogonality 728 | [17]: #robustness-principle 729 | [18]: #inversion-of-control 730 | [19]: #maximise-cohesion 731 | [20]: #liskov-substitution-principle 732 | [21]: #openclosed-principle 733 | [22]: #single-responsibility-principle 734 | [23]: #hide-implementation-details 735 | [24]: #curlys-law 736 | [25]: #encapsulate-what-changes 737 | [26]: #interface-segregation-principle 738 | [27]: #command-query-separation 739 | [28]: #dependency-inversion-principle 740 | [29]: #solid 741 | [30]: #first-principles-of-testing 742 | [31]: #arrange-act-assert 743 | [32]: https://en.wikipedia.org/wiki/KISS_principle 744 | [33]: http://principles-wiki.net/principles:keep_it_simple_stupid 745 | [34]: https://github.com/zakirullin/cognitive-load 746 | [35]: 747 | https://florian-kraemer.net/software-architecture/2024/07/25/The-Limits-of-Human-Cognitive-Capacities-in-Programming.html 748 | [36]: https://eugeneyan.com/writing/simplicity/ 749 | [37]: https://seeinglogic.com/posts/visual-readability-patterns/ 750 | [38]: http://c2.com/xp/YouArentGonnaNeedIt.html 751 | [39]: https://ronjeffries.com/xprog/articles/practices/pracnotneed/ 752 | [40]: https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it 753 | [41]: http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html 754 | [42]: https://en.wikipedia.org/wiki/Edsger_W._Dijkstra 755 | [43]: https://en.wikipedia.org/wiki/Separation_of_concerns 756 | [44]: http://www.sensible.com/dmmt.html 757 | [45]: https://en.wikipedia.org/wiki/Principle_of_least_astonishment 758 | [46]: http://wiki.c2.com/?CodeForTheMaintainer 759 | [47]: https://blog.codinghorror.com/the-noble-art-of-maintenance-programming/ 760 | [48]: https://en.wikiquote.org/wiki/Donald_Knuth 761 | [49]: http://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast 762 | [50]: https://en.wikipedia.org/wiki/Program_optimization 763 | [51]: http://wiki.c2.com/?PrematureOptimization 764 | [52]: https://www.youtube.com/watch?v=Ed94CfxgsCA 765 | [53]: https://work.stevegrossi.com/2016/11/04/optimize-for-deletion/ 766 | [54]: https://kellysutton.com/2017/05/29/deletability.html 767 | [55]: 768 | https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to 769 | [56]: https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) 770 | [57]: http://wiki.c2.com/?DontRepeatYourself 771 | [58]: https://en.wikipedia.org/wiki/Don't_repeat_yourself 772 | [59]: https://thevaluable.dev/dry-principle-cost-benefit-example/ 773 | [60]: https://en.wikipedia.org/wiki/Abstraction_principle_(computer_programming) 774 | [61]: http://wiki.c2.com/?OnceAndOnlyOnce 775 | [62]: https://en.wikipedia.org/wiki/Single_Source_of_Truth 776 | [63]: http://thedailywtf.com/articles/The-WET-Cart 777 | [64]: 778 | https://rachelcarmena.github.io/2018/02/27/duplication-you-are-welcome.html 779 | [65]: https://martinfowler.com/bliki/OpportunisticRefactoring.html 780 | [66]: https://connascence.io 781 | [67]: https://en.wikipedia.org/wiki/Connascence 782 | [68]: https://en.wikipedia.org/wiki/Coupling_(computer_programming) 783 | [69]: http://wiki.c2.com/?CouplingAndCohesion 784 | [70]: https://en.wikipedia.org/wiki/Law_of_Demeter 785 | [71]: https://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/ 786 | [72]: #lsp 787 | [73]: https://en.wikipedia.org/wiki/Composition_over_inheritance 788 | [74]: 789 | https://docs.microsoft.com/en-us/archive/blogs/thalesc/favor-composition-over-inheritance 790 | [75]: https://www.artima.com/intv/dry3.html 791 | [76]: https://en.wikipedia.org/wiki/Orthogonality_(programming) 792 | [77]: https://en.wikipedia.org/wiki/Robustness_principle 793 | [78]: https://martinfowler.com/bliki/TolerantReader.html 794 | [79]: https://en.wikipedia.org/wiki/Inversion_of_control 795 | [80]: https://www.martinfowler.com/articles/injection.html 796 | [81]: https://en.wikipedia.org/wiki/Cohesion_(computer_science) 797 | [82]: https://en.wikipedia.org/wiki/Liskov_substitution_principle 798 | [83]: https://reflectoring.io/lsp-explained/ 799 | [84]: https://en.wikipedia.org/wiki/Open/closed_principle 800 | [85]: 801 | https://blog.cleancoder.com/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html 802 | [86]: #curlys-Law 803 | [87]: https://en.wikipedia.org/wiki/Single_responsibility_principle 804 | [88]: https://en.wikipedia.org/wiki/Information_hiding 805 | [89]: https://blog.codinghorror.com/curlys-law-do-one-thing/ 806 | [90]: http://grsmentor.com/blog/the-rule-of-one-or-curlys-law/ 807 | [91]: http://principles-wiki.net/principles:encapsulate_the_concept_that_varies 808 | [92]: 809 | https://blogs.msdn.microsoft.com/steverowe/2007/12/26/encapsulate-what-varies/ 810 | [93]: https://en.wikipedia.org/wiki/Interface_segregation_principle 811 | [94]: https://en.wikipedia.org/wiki/Command%E2%80%93query_separation 812 | [95]: https://martinfowler.com/bliki/CommandQuerySeparation.html 813 | [96]: 814 | https://medium.com/@inzuael/solid-dependency-inversion-principle-part-5-f5bec43ab22e 815 | [97]: https://en.wikipedia.org/wiki/Dependency_inversion_principle 816 | [98]: https://www.baeldung.com/cs/dip 817 | [99]: https://agileinaflash.blogspot.com/2009/02/first.html 818 | [100]: https://wiki.c2.com/?ArrangeActAssert 819 | [101]: https://xp123.com/articles/3a-arrange-act-assert/ 820 | --------------------------------------------------------------------------------