Maxi Contieri Profile picture
Aug 9, 2020 67 tweets 13 min read Read on X
I’m creating a thread on #softwaredesing. One tip per day.
Until no advices are left or I reach thread limit. Whatever happens in the first time.
Tip 01: Do not subclassify concrete classes.
Tip 02: Variable names should indicate role. Never type
Tip 03: Do not comment code. Write declarative methods instead.
Tip 04: Do not user NULL. It generates a lot of coupling
Tip 05: Do not refactor unless you have great coverage. Just don’t
Tipo 06: YAGNI: You are (never) going to need it. Don't over design. vic @xkcd Image
Tip 07: Do not create incomplete objects. They should be valid since inception.
Tip 08: Do not use Setters or Getters. They expose your internal state
Tip 09: assertons and invariants should be turned on. Even in production environments
Tip 10: favor immutability. Just a few objects should mírate. And only in an accidental way.
Tip 11: Avoid Anemic Domain Models. Objects should never be a "bunch of data". Even the smaller ones have integrity rules and design decisions to hide (i.e. Coordinates or Dates)
Favor Composition over Inheritance. Do not create deep hierarchies. No more than 2 levels.
Tip 13: Classes' Single responsibility is to create instances. So no static or virtual methods should exists but the single canonical constructor
Tip 14: If you use a static language type to Interfaces, Never to classes. If you are typing to abstract classes you are introducing coupling
Tip 15: Hidden assumpstions are our second worst enemy. Make everything explícit. Beware of his close friend and first on our list: coupling
Tip 16: If you stick to TDD then you will never have uncovered code. Yes, U will hardcode a lot at the beginning but this is definitely better than #goldplating
Tip 17: Avoid Native data types. Even if your language have first class objects and Data objects (Strings, Dates, Arrays, Numbers)
Wrap them and protect them.
No. Performance is not always an issue.
In doubt, benchmark it. Don't *guess* things
Save milliseconds or save coupling
Tip 17: Avoid using IDs.
IDs are for external references, objects should know by each other by reference, not IDs.
Retrieving a full reference graph is an accidental problem, not an essential one. In real world those problem don't exist.
So keep your models as clean as possible
Tip 18: Use real object names. Think on metaphors and find real 'not evident' objects. Figure out how a 'paper system' would exist and reflect on the role of each part.

Avoid names like: Helper, Utils, Base, Abstract, Manager etc.
Tip 20: Do not create classes/interfaces with lots of methods. Think about cohesion.

1) if the class is large, your hierarchy might be wrong (specially if it is abstract). favor composition
2) it the Interface is large use interface segregation
Tip 21: Abstract classes should have no implementation, no attributes, just protocol. Abstract protocol most often

Composition is there for us.
Traits (when available) are a second choice
Tip 22: variable names should be injected into functions as roles and should not be named according to their accidental type

Wrong
function enroll(Student $student, School ) {

Better (not quite right)
function enroll(Student $applicant, School $learningVenue) {
Tip 23: Avoid accidental coupling

Adding persistence, serialization, displaying, importing, exporting code to an object bloats its protocol and brings coupling.
Objects must not be aware of them

Keep them as far away as possible
Tip 24: Bottom up designs favor domain learning and incremental business rules discovering.

Create your objects from concrete uses cases.
Unlike other architectures we don't need a detailed blueprint of every aspect before stacking our first bricks
Tip 25: Avoid Fragil (Erratic) tests

If you can't rely on tests you will fall under the broken window syndrome.
Try to find what is erratic. If test have no control over it, refactor them.
Tests must be in full environmental control. Avoid Coupling
If impossible remove the test
Tip 26: All validations should be performed on instance creation.

If validation is complex it should be in another object (a Factory) which should have their own tests.

Don't validate on front end
It traffic is a concern you can do just basic validations (Data types) on the FE
Tip 27: Avoid settings (specially boolean)
Settings do not add value.
They add coupling and complexity
Are hard to test and bring "undesired Ifs"
They don't make systems more flexible.

300 boolean needs to test 2^300 combinations.

There are about 10^78 atoms
we are short
Tip 28: Avoid Ninja Coding and Cowboy coding
Hacking will win battles for you but you are surely going to lose the war.

Don't buy yourself coupling
Tip 29: think on objects related to contexts
The same real object might have different responsibilities and roles according to contexts.

Contexts and roles are essential in big systems

If you see the same object in different contexts with same responsibility is a #codesmell
Tip 30: DRY
Don't repeat yourself.
You can repeat once. You can repeat twice
Make things work. Cover it. Then Refactor

Repeated code is a #codesmell of a missing abstraction.
Find what is repeating (it's not just text. It's a contextual sequence of collaborations) and extract it
Tip 31: Cover your branches
IFs and elses are #CodeSmells

If you really need to use them test and cover both cases.
Don't create defensive conditions you are not ready to test now.
If you cannot test the conditions your system is too coupled to scenarios you cannot control 💩
Tip 32:Never anticipate change
Avoid Goldplating and YAGNI
Neither you nor your client can predict the future
Make things work, create good models using real world metaphors
If changes come they will surely be welcome
(Of course change always comes, but not from where U expected)
Tip 33: Favor real names over Pattern names
Patterns are good for a common language.
But they are always worse than a real world entity name.

#CodeSmell: a Strategy is almost always present with a real domain name.

Switch to BDD and put away implementative solutions
Tip 34: Do not use ids.
bind your objects using real references to real objects.
If you need to provide an external reference use a real domain ID (not a made up one) , preferably a dark key (like a GUID)
Tip 35: Fail Fast.
Create exceptions if contract is violated.
Never coerce or bypass issues
Don't create a Class for every exception unless behaviour is different.

Corollary: If behaviour changes related to 'data' (i.e. an error message) class should be the same.

Don't Pollute
Tip 36: Do not use graphic tools to design
Most tools show attributes too early.
Graphic tools don't compile or execute

Focus on behaviour, protocols and interfaces.
Code don't lie.
Tests are your friends
Tip 37: Always subclassify by domain (essential) relationships.
Never subclassify for implementation reasons.
Don't create accidental hierarchies.
Look for Nature Taxonomies
Most languages give you only one subclassification axis.

When in doubt , favor composition
Tip 38: Prefer composition over traits

Traits are hard to test and bring more coupling that composing objects

As a Rule

Interfaces > Composition > Traits >Subclassification > Copy&Paste
Tip 39: Choose awful names for classes
Nobody (Even You) knows what a class represent until adding its protocol and its relationships.

Put a meaningless: TOBERENAMEDAccount.
After some days (and tests) make a rename

Choosing a name at first glance and keeping it is a #codesmell
Tip 40: Don't worry about performance (yet)
Making performance changes over a Good model covered with tests is easy.
Just follow this algorithm
-Don't assume anything
-Benchmark
-Fix Pareto

Making functional changes on premature optimization models is near imposible d/t coupling
Tip 41: WET
Write everything Twice

Don't generalize with two examples.

You can ask yourself "Haven't I written this before?" two times, but never three.
Tip 42: avoid repeated code

Repeated collaboration patterns are hard to maintain, debug etc

Too many people talk about repeated code, which is very easy to find using regex and linters.

Repeated design decisions are harder to find. Aim at there, instead !
Tip 43: Avoid using test doubles

Test Doubles are to bypass real objects because tests needs to be in full control. For example it is better to mock real database.

But mocking domain objects is discouraged since we should test real interactions to avoid false safety
Tip 44: Favor polymorphism on interfaces over Subclassing

Using NullObject Pattern is better for NullObject to be in a completely different hierarchy than RealObject

Use interfaces when possible.
If you add a new responsibility to the real object, add to the interface
Tip 45: Make explicit calls to subclasses

Do not use metaprogramming to traverse subclasses.
This dark references avoid refactoring and generate hidden coupling.

Make the list explicit. so you can also mock it and have full control on tests
Tip 46: Use mutation testing

Mutation testing talks a lot about your quality and a bit about your model.

A small (mutated) change should break a few tests.
If it breaks a lot of them your system is too coupled.

You might have unexpected results.

en.wikipedia.org/wiki/Mutation_…
Tip 47: Treat all object as equals

Even if you use a language where 'primitive types' like strings, arrays & numbers are not real objects wrap them as much as possible

You can reify the 'name' object which is not just a string or the 'money' object which is not a number

try it
Tip 48: Mocking and Test doubles

-Never mock business logic.
--If you have a heavy calculation algorithm, use another (not a mock one)
-Mock non business if you need (Api, oauths & specially databases)
-Tests should be in full control

You can use dependency injection for that!
Tip 49: Use refactorings

Safe refactorings are made by IDEs. don't change functionality. make code clean and modular
Choose an IDE that support as many as possible

Human refactorings are more tricky. They involve changing the how without changing what
-without tests is suicide
Tip 50: Choose your stack wisely

There's no such thing as a general purpose language

Check your project lifetime.
There are different weapons for short term shippable projects and large or legacy ones.

Always consider the accidental complexity.

No silver bullet
Tip 51: Use lots of small objects

Object creation is cheap. And object destroy is also very efficient
By using lots of objects, you can make sure that each object has one job and only one job (Cohesion)

Think as human cells analogy

Human organs rely on them

Or atoms, quarks..
Tip 52: Classes should be named after real entities and following metaphors

Avoid prefixing classes with letters, types or symbols
They generate accidental coupling and don't add value

Wrong
-flTaxAmount
-iSerializable
-strName
-objGraph

Right
-TaxAmount
-Serializable
-Name
..
Tip 53: Always consider Time on your Designs

Time and objects lifecycle are intertwined.
When your design is ready always double check how will your model support their change and evolution over time.

This is an invisible axis on every design: Objects and relations evolution. Image
Tip 54: Treat objects with #respect

There are many articles with quotes like this:

"'OOP is a way of defining things (most often data) in the form of objects'"

They speak about DTOs and anemic models.

Always focus on behaviour (essential) and not on data (accidental)
Tip 55: Encapsulate What Changes

Only one thing is constant in software, and that is Change

Encapsulate the code you expect or suspect to be changed in the future.

Do not encapsulate other code. YAGNI!

Wrap changes !
Tip 56: Create functional tests

Functional tests are user story tests.
They cover the essence of the problem and survive as long as the business exists

Unit Tests are coupled to accidental implementation.
Thay add less value

Favor Functional tests whenever possible
Tip 57: Avoid accidental IFs

Replace accidental Ifs with polymorphism thus enforcing open/closed SOLID principle

Leave Essential Ifs (Business rules)

Switches/cases should be strictly business rules or even replaced by #doubledispatch
Tip 58: Create indirections

Our worst enemy is coupling
Coupling es most times avoided by placing an "object in the middle"

Real tight connections among business objects should be kept.
Accidental implementation coupling must be removed by indirection.
Tip 59: Use plain language for methods

en.wikipedia.org/wiki/Plain_lan…

Avoid complicated method and classes names.

Do not use passive voice for naming.

Create long and declarative names.
Then minimize them by removing parts and check it is still readable.

Repeat until minimal
Tip 60: Use #defensiveprogramming

Making the software behave in a predictable manner despite unexpected inputs or user actions.

Create as many assertions as possible

Turn them on in production

#failfast

Only remove them if real performance issue (always benchmark as usual)
Tip 61: Prefer iterators over control flow

Iterators, Yields and generators are more abstract and are generally less coupled than while, for, repeats etc.

Iterators work over objects while whiles don't.

Fors are imperative.
Iterators are declarative.
Tip 62: Don't break encapsulation

Don't expose #getters.
Delegate obvious responsibilities to objects.

Wrong:
if (p.getAge() == 32 years)

Right:
if (p.isAged(32 years))

Think about Law of Demeter and avoid coupling !
Tip 63: model state

Model workflows, transitions and fsm with state pattern.

This way you will avoid ifs and favor polymorphism and honor open closed principle

Don't use strings to model state. Be respectful to your models
Tip 64: Model Strategies

Encapsulate what changes
Delegate into strategies
Unit test them
Hardcoding default strategy parameters is a #codesmell
They should be polymorphic
Don't use lambdas (closures or anonymous fn) heavily, wrap them on strategies

they deserve an object
Tip 65: Subclassing driven by Fear

If you need a small change to an existing class don't subclassify it. (Tip: 01)
Change it or refactor it
Think about Liskov

Method Overriding is a #codesmell of bad coverage, inheritance code reuse and coupling

Software is not for cowards!

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Maxi Contieri

Maxi Contieri Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @mcsee1

Jun 3, 2021
Code Smell 04 - String Abusers

Too many parsing, exploding, regex, strcomp, strpos and string manipulation functions.
TL;DR: Use real abstractions and real objects instead of string accidental manipulation.
😔 Problems

- Complexity
- Readability
- Maintainability
- Lack of Abstractions
Read 13 tweets
Dec 31, 2020
My *personal* recommendations on who to follow on 2021!

A Thread 🧵 on great content and great people on Twitter.
Happy new year to all of you!

(A-Z) 1/Many
@AlejandroPiad (Alejandro Piad Morffis)

Alejandro writes interesting content on software development and machine learning.
He teaches Computer Science and his content is great.
I love interacting with him.
@allenholub (Allen Holub)

Allen is a DDD passionate. His opinions are very strong and accurate.
I enjoy his development tips AND management and agile humor a lot.
I liked very much his courses on LinkedIn.
Read 29 tweets
Oct 4, 2020
Another 🧵 on #productivitytip and #LifeHacks

As usual one each day.

Disclaimer: Opinions are my own. I don't have the truth revealed.

I learn a lot with your replies so please contribute and discuss !
#productivitytip 1: Remove notifications

1 - Check your phone after a couple of hours.
2 - Keep an eye on the app with the most notifications
3 - Block them
4 - Don't fear #FOMO. Deal with it
5 - Repeat once a day.

Watch #TheSocialDilemma
#productivitytip 2: Slice your time

1 - Use blocks of time without interruptions (timeboxing).
2 - My favorite is @PomodoroTech.
3 - if you come across new tasks just write them down.
4 - Don't multitask.
5 - You cannot switch until time is up.
6 - 25 minutes it's a good slice.
Read 11 tweets
Sep 10, 2020
Any problem in computer science can be solved with another level of indirection

-@drdavidawheeler
You can mass-produce hardware; you cannot mass-produce software; you cannot mass-produce the human mind.

-Michio Kaku
I invented the term ‘object oriented’, and C++ was not what I had in mind

-Alan Kay
Read 122 tweets
Aug 29, 2020
Sometimes an idea fits in 280 characters

a 🧵 on Great #SoftwareEngineering great #quotes

One each day.
For each desired change, make the change easy (warning: this may be hard), then make the easy change

-@KentBeck
There are only two hard things in Computer Science: cache invalidation and naming things.

-Phil Karlton
Read 186 tweets
Aug 24, 2020
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
Read 49 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(