なぜバルクインサート・バルクデリートで統一しないのか
なぜ「複数(バルク)対応」だけにしないのか? すべてを配列([{...}])で受け取るようにすれば、確かにエンドポイントは一つで済みます。 しかし、以下の点がネックになる。
エラーハンドリングが複雑になる: 3件送って「1件成功、2件失敗」したとき、レスポンスをどう返すべきでしょうか?
一部成功を許すのか(HTTP 207 Multi-Status などが必要)。
一つでもダメなら全部ロールバックするのか。 単体APIなら「成功(201)か失敗(400/500)」の2択で済むので、フロントエンド側の処理が圧倒的に楽になえう。
バリデーション(入力チェック)のコスト: 100件のデータを一気に送られた場合、サーバーのメモリやDBの負荷が急増します。単体用APIなら、一回のリクエストに対する負荷を予測・制限しやすくなる。
開発者体験(DX): たった1件更新したいだけなのに、わざわざ [ と ] で囲って送らなければいけないのは、地味にフロントエンド開発者のストレス(とバグの元)になります。
lazygit おすすめの設定
# 1. 差分表示の強化 (Delta)
git:
paging:
colorArg: always
pager: delta --dark --paging=never
commit:
signOff: false
autoWrapCommitMessage: true
autoWrapWidth: 72
merging:
args: '--no-edit' # マージコミットメッセージ編集スキップ
# 2. UI の見た目と使い勝手
gui:
language: 'ja' # 日本語化
border: 'rounded' # 角丸でモダンな枠線
sidePanelWidth: 0.33 # パネル幅を黄金比に
showIcons: true # アイコン表示 (フォントが必要)
# 3. パフォーマンス向上
refresher:
refreshInterval: 10 # 自動更新間隔(秒)
fetchInterval: 60 # fetch間隔(秒)
# 4. キーバインド調整
keybinding:
universal:
quit: 'q'
return: '<esc>'
nextTab: ']'
prevTab: '['
commits:
copyCommitMessageToClipboard: '<c-y>' # コミットメッセージをコピー
# 5. 作業を爆速にするカスタムコマンド
customCommands:
# 'C' で Conventional Commits 形式のメニューを開く
- key: 'C'
command: 'git commit -m "{{index .PromptResponses 0}}: {{index .PromptResponses 1}}"'
context: 'files'
description: 'Conventional Commit を作成'
prompts:
- type: 'menu'
title: 'コミット種別を選択'
options:
- name: 'feat'
description: '新機能'
value: 'feat'
- name: 'fix'
description: 'バグ修正'
value: 'fix'
- name: 'docs'
description: 'ドキュメント'
value: 'docs'
- name: 'refactor'
description: 'リファクタリング'
value: 'refactor'
- name: 'chore'
description: '雑用'
value: 'chore'
- type: 'input'
title: 'メッセージを入力'
initialValue: ''
# 'D' でマージ済みブランチを掃除
- key: 'D'
command: 'git branch --merged | grep -v "\*" | xargs -n 1 git branch -d'
context: 'localBranches'
description: 'マージ済みのブランチを一括削除'
loadingText: '削除中...'
# 'F' でブランチから直接ファイルを取得
- key: 'F'
command: 'git checkout {{.SelectedLocalBranch.Name}} -- {{.SelectedFile.Name}}'
context: 'files'
description: '他ブランチから該当ファイルを取得'
# 'P' でプッシュ前に差分確認
- key: 'P'
command: 'git diff {{.SelectedLocalBranch.UpstreamRemote}}/{{.SelectedLocalBranch.UpstreamBranch}}..HEAD'
context: 'localBranches'
description: 'プッシュされる差分を表示'
DXF TEXT エンティティの読み方まとめ
はじめに
DXF ファイルは「グループコード(番号)」と「値」の組み合わせで構成されます。\ グループコードは「次の値が何を意味するか」を決める役割を持ちます。
この資料では、TEXT エンティティを例に\ DXF の読み方をわかりやすく整理したメモをまとめています。
基本:DXF の行はこう読む
10
130.39
- 10 → グループコード(意味:X 座標)\
- 130.39 → 値(X = 130.39)
DXF はすべてこの形式です。
代表的なグループコード(TEXT 用)
グループコード 意味
0 エンティティ種別 1 テキスト内容 5 ハンドル(ID) 7 テキストスタイル 8 レイヤ名 10 / 20 / 30 挿入位置(X / Y / Z) 11 / 21 / 31 第2基準点 40 文字高さ 50 回転角度 72 水平揃え(左・中央など) 73 生成フラグ
■サンプル TEXT エンティティ(DXF 生データ)
0
TEXT
5
A9
330
C
100
AcDbEntity
8
info
100
AcDbText
10
130.39496288806708
20
40.2434320017132
30
0
40
2.6458333333333335
1
4F : 11840mm
50
0
7
STANDARD
72
0
11
130.39496288806708
21
40.2434320017132
31
0
100
AcDbText
73
2
■サンプルの内容を読み解いた結果(整形表示)
ENTITY TYPE : TEXT
──────────────────────────────────
ハンドル : A9
レイヤ : info
表示文字列 : "4F : 11840mm"
文字高さ : 2.6458333333333335
回転角 : 0°
整列方法 : 左揃え (72 = 0)
文字生成フラグ : 2
挿入位置(基準点)
X : 130.39496288806708
Y : 40.2434320017132
Z : 0
第2基準点
X : 130.39496288806708
Y : 40.2434320017132
Z : 0
フォントスタイル : STANDARD
DXF の理解を深めるポイント
- DXF は すべてが「番号 → 意味 → 値」で構成される\
- TEXT の本文は グループコード 1\
- 座標系の基本は 10・20・30\
- 文字の見た目は 40(高さ)、50(角度)、7(フォント)\
- エンティティは 0 で始まり、次の 0 の直前までがひとつの塊
zshでIssueごとにBranch作る運用を助ける
Git Helper Functions
Issue単位でブランチを切り替える際の手間を軽減するためのZsh関数集。
gnew - 新しいIssue用ブランチへの切り替え
現在のブランチを削除し、main を最新化してから新しいブランチを作成する。
使い方
gnew <new-branch-name>
例
# feature/issue-123 ブランチで作業完了後、次のIssueへ gnew feature/issue-456 # 実行される処理: # 1. git checkout main # 2. git branch -D feature/issue-123 (現在のブランチを削除) # 3. git pull # 4. git checkout -b feature/issue-456
注意事項
- 未コミットの変更がある場合:
git checkout mainが失敗するため、先にコミットまたはstashしてください - main/master上で実行した場合: ブランチ削除をスキップし、pull → 新ブランチ作成のみ実行
- PRがマージされていない場合: リモートブランチは残るため、GitHub上で別途削除が必要
セットアップ
~/.zshrc に以下が追加済み:
gnew() {
local current_branch=$(git branch --show-current)
local new_branch=$1
if [[ -z "$new_branch" ]]; then
echo "Usage: gnew <new-branch-name>"
return 1
fi
if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
echo "Already on main/master. Pulling and creating new branch..."
git pull && git checkout -b "$new_branch"
return
fi
echo "Switching from '$current_branch' to new branch '$new_branch'..."
git checkout main && \
git branch -D "$current_branch" && \
git pull && \
git checkout -b "$new_branch"
}
反映方法
新しいターミナルを開くか、以下を実行:
source ~/.zshrc
【TypeScript】残余プロパティを使った分割代入
残余プロパティを使った分割代入
オブジェクトから特定のプロパティを除外して、残りのプロパティを新しいオブジェクトとして取得するパターン。 書いていて思いついたので、メモしておく!
パターン例
例えば特大オブジェクトがあるとする
// オリジナルのユーザーデータから特定フィールドを除外してコピーを作成 const { id: _id, password: _password, createdAt: _createdAt, updatedAt: _updatedAt, ...userDataWithoutMetadata } = originalUserData
このパターンの優れた点
| ポイント | 説明 |
|---|---|
| Immutable | 元のoriginalUserDataを変更せず、新しいオブジェクトを生成 |
| 型安全 | TypeScriptがuserDataWithoutMetadataの型を自動推論(除外プロパティを除いたOmit<T, 'id' | 'password' | ...>相当) |
| 宣言的 | 「何を除外するか」が明確に見える |
_プレフィックス |
「意図的に未使用」を示す慣例(ESLintのno-unused-vars対策にもなる) |
代替案の問題点
// NG例1: 手動コピー(DRY違反、メンテナンス困難) const userDataWithoutMetadata = { name: originalUserData.name, email: originalUserData.email, // ... 大量のプロパティを列挙 } // NG例2: delete使用(型が崩れる、意図が不明瞭) const userDataWithoutMetadata = { ...originalUserData } delete userDataWithoutMetadata.id delete userDataWithoutMetadata.password
汎用テンプレート
// 特定プロパティを除外してオブジェクトをコピー const { propToRemove1: _propToRemove1, // _ = 「意図的に捨てる」 propToRemove2: _propToRemove2, ...rest // 残りのプロパティを取得 } = sourceObject // TypeScriptの型推論 // rest → Omit<typeof sourceObject, 'propToRemove1' | 'propToRemove2'>
ユースケース
- 新規作成用データ: 既存データから
idを除外してPOSTリクエスト用に変換 - セキュリティ:
passwordやtokenを除外してログ出力やレスポンスに使用 - 状態リセット: 特定のフィールドをクリアしたコピーを作成
- APIレスポンス整形: 不要なメタデータを除外してフロントに返却
【拡張記事】structuredCloneで関数がクローンできない理由
structuredCloneで関数がクローンできない理由は、もともとStructured Clone Algorithmは他の実行コンテキストにデータを移送したり、データを永続化したりする目的で定義されていたからだと思われます。例えば、他のWindowにpostMessageでオブジェクトを送信するとき、あるいはオブジェクトをIndexedDBに保存する場合にStructured Clone Algorithmが使用されます。
とくに永続化のことを考えると、structuredCloneでクローンできるためにはデータがシリアライズできる必要があります。実際の実装はともかく、structuredCloneの挙動は仕様書上では「シリアライズしてからデシリアライズする」というアルゴリズムで定義されています。
- structuredCloneの元々の目的 javascript// 他のウィンドウにデータ送信 window.postMessage({ name: "太郎", age: 25 }, "*")
// データベースに保存 indexedDB.put({ name: "太郎", age: 25 }) → データを別の場所に移すための仕組み 2. シリアライズの問題 シリアライズ = データを文字列や bytes に変換すること javascript// これはOK(文字列に変換可能) const data = { name: "太郎", age: 25 } JSON.stringify(data) // '{"name":"太郎","age":25}'
// これはNG(関数は文字列にできない) const func = () => console.log("hello") JSON.stringify(func) // undefined 3. 関数が特殊な理由 javascriptlet x = 100 const myFunc = () => x + 1 // 外の変数xを参照
// この関数をコピーしても... // 新しい場所にxは存在しない! 環境依存 = 関数は周りの変数やスコープに依存している → 関数だけコピーしても動かない 簡単に言うと 「関数は周りの環境とセットじゃないと意味がないから、単体ではコピーできない」
【拡張記事】コンポーネントの中にコンポーネントを作るということ
Reactにおける再レンダリングの詳細な仕組み(Reconciliation)
1. 再描画の流れ(Reconciliation)
Reactの再描画処理は、2段階の比較を行って差分を検出します。
(1) Elementの種類(type)の比較
- 同じ位置のElement同士の
typeを比較。 - 異なればDOMを破棄し、再生成。
- 同じならDOMを維持し、次の段階へ進む。
(2) propsや子要素の差分比較
- propsや子要素を比較し、差分を検出。
- 差分があればその部分のみをDOMに反映。
- 差分がなければ再描画は行われない。
2. {renderInner()}が常にtype安定でも再描画される理由
疑問点
常にtypeが安定(例:
'div')なら、再描画されずpropsやstateの変更を認識しないのではないか?
回答
- 「typeが安定」は「DOMの破棄を防ぐ」ことを意味し、「再描画しない」ことではない。
- propsや子要素に変更があれば、差分のみが再描画される。
例
初回レンダリング時:
<div>0</div>
再レンダリング時(stateが更新):
<div>1</div>
- Reactはtype('div')が同じであるため、DOMを維持。
- 子要素の差分(0 → 1)のみ更新される。
3. コンポーネントの再生成でtypeが毎回異なる場合の挙動
例
function OuterComponent() { const [count, setCount] = useState(0); const InnerComponent = () => <div>{count}</div>; return <InnerComponent />; }
起こる現象
- typeが毎回異なるため、DOMが毎回破棄・再生成される。
- 差分比較が意味をなさず、全て再描画される。
- 非効率でパフォーマンスが悪化する。
4. 再描画処理のまとめ(比較)
| 状態 | typeが毎回変わる | typeが安定 |
|---|---|---|
| DOMの操作 | 全て破棄・再生成 | DOMを再利用 |
| 再描画範囲 | 全て | 差分のみ |
| パフォーマンス | 悪化 | 良好 |
| 副作用(useEffect等) | 毎回発生 | 初回のみ発生 |
| Reactの挙動 | 非効率 | 効率的 |
5. React公式ドキュメントでの表現(参考)
Reactは最初にElementの種類(type)が変わったかを調べます。種類が変わった場合、新しいElementのツリーが構築されます。同じ種類であれば、Reactはpropsを調べ、変更されたpropsだけを更新します。
6. 結論
- 「typeが安定していると再描画がされない」わけではなく、「typeが安定しているからDOMが維持され、propsや子要素の差分更新のみが効率的に行われる」。
🚩 実務上の注意点
- コンポーネントは外部で定義する(毎回新たに生成しない)。
- JSX要素のtypeを安定させることで、Reactの再レンダリング効率を向上させる。