Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
BFF and Developer Experience
Search
Yosuke Kurami
May 18, 2019
Programming
4.1k
15
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
BFF and Developer Experience
Inside Frontend 2019
Yosuke Kurami
May 18, 2019
More Decks by Yosuke Kurami
See All by Yosuke Kurami
TypeScript LSP の今までとこれから
quramy
1
2.2k
フロントエンドテストの育て方
quramy
12
3.9k
App Router 悲喜交々
quramy
8
760
上手に付き合うコンポーネントテスト
quramy
6
2.4k
Patched fetch did not work
quramy
6
810
GraphQL あるいは React における自律的なデータ取得について
quramy
18
6k
Next.js App Router
quramy
15
4k
Fragment Composition of GraphQL
quramy
17
4.9k
reg-viz VRT tools
quramy
4
1.8k
Other Decks in Programming
See All in Programming
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
360
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
110
信頼性の目標を誰も求めてない
shubox
0
490
Swift愛好会100回記念 第1回を振り返る
jollyjoester
0
120
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
110
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
110
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
280
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
120
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
0
230
Seeing Through Serverless: Observability for AWS Lambda with ADOT and CloudWatch Application Signals
seike460
PRO
1
120
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
180
iOS開発×AI駆動開発 〜最近使って便利だったスキルの話〜
nogu66
0
140
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.9k
Ruling the World: When Life Gets Gamed
codingconduct
0
320
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Designing Experiences People Love
moore
143
24k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
430
Faster Mobile Websites
deanohume
310
32k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Evolving SEO for Evolving Search Engines
ryanjones
0
280
Everyday Curiosity
cassininazir
0
310
Abbi's Birthday
coloredviolet
3
9.8k
Transcript
#'' %FWFMPQFS&YQFSJFODF :PTVLF,VSBNJ *OTJEF'SPOUFOE
"CPVUNF w ݟ༸ีʢ!2VSBNZʣ w ͓͠͝ͱ w ϑϩϯτΤϯυΤϯδχΞBU'0-*0 w ٕज़ސBU'J/$ w
։ൃิॿπʔϧΛ࡞Δͷׂ͕ͱ͖
None
None
#''
#BDLFOET'PS'SPOUFOET
ϑϩϯτΤϯυͷͨΊͷ αʔόʔ
By Sam Newman The BFF is tightly coupled to a
specific user experience, and will typically be maintained by the same team as the user interface. https://samnewman.io/patterns/architectural/bff/
ͳͥ#''ʁ
ϚΠΫϩαʔϏεͷ౷߹ͷͨΊ
6TFSFYQFSJFODF ύϑΥʔϚϯε 6*ʹඞཁॆͳ"1* ౷Ұ͞Εͨ6* .JDSPTFSWJDFT υϝΠϯʹྗͨ͠։ൃ γϯϓϧͰ࠶ར༻ੑͷߴ͍"1* αʔϏε͝ͱͷٕज़ಛҟੑ
6TFSFYQFSJFODF ύϑΥʔϚϯε 6*ʹඞཁॆͳ"1* ౷Ұ͞Εͨ6* .JDSPTFSWJDFT υϝΠϯʹྗͨ͠։ൃ γϯϓϧͰ࠶ར༻ੑͷߴ͍"1* αʔϏε͝ͱͷٕज़ಛҟੑ #''
'0-*0ʹ͓͚Δ#''
None
ࠓओʹίΠπͷ͓
8FC#''ͷ͓͠͝ͱ "1*"HHSFHBUJPO /PEFKTLPB 4FSWFS4JEF3FOEFSJOH 3FBDU 3FEVY
None
#''ಋೖͰྑ͍͜ͱ͍ͬͺ͍ όοΫΤϯυυϝΠϯ͝ͱͷαʔϏεͷ։ൃʹྗ ϑϩϯτΤϯυ6*ͷཁٻΛͦͷ··"1*Խ 443ʹΑΔߴͳॳظඳը
ྑ͍͜ͱ͍ͬͺ͍
ɾɾɾ
Ռͨͯ͠ຊ͔ʁ
ϑϩϯτͷࣄ૿͑ͯΔ w 41"ͷΈͷ߹ w 3FBDU 3FEVY෦Λ࡞ΕऴΘΓ w 41" #''ͷ߹ w
ࣗͨͪͰ"1*αʔόʔ࡞Δඞཁ͋Γ
ʮ#''Λ࠾༻͢Δʯ ʮϨΠϠʔ͕૿͑Δʯ ʮ։ൃʹ͕͔͔࣌ؒΔʯ
͜ͷ··͡Όμϝͩ
Α͏͘ࠓͷςʔϚ #''ΛαΫαΫ։ൃ͢ΔͨΊʹ
όοΫΤϯυͷ։ൃΛͨͳ͍ #''ͷ։ൃɾվम࣌Ͱɺ࣮αʔϏε͕ಈ࡞͠ͳͯ͘ Α͍ ϑϩϯτΤϯυόοΫΤϯυؒͰʮͲͷΑ͏ͳ"1* Ͱ͋Δ͖͔ʯͷ߹ҙ͕औΕ͍ͯΕฒߦ։ൃՄೳ
*%-ESJWFOEFWFMPQNFOU w *%- *OUFSGBDF%FpOJUJPO-BOHVBHF w "1*༷Λهड़͢ΔͨΊͷݴޠ w FH4XBHHFS H31$
(SBQI2- 84%- 40"1 FUDʜ w *%-͔Β֤छݴޠͷίʔυΛੜͰ͖Δͱخ͍͠
5ISJGU w '0-*0Ͱ5ISJGUͱ͍͏31$ϑϨʔϜϫʔΫΛ࠾༻ w IUUQTUISJGUBQBDIFPSH w ܕγεςϜΛඋ͑ͨ*%- w *%-͔Β+BWB4DSJQUΫϥΠΞϯτίʔυʢެࣜπʔϧʣ
5ISJGU*%- +BWB4DSJQU $MJFOU 8FC.PCJMF#'' /PEFKT 'JOBHMF 4FSWFS 4FSWJDF 4DBMB ࣗಈੜ
ϩδοΫΛ࣮
None
ࣗಈੜ͚ͩͰ ฒߦ։ൃʹ·ͩෆे
αʔϏεͷԾσʔλ͕ඞཁ ։ൃதαʔϏεͷ"1*ϞοΫσʔλʹࠩ͠ସ͍͑ͨ ։ൃࡁΈαʔϏεͷ"1*ςετڥΛར༻͍ͨ͠ ʢFHجຊతͳϢʔβʔใʣ ϞοΫͷར༻ੋඇ#''ͷίʔυ͔ΒෆՄʹ͍ͨ͠
͜͏͍͏ͱ͖ͦ͜ ʮؔ৺ࣄͷʯ
$SPTTDVUUJOHDPODFSO #''ͷओॲཧɿ ʮಛఆͷϚΠΫϩαʔϏεʹॲཧΛґཔ͢Δʯ ԣஅతؔ৺ࣄɿ ʮϚΠΫϩαʔϏεͷΓΛϞοΫ͢Δʯ
None
Πϯλʔηϓλ ࡞ΕͰ͚ͦ͏
ࢀߟɿ"01 w "TQFDU0SJFOUFE1SPHSBNNJOH w ԣஅతؔ৺ࣄΛॲཧຊମ͔Β͢Δ͜ͱ w ԣஅతؔ৺ࣄͷྫ w ϩΪϯά ྫ֎ϋϯυϦϯά
τϨʔγϯά FUDʜ
$PEFFYBNQMF
5ISJGUJOUFSGBDF *%- include "user_typedef.thrift" include "some_service_struct.thrift" include "common_exceptions.thrift" service SomeService
{ some_service_struct.UserAssetInfo getUserAsset( 1: required user_typedef.UserId userId ) throws ( 1: common_exceptions.ServerError serverError ) }
5ISJGUDMJFOU HFOFSBUFE ˞࣮ࡍ5ISJGUπʔϧ͕&4Ͱग़ྗ͢ΔͨΊɺ͔ͳΓಡΈʹ͍͘ class SomeServiceClient { constructor() { this.connection =
createConnection(); } getUserAsset(userId) { return new Promise(res => { this.connection.once("res_getUserAsset", res); this.connection.send("getUserAsset", [userId]); }); } }
$MJFOUΛར༻͢ΔՕॴʢ#''ʣ class SomeBFFLogic { constructor(someServiceClient, anotherServiceClient) { this.someServiceClient = someServiceClient;
this.anotherServiceClient = anotherServiceClient; } async getUserAssetWithDetail(userId) { const summary = await this.someServiceClient.getUserAsset(userId); const detail = await this.anotherServiceClient.getAssetDetail(summary); return { ...summary, ...detail }; } }
Πϯλʔηϓτʂ const mockResponseHandler = { get: (target, methodName) => {
const delegate = target[methodName]; if (typeof delegate !== "function") return delegate; return (...args) => getMockData(methodName).catch(delegate.bind(target, ...args)); }, }; const someServiceClient = process.env.NODE_ENV === "production" ? new SomeServiceClient() : new Proxy(new SomeServiceClient(), mockResponseHandler);
%JSFDU1SPYZͷར w ҆৺ײ w #''ओॲཧʢ5ISJGU$MJFOUͷݺͼग़͠ʣͷมߋෆཁ w ࣗಈੜ͞Εͨ5ISJGU$MJFOUͷίʔυͦͷ·· w IBOEMFSHFUτϥοϓͷҾ͔Β"1*໊শΛऔಘͰ͖ΔͨΊɺIBOEMFS ͷ෦ॲཧ͕۩ମతͳ"1*໊শΛؾʹ͢Δඞཁ͕ͳ͍
*OUFSDFQUPSDIBJO w OFX1SPYZ ͷΓΛ࠶OFX1SPYZʹ༩͑ΕɺෳͷΠϯ λʔηϓλʢIBOEMFSʣΛ࿈Ͱ͖Δ w '0-*0ͷ#''ͰϞοΫҎ֎ʹෳͷΠϯλʔηϓλΛ߹ w ࣮"1*ݺͼग़݁͠ՌͷϞοΫσʔλԽɺϦτϥΠɺ
2VFSZܥͷॲཧ ݶఆͰʣDBDIFɺFUDʜ
%ZOBNJDWT4UBUJD w %ZOBNJD1SPYZҎ֎ͰΠϯλʔηϓλΛ࣮ݱ͢Δ͜ͱՄೳ w ྫɿ#BCFMQMVHJO5ZQF4DSJQUDVTUPNUSBOTGPSNFSʹΑΓɺࣗಈ ੜ͞ΕͨίʔυΛ੩తղੳͯ͠ɺΞεϖΫτΛ৫ΓࠐΉΑ͏ʹ͢ Δʢ"45USBOTGPSNBUJPOʣ w ͜ͷ߹ɺϏϧυ࣌ʹ৫ΓࠐΈੋඇ͕֬ఆ͢Δ w
σϓϩΠޙʹڥมͰ৫ΓࠐΈͷ༗ޮແޮΛ੍ޚͰ͖ΔΑ͏ʹɺಈ తͳํࣜΛબͨ͠
༨ஊ w ࣮ͷͱ͜ΖϞοΫͷͨΊʹΠϯλʔηϓλͷΈΛ༻ҙͨ͠Θ͚Ͱ ͳ͍ w ॳʹ໘͍ͯͨ͠ʮϦΫΤετ͕ྃ͠ͳ͍αʔϏε"1*ίʔ ϧ͕كʹൃੜ͢Δʯͩͬͨ w ʮ൚༻తͳλΠϜΞτػߏΛͯ͢ͷϚΠΫϩαʔϏεݺͼग़͠ʹ ৫ΓࠐΉʯΈ͕ඞཁʹ
w ʮλΠϜΞτϋϯυϦϯά͞ΕΔΑ͏ʹQSPNJTFΛϥοϓ͢Δʯ ԣஅతؔ৺ࣄͰ͋Γɺ͜ΕΛղܾ͢ΔͨΊͷͱͯ͠։ൃ
͜͜·Ͱͷ͓͞Β͍ *%-͕ܾ·Ε#''ͷ։ൃʹணखͰ͖Δ w5ISJGU*%-/PEFKTΫϥΠΞϯτͷੜ w։ൃ࣌༻ͷϞοΫσʔλࠩ͠ସ͑
ં֯ͳͷͰ͏গ͠ศརʹ
8FC#''ͷ͓͠͝ͱʢ࠶ʣ "1*"HHSFHBUJPO /PEFKTLPB 4FSWFS4JEF3FOEFSJOH 3FBDU 3FEVY
#''Ͱ%FW͚ͷ6*࡞ΕΔ ϑϩϯτ։ൃ߹Ͱ "1*࡞ΕΔ 3FBDU 443 Ͱ 6*ఏڙͰ͖Δ
ͬͯΈΑ͏
None
%FNPOTUSBUJPO
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w ྫɿͷจ֬ೝը໘ w ϞοΫΛར༻͍ͯ͠ͳ͍ঢ়ଶ w εςʔδϯάͷόοΫΤϯυαʔ Ϗε͕ར༻͞ΕΔ w ΩϟϓνϟจՄೳঢ়ଶͷਤ
࣌ؒଳʹΑͬͯՄ൱͕ҟͳΔ
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w ։ൃऀϩʔΧϧςετڥͰɺ σόοά༻ͷϑολʔ͕ଘࡏͯ͠ ͍Δ
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w σόοά༻ϑολʔͷϦϯΫ͔Β ɺϞοΫͷڍಈΛίϯτϩʔϧ ͢ΔͨΊͷ։ൃઐ༻ը໘ભҠ w ༗ޮʹ͍ͨ͠ϞοΫΛબ͢Δ w ͦͷϒϥβͰͷΈɺબͨ͠Ϟο Ϋ͕ద༻͞ΕΔΑ͏ʹͳΔ
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w ΞϓϦέʔγϣϯͷը໘ʹͲΓ Ϧϩʔυ͢Δͱʜ w ϞοΫ͕༗ޮԽ͞ΕɺจෆՄೳ ঢ়ଶͱಉ༷ͷσʔλΛ#''͕ड͚ औͬͨঢ়ଶʹͳ͍ͬͯΔ
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w ద༻͞ΕͨϞοΫσʔλ:".- ܗࣜͰදࣔ͞Εɺը໘͔Β֬ೝ ͕Ͱ͖Δ w ΞυϗοΫʹϞοΫͷσʔλΛฤ ू͢Δ͜ͱՄೳ
˞ը૾ɾσʔλٕज़આ໌Λతͱͨ͠αϯϓϧͰ͢ w ϞοΫͷσʔλΛ্ॻ͖ͨ͠ޙʹ ࠶ը໘ΛಡΈࠐΉͱʜ w ্ॻ͖ฤूͨ͠༰͕ө͞ΕΔ
6*GPSEFWͷԸܙ ඇϑϩϯτΤϯδχΞʢFH2"୲ʣɺ࠶ݱқ ͷߴ͍ը໘ঢ়ଶΛ༰қʹ֬ೝͰ͖ΔΑ͏ʹͳͬͨ
ͦͷଞ%9্ͷ
4DB⒎PMEJOH w 3FBDUDPNQPOFOU4UPSZCPPLܗͷੜεΫϦϓτ w 3FEVYؔ࿈ʢBDUJPO SFEVDFS NJEEMFXBSFʣܗͷੜεΫϦϓτ
None
7JTVBMSFHSFTTJPOUFTUJOH w 4$.QVTI࣌ʹ$*Ͱ4UPSZCPPLͷΩϟϓνϟΛऔಘ w લճΩϟϓνϟը૾܊ͱࠓճΩϟϓνϟը૾܊Λൺֱ w ൺֱ݁ՌͷϨϙʔτΛ.FSHF3FRVFTUͷίϝϯτ
None
ಠࣗͷ&4-JOUϧʔϧ w ίʔυϨϏϡʔͰΑ͋͘Γ͕ͪͳࢦఠΛগͣͭ͠ϧʔϧԽ w ʮYYYͷ$PNQPOFOUੜͰΘͣʹZZZͱ͍͏ϥούʔΛ͓͏ʯ w ʮ͜ͷσΟϨΫτϦʓʓͷॲཧ͕ϝΠϯ͔ͩΒɺ[[[ΛJNQPSU͢ ΔΑ͏ͳॲཧॻ͔ͳ͍Ͱʯ w ଞͷϑϩϯτΤϯδχΞͰ&4-JOUϧʔϧΛ։ൃͰ͖ΔΑ͏ʹϋϯζ
ΦϯΛ࣮ࢪ
ଓ͖8FCͰ w 4UPSZCPPLपΓͷɿ IUUQTTQFBLFSEFDLDPNRVSBNZMJEFEVPJTJJTUPSZCPPL w 7JTVBMSFHSFTTJPOUFTUͷɿ IUUQTNFEJVNDPN!2VSBNZGPMJPͷը૾ճؼςετͷཪଆ DCD w &4-JOUͷϋϯζΦϯɿ
IUUQTHJUIVCDPN2VSBNZFTMJOUQMVHJOUVUPSJBMCMPCNBTUFS HVJEF3&"%.&KBNE
ࠓޙͷల
#''443ͷGFBUVSFUFTU w ࠓ͍࣋ͬͯΔΈ w ҙͷϚΠΫϩαʔϏεͷϞοΫࠩ͠ସ͑ JOUFSDFQUPS w 3FBDU$PNQPOFOUΛඳը݁Ռͷ7JTVBMUFTUJOH w
྆ํ͑ʮϚΠΫϩαʔϏεͷϦΫΤετऔಘʙ443$43Ͱͷ ϒϥβඳըʯΛҰؾ௨؏ͰςετͰ͖Δͣ
·ͱΊ
ࠓͨ͜͠ͱ w '0-*0ʹ͓͚Δ8FC#''ͷ֓ཁ w ͪΐͬͱָͯ͠#''Λ։ൃ͢ΔͨΊͷۤ࿑ w *%-ϕʔεͰͷ։ൃ w ΠϯλʔηϓλʹΑΔΫϥΠΞϯτͷࠩ͠ସ͑ w
FUD
͍͑ͨ͜ͱ ࡢࠓͷϑϩϯτΤϯυ༷ʑͳٕज़ཁૉͷͨΊʹɺ ։ൃ͕ෳࡶʹͳΓ͕ͪ ʮෆศʯͱײͨ͡Βগͣͭ͠ΤϯδχΞϦϯάͰղܾ ͢ΕΑ͍ ։ൃελοΫΛඥղ͚͖ͬͱԿ͔ݟ͔ͭΔͣʂ
Α͍ϑϩϯτΤϯυ։ൃΛ
5IBOLZPV