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
フロントエンドで 良いコードを書くために
Search
てけし
January 18, 2023
Programming
2.5k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
フロントエンドで 良いコードを書くために
フロントエンドLT新年会の資料
https://thecoo.connpass.com/event/269188/
てけし
January 18, 2023
More Decks by てけし
See All by てけし
eslint-flat-config
t_keshi
5
1.1k
Other Decks in Programming
See All in Programming
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
170
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
510
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
140
What's New in Android 2026
veronikapj
0
260
SlackアプリとLambdaの 連携を構築した話
pawn_4_s
1
120
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argument-syntax
kanaru0928
0
230
yield再入門 #phpcon
o0h
PRO
0
1k
Foundation Models frameworkで画像分析
ryodeveloper
1
610
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
470
プロポーザルを書いてもらう
pvcresin
0
500
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
160
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
180
Featured
See All Featured
WENDY [Excerpt]
tessaabrams
11
39k
Test your architecture with Archunit
thirion
1
2.3k
Unsuck your backbone
ammeep
672
58k
First, design no harm
axbom
PRO
2
1.2k
Context Engineering - Making Every Token Count
addyosmani
9
1k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
790
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
3
430
Darren the Foodie - Storyboard
khoart
PRO
3
3.6k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
410
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
The browser strikes back
jonoalderson
0
1.5k
Transcript
フロントエンドで 良いコードを書くために Sansan株式会社 技術本部 Strategic Products Engineering Unit Contract One
Devグループ 井上丈士
写真が入ります 井上丈士 Sansan株式会社 技術本部 Strategic Products Engineering Unit Contract One
Devグループ zenn: t-keshi twitter: t__keshi 趣味: サウナ駆動技術記事投稿
(我々は常に思い悩む) どうしたら良いコードが 書けるようになるだろうか...?🤔
知識や経験...?🤔 いや、もう少し具体化しないと コードを良くする方法が見えてこない
良いコードを書くための方法を、 以下のように分類・整理することはできないだろうか? そこで、、、 設計原則 フレーム ワークの知識 対話
①狭義の設計原則 設計原則
設計原則と聞いて、まず頭に浮かぶもののこと。 オニオンアーキテクチャや クリーンアーキテクチャのようなものが挙げられる。 「フロントエンドのクリーンアーキテクチャ」 一時期、流行った、バックエンドのアーキテクチャを輸入する方針 狭義の設計原則
設計原則の輸入の問題点
オニオンインオニオンを良しとする意見もある。 しかし、0コストで変更容易性が得られるわけではない。 可読性・複雑さとのトレードオフ。 その割に、フロントエンドはフレームワークへの依存が大きく、 どう足掻いても変更はそれほど容易にならない。 オニオンインオニオンの何が駄目か?
実装パターンとその背後にある考え方は、区別した方が良さそう。 実装パターンとその背後にある考え方 背後にある考え方 BE実装パターン FE実装パターン
例えば責務を意識したレイヤー分け ❌悪い例 データ取得の責務 getUsers()などに切り出すべき 表示の責務 その背後にある考え方? const UsersPage = ()
=> { const [user, setUsers] = useState(null) useEffect(() => { const asyncFn = async () => { const response = axios.get("https://hoge-api/users", { headers: {...省略...} }) return response.data } asyncFn() }, []) return <UsersTable users={users} /> }
いわゆるリーダブルコード的なもの。 設計原則に含めていいのか微妙だが、 設計本には、こうした内容も書いてある。 ex.)良いコード悪いコードで学ぶ設計入門 基本的には本の内容をFEにもそのまま適用可能。 JavaScript/TypeScriptでリーダブルなコードを考えるなら、 どんなことが言えるだろうか? 広義の設計原則
静的に分岐漏れを検出する。 条件分岐のコツ1 TypeScript 4.9以降 type Action = | { type:
"OPEN"; payload: { message: string } } | { type: "CLOSE" } | { type: "TOGGLE" } const reducer = (action: Action) => { switch (action.type) { case "OPEN": return { isOpen: true, message: action.payload.message } case "CLOSE": return { isOpen: false, message: null } default: // TOGGLEがないのでコンパイルエラー throw new Error(action satisfies never) } } TypeScript 4.9以前 type Action = | { type: "OPEN"; payload: { message: string } } | { type: "CLOSE" } | { type: "TOGGLE" } const reducer = (action: Action) => { switch (action.type) { case "OPEN": return { isOpen: true, message: action.payload.message } case "CLOSE": return { isOpen: false, message: null } default: // TOGGLEがないのでコンパイルエラー throw new Error((action as { type: "__invalid__" }).type) } }
処理の分岐というより、単純な対応を表す場合は、 Switchの代わりにObjectを使う。 条件分岐のコツ2 type Status = "active" | "inactive" |
"sleep" const UserStatus = (status: Status) => { const icon = { active: <ActiveIcon />, inactive: <InactiveIcon />, sleep: <SleepIcon /> }[status] return <div>{icon}</div> }
RoRoとは、”Receive an Object, Return an Object” オブジェクトで受けてオブジェクトで返すこと RoRo const createUser
= (userId: string, userAccountId: string) => { // 省略 } const UserRegistrationDialog = () => { const handleSubmit = (userAccountId: string, userId: string) => { // 引数を渡し間違える createUser(userAccountId, userId) } return <Dialog onSubmit={handleSubmit}/> } Objectを使うと混乱は防げる (他の言語でいう名前付き引数やキーワード引数) const handleSubmit = ({userId, userAccountId}) => { createUser({ userId, userAccountId}) }
Gap
②フレームワークの知識
あまりにもuseEffectが乱用されすぎている。 これはありがちな悲劇。 useEffectはエスケープハッチ、仕方なく使うもの。 useMemoなどで済むようなケースで、 安易にuseEffectを使ってはいけない。 例えばReactだと1
余計なFragmentが多すぎる。 些細な問題だが、多発すると可読性を下げる要因に。 nullもstringもnumberも 立派なReactElementであり、FCのReturnType。 例えばReactだと2
無闇にStateに入れまくる。 状態管理はシンプルに保つのがキモ。 ❌悪い例 例えばReactだと3 const HogeComponent = () => {
const [users, setUsers] = useState() const [admin, setAdmin] = useState() // その他数多くのStateなど, 500行くらい return <div /> // ようやくJSX }
(再掲)フロントエンドにはフロントエンドの実装パターンがある。 では、フロントエンドの実装パターンとは何だろう? それは、ある程度、フレームワーク依存になってしまう。 Reactの場合だと、 <CustomHook>と<コンポーネント設計> なのではないかと思う。 フレームワークの実装パターン
APIの呼び出しはsetLoadingやsetErrorなどのボイラプレートに溢れる これは特にCustomHookを使うべきところ react-useのCustomHookを参考にするのもおすすめ 込み入ったロジックはどんどんCustomHookに切り出していこう CustomHook const HogeComponent = () =>
{ const [state, setState] = useState() …500行くらいあるコード... return ようやくJSX } CustomHookで切り出そう
taroさんのLTに続く コンポーネント設計
Last Journey
③対話
コンポーネント、それが一番大事 - 基盤となるUIコンポーネントが不足していると、開発速度が出ない - 良いコンポーネントは、開発のアクセル そして、そんなコンポーネントを作るために必要なのが、
デザインチームとの対話
ビジネスサイドとの対話 - ビジネスサイド、開発サイドの相互理解 - いつもそれがうまくいくとは限らないが、チーム全体としてのたしかな進歩につな がる
まとめ
対話 フレームワークの知識 設計原則 良いコード
「なぜ良いコードが書けないんだろう」 悩んだときは、それを各要素に分解し、 各個撃破していくことが大事。 ぼんやりした問題を具体的な要素に分解することさえできれば、 「悩む」のではなく、「考える」ことができる。 今日はそんな話がしたかった。
採用情報はこちら https://media.sansan-engineering.com/ 積極採用中!!
ありがとうございました!
狭義の設計原則 WebフロントエンドでDDDを導入のメリットってあるでしょうか WEBフロントエンドにおけるソフトウェア設計の考察 広義の設計原則 Elegant Patterns in Modern JavaScript フレームワークの基礎知識
You Might Not Need an Effect 参考記事