cockscomblog?

cockscomb on hatena blog

二人目の子供が生まれました

およそ一週間前の21日午前1時頃、僕と妻の二人目の子供が生まれました。予定日を10日も過ぎて生まれた息子とは違い、予定日翌日のことでした。3,200グラムの女の子です。日が変わる頃に病院へ行って、そこからあっという間に産まれました。

息子のときより小さいせいか、なんだか違った風に感じています。その息子もまた新たな家族の誕生を喜んでおり、赤ちゃんの顔を覗き込んだり、なんだかんだと話しかけたりしています。

二人目ということで、僕にも妻にもいくらか心の余裕がありましたが、一方で前回とは違って2歳半になった息子もいるので、心配もしました。実際にこの一週間は僕と息子の二人で生活していましたが、息子の成長に驚かされるばかりでした。この二人暮らしのことは、僕にとっても生涯の思い出になりそうです。

この誕生に伴って、僕も少しの間だけ育児休業させていただくことにしました。仕事をしていない自分への恐れもありますが、しっかり子育てにコミットして、これまでと違った自分を見つけたいとも思っています。

引き続きよろしくお願いいたします。

Chromeが影響を受けたmacOS Catalinaの「Hiragino Kaku Gothic ProN」フォントファミリーに関する変更

macOS Catalinaにアップグレードすると、Google Chromeのフォントの表示が変わる、ということがあった。CSSでフォントファミリーとして「Hiragino Kaku Gothic ProN」を指定していても、この指定が効かずにフォールバックされてしまうというものである。macOS Catalinaから、「Hiragino Kaku Gothic ProN(ヒラギノ角ゴ ProN)」ファミリーが削除され、「Hiragino Sans(ヒラギノ角ゴシック)」だけになったのが原因とされている。

同僚のid:polamjagが教えてくれたのだが、Chromiumのbug trackerにissueが登録されている。

内容を読むと、単に「Hiragino Kaku Gothic ProN」ファミリーが削除されたというだけでなく、NSFontManager APIの呼び出し方によっても結果が異なるようだ。

NSFontManager.availableFontFamiliesの結果が「Hiragino Kaku Gothic ProN」を含まなくなり、NSFontManager.availableMembers(ofFontFamily:)を呼べば「Hiragino Kaku Gothic ProN」が見つかる。

import Cocoa

let hiraginoKakuGothicProN = "Hiragino Kaku Gothic ProN"

let fontManager = NSFontManager.shared

print(fontManager.availableFontFamilies.filter { $0 == hiraginoKakuGothicProN }) // []

if let hiragino = fontManager.availableMembers(ofFontFamily: hiraginoKakuGothicProN) {
    print(hiragino) // [[HiraKakuProN-W3, W3, 4, 0], [HiraKakuProN-W6, W6, 8, 2]]
}

NSFontManager.availableMembers(ofFontFamily:)でフォントが見つかるのは、Appleが互換性を保とうとしたからだろう。

Chromeはフォントファミリーをcase insensitiveで見つけるため、敢えてNSFontManager.availableFontFamiliesの方を使っていたということだったが、修正コミットとなるTest for font family on mac using NSFontManager::availableFontsForFamilyの該当部分をみると、NSFontManager.availableMembers(ofFontFamily:)を呼び出すようになった。説明によれば、NSFontManager APIは、case insensitiveにフォントを見つけてくれるようだ。

Marzipanを予想した答え合わせ #WWDC19

昨年のWWDCよりさらに前に、Marzipanを予想すると称して、与太話を書いた。その時は「UIKitの移植」と「まったく新しいUIフレームワーク」とそれらの「グラデーション」の3パターンを予想していたが、結果としてはこれらがすべて出た。

Project Catalyst

初めに、Marzipanと呼ばれていたものは、新たに「Project Catalyst」と呼ばれることになった。しかしAppleのドキュメントの中ではこのプロジェクト名ではなく、「UIKit for Mac」と記載されている。これこそ「UIKitの移植」である。

UIKitの移植とともにUIKitを拡張して、コンテキストメニューやメニューバーなど、macOSの基本的な操作に適合できるようにしている。ホバーがUIHoverGestureRecognizerとしてUIGestureRecognizerになっていたり、コンテキストメニューUIContextMenuInteractionとしてUIInteractionになっていたり、抽象度が妙に高いような傾向がみられる。

そのほかにもmacOSに合わせてカスタマイズする方法がいくつも提供されてはいるものの、AppKitでmacOSアプリを作るのと全く遜色ない、とまではいかないように思われる。UIKit for Macは、iOS、特にiPadOSに最適化されたアプリをmacOSへ移植し、クロスプラットフォーム開発を行う目的で利用するのが、自然なユースケースである。

SwiftUI

SwiftネイティブなUIフレームワークがこれほど早くに出てきたことには驚かされた。SwiftUIは昨年の予想における「まったく新しいUIフレームワーク」がまさに具現化したものである。SwiftUIにはView Controllerすらない。

SwiftUIは、最近ではReactに代表され、そしてFlutterやJetpack Composeもまたそうであるように、宣言的なUIフレームワークだ。そしてAPIはSwiftネイティブと呼ぶにふさわしい。Objective-Cの動的な機能がなくてもうまく動くように、CombineというRxめいた新しいフレームワークが様々に機能するようだが、まだ全容を掴みきれていない。

SwiftUIはmacOSiOS、tvOSそしてwatchOSに渡って利用できる。プラットフォームに合わせたUIについても配慮されている。ただしSwiftUIはこの秋にリリースされる最新のOSから対応となるため、すぐにSwiftUIへ移行できる開発者はごく少数だろう。

適応

UIKit for Macのねらいは、MaciPadの距離を近づけることにあるだろう。Macにはアプリが少なく、一方のiPadにはプロユースに耐えうるアプリが足りない。これをまとめて解決するためのクロスプラットフォームである。多くのiOSアプリは、Xcodeプロジェクトでチェックボックスをひとつ有効にするだけで、macOSでも動作するようになる。

反対にSwiftUIは、次世代のUIフレームワークという側面が強い。AppKitも、それよりはモダンなUIKitでさえも、すでに10年以上の歴史を持っている。Objective-CがSwiftになってパラダイムが変化したのに伴い、UIフレームワークの再設計を行なったものだ。少しずつ取り入れやすいように、既存のアプリを少しずつ置き換えられるようになっている。

昨年の「グラデーション」で示したように、いずれも既存のアプリで取り入れやすいように工夫がなされている。


ひととおり振り返ってみたところ、全体的に大意は当たっていたように思う。予想が当たったというより、演繹的に考えれば誰でも同じような考えに辿り着くようなものではある。

この何年か、他のプラットフォームにおける開発環境の改善と比して、Appleが水をあけられつつある、というような印象を抱くことがあった。しかしこの2019年のWWDCでは、そんな懸念を払拭するように、皆に望まれるような改善が行われたことが、何より嬉しい。UIKit for MacもSwiftUIも、ここから何年かかけてさらに磨き上げられていくことを思えば、楽しみが増すばかりである。

AWS CDK は React

AWS Cloud Development Kit(以下、CDK)というものがあるが、これの提供する抽象化について考えを巡らしていたところ、唐突にこれは React だと気付いた。

CDK と React の類似性

CDK の CloudFormation Resource は、React の DOM Element に対応する。

CDK の Construct は、React の Component に対応する。

CDK でデプロイするという行為は、React における reconciliation に対応する。すなわち、CDK が内部で CloudFormation を利用して差分をとって AWS サービス変更を適用するということは、React が仮想 DOM を利用して差分をとって実際の DOM を変更することに対応している。

このような React との近似性から、CDK の提供する抽象を捉えなおすことができる。CDK の Construct は、construct-tree を構成できるが、これは React の component-tree と対応づけて考えられる。Construct をどのように切り出すかの指針としても、React Component と同じように、ドメインを整理して、再利用性やカプセル化を意図して切り出せばよいと直感的に理解できるようになる。

そもそも CDK は、なぜか JSX をサポートしようとしていた(がその後 JSX サポートに関するコードは削除された)。このことからも、CDK が React にインスパイアされて作られたものである可能性が伺える。

CDK の抽象

ここで一応 CDK の提供する抽象について説明する。AWS CDK Concepts を見ると、CDK の抽象化はおおまかに以下のようになる。

  1. App
  2. Stack
  3. Construct

ここで App は、CDK で実行可能な単位で、複数の Stack を含めることができる。StackCloudFormation が提供するデプロイの単位で、Construct を含められる。Construct には種類があり、CDKによって提供されているものは二種類ある。

  • CloudFormation Resource
  • AWS Construct Library

CloudFormation ResourceAWS のサービスについて、CloudFormation の Resource が対応づけられた Construct である。AWS Construct Library は、CloudFormation Resource を内部に複数持ったもので、典型的なユースケースのためにうまく設計されたものである。

そして CDK のユーザーである我々もまた、必要に応じて自分たちの Construct を作ることができるのだ。


以上のようなことを、社内で話していて考えた。いつもAWS CDKについて教えてくれる同じチームの id:akiymid:taketo957 にはとても感謝している。

Amazon Web Services パターン別構築・運用ガイド 改訂第2版 (Informatics&IDEA)

Amazon Web Services パターン別構築・運用ガイド 改訂第2版 (Informatics&IDEA)

Flutterを試した

flutter.io

先日なんとなく物見遊山的にFlutterを試してみた。特に事前の知識もなく数時間で試した程度で、全体に不案内ではあるから、それなりの感想であることを先に断っておく。

(当方はiOS/Androidのネイティブアプリの開発や、Reactを使ったWebフロントエンド開発の多少の経験を有しています)

開発環境

f:id:cockscomb:20180521105915p:plain

IntelliJ IDEAのFlutter開発環境

セットアップ

Get Started: Installにしたがって環境を構築した。Homebrewなどでインストールできるようにしようという動きもあるが、現時点では手でSDKを配置する必要があるなど、少し手間がかかる。経験がないと少し難しいかもしれないが、時間が解決するだろう。

エディタ

IDEとしてIntelliJ IDEADartプラグインFlutterプラグインをインストールした。プラグインのできがよく、筆者は普段からJetBrainsのツールを愛用しているので、それほど調べずにDart 2.0を書くことができた。RunボタンでFlutterアプリを容易に実行できるのは当然として、リファクタリング関連の機能も完全に動作するし、コードを保存した際にdartfmtを呼び出す設定もできた。

Dart 2.0

Dart 2.0は、きちんと学んだわけではないが、書きやすく感じた。言語機能が妙にリッチで、例えばcascade notation (..)や、factory constructorなど、色々な機能がある。Genericsもあれば、pubというパッケージ管理の仕組みもあって、とにかく一通り揃っている。async/awaitの構文とFutureStreamによる非同期処理の手厚いサポートは便利に思う。プログラミング言語としての用途をクライアントサイドのソフトウェア開発に絞ったことで進歩的な機能を取り入れ易かったのだろうと想像する。

Hot Reload

React Nativeでもそうだが、コードを書いたらすぐにアプリに反映されるのは便利である。そろそろ「Hot Reloadは人権」のような言説が出てくる頃合いだと思う。依存するパッケージを追加してもきちんと動くし、画面遷移したあとも遷移先の画面にとどまってHot Reloadが動作するのには驚いた。

Flutter

肝心のFlutterであるが、Reactにインスパイアされた宣言的なUIフレームワークは扱いやすく、好ましく感じた。Reactのcomponentにあたる概念がWidgetで、StatelessWidgetStatefulWidgetをうまく組み合わせて使う。事前に用意されたMaterial DesignもしくはiOSに似せた(Cupertino)スタイルのwidgetを組み合わせると、それだけでもある程度のアプリができてしまう。

FutureBuilderのように、非同期に得られるデータを使ったUIを抽象化してくれるwidgetが特に便利である。非同期処理というのは「状態」に他ならないが、「状態」を宣言的にUIへ反映させられるからこその、宣言的なフレームワークである。直接的にこれと似ているのは、Apollo ClientのQuery componentだろうか。

ReactのようにJSXを使えたらとも思うが、Dartが引数ラベルをサポートしていることや、IDEがコンストラクタの呼び出しの後ろにnew Scaffold(); // Scaffoldというような行コメント風の表示で括弧の終わりを示してくれたりと、工夫を感じる。

簡単なアプリを作っていて、WebView widgetの不在に気がついた。考えてみれば、FlutterはOpenGLでまったく独自にUIを描画しているのだから、WebViewを実装するのは容易なことではない。この点でプラットフォームのUIをそのまま利用しているReact Nativeと大きな違いが生まれている。このトレードオフが今後どのように影響してくるのか、難しいところだろう。

全体的に

少し書いてみたところでは、Flutterはおもしろい。しかしまだバージョンが0.3と若く、未成熟さも感じる。来年に予定されるバージョン1.0のリリースまでには、さらに使いやすくなるだろう。またこのような未成熟さを、コントリビューションのチャンスと捉えることもできる。

Flutterが有効に機能する場面はまだ限定されていると思う。しかしこのような宣言的なフレームワークは業界の最新の流行であるから、学んでみて損はない。

github.com

Marzipanを予想する

予想というか、根拠のない与太話です。


Marzipanと呼ばれるAppleのプロジェクトは、どのようなものになるのだろう。噂では、iOSmacOSのアプリが一度に作れるようになるらしい。このふたつのOSのアプリを開発する上での主要な差異は、iOSのUIKitとmacOSのAppKitの、UIフレームワークである。その他のフレームワークのほとんどはすでに共通している。この状況を踏まえれば、MarzipanはUIフレームワークであると考えられる。

そのMarzipanがどのようなUIフレームワークになるのか、グラデーションをつけて考えてみる。

UIKitの移植

もっとも単純なのは、UIKitをmacOSへ移植してしまうパターンである。macOSのAppKitは古びてきているから、より近代的なUIKitを持ってきてしまう発想である。

もちろんtvOSのUIKitのように、同じUIKitでも異なるUIを提供することにはなるだろう。それはポインティングデバイスの特性であったり、要求されるUIの複雑さに依るところである。

一方で、ひところプライベートフレームワークとして存在していたUXKitとは異なる実装方法が取られるのではないか。UXKitはAppKitの上にオーバーレイするようなアーキテクチャであったが、そのような方法では不特定多数の開発者に安定的なAPIを提供するのが難しい。

UIKitの移植は、多くの開発者にとっては、iOSアプリを少ないコストでmacOSに移植できるメリットを得られる可能性がある。ただし一定のカスタマイズが必要になる可能性もある。

まったく新しいUIフレームワーク

このタイミングでまったく新しいUIフレームワークの導入が行われる可能性も存在している。それがどのようなものになるのか想像するのは楽しい。

まったく新たなフレームワークが作られるなら、最大の関心事は、それがSwiftネイティブなフレームワークであるかどうかであろう。Objective-Cと決別することで、よりSwiftの言語機能を活かすことができる。静的型付けを活かしたSwiftフレンドリーなフレームワークは、多くの開発者に喜ばれるはずだ。その反面で、これまでObjective-Cの動的な特性を活用してきた部分は失われる。例えばresponder-chainは、まさにそのような機能であり、単純なイベントハンドリングはもちろん、メニューバーやコンテキストメニュー、キーボードショートカットからTouch Barにいたるまで、多くの用途で利用されている。そのようなものが存在しないとすれば、もはや既存のものとはまったく異なるパラダイムのUIフレームワークであるだろう。

昨今ではReactに端を発した、宣言的にビューを構築するUIフレームワークが流行している。宣言的な記述でVirtual DOMを構築し、reconciliationと呼ばれるプロセスによって実際のビューを差分更新する。最近ではGoogleもReactにインスパイアされたFlutterというUIフレームワークを開発している。

Reactの新しいFiberアーキテクチャでは、非同期的にVirtual DOMを構築できる。これによって、一見すると同期的なコードでビューを構築しつつ、実際にはその部分の描画だけを遅らせるようなことが可能になる。これは単にUIのフレームレートを改善するだけに留まらない。時間のかかる処理に依存してビューを更新することが容易になるのはもちろん、アニメーションの表現もしやすくなる。

なんの傍証も存在しない妄言に過ぎないが、例えばReactのようなパラダイムを持ち込んだものがMarzipanであるなら、とてもおもしろい。その一方で、まったく異なるパラダイムフレームワークを導入した場合は、既存のアプリをそう簡単には移植できないため、移行に時間がかかることが懸念される。

グラデーション

UIKitの移植か、完全に新しいUIフレームワークか、二者択一というわけではなく、実際にはグラデーションが存在するだろう。例えばUIKitによく似たAPIで、少し抽象度の高いフレームワークが双方に導入されることも考えられる。あるいはまったく新しいUIフレームワークではあるが、既存のアプリに部分的に取り入れられるようになっている場合もあるだろう。

いずれにせよ、すでに存在しているiOSアプリから少しずつ移行できるようになっていなければ、多くの開発者はなかなかMarzipanを採用できない。AppleにとってMarzipanの開発の目的が、macOSのアプリを充実させることにあるなら、移行のしやすさは重要である。


Marzipanと呼ばれる秘密のベールに包まれたプロジェクトについて、Appleのファンボーイ的に予想を行なった。実際にどのようなものが出てくるかは、6月のWWDCまでわからない。しかし新しいUIフレームワークを予想するという行為そのものは、単におもしろいだけでなく、UIフレームワークの理想像について考察を深めるきっかけになることだろう。

ぜひ読者諸氏も、Marzipanを予想してみてほしい。

Docker for Macでコンテナの中からホストに繋ぐたった一つの冴えたやり方

Networking features in Docker for Mac | Docker Documentation

コンテナ中で docker.for.mac.localhost というDNS名を使うと、ホストのmacOSに繋がります。

メリークリスマス。

追記(2018/01/06 21:00)

Docker 17.12.0から新たに同じ用途の docker.for.mac.host.internal が追加され、今後はこちらが推奨されます。

これはlocalhost のサブドメインを禁止するRFCが提案されていることによります。

謹賀新年。

追記(2018/03/27 11:00)

https://docs.docker.com/docker-for-mac/release-notes/#stable-releases-of-2018

Docker 18.03.0からさらに host.docker.internal が追加され、今後はこちらが推奨されます。

ハッピーバースデー。