Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Business logic in Vue.js
Search
Sobolev Nikita
August 22, 2019
Programming
340
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Business logic in Vue.js
Sobolev Nikita
August 22, 2019
Transcript
51 slides
Никита Соболев github.com/sobolevn 1
Бизнес логика и Vue.js !2
Композиция и абстракция !3
Но во Vue.js - компоненты! !4
отображение = f(состояния) !5
отображение = f(состояния) !6
export default { data () { return { username: ''
} }, template: ` <button click="loadUser">Hello {{ username }}</button> `, loadUser () { this.username = this.$axios.get('...').data }, } !7
отображение = f(состояния) !8
export default { data () { return { username: ''
} }, template: ` <button click="loadUser">Hello {{ username }}</button> `, loadUser () { this.username = this.$axios.get('...').data }, } !9
export default { data () { return { username: ''
} }, template: ` <button click="loadUser">Hello {{ username }}</button> `, loadUser () { this.username = this.$axios.get('...').data }, } !10
f = check( transform( fetch() ) ) !11
f = fetch() |> transform() |> check() !12
Кто видит проблему? !13
Изменение логики !14
export default { data () { return { username: ''
} }, template: ` <button click="loadUser">Hello {{ username }}</button> `, loadUser () { this.username = localStorage.getItem('user') }, } !15
Плохие решения • Сделать два компонента • Передавать callback в
props !16
export default { // ... props: ['callback'], loadUser () {
this.username = this.callback(...) }, } !17
Вопросики • А если у нас нет возможности передать callback?
• А если очень глубокая вложенность? !18
Плохие решения • Сделать два компонента • Передавать callback в
props !19
Плохие решения • Сделать два компонента • Передавать callback в
props • Передавать флаг для поведения !20
export default { // ... props: ['http'], loadUser () {
if (this.http) { this.username = this.$axios.get(...) } else { this.username = localStorage(...) } }, } !21
Вопросики • А если поведений много? • А если у
нас нет возможности выставить флаг? • А если очень глубокая вложенность? • А как его тестировать? !22
Тестирование !23
import { mount, createLocalVue } from '@vue/test-utils' import MockAdapter from
'axios-mock-adapter' import MyComponent from '~/components/MyComponent' const localVue = createLocalVue() describe('unit tests for MyComponent', () => { test('should have correct logic', () => { const wrapper = mount(MyComponent, { localVue }) new MockAdapter(wrapper.axios) .onGet('...') .reply(200, ['sobolevn']) wrapper.loadUser() expect(wrapper.username).toBe('sobolevn') }) }) !24
Плохие решения • Терпеть !25
Хорошие решения: композиция и абстракция !26
provide / inject !27
import { mount, createLocalVue } from '@vue/test-utils' import MyComponent from
'~/components/MyComponent' const localVue = createLocalVue() describe('unit tests for MyComponent', () => { test('should have correct logic', () => { const wrapper = mount(MyComponent, { localVue, provide: { buttonCallback: () => 'sobolevn' }, }) wrapper.loadUser() expect(wrapper.username).toBe('sobolevn') }) }) !28
Рефакторинг компонента !29
export default { data () { return { username: ''
} }, template: ` <button click="loadUser">Hello {{ username }}</button> `, inject: ['buttonCallback'], loadUser () { this.username = this.buttonCallback() }, } !30
Создание контекста * https://mmhaskell.com/monads-4 !31
export default { provide: { buttonCallback: () => this.$axios.get('...'), },
components: { MyComponent }, template: `<MyComponent />`, } !32
Плохие решения • Пихать логику в компоненты • Делать вид,
что ты не пихаешь логику в компоненты !33
Рефакторинг компонента !34
import buttonCallbackFactory from 'logic/http' export default { provide: { buttonCallback:
buttonCallbackFactory(...), }, components: { MyComponent }, template: `<MyComponent />`, } !35
И не только для компонентов !36
C Vue понятно, а Vuex? !37
Плохие решения • Пихать логику во Vuex !38
отображение = f(состояния) !39
Vuex !40
import { Inject, Injectable } from 'vue-typedi' import { Action
} from 'vuex-simple' @Injectable() export default class UsernameModule { @Inject(tokens.USERNAME_SERVICE) public service // type: UsernameServiceProtocol @Action() public async fetchUsername () { const username = await this.service.fetchUsername() // ... } } !41
// type: UsernameServiceProtocol
Вставляй любую абстракцию! !43
provide / inject vs TypedDI !44
И не только DI • Higher Order Components • Slots,
Named Slots • https://github.com/vuejs/vue-function-api • Event Bus • Vue.observable, https://github.com/vuejs/vue-rx !45
Сегодня мы многое поняли !46
github.com/wemake-services/ wemake-vue-template !47
Полезные инструменты • https://github.com/sascha245/vue-typedi • https://github.com/typestack/typedi • https://github.com/gcanti/io-ts • https://github.com/gcanti/fp-ts
!48
Полезные ссылки • https://guide.elm-lang.org/architecture/ • https://markus.oberlehner.net/blog • https://blog.ploeh.dk/2016/03/18/functional- architecture-is-ports-and-adapters/ •
https://fsharpforfunandprofit.com/rop/ • https://www.destroyallsoftware.com/screencasts/ catalog/functional-core-imperative-shell • https://sobolevn.me/ !49
tlg.name/ opensource_findings !50
Вопросы? github.com/sobolevn sobolevn.me 51
More Decks by Sobolev Nikita
See All by Sobolev Nikita
adaptix_slides.pdf
sobolevn
0
24
Зачем программисту Twitch (что?) – Алексей Гладких, PythoNN
sobolevn
0
21
MQTT глазами BE для работы с embedded устройствами – Сергей Макаров, PythoNN
sobolevn
0
16
Я в СКРЫТОМ ПУЛЕ: выстраиваем процессы в команде без тильта – Максим Мельников, PythoNN
sobolevn
0
29
Я твой fastapi msgspec'ом ускорял – Александр Целуйко, PythoNN
sobolevn
0
29
Будущее локальных LLM – Алексей Голобурдин, PythoNN
sobolevn
0
120
Чего вы не знали о строках в Python – Василий Рябов, PythoNN
sobolevn
0
270
ИИ-Агенты в каждый дом – Алексей Порядин, PythoNN
sobolevn
0
240
Внутреннее устройство сборки мусора в CPython 3.14+ – Сергей Мирянов, PythoNN
sobolevn
0
160
Other Decks in Programming
See All in Programming
社内AIエージェント「Askワンバン」における コストチューニングの取り組み
t0yohei
0
170
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
170
선언형 햅틱 라이브러리 진동을 소개합니다
l2hyunwoo
1
320
AI Augmentation Techniques with Liberty
ivargrimstad
1
480
PyConTW 2026 - AI Coding 不只是工具升級, 區域醫院醫療資訊系統協作開發與資訊團隊轉型實踐
cclai999
0
250
Rails初心者がパスキーを実装してみて大変だったこと
ktombow
0
190
仕様駆動開発入門 (何を作るかを先に決めて渡す) | 目指せ Kiro マスター 05
inariku
PRO
2
160
Web3Dライブラリを作ってVue Custom Rendererの仕組みを理解しよう / lets learn vue custom renderer by making 3d library
drumath2237
1
140
LLM 101
dalinaum
0
490
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
2.1k
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
180
From Java 8-11 to Java 21-27 — Benefits, Challenges, and a Practical Migration Path
x5gtrn
PRO
0
100
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
350
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
380
Building Flexible Design Systems
yeseniaperezcruz
330
41k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
680
Facilitating Awesome Meetings
lara
57
7.2k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.4k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
520
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.4k
Design in an AI World
tapps
1
390
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
380
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
380