I have the week off from Lambda School due to Thanksgiving. To take advantage of that, I’ve been working on refactoring my portfolio site and upgrading it from JavaScript to React. I’m turning it into a Single-Page Application, but I ran into a little blocker that I’m trying to puzzle out.
I took a break this AM and decided to just check YouTube and learn a little about software design patterns, which are something that I’ve heard of but have no real understanding of. What I’ve learned so far makes them seem really useful for providing a design philosophy for how to construct components, or even what components to construct.
https://www.youtube.com/watch?v=WV2Ed1QTst8
Design patterns basically exist to provide a paradigm about how data flow, component communication and relationships in an application should work. Following one is supposed to help reduce code complexity and safeguard against potential bugs by providing a known, predictable method of flow and of thought. It helps reduce the likeliness of spaghetti code and of two-way data flow, which I know from React is something to be avoided in preference of a single source of truth for the state of data. Its also supposed to make code easier to read.
Anyway, I watched a video from the TechLead in which he spoke about some of his favorite design patterns. Afterward, the first two comments in the chat really stood out to me, and are the reason that I decided to post. Here they are:
veganaiZe
This is one of the most important, as well as overlooked, topics in software engineering. Tech focuses a lot more on the “Patterns” during this talk than on “Principles”. These software design patterns offer ways to accomplish certain behaviors, within a program, and also serve to benefit programmer communication. They all stand upon and are justified by principles.
I think the most important principles are the following:
D.R.Y. – Don’t Repeat Yourself – Pretty much self-explanatory. If you are re-writing the same block(s) of code in various places then you are ensuring that you’ll have multiple places to change it later. This is probably the #1 warning flag that you should look into an alternative/pattern.
Y.A.G.N.I – You Ain’t Gonna Need It – Don’t code out every little detail that you can possibly think of because, in reality, you probably won’t end up needing much of it. So just implement what is absolutely necessary (save the GUI until later, for example!)
K.I.S.S. – Keep It Stupid Simple – When in doubt, make it easy to understand. Don’t try to build in too much complexity. If a particular design pattern overly complicates things (vs. an alternative or none at all) then don’t implement it. This applies heavily to user interface design and APIs (application programming interfaces).
P.O.L.A. – Principle Of Least Astonishment – This has overlap with KISS… Do the least astonishing thing. In other words: DON’T BE CLEVER. It’s nice that you can squeeze a ton of detail into a single line of code. But your future self and other developers will judge it by the number of “F”-words per minute when they open your source file. It should be relatively easy to jump into what your code is doing, even for an outsider who isn’t quite as clever as you are.
Last, and most certainly NOT least…
S.O.L.I.D. (I saved this for last because it’s more specific, but it should probably land around #2 on this list)
Single Responsibility – A class should have only one reason to change; Do one thing and do it well.
Open/Closed Principle – A class should be open for “extension” but closed for “modification”.
L. Substitution Principle – Derived (sub) classes should fit anywhere that their base (super) class does.
Interface Segregation – Multiple specific interfaces are better than one general-purpose interface.
Dependency Inversion – Depend on abstractions NOT on concrete implementations. (Depend on abstract classes and interfaces, which can’t be instantiated, rather then any specific instance)

Of the above, I’ve heard of DRY and KISS. DRY is stressed at Lambda, and is a principle that I do keep in mind when coding. KISS is something that I’ve heard since I was a kid, back in grade school. POLA is something I’ve heard discussed, but by concept, not by name.
Here’s the other comment that stood out to me. This one detailed some of the video, itself:
Isaac
1. @3:00 Break programs into logically independent components, allowing component dependencies where necessary.
2. @3:10 Inspect your data objects and graph their interactions/where they flow. Keep classes simple. Keep one-way dataflow/interactions simple.
@3:29 Simplicity — keep a small number of class types (controller, views, data objects) avoid creating classes that aliases those classes (managers, coordinators, helpers, handlers, providers, executor). @4:02 — Keep dataflow simple (e.g., don’t let Views have business logic; views shouldn’t need to communicate any data upstream).
3. @4:33 Keep data model objects pruned of logic, except if the logic is part of the objects’ states. Single Responsibility Principle. If you can’t describe a class’s responsibility straightforwardly, it’s too complex.
4. @5:25 Inspect class composition (“follow ownership graph”). Follow the life of a child (composed) object to make sure that accessibility to and operations done on that object is managed.
5. @5:55 Singletons (“basically globals floating in a system”). Use dependency injection (?) to ‘scope singletons’ and make them testable (?). Singletons often represent independent (uncoupled) objects which is good for representing independent execution flow. Too many inter-communicating singletons in a system make it difficult to trace data flow and understand the overall transformation of the data through the system.
6. @6:50 Singleton communication patterns. Singletons expose Publisher/Subscriber interface (one publisher object, many subscriber objects listening to events).
7. @7:41 Delegate communication pattern. (?)
8.@8:02 Chain of Responsibility Pattern. Hierarchical data flow — unhandled events bubble upwards to parent objects who should handle them. Conflicts with (2) by allowing upstream dataflow. Use with discretion.
9. @8:53 OOP’s Inheritance can create tightly coupled hierarchical objects that are hard to refactor (object dependencies). Use composition pattern to allow flexibility in what the container object can do.
10. @9:58 Lazy initialization. Startup performance boost.
11. @10:06 Adapter Pattern.
12. @10:26 Factory builder classes.

While the above comments might not directly be design patterns, I think that their thinking can definitely inform best practices. Wikipedia has a list of design patterns available, and there are books and videos published on the subject. I’m looking at Head First Design Patterns as a primer on the subject.