3. DEFINITIONS
• SOFTWARE ENTITY
• STATEMENT / LINE / METHOD / CLASS / PACKAGE / SERVICE
• COMPONENT
• LOGICAL GROUP OF SOFTWARE ENTITIES.
• PACKAGE
• PHYSICAL (E.G. DIRECTORY, PHAR, JAR, GEM) GROUP OF SOFTWARE ENTITIES
• COLLOCATION:- PUTTING THINGS IN THE SAME COMPONENT / PACKAGE
• COHESION :- THINGS THAT ARE CHANGED TOGETHER
• COUPLING :- DEPENDENCY THAT POTENTIALLY PROPAGATES CHANGE
4. COHESION
• Cohesion is Intra – Module Concept.
• Its Indication of the relationship within module.
• Cohesion shows the module’s relative functional
strength.
• Cohesion is a degree (quality) to which a component /
module focuses on the single thing.
• Low cohesion would mean that the class does a great
variety of actions and is not focused on what it should
do.
• High cohesion would then mean that the class is
focused on what it should be doing.
• Strive for High Cohesion i.e. a cohesive component/
module focus on a single task (i.e., single-mindedness)
with little interaction with other modules of the system.
COUPLING
• Coupling is Inter -Module Concept.
• Its Indication of the relationships between modules.
• Coupling shows the relative independence among the
modules.
• Coupling is a degree to which a component / module is
connected to the other modules.
• Low coupling would mean that changing something
major in one class should not affect the other.
• High coupling would make your code difficult to make
changes as well as to maintain it
• Strive for Low Coupling i.e. dependency between
modules should be less.
All good software design will go for HIGH COHESION and LOW COUPLING.
5. WHAT IS SOLID?
• SOLID IS A MNEMONIC ACRONYM INTRODUCED BY MICHAEL FEATHERS
• FOR THE "FIRST FIVE PRINCIPLES" NAMED BY ROBERT C. MARTIN (UNCLE BOB) IN THE EARLY 2000.
• SINGLE RESPONSIBILITY PRINCIPLE (SRP)
• OPEN/CLOSED PRINCIPLE (OCP)
• LISKOV SUBSTITUTION PRINCIPLE (LSP)
• INTERFACE SEGREGATION PRINCIPLE (ISP)
• DEPENDENCY INVERSION PRINCIPLE (DIP)
• IT IS PART OF AN OVERALL STRATEGY OF AGILE AND ADAPTIVE SOFTWARE DEVELOPMENT
6. WHY SOLID?
• CHANGE IS ONLY THE CONSTANT.
• YOUR SOFTWARE IS BOUND TO CHANGE.
• WHEN YOU MAKE CHANGES TO OUR SOURCE IT TENDS TO ROT, IF ITS NOT PROPERLY DESIGN.
• IF THIS ROT ISN’T CORRECTED AS CHANGES HAPPEN THE SOURCE BECOMES UNMAINTAINABLE.
• CODE SMELLS ARE ARE SYMPTOMS OR ANTI-PATTERNS IN YOUR CODE WHICH INDICATE ROT.
• SOLID PRINCIPLES HELPS US TO WRITE CODE WHICH IS
• LOOSELY COUPLED
• HIGHLY COHESIVE
• MAINTAINABLE
• EASY TO EXTEND
• EASILY TESTABLE
7. WHEN SHOULD SOLID BE APPLIED?
• WHILE WORKING ON SOFTWARE TO REMOVE CODE SMELLS
• BY PROVIDING A FRAMEWORK THROUGH WHICH THE PROGRAMMER MAY REFACTOR THE SOFTWARE'S SOURCE CODE UNTIL
IT IS BOTH LEGIBLE AND EXTENSIBLE.
• REMEMBER THE AGILE PRINCIPAL YAGNI (“YOU'RE NOT GOING TO NEED IT”).
• ONLY APPLY SOLID WHEN REQUIRED OR
• ONLY WHEN YOU SMELL ROT IN YOUR CODE.
• USE TEST DRIVEN DEVELOPMENT (TDD) AND START WITH THE SIMPLEST THING THAT COULD POSSIBLY WORK.
• CODE SMELLS & DESIGN SMELL WILL DEVELOP AS YOU ADD NEW TESTS AND APPLY CHANGE TO YOUR CODE.
• THIS IS THE TIME TO APPLY SOLID.
8. DESIGN SMELL
• RIGIDITY
• DIFFICULT TO CHANGE. (EVERY/SMALL CHANGE CAUSES TOO MANY CHANGES IN OTHER PARTS OF THE SYSTEM)
• KNOWN EFFORT
• FRAGILITY
• EASILY BREAKABLE (EACH CHANGE BREAKS DISTANT AND UNRELATED THINGS)
• UNKNOWN EFFORT
• IMMOBILITY
• REUSE IS IMPOSSIBLE (THE CODE IS HOPELESSLY ENTANGLED)
• EXTRA EFFORT
• VISCOSITY
• COST OF ESSENTIAL OPERATIONS (CHECK-IN, CHECK-OUT AND MERGE) IS HIGH.
• CONTINUOUS EXTRA EFFORT(TIME)
• NEEDLESS COMPLEXITY
• BUILD SOFTWARE CONSIDERING FUTURE REQUIREMENT/EXTENSION
9. RIGIDITY
• WHAT IS RIGIDITY?
• EXISTING CODE THAT CAUSES EFFORT (KNOWN EFFORT)
• HARD TO CHANGE; MINOR CHANGE TAKES LOT OF TIME.
• TAKES MORE TIME TO TEST AND REBUILD FOR SMALL CHANGE.
• WHAT CAUSES RIGIDITY?
• COUPLING
10. FRAGILITY
● WHAT IS FRAGILITY?
○ EXISTING CODE THAT CAUSES RISK (UNKNOWN EFFORT)
○ SMALL CHANGE IS ONE MODULE CAUSES MISBEHAVIOUR OF OTHER MODULE.
○ EXAMPLE : ADJUSTING RADIO IN CAR IT OPENS WINDOW GLASS.
● WHAT CAUSES FRAGILITY?
○ COUPLING
○ LACK OF COHESION
11. IMMOBILITY
• WHAT IS IMMOBILITY?
• THE DIFFICULTY (EXTRA EFFORT) TO REUSE SOMETHING.
• RIGIDITY AND FRAGILITY IN THE CONTEXT OF REUSE.
• INTERNAL COMPONENTS CAN’T BE EASILY ABSTRACTED TO USE IN NEW
ENVIRONMENT.
• EXAMPLE : USER LOG-IN MODULE CAN’T BE USED SOMEWHERE.
• WHAT CAUSES IMMOBILITY?
• COUPLING
• LACK OF COHESION
12. VISCOSITY & NEEDLESS COMPLEXITY
• WHAT IS VISCOSITY?
• TOUGHNESS IN PRESERVING DESIGN (DOING THINGS RIGHT IS HARDER THAN DOING
THINGS WRONG)
• CONTINUOUS EXTRA EFFORT (TIME)
• COST OF ESSENTIAL OPERATIONS (CHECK-IN, CHECK-OUT AND MERGE) IS HIGH.
• WHAT CAUSES VISCOSITY?
• COUPLING
• BAD DEVELOPMENT SETUP / TOOLS
• NEEDLESS COMPLEXITY
• BUILD SOFTWARE CONSIDERING FUTURE REQUIREMENT/EXTENSION.
13. SINGLE RESPONSIBILITY PRINCIPLE (SRP)
• A CLASS SHOULD HAVE ONLY A SINGLE RESPONSIBILITY.
• I.E. A CLASS SHOULD HAVE ONLY ONE REASON TO CHANGE.
• THINGS THAT CHANGE FOR THE SAME REASONS, SHOULD BE GROUPED TOGETHER.
THINGS THAT CHANGE FOR DIFFERENT REASONS, SHOULD BE SEPARATE.
• SINGLE RESPONSIBILITY IS ABOUT USERS WHO IS GOING TO USE (CLASS) IT.
• SINGLE-RESPONSIBILITY IS THE UNIX PRINCIPLE "DO ONE THING AND DO IT WELL”.
• USING LAYERS IN YOUR APPLICATION HELPS A LOT.
• SPLIT BIG / FAT CLASSES IN SMALLER ONES, AND AVOID GOD CLASSES.
• FOLLOW KISS (KEEP IT SIMPLE AND STUPID) PRINCIPLE.
• RULE OF THUMB :
• IF YOU CAN’T COME UP WITH A NAME FOR YOUR CLASS, ITS PROBABLY DOING TOO MUCH.
• IF THE NAME CONTAINS WORDS LIKE "AND, OR, BUT OR IF" THEN THAT IS A PROBLEM.
14. OPEN/CLOSED PRINCIPLE (OCP)
• SOFTWARE ENTITIES SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION
• ADDING NEW FEATURE SHOULD ADD NEW CODE RATHER THAN UPDATING THE EXISTING ONE.
• REDUCES THE RISK OF INTRODUCING NEW BUGS TO EXISTING CODE, LEADING TO MORE ROBUST
SOFTWARE.
• REDUCES COUPLING AND INCREASES FLEXIBILITY.
• HELPS TO REMOVE SNAKE OF ‘IF-ELSE` CASES. AND REMOVE THOSE BAD SWITCH CASES.
• PATTERNS FOLLOWS OCP
• OBSERVER
• STRATEGY
• DECORATOR
• VISITOR
15. LISKOV SUBSTITUTION PRINCIPLE (LSP)
• OBJECTS IN A PROGRAM SHOULD BE REPLACEABLE WITH INSTANCES OF THEIR SUBTYPES
WITHOUT ALTERING THE CORRECTNESS OF THAT PROGRAM.
• DERIVED CLASSES SHOULD EXTEND WITHOUT REPLACING THE FUNCTIONALITY OF OLD
CLASSES.
• IF A PIECE OF CLIENT CODE WORKS FOR A TYPE, THEN IT MUST WORK FOR ALL DERIVED
TYPES.
• IS IT FINE IF DERIVED CLASS OVERRIDES BASE CLASS METHOD??
• BY HAVING
• DEGENERATED (DOES NOTHING) FUNCTION
• UNCONDITIONAL THROWS EXCEPTION
• RULES
• IMPLEMENT INHERITANCE BASED ON BEHAVIOR.
• OBEY PRE AND POST CONDITIONS RULES.
16. INTERFACE SEGREGATION PRINCIPLE (ISP)
• MANY CLIENT-SPECIFIC INTERFACES ARE BETTER THAN ONE GENERAL-PURPOSE
INTERFACE.
• CLIENTS SHOULD BOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DON’T
USE.
• AVOID FAT INTERFACES.
• ISP GUIDES US TO CREATE MULTIPLE, SMALLER, COHESIVE INTERFACES.
• WHICH GIVES FLEXIBLE, LOOSE COUPLED, TESTABLE CODE AND SO ON.
17. DEPENDENCY INVERSION PRINCIPLE (DIP)
• HIGH-LEVEL MODULES SHOULD NOT DEPEND ON LOW-LEVEL MODULES. BOTH SHOULD
DEPEND ON ABSTRACTIONS.
• ABSTRACTIONS SHOULD NOT DEPEND ON DETAILS. DETAILS SHOULD DEPEND ON
ABSTRACTIONS.
• ONE SHOULD “DEPEND UPON ABSTRACTIONS. DO NOT DEPEND UPON CONCRETIONS”.
• HIGH LEVEL POLICY SHOULD BE INDEPENDENT ON LOW LEVEL DETAIL.
• REASONING: HIGH-LEVEL MODULES BECOME MORE REUSABLE IF THEY ARE IGNORANT OF
LOW-LEVEL MODULE IMPLEMENTATION DETAILS.
• FOLLOW PROGRAMMING TO THE INTERFACE PRINCIPLE.
Walking on water and developing software from a specification are easy if both are frozen. “ - Edward V. Berard
Design Principles : Set of guidelines. Its not Rules.
Design Patterns : Solution to commonly occurring problem in a context.
Library : the overall program's flow of control is dictated by the caller (user).
Framework : A framework is a scaffold that you can you build applications around.
Provides some base functionality environment for better and faster development.
Ioc (Inversion of control): the overall program's flow of control is not dictated by the caller, but by the framework
Extensibility
Experience on working with any software/application or legacy code?
Don’t be STUPID.
Singleton
Anti Pattern
Does more than one thing
Introduces global state & Hidden dependencies
Difficult to test
Tight Coupling
Change in one module in your application requires you to change another module.
Untestability
Caused by tight coupling
Premature Optimization
Only cost, and no benefit.
Follow YAGNI principle.
Indescriptive Naming
Write code for people, not for computers.
Strpbrk, strcspn
Duplication
Follow DRY & KISS principle
Mnemonic for OSI layer. Mnemonic device is any learning technique that aids to retain information in human memory.
All People Seem To Need Data Processing.
Application: All
Presentation: People
Session: Seem
Transport: To
Network: Need
Data-link: Data
Physical: Processing
Code smell which indicate not really bugs, but usually are a kind of indicator for problems in the future.
Modular code doesn’t mean good design.
Design is all about managing dependencies.
Unmanaged dependencies kills your application.
Context independent : Can be rearranged.
UML diagrams are not design they are preliminary design.
The source code is the design.
List of possible code smells can be found: https://blog.codinghorror.com/code-smells/
Gives/Generates “Low Coupled”, “Highly Cohesive” code. Removes “Immobility Smell”.
Legible – Clear enough to read
Inheritance, Encapsulation and Polymorphism are mechanism in OO but they are not essential qualities.
Essentials qualities of OO
Ability to Invert key Dependencies, protecting high level policy from low level detail.
OO is all about Dependency management
Increasing productivity or time or money and saving on “waste”.
Primary value of software : Capable to tolerate and facilitate the ongoing change, without bug crashes and delays.
Secondary value of software : Software meets the current needs of the user. CUSTOMER STATISFICATION.
Modules are coupled.
Viscosity : Not having proper Editor, Version System, Code Quality Assurance Tool Setup, Continuous Deployment.
TIGHTLY COUPLED:- Multi tool knife (Screwdriver and hammer) - needed by 2 people or at 2 places.
Problem :- Makes the class harder to understand and harder to test, decreasing cohesion.
Strive for loosely coupled objects so that changing one object reflect changes in other object
Encapsulate what varies from what doesn't..
PRIME Number Printer
Multiple tasks – Not good Quality/better output.
Single tasks - Good Quality/better output.
Functions doing 2 things: Checking for Boolean, Null, If, Switch, Try, . Arguments are Boolean, Null.
Old Camera is not extensible. SLR camera is open for Extension, can attach different lenses.
Observer pattern :
Define a one-to-many dependency between objects so that when one objectchanges state, all its dependents are notified and updated automatically.
Strategy pattern :
defines a family of algorithms,
encapsulates each algorithm, and
makes the algorithms interchangeable within that family.
Undefined behavior means that it works okay during development but blows up in production.
A new subtype should not screw up the client code.
Square is a Rectangle but substitutability fails. Circle is-an Ellipse.
Bullock-cart is not substitution for 4 wheelers (Car). Break, Light, Accelerator, Doors.
Bird & Ostrich/Pigen - Ostrich can’t fly.
Visual 2005 can be substituted by Visual Studio 2010 (Backward Compatibility).
Fat classes - Class has lot of lot methods (Job classes).
Similar to normalizing database like normalizing database from 1NF to 3NF where a big table is broken into tables with related columns.
Without DI class is Brittle, inflexible, and hard to test. Tightly coupled modules are difficult to reuse, and also hard to test.
Code example.
Let’s see classic Button & Lamp application.
Dependency Injection : Putting high-level modules in different packages than the low-level modules it uses.
Dependency Injection Container : A way to auto-wire classes together.
IoC (Inversion of Control) : A software design architecture where the framework controls the program flow.
IOC is used to increase modularity of the program and make it extensible.
http://stackoverflow.com/questions/11316688/inversion-of-control-vs-dependency-injection-with-selected-quotes-is-my-unders
SOLID TEST
SIP - Test should be written for an actor
OCP - Production code should be open for extension and test should be closed for modification
LSP - Derivative classes (Classes derived from some class like Stub class) used for test should follow LSP.
ISP - If require Separate Interface for test cases.
DIP - Test (Low level detail) should depend upon Production Code (High Level detail) so that dependency can be in one direction BUT not vice-versa.
Encapsulate what varies from what doesn't.
Favor Composition over inheritance.
Program to interface not an implementation.
Strive for loosely coupled objects so that changing one object reflect changes in other object.
If you take the SOLID principles to their extremes, you arrive at something that makes Functional Programming look quite attractive.
Objects are a poor man's closures.
Closures are a poor man's objects.
Don’t be STUPID: GRASP SOLID!