1. others
1.1. styles
1.1.1. bad
1.1.1.1. Very bad
1.1.2. good
1.1.2.1. very good
1.1.3. not as good
1.1.4. not as bad
1.1.5. important
1.1.5.1. Very important
1.1.6. warning
1.1.7. link
1.2. AUTHOR
1.2.1. Nima Shokouhfar
1.2.1.1. Linkedin
1.2.1.1.1. Follow me on LinkedIn to stay updated on my latest professional insights and tech projects!
1.2.1.2. Youtube
1.2.1.2.1. code with nima
1.2.1.2.2. ideariver
1.2.1.3. Medium
1.2.1.3.1. ✍️ Follow me on Medium to read my latest articles on tech, coding, and innovation!
1.2.1.4. Github
1.2.1.4.1. ⭐️ Give my projects a star on GitHub and explore my repositories to discover new tools and innovations!
1.2.1.4.2. 💖 Sponsor me on GitHub to support my open-source contributions and help me create even more useful projects!
1.2.1.5. upwork
1.2.1.5.1. 💼 Hire me on Upwork for freelance projects. Let’s work together to bring your tech ideas to life!
1.2.1.6. main website: ideariver.ca
1.2.1.6.1. 🚀 Visit IdeaRiver.ca for all my latest projects, blogs, and ways to connect!
1.3. Styling Version
1.3.1. 3.0.1
2. main
2.1. Objective
2.1.1. in a nutshell
2.1.1.1. create a system that can pass the test of time
2.1.1.1.1. scalability
2.1.1.1.2. dependency control
2.1.1.1.3. reliability
2.1.1.1.4. reusability
2.1.1.1.5. extensibility
2.1.1.1.6. interprobabibility
2.1.1.1.7. standardization
2.1.1.1.8. being agnostic
2.1.1.1.9. low barrier to entery, high celling
2.1.1.1.10. be agile
2.1.1.1.11. business side
2.1.1.2. since failure is inevitable, let's embrace it
2.1.2. detail
2.1.2.1. Scalability
2.1.2.1.1. example
2.1.2.2. Dependency control
2.1.2.2.1. decoupling
2.1.2.2.2. example
2.1.2.3. Maintainability
2.1.2.3.1. single source of truth
2.1.2.3.2. solid principles
2.1.2.3.3. test driven development
2.1.2.3.4. back compatibility matters
2.1.2.3.5. issues
2.1.2.4. reliability
2.1.2.4.1. automated test
2.1.2.4.2. ci cd
2.1.2.4.3. infrastructure as a code
2.1.2.4.4. Why?
2.1.2.5. interprobability
2.1.2.5.1. open portocols
2.1.2.5.2. plugin systems
2.1.2.5.3. Why?
2.1.2.6. reusability
2.1.2.6.1. example
2.1.2.6.2. Why?
2.1.2.7. standardization
2.1.2.7.1. follow standards
2.1.2.7.2. not reinventing the wheel
2.1.2.7.3. repeatability of the patterns
2.1.2.7.4. Why?
2.1.2.8. extensibility
2.1.2.8.1. example
2.1.2.8.2. Open close principle
2.1.2.8.3. Why?
2.1.2.9. being agnostic
2.1.2.10. low barrier to entery, high celling
2.1.2.11. be agile
2.1.2.11.1. refactoring
2.1.2.11.2. iteration
2.2. Solid principles
2.3. tdd
2.3.1. why
2.3.1.1. automated test
2.3.1.1.1. especially, for multiple instances of same class
2.3.1.1.2. plugin systems
2.3.1.1.3. Sometimes, it is faster to test a functionality by automated tests than doing it manually
2.3.1.2. catch bugs that are extremely difficult to create manually
2.3.1.3. refactoring
2.3.1.3.1. When changing the code, you do not create a time bomb
2.3.1.4. Maintenance
2.3.1.4.1. Passing to other engineers
2.3.1.5. Performance testing
2.3.1.5.1. Execution time testing
2.4. domain driven design
2.4.1. uncle bob clean architecture
2.4.1.1. objective
2.4.1.1.1. the separation of concerns
2.4.1.2. The Dependency Rule
2.4.1.2.1. The concentric circles represent different areas of software
2.4.1.2.2. This rule says that source code dependencies can only point inwards.
2.4.1.2.3. LAYERS
2.4.1.3. Styles
2.4.1.3.1. bad
2.4.1.3.2. good
2.4.1.3.3. not as good
2.4.1.3.4. not as bad
2.4.1.3.5. important
2.4.1.3.6. warning
2.5. dependency control
2.5.1. god objects
2.5.2. object drilling
2.5.3. dependency injection
2.6. abstraction / interfaces
2.6.1. Why we do abstraction?
2.6.1.1. enable some well know patterns
2.6.1.1.1. plugin systems
2.6.1.1.2. Decorator
2.6.1.1.3. chain of responsibility
2.6.1.2. to ship first and develop later
2.6.1.3. TDD
2.6.1.3.1. Write test first and implement later
2.7. This principle simply says that you should introduce abstraction between high-level and low-level classes that allows us to decouple the high-level and low-level classes from each other.
2.7.1. If classes depend on each other then they are tightly coupled to each other.
2.7.1.1. When classes are tightly coupled then change in any one class triggers changes in all other dependent classes as wel
2.7.1.2. Instead, low-level classes should implement contracts using an interface
2.7.1.3. high-level classes should make use of these contracts to access concrete types
2.8. Code Smells
2.8.1. Bloaters
2.8.1.1. Long Method
2.8.1.2. Primitive Obsession
2.8.1.3. Data Clumps
2.8.1.4. Large Class
2.8.1.5. Long Parameter List
2.8.2. Object-Orientation Abusers
2.8.2.1. Alternative Classes with Different Interfaces
2.8.2.2. Refused Bequest
2.8.2.3. Switch Statements
2.8.2.4. Temporary Field
2.8.3. Change Preventers
2.8.3.1. Divergent Change
2.8.3.2. Parallel Inheritance Hierarchies
2.8.3.3. Shotgun Surgery
2.8.4. Dispensables
2.8.4.1. Comments
2.8.4.2. Data Class
2.8.4.3. Lazy Class
2.8.4.4. Duplicate Code
2.8.4.5. Dead Code
2.8.4.6. Speculative Generality
2.8.5. Couplers
2.8.5.1. Feature Envy
2.8.5.2. Incomplete Library Class
2.8.5.3. Middle Man
2.8.5.4. Inappropriate Intimacy
2.8.5.5. Message Chains
2.8.5.5.1. In code you see a series of calls resembling a->b()->c()->d()
2.9. setters & getters
2.9.1. Why?
2.9.1.1. You want to have a gateway to control the access to properties
2.9.1.1.1. application examples
2.9.1.2. avoid redefinition of a property
2.9.1.2.1. Setting a variable directly gives control to outside code like
2.9.1.2.2. code
2.9.1.2.3. Solution
2.9.1.3. easy relocation of data
2.9.1.3.1. Maybe in the original code, accessing data directly could be ok
2.9.1.3.2. However, based on requirements you may want to relocate the data to a database, file, or cache
2.9.1.4. Legacy codes without setter and getters are extremely unmaintainable
2.10. mono repo
2.11. single source of truth
2.11.1. database
2.12. event driven design
2.12.1. cqrs
2.12.2. saga
2.12.3. data redundancy
2.13. ci cd
2.13.1. Publish packages
2.13.2. update production floor
2.14. patterns
2.14.1. Repository
2.14.2. unit of work
2.14.3. Saga pattern
2.14.4. Specification pattern
2.14.5. Fluent API
2.14.6. Mediator
2.14.7. chain of responsibility
2.14.8. observer
2.14.9. Template method
2.14.9.1. Main
2.15. API first approach
2.15.1. modern
2.15.2. Traditional "code-first"
2.15.2.1. development can result in delays, rework, and a disjointed developer experience due to late API integration.
2.15.3. API-first design
2.15.3.1. It prioritizes the API's creation before the main application, promoting better cohesion and future integrations.
2.15.3.2. API-first methods align with agile practices,
2.15.3.2.1. allowing early stakeholder feedback and design adaptability.
2.15.3.3. API-first development emphasizes making functionalities available as APIs initially,
2.15.3.3.1. ensuring stability and predictability.
2.15.3.4. API-first design involves thorough planning before building the API,
2.15.3.4.1. focusing on functionality, scalability, and developer experience.
2.15.3.5. Hiram's Law
2.15.3.5.1. "With a sufficient number of users of an API, it does not matter what you promise in the contract; all observable behaviors of your system will be depended on by somebody."
2.15.3.5.2. highlights the challenge of separating interface from implementation
2.15.3.5.3. the importance of understanding consumer reliance.
2.15.3.5.4. in simple form
2.16. ID VS NameTag
2.16.1. Does having a name tag in addition to an ID defeat the purpose of using an ID?
2.16.1.1. Purpose of an ID vs. Name Tag
2.16.1.1.1. ID (Unique Identifier)
2.16.1.1.2. Name Tag (Display Name)
2.16.1.2. Examples of Systems Using Both
2.16.1.2.1. npm
2.16.1.2.2. GitHub
2.16.1.2.3. Databases
2.16.1.3. Why Both are Useful
2.16.1.3.1. Changing Names Over Time
2.16.1.3.2. Disambiguation
2.16.1.3.3. Version Management
2.16.1.4. Trade-Off Without a Name Tag
2.16.1.4.1. IDs alone are not user-friendly for search, filtering, and UI/UX.
2.16.1.4.2. If you only use names, you may encounter duplication issues, as names might not be unique or consistent.
2.16.1.4.3. Without nameTags, IDs become cumbersome for programmers to track and refer to.
2.16.1.5. Trade-Off Without an ID
2.16.1.5.1. Name Tags Only