Knowing the problems is the first step to solving them.
A thread on #CodeSmells 🧵⬇️📅
#CodeSmell 01: Your objects are a bunch of public attributes
Problem: en.wikipedia.org/wiki/Anemic_do…
Solutions:
1) Find Responsibilities.
2) Protect your attributes.
3) Hide implementations
4) Delegate
#CodeSmell 02: Code has lots of comments
Problem: Comments are coupled to implementation
Solutions:
1) Refactor methods
2) Rename methods to more declarative unes
3) break methods
4) If a comment describe what a method does. Just name the method with this description
#CodeSmell 03: Functions are too long
Problems: Low Cohesion, High coupling, Difficult to read
Solutions:
1) Refactor
2) Create small objects dealing with some of the tasks. Unit test them
3) Compose methods
#CodeSmell 04: Function receiving too many arguments
Problems: Low maintainability. Low Reuse. Coupling
Solutions
1) Find cohesive relations among arguments
2) Create a "context"
3) Consider using a MethodObject Pattern
4) Avoid "basic" Types, Specially arrays. Think on objects
#CodeSmell 05: Object with too many attributes
Problems: Same as #CodeSmell 04
Solutions
1) Find methods related to attributes
2) Cluster this methods
3) Break the object related to those clusters
4) Find real objects related to this new objects and replace existing references
#CodeSmell 06: Constants and Magic Numbers
Problems: Coupling, Low testability, Low readability
Solutions
1) Replace constants with parameters so you can mock them
2) The constant definition is often a different object than the constar (ab)user
3) Group the cohesive parameters
#codesmell 07: switch/case/elseif/else/if statements
Problems:
Two Many decisions together
Coupling
Duplicated code
Nulls
Solutions
1 polymorphism
2 Open closed principle
3 state pattern
#codesmell 08: a Small change in requirements is a big change on model
Problems:
Coupling
Solutions:
1 refactor and isolate what is changing
2 depend on a interfaces
3 avoid ifs
Codesmell 09: Long chains of collaborations
Problems:
Coupling
Break encapsulation
Solutions:
1 Think about en.wikipedia.org/wiki/Law_of_De…
2 Create indirect collaborations
3 Create higher level messages
Wrong: dog->feet-> move
Right: dog->run
Codesmell 10: Two sibling classes sharing implementation but not fulfilling 'behavesLike' relation
Problems:
Accidental coupling
Liskov's substitution
Solutions:
1 Refactor what they have in common.
2 Use Composition and break hierarchy
#Codesmell 11: Avoid string abusers
Problems:
Too many parsing, exploding, regex, strcomp, strpos and string manipulation functions
Solutions:
1 Work with objects
2 Replace strings with data structures dealing with object relations
3 Go back to Perl :)
#Codesmell 12: Avoid protected methods
Problems:
Concrete protected methods are a code smell of subclassification for reuse purposes
Solutions:
1 Favor composition
2 Don't subclassify
3 extract behaviour
4 Use traits (if available)
#CodeSmell 13: Objects referenced via ids
Problems:
Accidental Coupling
Bad Models
Premature Optimization
Solutions:
1 Do not Mix Ids with objects.
2 Ids are only necessary when giving reference to an external system.
3 Objects know objects by references. not by Ids
#codesmell 14: model objects persisting/retrieving
Problems
coupling
Premature optimization
No testability
Solutions:
1 Separation of concerns
2 Decoupling persistence
3 Domain driven design
#codesmell 15: Cyclomatic complexity:
Problems:
too many branches or loops
Readability
Solutions:
Break up functions into smaller functions
Create private functions
Create a Method Object
#Codesmell 16: Overriding concrete implementation
Subclass deciding NOT to do what is declared by super
Problems:
Bad Cohesion
Coupling
Subclassing for code reuse
Solutions:
Break inheritance
Move default implementation down
Favor Composition
#CodeSmell 17: Naming a variable is a Bad Naming smell
Names too abstract referring to metamodel like:
-Abstract
-Value
-Result
-Object
-Outcome
-Input
Are code smells.
Find which real world roles are misrepresented on your code
#CodeSmell 18: avoid too abstract names.
Implementative Naming is a code smell.
Repository is an awful name.
Think about real world names like:
-schedule
-notebook
-diary
-journal
CodeSmell #19: Coupling to other objects implementation
When an object is coupled to implementation and not to protocol any change will cause ripple effect.
a Public attribute is a smell of this.
The outcome might be a funny en.wikipedia.org/wiki/Object_or…
CodeSmell: #20: Using nulls
Nulls are an anti pattern
You can use nulls on databases because null don't execute, but interpreting this nulls is impossible since it might represent different meanings.
Remember Null's autor regret and have mercy on him
CodeSmell: #21 Repeated Code
Problems:
-Coupling
-Maintainability
-DRY
Solutions:
-Find the missing abstraction in real world and extract the code there
-Use the new abstraction
CodeSmell: #22 Caches
Problems
-Coupling
-Invalidation brings functional problems
-Premature Optimization
-!Testability
-Global references
Solutions
-Avoid General Purpose Cach
-Benchmark
-Find Bottlenecks
-Create functional contexts and proxies (object in the middle)
-Ask Knuth
#CodeSmell: 23 Missed Preconditions
Problems
-Not fail fast
-Contract breaking
-Hard to debug
-Bad cohesion
Solutions
-Create strong preconditions
-Raise exceptions
-Fail Fast
-Defensive Programming
#CodeSmell 24: Magic Numbers
Problems:
-Maintainability
-Fear to change
Solutions:
-Create constants with long, intention revealing values
-Do not add those constants as static class constants, this will prevent from testing
--Test must be in full control to "play" w/t constants
#codesmell 25:
Trying to build complex solutions for a simple functional problem
with excellent models there's a mapping between code and functional complexity
A simple problem in real world should be fixed simple
If building complex algorithms caches go back
Solve it with PO
#CodeSmell 26: Avoid excessive Pattern Naming
A class StrategyFactoryDispatcherStateHandler is a code smell of coupling and low cohesion.
A class with more than 1 pattern on its name is a code smell of bad coupled protocol
#CodeSmell 27: Code that autocorrects without warnings
Some programming languages make invalid coercions hiding the source of errors and deferring debugging (tracing these errors is almost impossible)
Examples:
-new Date(31,02,2020)
- 1 + 'Hello'
- !3
All 3 are errors
#CodeSmell 28: Inconsistent Names
In order to fulfill least surprise principle all names mus be consistent.
For example if you have a method open() you should use close(), not doclose(), remove(), finish() etc
#Refactorings are free nowadays so must do it whenever you encouter
#CodeSmell 29: Primitive Obsession
Using Data types to represent anemic Objects
Examples:
a Date created from 3 integers
a Coordinate create by two floats
an integer to represent money
Don't be afraid to create small objects.
They fall fast and don't coerce !
#CodeSmell 30: Refused Bequest
A subclass overrides most of superclass protocol
Problems:
-Bad design
-Coupling
-Inheriting for code sharing (accidental)
-Very Low cohesion
Solution:
-Move away subclass
-Use composition or traits
-Use interface segregation
#CodeSmell 31: Library Objects
an Object that performs lots of interactions with its arguments but does not call self.
Problems:
-Bad Cohesion
-Long Methods
Solutions:
-Split into method object
-Create an object for every different function
-Change the name: DO NOT USE HELPER
#CodeSmell 32: Polymorphic Shame
Methods that do the same thing but have different signatures for what they do
ej: listSort() vs arraySort()
Problems:
-Ifs/cases/switchs
-Violate Open/Closed Principle
Solutions:
-rename them to sort() if possible
-change language (if not)
#CodeSmell 33: Message Chains
A method calling a different method which calls a different method which calls a different method...
Problems:
-Coupling
-Fragility
-Demeter's Law
-Information (not) hiding
Solutions:
-shortcuts
-create chain methods
Dog>Leg>Move
Dog>MoveLeg
#CodeSmell 34: Parallel inheritance hierarchies
Problems:
-Complexity
-Repeated Code
-Coupling
Solutions:
-Composition instead of inheritance
-Abstract Factory
-Compact Code
#CodeSmell 35: Constructors calling super
Problems:
-Inheritance for code reuse
-implementation on abstract classes
-Deep Hierarchies
Solutions:
-Remove abstract constructors and their associated attributes
-Full initialization should be done on concrete
-Refactor Hierarchy
#CodeSmell 36: Do not use globals.
Seems pretty obvious but classes and namespaces are also globals :)
Problems:
-Coupling
-Ripple Effect
-Singletons
Solutions:
-Talk to a context provider
-Mock this providers on tests
#CodeSmell 37: Many Mixed Exceptions
In a try/catch block exceptions should be independent and orthogonal and at the same level than code.
Do not mix low/high level exceptions
try{}
catch Exception
catch Specific
Borrowed from @MattCodeJourney here
#CodeSmell 39: Static Methods
Problems:
-Coupling to globals (classes)
-Not Mockable
-Violation on Solid's SOR (class sole responsibility is to create instances)
-Lack of Maintainability
Solutions:
-Move the method to instance in a smaller class
-Refactor
-Dependency injection
#CodeSmell 40: Todo: Fix after demos
Proof of concepts, prototypes and MVP are excellent for exploration and sales
If you encounter this kind of #technicaldebt, run away !
Prototype code should be discarded
There's a proverb stating second time we implement sth we do it better
#CodeSmall 41: Unreferenced Classes
Problems
-Dead Code
-Metaprogramming
-Only referenced by tests
Solutions
-Remove class
--If some test fails there's metaprogramming #smell. Make reference explicit instead
--If production fails may god help you
CodeSmell 42: Unreferenced Methods (See above)
Problems:
-Dead Code
-Metaprogramming
-Only referenced by tests
Solutions
-Remove method
--If some test fails there's metaprogramming #smell. Make call explicit instead
--If production fails may god help you
Avoid Metaprogramming
CodeSmell 43: Hang from classes
Everytime you hear the expression is someone buying #techdebt
Problems
-Lots of coupling
Solutions:
-Do not subclassify concrete classes
-Do not reuse code by subclassing
-Do not violate Solid principles
-Be mature when coding
@threadreaderapp unroll
#CodeSmell 44: Shotgun Surgery
A small business change impacts on lots of different objects.
Problems:
-Low Cohesion
-Coupling
Solutions:
-Encapsulate what changes and use Single Responsibility Principle
-Delegate
#CodeSmell 45: No Behavior at all
-Choose 1 rand source file
-Count the lines with real behavior methods (no, setters are not behavior)
75% of lines min should have business behavior
If not you're creating anemic models
Try imperative languages instead
They are not bad at all
#CodeSmell 46: Class with just one method.
Either this method is large
-It should be splitted
or is small
-it is probably a masked global
The class sure has #lowcohesion
#CodeSmell 47: Cohesive parameters
Two related parameters not working together
Wrong:
moneyMovements($dateFrom, )
//Valitations
Right:
moneyMovements($dateRange)
new DateRange($since, )
//Validation
These small objects are not obvious !
#codeSmell 48: Globals
Avoid globals.
They generate coupling, side effects and makes testing very difficult.
BTW: Classes are globals (even if you can use namespaces)
Their coupling can be avoided with #dependencyinjection and #factories
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.
