0% found this document useful (0 votes)
4 views55 pages

CodingAcademy CleanCode

The document outlines best practices for mastering coding skills, emphasizing the importance of code quality, naming conventions, and design principles such as SOLID. It discusses various coding techniques, including error handling, dependency injection, and the significance of clean code through practices like Test-Driven Development (TDD). Additionally, it highlights the need for modularization, separation of concerns, and avoiding over-engineering to maintain a lean and maintainable codebase.

Uploaded by

shayisso
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views55 pages

CodingAcademy CleanCode

The document outlines best practices for mastering coding skills, emphasizing the importance of code quality, naming conventions, and design principles such as SOLID. It discusses various coding techniques, including error handling, dependency injection, and the significance of clean code through practices like Test-Driven Development (TDD). Additionally, it highlights the need for modularization, separation of concerns, and avoiding over-engineering to maintain a lean and maintainable codebase.

Uploaded by

shayisso
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Mastering your Coding Skills

Smells are certain structures in the code that indicate violation of


fundamental design principles and negatively impact design quality
Spaghetti code is unstructured and difficult-to-maintain source code
Anti Pattern

An anti-pattern in is a common response to a recurring problem that is


ineffective and counterproductive.
code quality factors
Readability, complexity, modularity, reusability,
testability, extensibility, reliability, performance,
security, scalability, usability, portability, …
Code Quality measurement
WTFs / Minute
Naming is Everything
Naming things properly
Use descriptive and meaningful names for variables,
functions, classes, and modules.

// Use meaningful and pronounceable variable names

// Bad:
const yyyymmdstr = moment().format("YYYY/MM/DD")

// Good:
const currentDate = moment().format("YYYY/MM/DD")
Naming things properly
// Use the same vocabulary for the same type of variable

//Bad:
getUserInfo()
getUserData()
getUserRecord()
getUserObj()

// Good:
getUser()
Naming things properly
// Use searchable names

// Bad
const events = getNearByEvents()
const posts = getRelatedPosts()
const document = getDocument()

// Good
const eventos = getNearByEventos()
const stories = getRelatedStories()
const doc = getDoc()
Naming things properly
// Don't add unneeded context
// If your class/object name tells you something,
// don't repeat that in your variable name.

//Bad:
const Car = {
carMake: "Honda",
carModel: "Accord",
carColor: "Blue"
}

function paintCar(car, color) {


[Link] = color
}

// Good:
const Car = {
make: "Honda",
model: "Accord",
color: "Blue"
}

function paintCar(car, color) {


[Link] = color
}
Naming things properly
// Function names should say what they do

// Bad:
function addToDate(date, month) {
// ...
}

const date = new Date()


// It's hard to tell from the function name what is added
addToDate(date, 1)

// Good:
function addMonthToDate(month, date) {
// ...
}

const date = new Date()


addMonthToDate(1, date)
Readable large numbers
// Use numberic seperators

// Bad:
const largeNumbers = 1000000000

// Good:
const largeNumbers = 1_000_000_000
Avoid using export default
// Bad:
export default {
query,
get,
post,
put,
remove
}

// Good:
export const storageService = {
query,
get,
post,
put,
remove
}
use the strict type comparison
It is preferred using the === operator
(and avoid using the == operator) as its more accurate.

Here are some examples:


Fail Fast
Use guard clauses to handle exceptional cases at the beginning
of a function
Improving code readability and reducing nested conditionals.
Early Returns/Guard Clauses
// Bad:
function addNums(x, y) {
if (typeof x === 'number' && typeof y === 'number') {
// do something
return x + y
} else if (typeof x !== 'number') {
throw new Error(`${x} is not a number`)
} else {
throw new Error(`${y} is not a number`)
}
}

// Good:
function addNums(x, y) {
if (typeof x !== 'number') throw new Error(`${x} is not a number`)
if (typeof y !== 'number') throw new Error(`${y} is not a number`)
// do something
return x + y
}
Early Returns/Guard Clauses
Single Responsibility
// Functions should do one thing
// Bad:
function emailClients(clients) {
[Link](client => {
const clientRecord = [Link](client)
if ([Link]()) {
sendEmail(client)
}
})
}

// Good:
function isActiveClient(client) {
const clientRecord = [Link](client)
return [Link]()
}

function emailActiveClients(clients) {
[Link](isActiveClient).forEach(sendEmail)
}
Limit the amount of function parameters
// Function arguments
// Bad:
function createMenu(title, body, buttonText, cancellable) {
// ...
}

createMenu("Foo", "Bar", "Baz", true)

// Good:
function createMenu({ title, body, buttonText, cancellable = false }) {
// ...
}

createMenu({
title: "Foo",
body: "Bar",
buttonText: "Baz"
})
Open-Closed Principle (O)
software entities (classes, modules, functions, etc.) should be open for
extension, but closed for modification

// Bad:
function processPayment(price, cardDetails) {
/*...*/
[Link]('Paid with Card.')
}

// Good:
function processPayment(price, accountDetails) {
/*...*/
[Link]('Paid with PayPal.')
}
Liskov Substitution Principle (L)
A principle stating that an object (such as a class) may be replaced by a
sub-object without breaking the program
Liskov Substitution Principle (L)
// function to make HTTP requests
function makeRequest(url, errorHandler) {
fetch(url)
.then(response => [Link]())
.catch(error => errorHandler(error))
}

// We can have several functions to handle errors


const consoleErrorHandler = (error) => {
[Link](error)
}

const externalErrorHandler = (error) => {


sendErrorToExternalService(error)
}

makeRequest(url, consoleErrorHandler)
makeRequest(url, externalErrorHandler)
Interface Segregation Principle (I)
// no class should be forced to implement
// interfaces or methods that it will not use

// Bad:
class Product {
getDetails() { /* */ }
print() {/* */ }
}

class PhyisicalProduct extends Product {


// print() is extended but not necessary }
}

// Good:
class Product {
getDetails() { /* */ }
}

class PrintableProduct extends Product {


print() { /* */ }
}

class PhyisicalProduct extends Product {


// print() is not extended
}
Dependency Inversion Principle (D)
// Bad
class MySqlConnection {
connect() { /* */ }
}

class PasswordReminder {
constructor() {
[Link] = new MySQLConnection()
}
}

// Good
class MySqlConnection {
connect() { /* */ }
}
class PostgreSqlConnection {
connect() { /* */ }
}

class PasswordReminder {
constructor(connection) {
[Link] = connection
}
}
Dependency Injections
Dependency injection (DI) is a technique
in which an object receives other objects
that it depends on

Here is a Java Spring Example:

public class Car {


@Autowired
public Car(Engine engine, Transmission transmission) {
[Link] = engine;
[Link] = transmission;
}
}
.Net Core DI

[Link] Core also supports the dependency


injection (DI) software design pattern

public IActionResult About([FromServices] IDateTime dateTime)


{
return Content( $"Current server time: {[Link]}");
}
Separation of Concerns
Separation of concerns is achieved using
modularization, encapsulation and arrangement in
software layers.
Example: MVC
Separation of Concerns
Example: Vue3 Composition
You Aren't Gonna Need It (YAGNI)
Don't code things "just in case" you might need it later.
• Focus on Immediate Needs
• Avoid Over-Engineering
• Keep Codebase Lean and Maintainable
• Iterate and Refactor
Reuse (DRY)
• DRY – don’t repeat yourself
• Keep your code base small and maintainable
• Use existing working code whenever possible
• The nemesis of Reuse is Tight Coupling

Recognize the more general idea or


usage of a function
Coupling
• The degree to which each program module relies on
each one of the other modules.
• Keep coupling low even if it means adding some lines
of code.
Decoupling
• Avoid globals, Use good naming's and scopes
• Don’t get intimate with other components
– Don’t rely on knowledge of internal structure or algorithms
– Avoid Expecting a certain order of function calls
– Avoid sending/receiving too many params

• Mind with inconsistent objects


(not fully loaded, or lazy initialized)
Error handling
• Implement proper error handling mechanisms to handle
exceptions and errors gracefully.
• Use try-catch blocks to catch and handle exceptions, provide
meaningful error messages to aid debugging.
• Avoid revealing sensitive information in exceptions
Don't ignore caught errors
// Bad: swallowing exceptions
try {
functionThatMightThrow()
} catch (error) {
[Link](error)
}

//Good:
try {
functionThatMightThrow()
} catch (error) {
[Link](error)
notifyUserOfError(error)
reportErrorToService(error)
}
Don't ignore rejected promises
// Bad:
getData()
.then(data => {
functionThatMightThrow(data)
})
.catch(error => {
[Link](error)
})

// Good:
getData()
.then(data => {
functionThatMightThrow(data)
})
.catch(error => {
[Link](error)
notifyUserOfError(error)
reportErrorToService(error)
})
Handling nulls and undefined
Use the correct syntax
(nullish coalescing assignment operator)

// Using if statement - verbose and repetitive


if ([Link] === null || [Link] === undefined) {
[Link] = 'Anonymous'
}

// Using || operator - catches too much


[Link] = [Link] || 'Anonymous' // Replaces '', 0, false too

// Using ternary - gets messy with longer expressions


[Link] = [Link] === null || [Link] === undefined
? 'Anonymous'
: [Link]

// Using ??= - clean and precise


[Link] ??= 'Anonymous'
The ?= Operator (syntax is still under heavy debate)
// Classic way:
async function fetchData1() {
try {
const res = await fetch('[Link]
try {
const data = await [Link]()
return data
} catch (parseError) {
[Link]('Failed to parse JSON:', parseError)
}
} catch (networkError) {
[Link]('Network request failed', networkError)
}
}

// New purposed way:


async function fetchData2() {
const [err, data] ?= await fetch('[Link]
if (err) [Link]('Error:', err)
}
A leaky abstraction in software development refers to a
design flaw where an abstraction, intended to simplify and
hide the underlying complexity of a system, fails to do so.
Example – Axios

• The axios library encapsulates the fetch API and


provides some useful methods on top of it.
• However, requests that don’t return successful status
codes are treated as errors.
• This is a difference from the normal fetch API that the
user of the library needs to be aware of.
• To successfully use this abstraction, one needs to
understand its inner workings.
Example – Axios

// Function to demonstrate fetch error handling


function fetchDemo() {
fetch('[Link]
.then(res => {
if (![Link]) {
throw new Error('Network response was not ok ' + [Link])
}
return [Link]()
})
.then(data => [Link]('Fetch data:', data))
.catch(error => [Link]('Fetch error:', error))
}
Example – ORMs

in real-life it is usually needed to write plain old raw SQL


Example – Design System via extending a 3rd party
Components library
Code Linters
Employing tools to enforce coding standards
Automated Tests
Ensuring code quality with unit tests and integration tests.
Coverage
Use coverage report to see how much of the
code is covered by tests:
TDD
Practice Test-Driven Development (TDD) to write clean,
maintainable code with fewer defects.
Writing tests before implementing code helps to clarify
requirements and design, leading to better code
structure.
E2E Testing
Here is an example:
E2E Testing
Here is an example:
Summary

• Code Smells and Anti Patterns • Error handling


• Naming things • Leaky Abstractions
• Failing fast and Guard clauses • Code Linters
• Solid • Tests, Coverage and TDD
• Dependency injections
• Separation of Concerns
• YAGNI
• Reuse (DRY)
• Decoupling
Code Quality measurement
WTFs / Minute
Clean Code
Mastering your Coding Skills

Yaron Biton, CTO


May the force be with you

Yaron Biton
MisterBit CTO

Coding Academy
Chief Instructor

You might also like