css | theme | drawings | highlighter | lineNumbers | layout | info | ||
---|---|---|---|---|---|---|---|---|
unocss |
geist |
|
shiki |
false |
cover |
## Software Design and Architecture
|
Part II
Open slides here: https://sda.np-overflow.club
Due to certain language limitations of Python, we'll be using ✨ Typescript ✨ for this workshop!
Please install the following:
- NodeJS & NPM Install here
- Your favorite code editor or VSCode
To run a file: open a terminal window and type:
npx tsx /path/to/file
- Don't panic, find help
Head over to #tech-support
on our Discord server
- Object-Oriented Programming (with Python 🐍)
- Creation patterns
- Singleton
- Abstract classes
- Structural patterns
- Decorators
- Bridges
⁉ ️How can we use this in our code
- SOLID - 5 principles that compliments OOP
- Also helps you write good code 👍 (maintainable, readable, understandable, flexible... developers good code)
Character | Idea | Important |
---|---|---|
S | Single responsibility principle | ✅ |
O | Open closed principle | ✅ |
L | Liskov substitution principle | ✅ |
I | Interface segregation principle | ✅ |
D | Dependency inversion principle | ✅ |
- Each class should only manage a single thing
✅ keyboard.ts
class Keyboard {
type() {
console.log('clang clang')
}
}
✅ mouse.ts
class Mouse {
scroll() {
console.log('wheeeeee')
}
}
❌ accessories.ts
class Accessories {
type() {
// ...
}
scroll() {
// ...
}
}
- Clases should be open for extension but closed for modification
✅ keyboard.ts
class Keyboard {
type() {
console.log('clang clang')
}
}
✅ rgb-keyboard.ts
class RGBKeyboard extends Keyboard {
colors = ['red', 'green', 'blue']
showFancyLights() {
console.log(colors)
}
}
❌ keyboard.ts
class Keyboard {
colors = ['red', 'green', 'blue']
type() {
console.log('clang clang')
}
showRGB() {
console.log('beep boop')
}
}
- If class
RGBKeyboard
is a subclass ofKeyboard
:RGBKeyboard
should be able to replaceKeyboard
without any side effects
developer.ts
class Developer {
keyboard: Keyboard
constructor(keyboard: Keyboard) {
this.keyboard = keyboard
}
writeCode() {
this.keyboard.type()
}
}
main.ts
const logitechKeyboard = new Keyboard()
const qinguan = new Developer(logitechKeyboard)
qinguan.writeCode() // Writes code with `Keyboard`
const razerKeyboard = new RGBKeyboard()
const jimmy = new Developer(razerKeyboard)
jimmy.writeCode() // Writes code with `RGBKeyboard`
- Interfaces (methods/properties of a class) should be split into their logical concerns
- For example, read vs writes to a database can be 2 interfaces, instead of a huge interface
✅ keyboard.ts
interface KeyboardDatabaseWriter {
create(keyboard: Keyboard)
update(keyboard: Keyboard)
delete(keyboard: Keyboard)
}
interface KeybaordDatabaseReader {
findByName(name: string)
findByBrand(brand: string)
findByPrice(price: string)
}
❌ keyboard.ts
interface KeyboardDatabase {
create(keyboard: Keyboard)
findByName(name: string)
findByBrand(brand: string)
findByPrice(price: string)
update(keyboard: Keyboard)
delete(keyboard: Keyboard)
}
- Dependencies should be on abstractions and not concretions
- Instead of depending on classes, which are "concrete" and contain implementation, use interfaces which only define methods & not implementation
developer.ts
// Anything that I can type on is a keyboard!
interface Keyboard {
type()
}
class Developer {
keyboard: Keyboard // Depend on an interface
constructor(keyboard: Keyboard) {
this.keyboard = keyboard
}
writeCode() {
this.keyboard.type()
}
}
main.ts
// Any class that has a `type()` method can be used
const logitechKeyboard = new Keyboard()
const qinguan = new Developer(logitechKeyboard)
qinguan.writeCode() // Writes code with `Keyboard`
const razerKeyboard = new RGBKeyboard()
const jimmy = new Developer(razerKeyboard)
jimmy.writeCode() // Writes code with `RGBKeyboard`
- Separate your program into layers
- Achieve a few objectives
- Independent of framework
- Independent of user interface
- Independent of database
- Independent of external interfaces
- Highly testable
Layer | Purpose |
---|---|
Entity | Entities and their corresponding rules |
Use case | Service/business functions |
Interface adapter | Mapping/connecting our use cases to frameworks/drivers |
Frameworks/drivers | Databases, HTTP handlers, user interfaces, etc |
layout: iframe-right url: https://app.sli.do/event/aBFgfQS8ZNRrYLJxxMzNhj/embed/polls/ae6f1842-b636-47fa-a5db-6e128bb8c492
Duration: 10 minutes
Task: Find a real life application which you can apply Clean Architecture to
Once done: Submit to sli.do on the right!
- Let's rewrite a program with Clean Architecture
- The program
- Has an HTTP API endpoint we can interact with
- Shows the keyboards in our collection
- When new keyboards arrive, add them to our collection
- Before we begin, we need a few things:
Open them on your laptop!
Open the downloaded file in your editor