2021年に作ったモノや技術をふりかえる

f:id:laiso:20211224210727j:plain

前回までのあらすじ:2020年に作ったソフトウェアや開発技術をふりかえる - laiso

Write Code Every Day

プログラマーの人にありがちな趣味だと思うんだけどWrite Code Every Day (John Resig - Write Code Every Day)を2008年ぐらいからやっていて、昼に仕事でコード書いて夜になったら自分の楽しみのために何か作るか〜というのを繰替えして生活してる。

John Resig の記事との違いは今読みながら比較していたんだけどGitHubに上げるっていう部分はやらなくなってしまった。クレデンシャルとかハードコードしてるやつとか半分他人のコードコピペしたやつとかの清書がめんどくさいというのがあるし、クローラーなどは自分だけが使うぶんにはいいけど公開した方が迷惑になる——みたいなジャンルのコードが結構あって段々省くようになってしまった。

作ったソフトウェアもポートフォリオとして収めてゆくゆくは個人開発で一発当てるぞ! という自意識を持っていたんだけど最近はとりあえず自分や知り合いだけが使えるプロトタイプをたくさん作ってすぐ捨てるという行動になってる。

便利なものを思い付いても実際に作ってみるまで便利か分からんから作りながら考えてるみたいな状態なので、まずは他人に使ってもらうためのエネルギーをかけずに作ること自体を目的にしだした。

YouTubeを観るやつ(Google Drive/Serverless Next.js Component etc)

コーディングってものづくりするクリエイターのイメージがあると思うんだけど、僕は「ブラウザとかアプリケーションを操作してウェブサービスを使う」という行動と同じ目的でスクリプト書いてサービスを使うっていうのをよくやってて、この時は「消費者としてプログラムをインターフェイスにしてコンテンツにアクセスしてるな」っていう気持ちでいる。

YouTubeTwitterを見るツールもその類で何個も作って使っていて、今年はYouTube関連のものを多く作った気がする。

チャンネルは個人とかグループとかが開設してて事務所に所属して出演者たちがプロデューサー兼監督兼編集兼なりを全部自分たちでやってるようなのを好んでる。芸能人やテレビ番組的に作られてるやつはあんまり観てない。VTuberやTuberやゲーマーがやってるストリーミング配信も多い。

ライブ配信はたいてい長時間に及んで全部観てられないので、多くの人は切り抜き動画っていうファンが善意で編集して複製してる動画が主流のようだった。ただ僕は複製しないでも見たいところだけ見られるツールがあればいいんじゃ? と思ったので、自分で作ることにした。

まずはYouTubeライブチャットリプレイコメントを取得して*1自分のGoogle Driveに保存しておくことで動画の任意の箇所を検索して再生できるようにした。これのフロントエンドにNext.jsを使った。

最初は Vercel でホストして動かしていたんだけど転送量などの無料プランの制限の限界が来たのでAWSに引越した。AWSにしたことで料金も月5ドル以下になった。

この過程で制限を越えたままVercelを使い続けるとアカウントのすべてのアプリケーションが HTTP 402 Payment Required を返すようになるというのを知った(Payment Requiredなのは来訪したユーザーじゃなくて管理者なのでは?という話もある)。刃牙の家っぽい。

「402 Payment Requiredやlaisoォ!!」 *2

ヘルプページによると一度402の刑になると30日間凍結されるらしいから待っていたんだけど、全然解除されなかったので反省文を2回ほど送ったところ今は解除してもらえた。

ちょうどAmplify Console がISRに対応したというニュースが来た頃で*3 Amplifyで組んでいたんだけどうまく動かなかったので、ソースコードを見に行って中身がServerless Next.js Componentであることが分かったので直接使うことにした。

直接使ったらうまく動かなかった部分も分かったのでついでに直してプルリクエストしたら取り込んでもらえた。ので以下を書いた。

デスクトップ版

ライブチャットリプレイの取得はChrome拡張でYouTube上に組込むバージョンや、オンブラウザで動いてElectron 経由でSQLite3に保存して全文検索かけるリアルタイムバージョンも作ってみたんだけどやはりデータ容量や検索速度を気にしなくていいぶんGoogle Driveを使い続けるのがよさそうだった。安いし。

でもこの時にVue3をいっしょに試した。Vue 3にする場合、コンポーネントライブラリの選択が曲者で、いろいろ探した末 Element Plus に落ち着いた。

Chrome拡張やElectronは数年ぶりに使ったんだけどどちらもIPCのAPIがこなれてて使いやすくなっていたので、また何か作りたい。

ギガッ

「独自ツール開発してYouTube動画観てる」というのを人と話してて、それを他の人でもできるようにするにはどうすればいいんだろう? と思って作ってみたのがこれ(新しめのチャンネルに対応してない)。ネタバラシすると「草」で検索して並び替えてるだけ。

そういえばVercelの無料枠を使いきったのはGIGAZINEで紹介されたせいだった。GIGAZINEゆるせねぇ・・

自然言語解析(Mecab/Gensim etc)

上記はgrep草ことAIなんですけど、チャットの投稿のメッセージには時間とテキストがあるのでテキストを解析したら再生時間 XX:XX 秒の特定の箇所に話題のメタデータを付けたりコメントの感情が変化したことを検知できるのでそれを使ってなんかできないかなーと思っていろいろ試していた。

基本戦略としては形態素解析でバラしてWord2vecで分類してっていうのとシンプルなネガポジ判定なんですけど、テキストが短か過ぎるのかあんまり予想どうりの結果にはならなかった。もうちょっと基礎知識があれば改善できるかもしれない。Gensimっていうライブラリをよく使った

NotionのページをFlutterアプリにするやつ(Server-Driven UI/Flutter)

AirbnbがGraphQLでネイティブアプリのコンポーネントを動的に組替えてるっていう記事に触発されて似たようなの作りたいと思って書いてたアプリ。

仕組みは簡単でNotion APIで接続したユーザーが共有したページとDatabaseのブロックデータを取ってこられるので、定義に従って用意されたFlutterアプリのコンポーネントで再生するというもの。

Notionのページ情報には他のページへのリンクも含まれるのでFlutterのNavigateをうまく使うと画面遷移も組替えることができる。宣言的UI万歳。

ただ

  • Notion APIがまだ対応してないパーツがある(カラム分けやRemarkや)
  • Authorizationがネイティブアプリで使いづらい

という諸問題もあり、完成できてない。

パーツは待っていれば対応されそうだけど、Authorizationは例えばユーザーが notion.so で権限を許可したら→中間サーバーにリダイレクトして→myapp://にまたリダイレクトして→アプリのメモリ内に存在するUUIDをチェックして——というフローがもうちょっとなんとかスマートに実装できないのかねと気になってる。

Flutterについては以下の本を副読本に買った

Riverpod

よくあるProviderを使ったコンポーネント間のデータ管理しか作ったことなかったんだけど、次世代のState-Managementフレームワークとして聞いていたRiverpodを導入してみた。結構前の記憶なので忘れちゃったけどReact HooksのプリミティブなAPI使っているようなイメージだった気がする。便利だった。

FlutterKaigi 2021 で知ったんだけど、Riverpodの代替としてGetXというパッケージを使っている人たちもいるらしく、そっちも気になってる。

従来型SPA代替技術(Hotwire/Livewire/Inertia.js)

ウェブアプリケーションフレームワーク界隈では最近はSPA代替技術の開発が盛り上っていてRails 7.0には標準でHotwireが使えるようになった。

Stradaはまだリリースされてなく。噂では来年になるらしい*4

SPA代替技術は先行するLaravelのLivewirePhoenixLiveViewASP.NETBlazorあたりとセットで「JavaScript以外で動的なUI書く」のを語られることが多い(flutter_webも入れていいかもしれない)。

JavaScript以外で書くと言っても多くの処理はクライアントサイドのJavaScriptライブラリのエンジンが肩代わりしていて、フレームワークのユーザー側に簡単なレールが提示されてそれに則ってUIを作るというスタイルが一般的になっている。

プログラミング言語の話に終始しがちだけど重要なのはAPIサーバー/クライアント/UIバインディングの定型的なコードをなくしてる点だと思った。その点でスキーマコードジェネレーター系も同カテゴリに入れていいのかもしれない。ReactやVueのコンポーネントをサーバーサイドのテンプレートファイルにすることを目指すInertiaも意欲的なので注目してる。

個人開発という点ではHotwireの筋の善し悪し以前にPostgreSQL/MySQLサーバーの維持コストが嵩みがちなのでRailsやLaravelの出番はあまりなかった。後述の新興DBaaS勢が今後目立ってくるようになったら試しに組合せて運用してみるかもしれない。

Twitter(俺だけ)便利ツール

YouTubeと同じくコンテンツ消費のためにプログラミングしてる例なんだけど、僕はTwitterが公式に用意してるフォローの機能を使わずにリストとか検索系のAPIを叩いて利用しているのでそれを今年も保守していた。

その過程で「検索結果を綺麗にするために大量にMuteする」っていう機能が必要で、"AWS"で検索すると特定の動物園情報が来訪客が含まれたり"GCP"で検索すると医療情報やメイド喫茶が出てきたりするのから自分の欲しいクラウド関連のニュース関連だけに絞るためにやってる。

しかしTwitterのMuteの挙動上「Muteしたけど検索結果に残るアカウントある」とか「usernameはそもそも無視したい」などの問題があったので自分のプログラム側でフィルター処理を作ることにした。これの構築にSvelteKitを使ってる

SvelteKit特有の機能たしいて使ってないんだけどVercelアカウントはバキの家にされちゃったのでNetlifyにデプロイして便利に使ってる。Twitterログインはちょっと癖があった

本当は難しいツイ消し

ツイート全部消すのはAPI制限上難しい=最大何件までしか遡れない。っていう問題を聞いて、じゃあ世の中のツイ消しサービスはどうやって実装してるんだろうと思って調べていた。

簡単に説明するとTwitterアーカイブダウンロード機能でエクスポートできるJSONファイルにidが載っているのでそれをユーザーにアップロードさせてパースすることで1つ1つ削除APIを叩く。という方法を実現しているようだった。

この処理はぱっと想像してみてもサーバーのリソースを結構食いそうで、みんな有料機能として提供していた。

有料サービスを使ってもいいんだけどGitHubtwitter-cleanerというGoで書かれたプログラムを公開している人がいてそれを実行するのが良さそうだった。便利賞なので数ドルsponsorで送った。

動作確認していたら自分のツイート全部消えたけどまぁいいか。的な

チャットの話題提供BOT(Cloud AutoML)

f:id:laiso:20211224212219p:plain

チャットにインターネットのおたく(この場合パソコン愛好家の意です)がリンクをシェアするとそれについて各自が話出すみたいな作法があるんですけど、だいたい情報源のサイトやTwitterなりが限られているし話している話題も偏ってるから、おたくが好きそうな話題を自動でシェアできるようにならない? って思ってBOTを作っていた。

Slackのログをエクスポートしてきてリンクを抜き出しトレーニングデータにする、機械学習でいい感じに機械が学習。情報源となるニュースサイトのリンク一覧と付き合わせてニュースサイトに更新がある度に「このリンクは%ぐらいお宅のおたくが好む」っていう数字を出してくれるので、閾値を上まわったらそれをBOTがチャットに投稿する。という流れで実装した。

このトレーニングとモデルのデプロイにCloud AutoMLを利用した。

CSV掃き出してAPIで自動化するだけなので超簡単にできるんだけど、トレーニングするために僕のクレカに5000円づつチャージされていて遠い目になってきたので停止してしまった。

BOTの動作環境はCloudflare WorkersとDeno Deployを比較してCloudflare Workersにした。

エッジで動くアプリケーション

余談だけど今はブラウザ向けのJSは軽くして重い処理はサーバー側のBFFの裏のNode.jsに任せるっていうのが一般的だけど、こういうフロントのサーバーがCDNの軽いランタイムで動くようになるとNode.jsで書いてた重い処理の全面にHTTPベース完結する軽い層が必要だなとRemixを使っていて思った。Micro Frontendsの将来かもしれない。

日英日翻訳

f:id:laiso:20211224212407p:plain

機械翻訳を重ねがけして精度を上げるみたいなライフハックが話題になっていて*5、たしかに確かにやったことあるなーと思ったものの毎回フォーム操作するのが面倒だなと思ったので1クリックでできるようにした。

これに早くからVue3に対応していたIonicを使った。レスポンシブデザインなUI何も考えずに作れて楽だと思う。Angularでずっと使っていたけど最近はReactやVueでも書ける。

Compose Multiplatform

JetBrainsがAndroidJetpack Composeのマテリアルコンポーネントをデスクトップやウェブにも適用できるCompose Multiplatformっていうフレームワークを公開していて注目してる

出てきた時は「Kotlin版Flutterだ!」と思ったんだけどソリューション的にはElectronとかJavaFXでアプリケーションを書く時の代替手段になりそうだった。

次世代IDE Fleet のフロントエンドをこれで作っているのでは? と予想しているんだけど、公開されている情報は見あたらない(中の人がKotlinとC++で書いてると言ってるのは見た)

Kotlin経由でReactコンポーネント書くサンプル がお気に入り

DBaaS(PlanetScale/Supabase)

Firebase以降の新興のDBaaSが色々出てきていてPlanetScaleとSupabaseを定期的にチェックしてる

PlanetScaleは個人開発者の文脈でいうとHeroku Postgres アドオンで格安でウェブアプリケーション動かしたかった人の選択肢として朗報だと思う。裏側にVitess クラスタがあって(たぶん)ユーザーとしてはネイティブのMySQLドライバーでORMからインターネット越しにアクセスできる。

Isomorphic JavaScript勢にも向いててLambdaでコネクションプーリングどうするのという問題もエンドポイントの向うで解決してくれていた

SupabaseはフロントエンジニアフレンドリーなSDKを提供するBaaSでそれがFirebaseとの差別化になっているようだ。

こちらもアジアリージョンにPostgreSQLサーバーを立ててくれてネイティブドライバでアクセスできる。クライアントサイドから使う時は基礎技術のPostgREST をベースにしたSDKを使ってDSLでアクセスし、認証認可もする。

このためフロントエンドがDB触るためにバックエンドAPI構築するっていう作業が省けるし、バックオフィスの管理画面は別途好きなウェブフレームワーク使うのとかできる(スキーマ管理がごちゃりそうだが……)。

コンポーネントが全部公開されててマイクロサービス思ち帰りセットになっているので、例えば自分のAWS環境にSupabaseと同じ環境を作ってDBはRDSにして使うってことができるのだと思う。

Ethereum

スマートコントラクトをデプロイしてWebアプリと連携して動かすっていう開発に再入門した。2018年ぐらいにもやっていたので開発環境自体は分っていたんだけど、色々こなれててフロントエンドエンジニアが触りやすく進化していた。

開発ツールはHardhatが使いやすかった。TypeScriptをサポートしていたりAPIクライアントにweb3.jsの代替としてethers.js を使っているのでドキュメントがあったりする。

ネットワークの入口となるノードサービスと開発プラットフォームはAlchemyを使うようにした。使ったことないけどクライアントサイドライブラリとかNFT便利API機能とか付加価値が付いてくるようだ。

ネットワークはなんとなくPolygonってやつ使ってる。理屈はよく分からんがwebpackとesbuildみたいな関係ではと解釈してる。

トークンにひもづくアセットはIPFSネットワーク上に置くのが通例らしい。Pinataをゲートウェイに使っている例が多かった。

Solidityを使ったアプリケーション開発は、翻訳なのでちょっとバージョンが古めだけど以下の本が良かった

ブロックチェーンを使って何かおもしろいものが作れそうかというとまだまだ知識が足りてないのでピンときてない。Web3ビジョナリストの言う利点は分かるけど、ユーザーとしての自分は特に求めてない、ぐらいの塩梅にある。ソフトウェア開発というより経済学とかの素養が必要なのか? と疑ってる。

でも今のところERCのプロポーザル見てるのが一番勉強になるかもしれない。

Solana

早い安いRustが書けるみたいな触れ込みで知って。Rustを書く理由を求めていたのでEthereumを一緒に入門した。Solidityなかなかいいなと最近思えてきたのであんあり動向をチェックしてない。

SQL

去年SQLを何回勉強しても分からないと書いたけど*6 実際に分からない=身についた感触がないのはデータベースを使ったプログラミング全般だと思ったので再入門した。

今年は以下2つの本を読んだら大分苦手意識が減った。

今まではORMのAPIレベルで思考していて、このAPIを使う時に発行されるSQLはこれで——という手順を踏んでいたけど実は逆で、SQLでもNoSQLでもクエリを基準に構造を考えることが重要だと思った。

  1. アプリケーションの機能に対してSELECT/INSERT/UPDATE/DELETEクエリを考える
  2. そのクエリがシンプルにできるテーブル設計を考える
  3. 考えたクエリをORMのAPIで再現する
  4. アプリケーションのプログラミング用に型付けする(DBの詳細は隠す)

というやり方に宗旨変えしたらうまく組めるようになった

MacBook Air(Apple M1)

一番安いMacBook Airを買った。

開発に使う場合、コンパイル速度とディスク容量が足りなくて困ってる。

とくに

がディスクを馬鹿食いしていて消したり入れたりして運用でカバーしてる。今ならProにしそう。

Xiaomi 11T Pro

iPhone 11 をずっと使っていたんだけどMNPを期にXiaomi 11T Proに機種変した。120W急速充電というので10分ぐらいで充電が完了するので、給電を習慣にしなくてよくなった。

まとめ

  • パソコンを使うこととコードを書くことが地続きの生活にある
  • WebのUI開発はもうひと段階の変化が起きそう
  • 良いお年を

Strada探検隊

f:id:laiso:20211009143132p:plain
Strada

こんばんわ、Strada探検隊のお時間です。

Stradaとは?

Turbo NativeとモバイルOSのネイティブAPIを連携させるHotwireシリーズ最後のミッシングパーツだと目されています*1

Stradaは目下開発中の身であり全容が分っていないのですが、既にHEYアプリに投入されているため、HEY iOSアプリの構造を見て取ることでその仕組みが予測できるのではないかと考えました。

計画

Standardizes the way that web and native parts of a mobile hybrid application talk to each other via HTML bridge attributes. https://hotwired.dev/

とあるので特別なHTML定義をStradaが解釈してUIコンポーネントへ受け渡すことが予想できます。なので特殊なHTMLを経由していそうな箇所を探します。

turbo-ios

hotwired/turbo-ios: iOS framework for making Turbo native apps

turbo-ios をおさらいします。turbo-iosはturboで作成したウェブページをiOSのWKWebViewで動作させるために追加で入れるフレームワークです。

turboで作成したウェブページはそれ単体でもWebViewで動くただのWebアプリではあるのですが、画面制御や認証情報をOS側に保存するなどのWebViewの外で実行する必要のあるコードをturbo-iosを使って実装します。なのでStimulus*2のネイティブ版的な役割だと解釈しました。

ドキュメントには

This is fine for simple tasks, but we've found we need something more comprehensive for our apps, which is why we created a new framework called Strada. https://github.com/hotwired/turbo-ios/blob/956484e3524eaf203d12807313e7119427a5771d/Docs/Advanced.md

とあるので、WebViewの拡張ではなくてアプリ内ブラウザを作ってそこに自分たちのWebViewを乗せたいという意図を感じます。

ログイン直後

HEYアプリでログインをすると。JSONでアプリのロードに必要なファイルを取得しています。Web版にはない挙動なのでこれがアプリ実装独自のものであることがわかります。

スクリーンショットは市民の権利であるところの Charles Proxy を使用しました

navigation.json

{"items":
[{"title":"Imbox","app_url":"https://app.hey.com/imbox","hotkey":"command+1","highlighted":false,"icon":{"name":"imbox","android_url":"https://production.haystack-assets.com/assets/icons/imbox-79d9f42c3186cc31d1032da369799121be75c8a2ec6dd32210c45bbae96662f4.svg","ios_url":"https://production.haystack-assets.com/assets/icons/ios/imbox-2bbd76a4e5cba992f779de32a6c5820426e35f31bb9560284f6373cc87a46678.png"}},
{"title":"The Feed","app_url":"https://app.hey.com/feedbox","hotkey":"command+2","highlighted":false,"icon":{"name":"feedbox","android_url":"https://production.haystack-assets.com/assets/icons/feedbox-b595638e37da5175c6ef848245712f0037964fccf0106b90e2b0de95545788ac.svg","ios_url":"https://production.haystack-assets.com/assets/icons/ios/feedbox-cc4dd8e4c3a28175e54b4e8e7fd0a87f5414658beaeff5af0c33d3ebe473ac8c.png"}},
// ...

データから推測するとフッタのナビゲーションウィンドウの中身だと分かります。Server-driven UI っぽい*3

ios-v3.json

正規表現 => properties の定義が配信されてくる。"presentation": "modal" とあるのでURLのパターンにマッチした画面の制御を行っている仕組みだと思いました。

これはturobo-iosのPath Configuration機能らしい *4

  "rules": [
    {
      "patterns": [
        "/recede_historical_location"
      ],
      "properties": {
        "presentation": "back",
        "visitable": false
      }
    },
    {
      "patterns": [
        "/new$",
        "/edit$",
        "^/topics/[0-9]+/publication",
        "forwardings/outbounds",
        "contacts/[0-9]+/box_settings",
        "contacts/[0-9]+/notification_settings",
        "/projects/[0-9]+/status",
        "/collections/[0-9]+/status",
        "/my/preapproval",
        "/folders/[0-9]+/confirm_destroy",
        "^/mailto/",
        "postings/projects/[0-9]+/add_topics",
        "postings/collections/[0-9]+/add_topics",
        "/my/accounts/[0-9]+/external_accounts/[0-9]+/trash",
        "domains/[0-9]+/auto_screening",
        "domains/[0-9]+/notification_settings",
        "/autofileables/.*/autofilings",
        "/attachments/senders"
      ],
      "properties": {
        "presentation": "modal",
        "always-dismiss": true
      }
    },

topics

メールの内容や返信がtopicsの単位になっている。ここはWeb版とほぼ同じなので普通にWebViewでHTMLを受け取ってturb-frameで更新しているのだと思われる。

toolbar

topic下部に出てくるメニューのこと。turbo-frameで取得されている。

class="u-hide@mobile" はデスクトップとモバイル版で出し分けをするために定義されている。

<turbo-frame id="topic_toolbar">
  <turbo-frame id="topic_composer" data-controller="disable-on-mobile reset-frame-source">
      <div class="page-toolbar ">
        <div class="page-toolbar__content" data-controller="action-bar bridge--action-bar" data-action="action-bar:updateSelection->bridge--action-bar#updateSelection" data-action-bar-highlight-class="page-toolbar__action--selected" data-bridge--action-bar-highlight-class="page-toolbar__action--selected">
          <div class="page-toolbar__item">
      <a role="button" data-topic-typing-target="replyPrompt" data-controller="hotkey bridge--hotkey" data-hotkey="r,R" data-bridge-hotkey="command+r" data-bridge--action-bar-target="item" data-bridge-title="Reply" data-bridge-icon-name="reply" data-bridge-icon-android-url="https://production.haystack-assets.com/assets/icons/android/reply-fae46c7a6889c98d1ac6439182bc23fb1eafcb01a4a7db45f042101a98569668.svg" aria-label="Reply now" class="page-toolbar__action page-toolbar__action--reply btn--focusable" href="/entries/460727690/replies/new">
        <span class="u-hide@mobile">Reply Now</span>
        <span class="u-hide@desktop">Reply</span>
        <kbd class="page-toolbar__action-hotkey action-group__action-hotkey">r</kbd>
</a></div>

momd

更に奥地へ進んで行きます。念力を使ってパッケージバンドルを透視したところmomdが含まれているのでCore Dataを使っているのが分かりました*5

Haystack.momd/
├── Haystack.mom
└── VersionInfo.plist

アプリ向けDBモデルが構築されていることが分かります

turbo-iosはWebViewとその制御が責任範囲で、ローカルストレージのDBをどうするのかという部分は独自に実装されていると思います。なのでここはStradaっぽさがある

composer

composer.html からなる小さなローカルWebアプリがある。trix-core.jsが組込まれていることからメールエディタの部分ではないかと思われる。

これだけローカルに含まれているのはオフライン時にメール書いたり、とかの機能を担保するのが目的かもしれない。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no">
  <title></title>
  <link rel="stylesheet" type="text/css" href="hey-composer://localhost/_bundle/trix.css">
  <link rel="stylesheet" type="text/css" href="hey-composer://localhost/_bundle/composer.css">
  <script type="text/javascript" src="hey-composer://localhost/_bundle/trix-core.js"></script>
</head>
<body>
  <form>
    <input id="content" value="" type="hidden" name="content">
    <trix-editor class="entry-composer__textarea trix-content" id="editor" input="content" data-blob-url-template="/rails/active_storage/blobs/redirect/:signed_id/:filename"></trix-editor>
  </form>
</body>
</html>

HEYのカスタムスキーマhey:// のはずなので hey-composer:// は内部リソースを読み込むために解釈される? なぞの部分。

strada.js

Strada本体のJavaScript部分。

数十行のファイルで、やっていることは document.addEventListener() して postMessage() するだけ。これ自体は検索すれば出てくるぐらいに、WebViewとネイティブでメッセージングした時によくある実装方法だと思う*6

Strada_Strada.bundle/
├── Info.plist
└── strada.js
document.addEventListener("web-bridge:ready", () => window.webBridge.setAdapter(this))
// ...
window.nativeBridge = new NativeBridge()
window.nativeBridge.postMessage("ready")

他にコンポーネントregister/unredister 関数がある。おそらく最低限のサンドボックスの仕組みだと思う。

その後

他にも念力を駆使しようと試行錯誤したけど、新たな発見はしばらく得られなかったので我々はStradaを後にした。

僕より強いサイキッカーの人が挑めば何か収穫があるのかもしれない……

わかったこと

  • HTML Over The Wire と言えどHEYアプリには多数のJSONレスポンスを返すAPI呼び出しがある。
  • モバイルアプリだけ独自 <strada-feature></strada-feature> タグとか謎の通信してるのを期待したが思ったより普通のネイティブアプリ+JSON APIの部分しか観測できなかった
  • Server-driven UI っぽいものをがんばろうとしているのは明かだった。でもこれはAirbnb事例を見てもStradaに限らず業界的なトレンドであるとは思う

豆知識

  • HEYのプロジェクトのコードネームは Haystack *7
  • Basecampの人々はJSの行末セミコロン書かない派

Airbnb’s Server-Driven UI System(Ghost Platform) の感想

Airbnb’s Server-Driven UI System(Ghost Platform) とは何か

Airbnbが社内で取り組んでいる最新UI開発システム Ghost Platformとそのコンセプトの名前

Airbnb AndroidエンジニアRyan Brooksによるポストを参照

A Deep Dive into Airbnb’s Server-Driven UI System | by Ryan Brooks | The Airbnb Tech Blog | Medium

f:id:laiso:20210920210659p:plain
A Deep Dive into Airbnb’s Server-Driven UI System

どういうものか

  • サーバー(API)からデータと画面構造(UI)を配信して各プラットフォームで再生する仕組み
  • UI言語部分を抽象化したもの
  • Web、iOSAndroidに対応する

なぜ画面構造を配信するのか

  • アプリケーション上で動的な画面構成を実現するため
  • データから画面構造を計算するロジックをサーバーサイドに寄せる
  • インターフェイスにGraphQLを使う

GraphQLが必要な理由

  • プラットフォーム間で共有するためにGraphQLスキーマの表現力を使いたい
  • AirbnbではGraphQL Fragment からクライアントサイドのコンポーネントで利用するTypeScriptやKotlinの型定義を自動生成してくれるらしい*1

今までの方法

  • APIからデータのみを受け取る
  • データからクライアントサイドで画面構造を計算して描画する
  • もしくは画面構造が静的なので計算しない

Ghost Platformの方法

変わらない部分

  • ビューの描画や画面遷移をするためのコードをクライアントサイドで書く
  • イベント処理のコードをクライアントサイドで書く
  • ローディングのビューやスケルトンをクライアントサイドで書く
  • 各画面上での操作で通信が発生したり画面を更新したり

コンテキスト

疑問点

  • クソデカJSONを毎回取ってくるの? CDNに乗せられないデータはあるのか
  • プラットフォームごとの分岐の必要は? iOSネイティブではメニューが上だけどAndroidは下とか
  • Ghost Platformクライアントフレームワーク部分が公開されないと解明できなさそう

まとめ

Ghost Platformでは動的なレイアウトシステムを実現するために

FAQ

これを実現するための技術的なブレークスルーがあったの?

  • ないと思うけどAirbnbでのGraphQL活用とUIシステム研究が悪魔合体して発表できるぐらいの粒度になったのかもしれない
  • 画面構造をサーバーから取ってきて動的に組替える。程度のことは各プロジェクトやっていた

宣言的UIにしなきゃだめなの?

  • だめじゃないけど可変レイアウトやコンポーネント単位に切り出してコード書くので相性はよさそう
  • AirbnbではJetpack Composeはまだ使ってない(Epoxyがある) *2

審査なしでApp Storeのアプリをアップデートできますか?

  • 画面構造の更新だけで提供できるアップデートなら可能
  • Airbnbの例ではアプリの全ユーザーの機能を最新にできていいよね。みたいなことを言っている
    • versioning 機能を使わないと古いバイナリに新しいコンポーネントが同梱されてなくてエラーとかは起きそう
  • 新機能の画面を非表示でリリースしてあとで入れ替えるということも原理的には可能だけどAppleはそれは認めていない

私達のプロジェクトで使えますか?

  • 動的なレイアウトを実現するネイティブアプリのUIを作っていてGraphQLを活用しているのだったらコンセプトは真似してみる余地はありそう
  • ただ別にAirbnbフレームワークを公開しているわけでもないからエンジン部分から自作しないといけない
  • Airbnbアーキテクチャをコピーしなくても最小限の画面構造と入れ替え可能なコンポーネントでServer-Driven UI Systemをはじめることはできると思う
  • UIシステムに関心がなくただ開発工数を減らしたいのならWebView使えばいいと思う
  • Davidっていうレーサーが「テクノロジーの多くは、それが生まれた環境を反映しています」って言ってました *3

References

Re—Engineering Travel with GX 3番目のRyan Brooksのセッション

Ryan Brooks's Post | LinkedIn

Clubhouseのユーザーインターフェイスを支えるObjective-Cの確かな信頼と実績

f:id:laiso:20210202231917j:plain

ClubhouseのiPhoneアプリは各所でお馴染みのObjective-Cライブラリが使用されており、アプリ自体は最先端のムーブメントながらもUIからはシニアの職人技を感じます。根拠はないですがアプリの実装もObjective-Cでゴリゴリ書いてそうです。

ここではそんなObjective-Cライブラリの一部を紹介します。

IGListKit

https://github.com/Instagram/IGListKit

Instagram開発チームのコレクションビューの差分描画最適化のノウハウが詰ったライブラリです。

アプリの肝となるフィード系の画面で使われています。

UIScrollView+InfiniteScroll

https://github.com/pronebird/UIScrollView-InfiniteScroll

無限スクロールを実現するライブラリです

FlagPhoneNumber

https://github.com/chronotruck/FlagPhoneNumber

TEL入力フィールドに登場します

DZNEmptyDataSet

https://github.com/dzenbot/DZNEmptyDataSet

empty state として使われています

SZTextView

https://github.com/glaszig/SZTextView

標準テキストフィールドの代替ビューです

autorelease

ありがとう Brad Cox

Hotwireの感想

Hotwire

f:id:laiso:20210124034255p:plain

https://hotwire.dev/

  • Turboを中心としたウェブアプリケーションアーキテクチャの要素技術やコンセプトをPRするための名称
  • Hotwireというライブラリがあるわけではない
  • 役割としてはMicro FrontendsとかReactのlearn once, write anywhereなどに似ている
  • アプリケーション実装言語非依存だけど現状Railsアプリケーションしか実用できる基盤がない

Hotwireの思想

  • アプリケーション開発者の生産性を上げることを目的にしていること
    • サーバーサイド言語でフロントエンドを実装したいアレではなかった
  • プログレッシブ(段階的に利用可能)であること
    • 必要な技術だけを使い無駄なことをしないことで効率化する
    • Hotwireが列挙する技術は1つづつ有効にできる
  • クライアントサイドでViewを差分更新する現在の主流のシングルページアプリケーション開発のオルタナティブなこと
    • 既存の方法は効率が悪いという作者たちの考えが反映されている
    • とくにビルドツール依存の開発が目の敵にされている
    • 逆にSPAが必要ない人やSPAのクライアントサイド開発者には刺さらなそう

Hotwireの仕組み

  • TurboというJavaScriptライブラリがある
  • これがウェブブラウザ上で動き続けることでアプリケーションに動的な機能を提供する
  • 通常すべてのドキュメントリクエストを乗っ取り、XHRで取得したコンテンツ(HTML)部分だけをブラウザではなくTurboが置き換える
  • turbolinksと呼ばれていたRailsの機能のことで、JavaScriptイベントの挙動に副作用が生じてよく無効化されていた。これがTurbo Driveという概念になった

Turbo Frame

  • Turbo Driveが書き換えるコンテンツを <turbo-frame> タグ以下で制御する仕組み
  • <turbo-frame> 内にある <a> タグや <form> タグでイベントが発生した時にXHRのレスポンスの内容を現在のViewに差分更新する
  • コンテンツ自体はサーバーサイドで出力された結果になる
  • <turbo-frame> 外のコンテンツを書き換えるオプションが用意されており画面の共通部分の更新などはここを経由する

Newボタンをクリックする。このボタンのマークアップがaだったりformだったりする。

Turboによって https://app.hey.com/folders/new へリクエストが送信されると <turbo-frame> でダイアログの中身が返される

iframeのようにこの中身を直接開ける

Turbo Stream

  • ユーザー側のイベントではなくサーバー側から更新をPushしていて更新する仕組み
  • それぞれのサイバーサイドフレームワークが各自の機能を使ってブラウザからWebSocketやSSEでメッセージを待ち受け、決った仕様のHTMLをDOMのAPIに渡すとあとはTurboが画面更新をする
  • それを turbo-stream のタグに定義してアプリケーション開発者がテンプレートに埋め込めるようにする
  • 制約上、サイバーサイドフレームワークへの依存が強い。turbo-rails ではAction Cableを使って実現されている

Stimulus

  • Turboがサーバーサイドで生成したHTMLをいかに画面に適応するかという役割を「のみ」を担っている
  • 更新されたHTMLに対してボタンが押された時にCSSクラス名を変えたいのだとか、クライアントサイドだけで完結すればいい処理を書く場所が必要でそれがStimulus
  • 必須ではないがTurboはアプリケーションで実行されるJavaScriptのロジック面倒を見てくれないので何かしろクライアントサイドのコードを管理する仕組みが必要
  • 特定のHTMLのブロックに対して割り当てるふるまいをJavaScriptのclassとして記述していく
  • その仕組みがHTMLをブロック単位で配信するTurboと相性が良い

Turbo Native

  • 動作環境がウェブブラウザではなくiOS/AndroidアプリのWebView上になる
  • https://hey.com/apps/ で利用されてる
  • WebView上のアプリケーションが効率よく動作するためにクライアントサイドSDKが配布されていて、アプリケーション開発者はこの基盤の上で利用する

Strada

  • Turbo NativeからiOS/AndroidアプリのネイティブAPIをブリッジして呼び出して開発できるようにする仕組み。未リリース
  • ウェブアプリケーションをブラウザとiOS/Androidアプリに共通でホストするという点でアプローチがIonicに近い
  • ただしStradaはリモートのウェブサイト経由でネイティブAPIを実行しようとしているところがIonic(Cordva/Capacitor)と設計が異なる
  • 通常この方法はAppStoreのガイドライン接触し問題になるソフトウェアが過去にいくつかあった

2.5.2 Appはバンドル内で完結している必要があります。他のAppを含め、指定されたコンテナエリア外に対するデータの読み書き、またはAppの特徴や機能を導入したり変更したりするコードをエリア外からダウンロード、インストール、実行することは許可されません。 https://developer.apple.com/jp/app-store/review/guidelines/#performance

  • ただしCodePushのように「既にバンドルされているネイティブ実行コードではないアセットファイルを外部から更新する」というスキームで回避できている例もある(しかし結局レビュワーガチャによってリジェクトされている)

https://github.com/microsoft/react-native-code-push#store-guideline-compliance

勘違いしていたこと

  • Phoenix.LiveView インスパイヤなのでWebSocketやロングポーリング必須だろう
    • Turbo Streamを動かす場合に必要なだけだった。WebSocketサーバーがなくても他の機能は利用可能

ReactやVueを使った開発と比較して期待できそうな点

  • サーバーサイドレンダリングがデフォルト
  • 実装するレイヤーが減ってシンプルになる
    • APIエンドポイントとクライアントがいなくなり、DBからデータを取得してViewまで落とし込むまでの距離が短かくなった
    • React Server Components の解説でもこの利点が書いてあった

不安な点

  • ReactやVueを前提とした便利なUIライブラリの存在
  • JavaScriptビルドパイプラインは回避することができるけど謎のJS/CSSをインストールするだけのgemを管理し続ける問題は残ったまま……(Railsの場合)
  • Turbo自体の学習コスト。テンプレートを細かく分けて記述するようになって、どこで何が起きているのか把握しずらかった
    • ReactやRxやMVVMにも複雑さを感じていたが慣れたので、いずれ気にならなくなるかも……
  • React以降にUIをデータと関数でプログラミングできるようになって前進した手応えがあったが、Stimulusで生DOM API+手続きコードのBackbone.js時代に戻されてしまったかのような不安
  • 実際 hey.com コンソールを開くと大量の contoller.js クラスが……
  • TypeScriptは諦めてるような雰囲気(ブラウザで動かないものだから)
    • 一旦型に保護されたプログラミングに慣らされると、取り上げられた時に不安になる

実際のプロジェクトでの利用

  • 今の主流のシングルページアプリケーションのスタックについてはモバイルアプリのAPI開発との共通化が影響していると思っているのでHotwireを全面的に使うか? という判断はWebView製のモバイルアプリを許容できるか。というところにかかっていると思う
  • WebView製のモバイルアプリがどんなものかというのは実際のHeyのiOS/Androidアプリで試すことができる
  • WebView製のモバイルアプリが不要、もしくは許容できるとしてもプロジェクトに充分なフロントエンドエンジニアやモバイルアプリエンジニアが居たとしたら技術スタックごとに分担した方が効率がいいという意見の人は多いと思う
  • なので「フロントエンドエンジニア+React Native+サーバーレスアーキテクチャで最小構成ではじめる」例のように、「RailsエンジニアがDBとAPIとSPAを同時に作らなくていい方法」として局所的な活用方法に最初はなるのではないか
  • 最小のRailsアプリケーションを開発して、少しづつシングルページアプリケーション化を取り入れていくという時の用途にも使える
  • 今までの考え方からすると、ある時えいやでSPA化するということをみんなしていた

この技術が分からん2020

My Ninja Book 285/365

2020年に作ったソフトウェアや開発技術をふりかえる で分かったことばかり書いたけど相変わらずなんべん勉強しても分からんな〜と思うことも多いのでそれもリストアップしてみることにした。

SQL

10年以上触っているはずだけど集合のイメージが頭に入ってこなくて全然文を組み立てられずにいる。ゆるふわORMを適当に使ってる。

CSS

10年以上触っているはずだけど制約のイメージが頭に入ってこなくて全然レイアウトを組み立てられずにいる。ゆるふわTailwindCSSを適当に使ってる。

Unity

何回もダウンロードして教材を買ってるんだけど。アセットを組み立てて何か意味のあるものを作るっている状態まで行かない。Flashは使いこなしていたはずなのになぜ

UIデザイン

作る時に一定の理屈っぽいこだわりがあるんだけど、何か自分で作るというところまでいかない上に、深く理由を考えたことすらなかったので、こだわりがあるけど関心が低い。という変な状態だと思う。

VSCode

IntelliJ IDEA派だからなんだけど。VSCodeで使うことを前提とされたツールとかを見て大丈夫かなこれと思ったりする。

GoやRust

最近のシステム言語を身につけた方がキャリアの広がりができてよいとずっと思っているんだけど、何か別の言語で簡単に同じことできるじゃんという邪念が邪魔して真剣に取り組めてない。書けば分かるよ? 書けばな〜。必要性がな〜。と言い訳している

ネットワーク

サブネットとかルートテーブルとか概念は分かるがいつもはい…はい…と念じながら整えている感覚があり気持ち悪い。

数学

ありがち。必要→納得→興味→関心のパイプラインにすら到達していない気がする。

競プロ

アルゴリズムコンピュータサイエンス、数学ぐらいの具象化されたものより抽象的なものを求めているのか楽しさが分かってなくてのめりこめずにいる*1

あと単に基礎知識が不足している。

英語

英語がしゃべれないと死ぬ(比喩)ような環境に飛び込んでたらいける論があるけど普通に生活に支障が出ているし生存バイアスから漏れてしまっている。

人間の気持ち

オライリーブックス『詳解 人間の気持ち』が欲しい

そもそも——

プログラミング自体が数年がかりでできなかった。同時期にネットをはじめた知人がPerlCGIテキパキ組んで仕事をしているのをうらやましく見ていた。

その後、数年わからん続けて本屋で 改訂版 FreeBSD徹底入門 を買って読んでみたけど全然わからなくて読むのをあきらめた。

そのまた数年後 みるみるプログラミングがわかる本 を読んで壁を超えた気がする。この本自体が初学者にすごくおすすめというわけではなかったんだけど、特徴ある点としてはプログラミング言語とは言語の違いではなくて開発ツール(IDE)の違いですってことが書かれていたと思う。現在も開発環境おたく気質があるからそこが性に合っていたんだろ思う。

あと、自分は高等教育を受けることに失敗しているので、独学してみて分からなく挫折する状態に慣れているんだと思う。良い面もあるし悪い面もありそう。

分からんのスコープ

ソフトウェアで何かやりたいことがあるとして

  • やり方を知らべる
  • ドキュメントを読む
  • 実行する

という行動が取れる自信がある時は自分はそれを「できる(できそう)」にカテゴリしてるんだけど、他の人と話していたらそれは実績がないから「できない(やったことない)」に区分されるという意見を聞いてそうなんだと驚いたことがある。

それ以来は、分からないけどやったらできそうではある。となるべく正確に答えることにしている。

*1:https://b.hatena.ne.jp/entry/4695815452087964034/comment/redreborn を読んで思ったけど抽象的という喩えよりいい言い方があるのかもしれない

2020年に作ったソフトウェアや開発技術をふりかえる

概要

よくある年末っぽい日記の記事です。

だいだいこれどうりのバランスでソースコードも書いてる

  • 言語はなんでもいい時はNode.jsで書く。移植性が高いので。複数人でメンテしそうな時はTypeScriptを採用し、プライベートの時は型を完全に無視する
  • PHPはほぼLaravel。ビジネスのみの関係
  • Swiftはそんなに書いた記憶がないけどアプリのメンテをしてたと思う
  • Vueも仕事で使っていたけど最近はReactに傾いてる
  • Objective-Cは書いてない
  • グラフに含まれてない部分だとAndroidアプリでKotlinを使って、データ分析でPythonを書いた

このグラフは GitHub Profile Summary Cards っていう便利ツールを使わせてもらって自動生成している。

記録方法

  • コードを書く時はおもむろに ~/tmp 以下にディレクトリ掘ってIDEを開きはじめるので実質そこがプロジェクトサンドボックスみたいになってる。
  • なのでその場所を時系列に並べてチェックしていくことで何をやっているのか分かった。
  • あとはGitHubとかTwitterとかに記録が残っていた。

フロントエンド

ReactやVueに本格入門した年だった。

Nuxt

SPA+外部APIアクセスで開発するのに最適なウェブアプリケーションのプロジェクトがあったので採用した。

SSRが不要なのでvue-cliを使うか迷ったけれど、コミュニティの充実ぶりを見てNuxtにした。

複数人でメンテする可能性もあるので最初からTypeScript化した。苦心したのはStore層であんまり型が生かせてない書き方しちゃったり、vue/test-utils を使ったユニットテストがうまく構成できずにVueコンポーネントでラップしてテスト書いてたという部分。こういうのって他所の開発チームに実際入ってみないと作法がよく分からないなと感じた。

Amplify

外部APIAWSで動いてて、それにあわせてデプロイ先をAWS Amplify コンソールにしたがこれがすごい楽でよかった。また使いたい。

いっさいドキュメント系読まないでも、よくある既存のPasSのあの機能みたいなものね〜という感覚ですんなり運用できた。

Amplifyのバックエンド系の機能は全然使ってないので、そこは別の学習コストがあるのかもしれない。

Next

DBに数千件ある既存のコンテンツのページを生成する、各ページもSPAとして動的な機能を持つっていうのを作っていてv10.0が出て丁度良さそうだったNextを使った。

最初はFirebase Hostingへgenerateしたhtmlをアップロードしていったんだけど、ビルド時間の膨大化問題に悩まされてこれはSSRが必要になってくるなと思いVercelに移行した。

Vercelに移行してSSRを併用しはじめたらNext印象がまた変化しました。魅力をひとことで説明するのは難しいのだけど「いかに静的に確定する部分を増やして、それを CDN に置くか」 っていう文章を読んでそれや! としっくりきてしまった。

アプリケーションを書く視点で見ると、サバクラ2階層MVCの手続き型のコードだった部分が丸ごと宣言型のコードになるのでだいぶシンプルになったように感じました。

ちょうど2014年ぐらいにReactをはじめて使った時のDOM操作の複雑な手続きが一気になくなった感覚がウェブアプリケーション全体に拡張されているかのようです。

Gatsby

Nextのプロジェクトと似た構成で、数千コンテンツのページを生成するツールを作ってた。こっちはJAMstackという言葉に踊らさせていた時期だったのでNetlifyにデプロイしていた。

HerokuのPostgreSQLをパブリックで空けてデータを突っ込み、Netlifyのビルドサーバーから gatsby-source-pg 経由で吸う。という構成にしていた。

GraphQLの参照系のパワフルさはこのGatsbyの利用で体験できた。最終的にはもしろGraphQLフレンドリーになるようにポスグレのスキーマ側を調整したりしてた。

Gatsbyもnext buildと同じく最終的にはビルド時間の最適化との闘いになりそうだなと思った。Gatsby社のプラットフォームにインクリメンタルビルドの仕組みが提供されているけど。自力でそれを構成するには骨が折れそう(できる人は別のアプローチも取れそう)、という部分もVercelと似ている。

Laravel

はじめてまともに使ったけどRails並によくできていた。

強いて言うならPHP以外だとよかった。が、Symfony Components にもとづく物であろうのでPHPでなければ駄目だった。ありがとうPHP

PHP自体も久しぶりに書いたけどあんまり変わってなかった。ウェブに出回っている利用例の情報量は多いのだけど、Kubernetes環境+nginxの組合せで使っている人たちがあんまりいなかったのでインフラ構築に苦労した。

Viewは時代に逆行してSPA完全無視でbladeとlaravel-admin活用して作ってる。その方が目的が早く達成できそうだったのでそうした。

Helm

2019年はKubernetesとKustomizeに入門したので、今年はHelmfileでHelmパッケージとしてシステムをデプロイできるようにしてみた。2019年に導入しかけて、難しいなーと思い見送った時よりウェブ情報が充実していたのですんなり理解できて良かった。

Rails

3.x系のまま誰にもメンテされなかったアプリケーションを引き取り、サーバーの体調が悪化した時に救急手当をしばらくしていたんだけど「これ? Dr.コトーじゃん・・」と思ったのでSlackのアイコンをDr.コトーにした(とくに意味はない)

2020年まで精一杯生きて静かに息を引き取った。

Python asyncio

クローラー開発でPythonを使うことを決め(参考実装がPythonだった)、素朴なPythonブロッキング処理を書いていたんだけどそうすると長時間化していって動作環境のGitHub Actionsの従量課金に苦しめられることになったので並列実行を検討しはじめた。

今どきのPythonはasync/awaitでノンブロッキング処理書くぞと噂で聞いていて知っていたので挑戦してみた。Node.jsで慣れてるのですんなり使いこなすことはできたけど、どうしても外部ライブラリが非同期処理に対応できていなくて最終的にマルチプロセス+スレッドプール+asyncioで非同期と多重にしたら現実的なラインまで改善したので良しとした。

この過程でGitHub Actionsを月4000分以上使うなら1人チームのGitHub Enterpriseを申し込んだ方が安い。というニッチなtipsを得た。

自然言語処理機械学習

Pythonプログラミングのリハビリをして気をよくしたので、かねてからの懸案だった「数理的な知識をつける努力をせずに機械学習ツールを使いこなせるようになりたい」という実現に乗り出すことにした。

データ収集、前処理、トレーニング、テストなどの必要な手順の概念と、代表的なアルゴリズムチュートリアル。sklearn,gensim,kerasなどの組込み方を覚えたので。他人からアドバイスを受けて何か実践する。ぐらいのことができるようになったと思う(自分でウェブ検索しても出てこないような問題のアプローチを1から考える、というのは難しい)

Android

Jetpack Compose

ちいさなアプリを書いてだいたいどういう感じか把握した。

[Jetpack Compose] Glide経由でコンテンツ一覧を表示してタップされたらブラウザで開く

SwiftUI版も作ったと思うだけど、コードが残っていなかった。何も思うところがなかったのだろう

トルコ語アルファベット

トルコでのみアプリが落ちるという不具合があって、調べてみたらKotlinのenumJavaのStringに変換する処理で端末のロケールが使われトルコ語アルファベットになり正常に動作しないという現象が起きていた。

トルコ語アルファベット自体をこの時はじめて知ったので勉強になった。

Flutter Engine

Flutterは明かに今までのモバイルクロスプラットフォームとはアーキテクチャが違うので、その内部構造から理解したいなぁと思い。C++で実装されたエンジン部分のソースコードをチェックアウトして動かしたりしてみた。

Dartの部分を別の処理系に置き換えるには何が必要? という観点で読んでいた。1-2月に取り組んでてだいぶ間が空いてしまったのですっかり今は忘れてしまったけど。DartVMからSkia命令を叩く一連の流れを把握したと思う。

Mac DE Xamarin

Covid-19 Radar 関連でひととうりVisual StudioやらXamarin SDKを揃えたんだけどもう残ってない。

mhlwリポジトリは今見てみたらコミットが積まれていた。やるじゃんパーソル

https://github.com/cocoa-mhlw/cocoa/commits/master

Hiraganize

ウェブページを全部ひらがなに変換してしまうiPadのウェブブラウザ。漢字を読めない人とかに便利だと思う。

expo(React Native) + kuromoji.js でJSベースでテキスト変換処理をがんばっていたがモバイル端末で動かすには重過ぎたので途中からlibmecabとSwiftで書き直した。

ネイティブアプリの強みを生かしてSafari Actionにして、アプリ起動しなくても今見てるページをSafari上でそのまま変換するってところまで作った (https://twitter.com/laiso/status/1225438961738235905)

その後、漢字重要だよねということに気付いたので漢字は残しふりがなをふるブラウザに拡張してみた。

今は放置してる

プリント検索アプリ

私立小学校というアナログ推進団体と利害関係を持っているんだけど、彼等が毎日毎日 大量のミッションクリティカルなA4書類を配布してきて毎回紛失して困っていたので電子化して検索できるようにした。

これには ionic というフレームワークを使ってまずAngularベースのウェブアプリケーションを構築して

  1. 写真を取ってCloud Storageに上げる
  2. Cloud FunctionsでCloud Vision APIを叩いて文字情報を読み取る
  3. 文字情報をAlgoliaでインデックスして検索可能にする

という設計にした。ついでにオンブラウザでJPEG -> PDF変換機能も実装してみた。

ionicのいいところとしてはウェブアプリケーションとして作ってみて、その後モバイルネイティブAPIが必要になった段階でフォールバック的にWebViewでラップしたアプリに拡張できる点だと思う。

Angularが第一級市民だったので使ったけど今はクロスコンポーネント化されてReactやVue3向けのインターフェイスも提供されている。

note関連ツール

unnote

https://github.com/laiso/unnote

なんとなくこんな検索結果になったおもしろいなと思って作っていたやつ

ウェブサービスとして提供している人がいるのでそれを使うのがいいと思う。

noteのバックアップ/エクスポートファイルを無料で作成 - noteエクスポートβ

md2note

Electron下からnoteの非公開APIをNodeで叩いてパースしたMarkdownファイルで無理矢理記事を作成しちゃうやつ。

汎用的なツールにできないので自分だけ使っている状態……

findlist

https://gist.github.com/laiso/85b6e8666569a0ed6c86391f70e783cc

Twitterの非公開リストのパーミッションが壊れる障害があった時に、連番で探索するスクリプトを組んでた(いい話)

ここをこう持つ

歴代Xcodeのダウンロードサイズ

Xcodeがデカ過ぎることにむかついて作った

Qiitaからはてなブログにデータ移行するコード

Qiitaからはてなブログに記事を一括インポートする - Qiita

LINE BOT経由でYoutube動画をダウンロード

ペアブラウジング

なんとなくこういうツールが作れそうだと思ってやってみたけど用途はよく分からない

まとめ

  • 環境に恵まれているのもあってとにかくずーっとコード書いてた
  • 一方プロジェクトにはすぐ飽きてしまう。やりきる力が来年の鍵
  • 生活や健康には悪影響があると思うのでほどほどにできたらいいなと思う
  • あとこういうプログラミングが趣味な人は学習コストを低く見誤る傾向があると思った
  • この記事を自分で読んでて思ったけどこのまま行くと「町の変人発明家」ポジになってしまうのでは????