Maxi Contieri Profile picture
🎓Learn something new every day.📆 💻CS software engineer / Book Author (bsky) https://t.co/yvZghR24tl https://t.co/PZfiuS12HV

Aug 24, 2020, 49 tweets

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

#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.

Keep scrolling