Disclaimer Disclaimer This talk is not about the front end - - PowerPoint PPT Presentation

disclaimer disclaimer
SMART_READER_LITE
LIVE PREVIEW

Disclaimer Disclaimer This talk is not about the front end - - PowerPoint PPT Presentation

Disclaimer Disclaimer This talk is not about the front end Disclaimer This talk is about software architecture Disclaimer This talk is about software architecture (Yes, at 18:00 on a Saturday. Sorry not sorry) BACK We asked for


slide-1
SLIDE 1
slide-2
SLIDE 2

Disclaimer

slide-3
SLIDE 3

Disclaimer

This talk is not about the front end

slide-4
SLIDE 4

Disclaimer

This talk is about software architecture

slide-5
SLIDE 5

Disclaimer

This talk is about software architecture

(Yes, at 18:00 on a Saturday. Sorry not sorry)

slide-6
SLIDE 6

BACK

slide-7
SLIDE 7

We asked for responsibilities

slide-8
SLIDE 8

The Art(?) of Front-end Architecture

slide-9
SLIDE 9

👌 Hi! I’m Adrià Fontcuberta

Senior(?) Software Engineer @ Holaluz Member of the official Vue Test Utils Member of Testing Library Co-organizer of VueJS Barcelona

@afontq afontcu.dev

slide-10
SLIDE 10

HLFF20

slide-11
SLIDE 11

What are* we aiming for?

slide-12
SLIDE 12

Write maintainable, scalable apps

What are* we aiming for?

slide-13
SLIDE 13

Write maintainable, scalable apps Stay away from the framework

What are* we aiming for?

slide-14
SLIDE 14

Write maintainable, scalable apps Stay away from the framework Share knowledge between teams and areas

What are* we aiming for?

slide-15
SLIDE 15

Write maintainable, scalable apps Stay away from the framework Share knowledge between teams and areas Reduce the gap between Front and Back

What are* we aiming for?

slide-16
SLIDE 16

This is not about writing good software, but how to build software that can change over time

slide-17
SLIDE 17
slide-18
SLIDE 18
slide-19
SLIDE 19
slide-20
SLIDE 20
slide-21
SLIDE 21
slide-22
SLIDE 22
slide-23
SLIDE 23
slide-24
SLIDE 24
slide-25
SLIDE 25
slide-26
SLIDE 26
slide-27
SLIDE 27
slide-28
SLIDE 28
slide-29
SLIDE 29
slide-30
SLIDE 30
slide-31
SLIDE 31
slide-32
SLIDE 32
slide-33
SLIDE 33
slide-34
SLIDE 34

Business stuff Delivery stuff

slide-35
SLIDE 35
slide-36
SLIDE 36

Business stuff Delivery stuff

slide-37
SLIDE 37

Business stuff Delivery stuff

slide-38
SLIDE 38

Business stuff Delivery stuff

slide-39
SLIDE 39

Delivery stuff

slide-40
SLIDE 40

Domain Use cases

Delivery stuff

slide-41
SLIDE 41
slide-42
SLIDE 42

Domain

slide-43
SLIDE 43

Domain Use cases

slide-44
SLIDE 44

Domain Use cases Delivery

slide-45
SLIDE 45
slide-46
SLIDE 46

This layer has two streams

  • f data
slide-47
SLIDE 47
slide-48
SLIDE 48
slide-49
SLIDE 49

Infrastructure

slide-50
SLIDE 50

Infrastructure UI / Input

slide-51
SLIDE 51

Infrastructure

API repositories Cookies Web Storage

slide-52
SLIDE 52

UI

¯\_(ツ)_/¯

slide-53
SLIDE 53

What does layer really mean?

slide-54
SLIDE 54
slide-55
SLIDE 55

Dependencies only point inwards

slide-56
SLIDE 56

Dependencies only point inwards An inner layer should never rely on anything from an outer layer.

slide-57
SLIDE 57

Dependencies only point inwards An inner layer should never rely on anything from an outer layer.

slide-58
SLIDE 58
slide-59
SLIDE 59
slide-60
SLIDE 60

Use case “Get user information” depends on “User”

slide-61
SLIDE 61

Use case “Get user information” depends on “User”

slide-62
SLIDE 62

Use case “Get user information” depends on “User”

slide-63
SLIDE 63

Use case “Get user information” depends on “User” Use case “Get user information” depends on the UI framework

slide-64
SLIDE 64

Use case “Get user information” depends on “User” Use case “Get user information” depends on the UI framework

slide-65
SLIDE 65

Use case “Get user information” depends on “User” Use case “Get user information” depends on the UI framework

slide-66
SLIDE 66
slide-67
SLIDE 67
slide-68
SLIDE 68

BACK

slide-69
SLIDE 69

The Web is a delivery mechanism

slide-70
SLIDE 70

It is not the center. It is external.

slide-71
SLIDE 71

It is really, really hard to get it right

slide-72
SLIDE 72

We need to adapt its content for our inner layers

slide-73
SLIDE 73

We need to adapt its content for our inner layers

slide-74
SLIDE 74

Domain Use cases Infrastructure Adapter UI

slide-75
SLIDE 75

Domain Infrastructure Adapter UI Use cases

slide-76
SLIDE 76

Independent of the framework Domain Infrastructure Adapter UI Use cases

slide-77
SLIDE 77

Independent of the framework The framework™ Domain Infrastructure Adapter UI Use cases

slide-78
SLIDE 78

Independent of the framework Domain Infrastructure Use cases

slide-79
SLIDE 79

Independent of the framework Domain Infrastructure Use cases

slide-80
SLIDE 80
slide-81
SLIDE 81
slide-82
SLIDE 82
slide-83
SLIDE 83
slide-84
SLIDE 84

domain app* UI infra adapter

slide-85
SLIDE 85

domain app* UI infra adapter

👪

slide-86
SLIDE 86

Actions Reducers State View Actions Mutations State View

slide-87
SLIDE 87

domain app UI adapter infra

slide-88
SLIDE 88

domain app UI adapter infra

👪

slide-89
SLIDE 89

actions mutations state

domain app UI infra

slide-90
SLIDE 90

actions mutations state

domain app UI infra

👪

slide-91
SLIDE 91

type Coordinate = 0 | 1 | 2 type Sign = "X" | "O" | "" class Board { public isFull(): boolean {} public isPositionTaken(cell: Cell): boolean {} public fillPosition(cell: Cell, player: Player): void {} } class Cell { private row: Coordinate private col: Coordinate } class Player { public sign: Sign public equals(player: Player): boolean {} }

slide-92
SLIDE 92

type Coordinate = 0 | 1 | 2 type Sign = "X" | "O" | "" class Board { public isFull(): boolean {} public isPositionTaken(cell: Cell): boolean {} public fillPosition(cell: Cell, player: Player): void {} } class Cell { private row: Coordinate private col: Coordinate } class Player { public sign: Sign public equals(player: Player): boolean {} }

THIS IS NOT "THE RITE WAY”

slide-93
SLIDE 93

type Coordinate = 0 | 1 | 2 type Sign = "X" | "O" | "" class Board { public isFull(): boolean {} public isPositionTaken(cell: Cell): boolean {} public fillPosition(cell: Cell, player: Player): void {} } class Cell { private row: Coordinate private col: Coordinate } class Player { public sign: Sign public equals(player: Player): boolean {} }

slide-94
SLIDE 94

class Game { private board: Board private isEnded: (): boolean private getLastPlayer(): Player public makeMove(player: Player, cell: Cell): void { if (this.isEnded()) throw new FinishedGameException() if (player.equals(this.getLastPlayer())) throw new AlreadyPlayedException() if (this.board.isPositionTaken(cell)) throw new AlreadyTakenException() this.board.fillPosition(cell, player) } }

slide-95
SLIDE 95

function makeMoveUseCase({ game, player, cell }, { onSuccess, onError }) { try { game.makeMove(player, cell) } catch (error) {

  • nError(error)

return }

  • nSuccess(player, cell)

}

slide-96
SLIDE 96

function makeMoveUseCase({ game, player, cell }, { onSuccess, onError }) { try { game.makeMove(player, cell) } catch (error) {

  • nError(error)

return }

  • nSuccess(player, cell)

}

slide-97
SLIDE 97

function makeMoveUseCase({ game, player, cell }, { onSuccess, onError }) { try { game.makeMove(player, cell) } catch (error) {

  • nError(error)

return }

  • nSuccess(player, cell)

}

slide-98
SLIDE 98

import { makeMoveUseCase } from 'application/../' const actions = { makeMove({ state, commit }, cell) { commit('MAKE_MOVE_REQUEST') makeMoveUseCase({ player: state.currentPlayer, game: state.game, cell }, {

  • nSuccess: (player) =? commit('MAKE_MOVE_SUCCESS', player),
  • nError: (error) =? commit('MAKE_MOVE_ERROR', error.message)

}) } }

slide-99
SLIDE 99

import { makeMoveUseCase } from 'application/../' const actions = { makeMove({ state, commit }, cell) { commit('MAKE_MOVE_REQUEST') makeMoveUseCase({ player: state.currentPlayer, game: state.game, cell }, {

  • nSuccess: (player) =? commit('MAKE_MOVE_SUCCESS', player),
  • nError: (error) =? commit('MAKE_MOVE_ERROR', error.message)

}) } }

slide-100
SLIDE 100

import { makeMoveUseCase } from 'application/../' $(‘#submit_move’).click(function() { makeMoveUseCase( { player: $('#current_player').val(), game: window.game, cell: [$('input[name="row"]').val(), $('input[name="col"]').val()] }, {

  • nSuccess: () =? $('#success_message').fadeIn('slow'),
  • nError: () =? window.alert('oops something went wrong')

} ) })

slide-101
SLIDE 101

import { makeMoveUseCase } from 'application/../' $(‘#submit_move’).click(function() { makeMoveUseCase( { player: $('#current_player').val(), game: window.game, cell: [$('input[name="row"]').val(), $('input[name="col"]').val()] }, {

  • nSuccess: () =? $('#success_message').fadeIn('slow'),
  • nError: () =? window.alert('oops something went wrong')

} ) })

slide-102
SLIDE 102

src/ domain/ application/ infrastructure/ ui/

slide-103
SLIDE 103

domain app UI adapter infra

slide-104
SLIDE 104

domain app UI adapter infra

slide-105
SLIDE 105

Disclaimer #1

You might not need any of this

slide-106
SLIDE 106

Disclaimer #1

You might want some parts of it

slide-107
SLIDE 107

Disclaimer #2

This talk was actually about the front end

slide-108
SLIDE 108

Front-end development is software development

slide-109
SLIDE 109

Disclaimer #3

Nothing explained here today is new

slide-110
SLIDE 110
slide-111
SLIDE 111
slide-112
SLIDE 112

Wrapping up

slide-113
SLIDE 113

Wrapping up

Organize code around business rules, not frameworks

slide-114
SLIDE 114

Wrapping up

Organize code around business rules, not frameworks Dependency Rule Keep details away from the core

slide-115
SLIDE 115

Wrapping up

Organize code around business rules, not frameworks Dependency Rule Keep details away from the core Make everything easy to test

slide-116
SLIDE 116

Wrapping up

Organize code around business rules, not frameworks Dependency Rule Keep details away from the core Make everything easy to test Front-end development is software development

slide-117
SLIDE 117

This is not about writing good software, but how to build software that can change over time

slide-118
SLIDE 118

Ok Adri this is cool

Where should I start?

slide-119
SLIDE 119

Ok Adri this is cool

Where should I start?

noti.st/afontcu

slide-120
SLIDE 120

👌 That's all!

@afontq afontcu.dev

noti.st/afontcu