パルカワ2

最近はFlutterをやっています

Dartのextensionについてぼんやり思っていること

Dartには Extension methods | Dart というのがある。ぼんやり思っていることをメモしておく

前提

extensionは

  • クラスにメソッドを追加することができる
  • テストするためにクラスを作る必要がある
  • インスタンスフィールドは持てない
  • クラスの責務の大きさはextensionで切り出しても小さくならない

思っていること

変更できないクラスにどこでも使えるメソッドを生やすのはいいと思う

  • 変更できないクラスとは、StringやListなどDartが提供しているクラスやライブラリが提供しているクラス
  • どこでも使えるメソッドとは、Listをsliceするとか特定のドメインを扱う時のみ利用するメソッドではないもの

ほとんどがdartxdart:collectionにあると思われる。

逆に言えば、以下のようなパターンはextensionは使わずクラスを定義したほうがよいと思う

  • 自分が定義したクラス
  • 特定のドメインのみを扱う時に利用するメソッド

別クラスとして定義して、テストをする時に依存する情報を減らしたりクラス自体を小さくしたほうがいいと思う。

一応例外はあって、enumは自分が定義していて特定のドメインでのみ扱う場合でもextensionを使っている。そうしないとenumにメソッド生やせないので。

extensionを定義する場所をまとめる

様々な箇所でextensionを実装すると似たようなextensionが生えたり別でクラスを作ったりしてしまいそうなので、すべてまとめておいてまとめてexportする形にしておくのがよかったかもしれないと思っている。

変更できないクラスにどこでも使えるメソッドを生やすというルールだったらそれが出来る気がする。

リファクタリングをするために"一時的に"別ファイルに持って行くために利用する

リファクタリングを行う時に変更回数が多い+コードの行数が長いファイルをまず別ファイルに切り出してから少しずつリファクタリングすることがある。extensionを使えば簡単にクラスから別ファイルに切り出すことができる。ただ切り出し方にも工夫は必要で、例えばたくさんある切り出したいメソッドをまとめて別ファイルに切り出すというようなやり方をしてしまうと結局大きなファイルになってしまうのでクラスとして切り出すことを想定して切り出す必要はある。

また切り出して終わりにするとクラスは責務過多のままなので、ちゃんとリファクタリングしていく必要がある。

まとめ

僕はDartのextensionはあんま使う必要がないなと思っていますがみなさんはどうでしょうか

FlutterKaigi 2022で「Dartにおける静的解析」を話してきた

speakerdeck.com

初の動画撮影だったんですが、mmhmmで細切れで撮影したのでむしろ楽だったかも。最初は頑張って話そうとしてたんですが、録画していると思うと緊張して全くうまく話せなかったので、スクリプトを書いて読む形にしたりした。

内容的には、custom_lintcodemodを知らなかったとかコメントがあったりしたので話して良かった。

反省としては、時間的制約があって色々話せなかったこともありanalyzer pluginの説明をバッサリ端折ったので意味わかんない人は意味わかんなかったかも。端折るところ間違えたかもしれない。あとanalyzer pluginのメモリ消費多いよ問題の話も話してないので、興味ある人はイシューを読んでください。

運営のみなさん、ありがとうございました!

GoogleカレンダーからHourStackのEntryを作成した時にプロジェクトを自動で付ける

HourStackでタスクと時間の管理をしている。

HourStackは、Zapierと連携が出来て色々自動化出来るので、Googleカレンダーで作ったEntryはプロジェクトを自動で付けるようにした。

  • HourStackのEntry CreatedをTriggerに選ぶ
  • Source Prov が google-calendar のときのみ実行するようにフィルタ
  • Project が Does not exist のときのみ実行するようにフィルタ
  • GoogleカレンダーからFind Event
    • Search Termに作成したEntryの Name を指定
    • Start Time に Start Date と Start Timeをスペース区切りで指定
  • Run Python
    • Googleカレンダーの色分けからプロジェクトを決める
    • Inputには Color ID, Start Date, Start Timeを指定する
  • Update Entry in HourStack
    • 何も指定しないと指定していない状態で更新されるので、Entry Createdの情報を指定する
    • Start AtをRun PythonでOutputした start_at を指定する。Start Onを指定しない。
    • Project IDには、Run PythonでOutputした project を指定する

Run Pythonに書くコードは以下の通り。Project IDは自分で指定する。

from datetime import datetime
from dateutil import parser
import math

color_id = "0"
if "color_id" in input_data:
  color_id = input_data['color_id']

start_at = ''
if "start_time" in input_data:
  start_at = f"{input_data['start_date']} {input_data['start_time']}+00:00"
 
project = {
  "0": "<Project ID>",
  "1": "<Project ID>",
  "2": "<Project ID>",
  "3": "<Project ID>",
  "4": "<Project ID>",
  "5": "<Project ID>",
  "6": "<Project ID>",
  "7": "<Project ID>",
  "8": "<Project ID>",
  "9": "<Project ID>",
  "10": "<Project ID>",
  "11": "<Project ID>",
}[color_id]

output = {'project': project, 'start_at': start_at}

HourStackのProject IDは、Update EntryでProject IDを指定しようとすると出てくる。 GoogleカレンダーのColor IDは Google カレンダーの色 - SAKI Web Design を参考にした。

Googleカレンダーの色分けとHourStackのプロジェクトの色を同じにしている。こんな感じでカラフルになってかわいい

Mimestreamを使い始めた

Mimestream | A native macOS email client for Gmail

  • 会社MacChromeでは、会社のGoogleアカウントでログインして使っている
  • 会社のGoogleアカウントでChromeにログインしていると個人アカウントにログインできない
  • なにかに登録やログインする時に個人アカウントで基本登録しているので、メールを見るために個人アカウントのChromeプロファイルに切り替えている
  • めんどくさすぎるのでどうにかしたい
  • メールのクライアントを使うのがよさそう
  • Gmailのフィルタを結構がっつり使っているのでGmailに特化したものがほしい
  • MimeStreamというのがあるらしい

という感じで使い始めた。

FlutterでMacアプリをビルドしてFirestoreにつなげようとすると固まる

趣味でMacアプリでも作ってみるかと思ったら早速ハマってしまった………

Firebase準備

  • プロジェクトを作る
  • Firestoreのデータベースを作成する

コマンド

cd app
flutter create --org com.hisaichi5518 --platforms=ios,macos .
firebase login
dart pub global activate flutterfire_cli
flutter pub add firebase_core
flutter pub add cloud_firestore
flutterfire configure --platforms=ios,macos --ios-bundle-id=com.hisaichi5518.app --macos-bundle-id=com.hisaichi5518.app

macos/PodfileにてFirestoreが依存する最低バージョンに書き換える

platform :osx, '10.12'

アプリを立ち上げたらFirestoreのドキュメントが作られるコードを書いてみる

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  final db = FirebaseFirestore.instance;
  final user = <String, dynamic>{
    "first": "Ada",
    "last": "Lovelace",
    "born": 1815
  };
  final doc = await db.collection("users").add(user);
  print('DocumentSnapshot added with ID: ${doc.id}');
  runApp(const MyApp());
}

Macアプリの場合は、無が表示されてしまう。ログすら出ないので困った。

iOSアプリはうまくドキュメントが作成されて画面も表示される。

アプリが作成された時点ではBundleIdが、 ios, macosともに com.hisaichi5518.app になっているのでそれぞれ変更してみたけどダメだった

またFirebaseは無料版はアプリが3個しか登録できない。flutterfire configureがよしなに作成してくれるが3個以上作ってもエラーにならないので注意

追記: 解決方法

macos/Runner/DebugProfile.entitlements に以下の設定を追加してあげれば動いた。

<key>com.apple.security.network.client</key>
<true/>

SocketException: Connection failed (OS Error: Operation not permitted, errno = 1) with flutter app on macOS - Stack Overflow

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.2, on macOS 12.5.1 21G83 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] Android Studio (version 2021.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.1)
[✓] VS Code (version 1.71.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

• No issues found!

サンプルアプリは動く

flutterfire/packages/cloud_firestore/cloud_firestore/example at master · firebase/flutterfire · GitHub

関連

Add Firebase to your Flutter app

まとめ

flutterfire configureが便利だった。 FlutterFireのmacOS対応はまだβ版らしいので本格的に使うのはまだ先かなぁ

VSCode環境改善活動

定期的にVSCodeやInteliJでGitの操作をしたい期がやってくる。4年前も挑戦して挫折している。

最近はInteliJを使ってなくてVSCodeだけになってる。Gitの操作をするときは、VSCodeからiTerm2に移動していてまあそれでも大きくは困ってないんだけど、VSCodeからiTerm2に移動するときはVSCodeで開いてるディレクトリでGitを操作すること以外していないのでVSCodeで完了させたい気がしてきた。

VSCodeGUIでGitを操作することもやってみたけど、自分には無理だったのでVSCodeのTerminalを使うことにする。

TerminalとEditorの移動をキーバインドでできるようにする

VSCodeのUserInterfaceドキュメントを見て何から何に移動したいのか確認する。以下を満たしたい。

  • 特定のEditor GroupsからPanel(Terminal)に移動する
  • Panel(Terminal)から特定のEditor Groupsに移動する

キーバインドの設定を検索する。

  • Terminal: Focus Terminalというのがあったのだけど、デフォルトではキーバインドが設定されていない(!)
  • パネルのターミナルにフォーカスを当てると ^` と表示されていてcontrol+@で移動できるのでこれで良い
  • Editor Groupsには、command+1-9で移動できる

ちなみにcommand+0でサイドバーに移動できる。エクスプローラーとか具体的なのは command+shift+eとか。

また他のパネルは、command+shift+mなどなのでcommand+shift+なんかに統一したい気持ちを抑えてcontrol+@を使う。

ただターミナルにフォーカスが当たっているときにcontrol+@したらEditor Group 1に戻れるように追加した。

[
    {
        "key": "ctrl+[BracketLeft]",
        "command": "workbench.action.focusFirstEditorGroup",
        "when": "terminalFocus"
    }
]

Terminalを開いたらtmuxを開くようにする

tmuxのキーバインドに手が慣れているのでそうした。すでにセッションがある場合は、attachするなどは不要だと思ったのでやっていない。複数のディレクトリをVSCodeで開くのでattachされるとむしろ困るかもしれない。

  • コマンドパレットを出して、Terminal: Select Default Profile を選択
  • tmuxを選択

Terminalを開いたらVSCodeで開いてるディレクトリを開く

VSCodeでTerminalを操作するときは、ほぼ確実にVSCodeで開いてるディレクトリに移動している。

設定に以下を追加

    "terminal.integrated.cwd": "./",

ちゃんとキーバインドを覚える

環境というか自分の問題である…………。

InteliJからVSCodeを使うようになってからキーバインドがわからないままになってたりしてたんだけどちゃんと確認した。

あと最近もともと使えてたキーバインドが使えなくなったりして困ってたんだけどちゃんと原因を調べたりした。Karabiner-Elementsの設定がオフになってた……。

TerminalからVSCodeを開くようにする

日々何個かのディレクトリを行き来している。たくさん開いてると重くなる気がするので不要になったらウインドウを閉じている。再度開く必要があるとき毎回マウスでポチポチしていたけど、fzfで移動出来たら便利じゃんと思ったので作った。 ちなみにすでに開いてるとそのウインドウに移動してくれる。

control+@ -> control+v -> 文字入力 -> 移動 という感じになって楽

fzf-open-vscode() {
  local repo=$(ghq list | fzf --preview "ghq list --full-path --exact {} | xargs exa --color=never --no-permissions --no-user --no-filesize --git-ignore --sort name --tree --level 2")
  if [ -n "$repo" ]; then
    repo=$(ghq list --full-path --exact $repo)
    BUFFER="cd ${repo} && code . && cd -"
    zle accept-line
  fi
  zle clear-screen
}
zle -N fzf-open-vscode
bindkey '^v' fzf-open-vscode

まとめ

手癖でiTermを開いてしまうことがあるけど減らしていける気がする

Mac環境改善活動

ここ数年会社Macの開発環境がかなりいい加減でちゃんと設定してない状態だったので、久しぶりに整えるかという気持ちになったので整えた。

oh-my-zshをやめてZimに移行した

GitHub - zimfw/zimfw: Zim: Modular, customizable, and blazing fast Zsh framework

ターミナルを立ち上げるたびにずっと遅いな〜と思っていたので早いやつに移行しようという気持ちになって移行した。Sixeightさんのひさしぶりにzshに戻りました - ちなみに を参考にして色々設定した。ありがとうございます!

もっさりしてたけど、早くなったので良かった。

pecoをやめてfzfに移行した

GitHub - junegunn/fzf: A command-line fuzzy finder

pecoを愛用してたんだけど僕のiTerm2の設定だと色が若干見にくくて設定を直せばいいんだけどめんどくせ〜と思ってずっと放置してた。Sixeightさんの記事を読んでfzfを使ってみたら色も問題ないしpreviewとか出せて便利じゃんとなって移行した。

exaとかbatとかいれた

色がついてて綺麗!!!ただfzfのpreviewでexaを使ってるけど、colorを付けると文字がズレる問題があったのでオフにしてる。普通に使うぶんには困らないのでlsなど置き換えた。

Raycastで社内ドキュメントを検索できるようにした

Raycast

RaycastにNotion Extensionがあるんだけど、タイトル検索ではなかったりChromeの閲覧履歴を検索出来なかったり遅かったりしたので自分で作った。実は前から作ってたんだけど結構バグっていたり情報がなくて困ることがあったりしたので諸々直したりした。

SpotlightをやめてRaycastだけにした

元々はSpotlightとRaycastを併用していてアプリケーション検索はSpotlight, その他はRaycastを使うという感じで使い分けてた。前はRaycastだけだと満足出来なくて併用してた気がするけど理由は忘れてしまった。

RaycastのQuicklinksを設定する

ちゃんと設定すれば便利な気がするなと思ったので設定した。例えば特定のプロジェクトのFirestoreを開きたい時はRaycastのQuicklinksを設定しておいてそれを使って開くと早い、みたいな。ブラウザのブックマークを検索できるSearch Browser Bookmarksもあるけど、Search Browser Bookmarksを選択して検索するみたいなのがめんどくさいのでQuicklinksにした。

RaycastのExtensionをいれる

たくさん入れても忘れるので自分がよくやることを解決するものだけ入れて使わないコマンドはオフにした。

前はJIRAのExtensionとか入れてたけど結局使ってなかった。検索するよりボードの一覧を見ることが多いので自分が見るボードのQuicklinksを追加するみたいな感じで自分の行動に合わせるようにした。

まとめ

Raycast便利。ただScriptの結果をFilterしてアクションするみたいなfzf的なことが出来ない。AlfredはできるらしいのでAlfredのほうが便利かもしれない。あとRaycastのExtensionで日本語を打つとEnterキーで遷移してしまうバグがあるのがずっと直ってない。Alfredのほうが良い気がする。ただExtensionの開発が楽しいのでRaycast使ってる。