Builderscon Tokyo 2017の興奮も覚めやらぬ中、Markdown Night 2017 Summerというイベントを開催することにしました。
普段吉祥寺.pmというイベントを定期的に開催しているけど、そろそろ別の形式のイベントもやってみたい、ということでgfxさんの発案に乗っかり、更にはメルカリ様の会場提供という嬉しい展開も有り、なかなか盛り上がる予感です。
去年のBuilderscon2016は行けなかったけど、今年はチケットを確保してYAPC::Asia 2014以来の日吉へ。
参加できたのは8月4日の二日目のみ、懇親会は不参加と限定的な参加でしたが、非常に面白いトークを聴くことができました。
牧さんのオープニングを聞いたら間髪を入れずすぎゃーんさんのトークへ。 最後の方のデモで「これは認識するかな?」とすぎゃーんさんが発言していて、「自分で識別してるよね?」ってかけ声が一番のハイライト。
管理画面を作ったり、色々なハックが有ったりと、さざまななノウハウの上に成立してて、ほんと凄い。
まさに脱ドルオタされたすぎゃーんさん卒業公演にふさわしい内容でした(顔認識は続けるそうなので、卒業じゃないけど)。
「アイドルとはなにか?」「実用的とはいったい」などなど、名言の多いトークでした。
色々な制約の中で、新しいサービスを立ち上げるための数々の工夫点が端的にまとまっていました。
やらないことを明確に決めているところと、最初から分析基盤をきちっと作り込んでおくこと(ログとか)の大事さがよく分かりました。
実践的で学びが多い。
最も実践的な学びの多かったトーク。これはあーだこーだ言ってもしょうがないので、設計を生業とする人は全員スライド見た方が良い、JavaScript関係無いと言えば、関係無い。もっと本質的な話。
QAで良い設計ができたと分かるタイミングは?みたいな話があって、「機能追加をするとき」って回答が一番良かった。だからこそ機能追加する時に、やりづらかったところと、やりやすかった所は必ず次の開発に生かすためにも残すべきだと思う。
builderscon 2017ベストトークのそーだいさんのトーク。これもとにかく読んだ方がいい。
マジカルな設計を天才がなんとかしてしまう展開は「あーーーー」って思ってしまった。
直接発表が聞け無かったけど、TwitterのTLがこれで埋まった力作。
これもTwitterのTLがけっこう気になった。まだスライドが出ていないのか、見つけられなかった。
スポンサーセッションのお弁当がもの凄い行列だったので、gfxさん、かるぱさん、かじさんと歴戦のPerl Mongerな方々と外へご飯を食べに行きました。
意外とイベントの懇親会で夜話す機会は有ってもお昼ご飯を食べながらテックトークする機会が無かったので貴重な体験でした。
カンファレンスのお楽しみと言えばノベルティです。特にトートバックは色々と使えて嬉しい。
あと、個人スポンサーで参加したのでパーカーと、しゃもじを頂きました。
見透かされている!と思うほどのピッタリのやつが出てきたので、これ最高です。
1日目、3日目も色々と面白そうなトークが目白押しで、TwitterのTLも大変なことになっていたので、ぜひ来年も参加したい。
buildersconやYAPC、RubyKaigiの盛り上がりを見ていると、そろそろテックカンファレンスで町おこしって話が出てきてもおかしくないんじゃないかと思った
— magnoliak (@magnolia_k_) 2017年8月5日
MacBook ProのUSB Type-C搭載モデルへ移行するための買い物メモ。USB Type-Cはあまりに難しい。
7/8 追記 USB PDのケーブル最大長を間違えていたので修正(2.0m -> 4.0m)。ついでにモバイルバッテリのことを追記。
USB PDという規格に対応しているので、色々なサードパーティー製が選べるはずが…という状況。
いまのところサードパーティー製のUSB PD規格にちゃんと対応した充電器はほとんど流通しておらず、ほぼAnker一択の模様。ただし、30Wモデルなので、充電スピードはMacBook Pro付属のものより遅くなる。純正よりは軽いし、価格も安価なので外出先で使う分には良いかも。
Anker PowerPort Speed 1 PD30 (Power Delivery対応 30W USB-C急速充電器)
参考にしたのはこのサイト。
MacBook Proの純正電源アダプタは61W以上ので、充電には5AをサポートしたUSBケーブルが必要となる。Apple純正のケーブルは当然5A対応だが、明示的にPD 5A対応と書かれたケーブルは意外と少なく、それ以外のケーブルでは3Aまでとなる。
前述のAnkerの充電器は30Wなので、そちらと一緒に使うなら5Aのケーブルは不要といえば不要だが、純正電源アダプタに使うことも考えて5A対応のものを買っておいた方がよさそう。
ただし、そうすると選択肢はほとんど無い。ELECOMあたりがよく売られている。
エレコム USBケーブル USB2.0 C-Cタイプ PD対応 USB規格認証品 5A出力 2.0m ブラック U2C-CC5P20NBK
特に1.0mを超えるものが無い。USB PDの規格上は4.0mまで対応するが、USB 3.1 Gen2のケーブル最大長が1.0mなので、両方に対応すると1.0mまでとなるため(Gen1だと2.0mまでだが、USB PD 5A対応かつ、USB 3.1 Gen1対応で2.0mのケーブルは見つけられなかった)。
ストレージ接続用と共用せず、充電用と割り切った方が良さそう。
なので、Appleはわざわざ「USB-C 充電ケーブル」という言い方をしている。実際にはデータ転送はできるが、あくまでUSB 2.0の規格(最大480Mbps)までしか転送できない。
アップル USB-C充電ケーブル(2m) MLL82AM/A
USB PD採用の最大の利点はノートPCのモバイルバッテリが汎用化したことではないかと思う。Ankerからリリースされている以下のモバイルバッテリがメジャーな模様。今すぐ必要な場面は無いが、旅行のときには良さそう。
Anker PowerCore+ 20100 USB-C (Type-Cポート搭載 大容量 モバイルバッテリー) 新しいMacBook、iPhone、Android各種他対応 (ブラック)
まだまだUSB Type-A端子が必要に場面も多いので、HUBが必要になる。Touch Bar無しモデルだとUSB Type-Cの端子も二つしか無いので、なるべく集約したいがそうすると、ELECOMのこのモデルくらいしか選択肢が無い。
エレコム USBハブ 3.1 Gen1 Type-C Aメス2ポート Cメス1ポート+Cメス充電用1ポート バスパワー ブラック U3HC-A413BBK
なぜなら、USB Type-Cの端子が給電用と、周辺機器接続用の両方が用意されているのはこの製品くらいしかなく、たいていはどちらか片方しか無いから。
ストレージ等を接続するためにはUSB 3.1 Gen2対応のケーブルを用意する必要が有る。5AのUSB PDにも対応しているものが良さそう。
これも選択肢は少ない。ELECOMが用意している。周辺機器接続用なので、0.5mで十分かな。
エレコム USBケーブル USB3.1 C-Cタイプ PD対応 USB規格認証品 5A出力 0.5m ブラック USB3-CC5P05NBK
HDDケースにはUSB 3.1 Gen2対応がいくつか出ている。
玄人志向 2.5インチHDD/SSDケース USB3.1 Gen2対応 GW2.5FST-SU3.1
常時外部ディスプレイを接続することは無いけど、勉強会等で発表する時に必要になる。かさばらないように、単体のHDMI変換アダプタが良さそう。
Anker USB-C & HDMI 変換アダプター 【4K/60Hz対応 / 新しいMacbook、Chromebook Pixel 他対応】
USB Type-Cにはオルタネートモードという別の規格の信号を流す機能が用意されている。Thunderbolt3とか、DisplayPortとか…当面使うことも無さそうなので、割愛。
ただし、端子は同じでもケーブルが異なる(Thunderbolt3は専用のケーブルが必要)等、注意が必要。
金に糸目をつけなければ、このDockが最強と思われるが、4万円超え。
belkin Thunderbolt3 拡張ドック Mac対応 ケーブル1.0m付き USBハブ Express Dock HD F4U095JA-A 【国内正規代理店品】
USB Type-Cはとにかく規格が色々有って、ややこしい。スマートフォンの充電くらいであれば適当に繋がるが、PC用は規格を理解して使わないと、全然思った通りに動かない可能性が高い。
特にケーブル類は買ったらすぐに規格名を書いたタグを付けておかないと絶対に混乱する。
Mr-Label(10枚、300ラベル)屋外でも使える セルフラミネート ケーブル表示ラベル - 無料の作成ソフト付き (5組合せ色)
前回に続いて、The Central Repositoryで検索する話です。
前回のエントリ blog.magnolia.tech
今度はREST APIを使います。
The Central RepositoryにはGUI経由の検索だけでなく、REST API経由での検索機能も提供されています。
例えば、junit
を検索するURLは以下のようになります。
http://search.maven.org/solrsearch/select?q=junit&rows=20&wt=json&start=0
curlコマンド
に上記のURLを引数として渡すと、結果がJSONで返って来る様子が分かります。
{"responseHeader":{"status":0,"QTime":0,"params":{"spellcheck":"true","fl":"id,g,a,latestVersion,p,ec,repositoryId,text,timestamp,versionCount","sort":"score desc,timestamp desc,g asc,a asc","indent":"off","q":"junit","qf":"text^20 g^5 ....................(長くなるので、以降省略)
APIの解説は以下のドキュメントに一応記載されています。個々のパラメータの詳細までは説明されていませんが、検索機能はApache Solrで構築されているので、Solrを使った検索経験が有ればある程度分かると思います(q
とかrows
とかstart
)。
ただ、ちょっと分かりづらいので、rubyでパラメータを組み立てるようなコードを用意しました。レスポンスもrubyのハッシュに変換してダンプします。各パラメータの値を変えながら、結果がどう変化するのか試してみてください。
require 'uri' require 'open-uri' require 'json' require 'pp' params = { :q => "junit", :wt => "json", :rows => 20, :start => 0, } base_url = "http://search.maven.org/solrsearch/select?" url = base_url + URI.encode_www_form(params) res = OpenURI.open_uri( url ).read puts url pp JSON.load( res )
以下に、パラメータの内容をまとめてみました。
主なパラメータは以下の通りです。
q
クエリの内容を指定します。
キーワード検索
GUIからの検索と同じようにGroupIdか、ArtifactIdのどちらかにマッチするArtifactを検索するキーワード検索です。q={keyword}
というようにキーワードを単体でセットします。例えばjunit
を検索したい場合は、q=junit
になります。ドットや、ハイフンで分割した単語単位で完全一致するものを特定しているようです(例えばyoda-time
、yoda-
はマッチするが、yoda-ti
ではマッチしない)。
GroupId検索
GroupIdのみを検索対象に指定できます。q=g:"org.scala-lang"
と指定すれば、GroupIdがorg.scala-lang
のArtifactのみが抽出されます。
ArtifactId検索
GroupId検索と同様にArtifactのみを検索対象に指定できます。q=a:"scala-dist"
と指定すれば、ArtifactIdがscala-dist
のArtifactのみが抽出されます。同じArtifact名でもforkされたものが複数のGroupIdで登録されている場合が有りますので、どれが目的のパッケージなのかは、結局はそれぞれのpomファイルのメタデータや、GroupId等から識別する必要が有ります。
GroupIdとArtifactIdのAND条件検索
GroupIdと、ArtifactIdのAND条件検索も可能です。q=g:"org.scala-lang"+AND+a:"scala-dist"
と指定すれば、両方の条件を満たすArtifactが抽出されます。Artifactは、GroupIdとArtifactIdで一意に特定されるので、通常はこの指定でマッチするものが有れば結果は一つしか返却されませんが、後述するcore=gav
指定で、バージョンの一覧を取得します。
rows
一度に取得する検索結果の数を指定します。省略した場合のデフォルト値は10です。最大値はAPIガイドに明記されていませんが、391以上で500エラーが出ました。いずれにしてもあまり大きな数値を指定すると1クエリあたりの負荷が大きくなるので、控えた方が良いでしょう。
start
当然実際の検索結果がrowsで指定した個数を超える場合があり得ます。そんなときは、このstart
パラメータを指定することで、検索結果の何個目以降を取得する、という指定ができます。省略した場合のデフォルトは0です。
wt
検索結果をJSON形式で受け取るか、XML形式で受け取るか指定します。省略するとJSONになるので、特に指定する必要は無いでしょう。
core
qにGroupIdと、ArtifactIdを両方指定した際に、合わせてcore=gav
をセットすると、バージョンの一覧を取得します。
上記のパラメータをREST APIのお作法に則り組み合わせたURLを使って検索を実行します。APIの組み合わせ例は公式ドキュメントを確認してみて下さい。
検索の結果、マッチするものが有れば、JSONオブジェクトのキーをresponse -> numFound
とたどると、Artifactの数が分かります。指定したrows
を超える数が返って来ていたら、start
パラメータにrows
の数を足して繰り返しクエリを発行します。
実際のArtifactの情報はresponse -> docs
の配列に格納されています。
Artifactが一意に特定されるように、qパラメータにGroupIdと、ArtifactIdの両方を指定し、coreパラメータにgav
を指定すると、バージョンの一覧を取得します。Artifactの情報にv
が追加され、バージョン情報が追加されます。
例えば、先ほどのrubyのコードのparamsの中身を以下のように書き換えるとscalaのバージョンの一覧が取得できます。
params = { :wt => "json", :rows => 20, :start => 0, :core => "gav", :q => %{g:"org.scala-lang" AND a:"scala-dist"}, }
その他、クラス名や、ファイルのSHA-1、tagsでの検索など有りますが、おそらく使うことはあまり無いと思いますので割愛します(APIガイドではtagsによりscalaのArtifactの検索性が上がるように見えますが、実際には全然登録されていないので、機能しません)。
GroupId、ArtifactId、Versionと、ファイル名が分かればファイルをダウンロードできます。パス名は以下の通りです。
http://search.maven.org/remotecontent?filepath={GroupIDのドットをスラッシュに変換したもの}/{ArtifactID}/{version}/{ArtifactID}-{version}.{拡張子 or ファイル名}
Artifact名にドットが入っているものも有るので、ArtifactIDもドットをスラッシュに変換した方が良さそうです
例えば、mockito-core ver.2.8.47のpomファイルはこのようなパスになります(XMLなのでブラウザで開くとそのまま中身が表示されます)。
jarファイルだとこうなり、ブラウザでアクセスするとダウンロードが始まります。
javadoc.jarだとこうなります。
検索用のAPIと組み合わせることで、例えば依存関係にあるjarの最新バージョンを特定して一気にダウンロードする、なんてことができるようになります。
単純な検索をするだけなら、GUIからの検索と変わりません。
しかし、例えばScalaのArtifactは末尾にメジャーバージョンを付与するルールとなっていて(Scala 2.12用のScalaTestのArtifactIdはscalatest_2.12
となります)、かつメジャーバージョンごとにArtifact自体のバージョニングが行われ、メジャーバージョンをどこまでサポートするかは完全に各Artifactのメンテナンスポリシーに依ります。そうするとどのArtifactがどのメジャーバージョンをサポートしていて、それぞれどのバージョンがリリースされているか?ということをきちんと調べないといけないので、なかなか大変です。
こんな時、REST APIが有れば、メジャーバージョン毎のバージョン一覧を取得することができます。
コードが長くなったのでgistに貼り付けていますが、取得したGroupIDをキーにArtifactの一覧を取得して、あとはメジャーバージョンごとにバージョン一覧の取得を行っています。
collect_scala_artifact_version.rb
コード例ではメジャーバージョンをキーにしたハッシュに格納して終わっていますが、例えばバージョン毎にサポートしているScalaのメジャーバージョン一覧を作るのも簡単にできます。
The Central Repositoryの検索サイトと、似たようなサイトに「mvnrepository.com」が有ります。
Maven Repository: Search/Browse/Explore
こちらはJVM系パッケージのリポジトリサイトの横断検索を行うサイトです。titleに「Maven Repository: Search/Browse/Explore」と出てきて公式っぽいですが、個人運営のサイトだそうです。
REST APIは公開されていませんが、検索結果の見やすさ等は工夫されていますね。
ただ、各リポジトリサイトはクロールを禁止していることが多いので、どうやってインデックスを作っているのか謎です。
言語ごとにパッケージエコシステムがどこまで面倒を見るか?という所が違っていて、Goのように「各自GitHubのリポジトリを探して下さい、以上!」というものから、Perlのように唯一のリポジトリ(CPAN)がパッケージ管理、検索、ドキュメント閲覧から、パッケージ自体の品質保証(メタデータの充足性、様々な環境でのテスト実行まで)までやってしまう至れり尽くせりの言語まで千差万別です。
JVM系は比較的淡泊な方で、結局はGitHubのリポジトリを見れば最新の情報は揃っているので、The Central Repositoryの検索機能は「リリースされたバージョン一覧の取得」以上の使い方は無い気もしますが、APIは使い方によっては色々と活用方法が有りますね(依存しているライブラリの公式サイトを全部リストアップするとか)。
ぜひ使ってみてください。
The Central RepositoryとはSonatype社が運営するJVM系言語のためのパブリックモジュールリポジトリです。Apache Mavenや、sbtといったビルドツールのデフォルトの参照先になっているので、最もよく使われているJVMのリポジトリといえるでしょう。
JVM系のモジュールパッケージは、Mavenの慣習にならってArtifact(歴史的価値の有る遺物、工芸品という意)と呼ばれますので、以降Artifactと記載します。
(Bintrayが運営するjcenterなどもメジャーなリポジトリですが、こちらでは一般的なpackageという記載になっていますね)
The Central Repositoryは単なるリポジトリのアーカイブだけでなく、Artifactの検索機能も提供しています。
The Central Repository Search Engine
キーワードを入力してSEARCHボタンを押下すると、GroupId(パッケージ名、大抵はドメイン名の逆順)か、ArtifactId(プロジェクト名)にマッチするものの一覧が表示されます。
例えば、junit
を検索した結果は以下のように表示されます。
「latestVersion」という列には最新バージョンと、The Central Repositoryに登録されているバージョンの個数が括弧付きで表示されます。junitの検索例では、GroupId、ArtifactIdがともに「junit」となっている7行目を見て下さい。最新バージョンが「4.12」、登録されているバージョンが全部で24個となっていることが分かるかと思います。
Artifactはforkしたプロジェクトが別のGroupIdで公開されていることが多いので、Artifact名だけだと目的のパッケージがオリジナルなのか、forkされたものなのか分かりづらいですが…
最新バージョンのバージョンナンバーをクリックするとpomファイルの中身(XML)が表示され、ウェブサイトの情報やライセンス、作者の情報などが確認できます。素のXMLがそのまま表示されるので、読み取りづらいですが、入手可能な情報はこれが全てなので、ここで全て確認することができます。残念ながらpomファイルの中身は検索対象にはなっていません。
また、左下にはMavenやsbtといった各種JVM系ビルドツールでArtifactへの依存関係の指定方法が例示されていますので、こちらをビルドの設定ファイルへコピペすれば依存関係を定義できるようになっています。地味に嬉しい機能です。
バージョン個数をクリックすると、入手可能なバージョンの一覧が表示されます。
検索対象がほぼほぼgroupIDとartifactIDに限られていること、命名規約的にPerlのモジュール名のような一般名詞の組み合わせでできているわけではないので、検索機能を使って未知のモジュールを探す、というより既知のモジュールのバージョン一覧を取得する方が主な使い方になるでしょう(最新バージョンの情報が欲しいだけならGitHubを参照した方が早いし、javadocの中身を直接表示する機能も無いので…)。
次回はREST APIを使って検索する話をします。
あまりこの手のリーダー論みたいなものを本で読むのが苦手なので、めったに買わないけど、周りで評判が良かったので買いました。
「サバイバルモード中毒」とか、「コミットメント言語」とかキャッチーな言葉で、世の中のプロジェクトで起こりがちな問題をきちんと定義していて、分かりやすいですね。常に、自分たちが「こんな状態になっていないか?」と確認するためには、非常に良いやり方です。
解決に向けたアドバイスは色々と書かれてはいますが、それは結局は各プロジェクトの状況次第なところも有って絶対的な正解は無いと思いますが、まずは自分たちの立ち位置を理解するために読むと良いですね。
6章の「コミットメント言語」だけでも読む価値有りです。
「joinしました」って言いたいだけです。
細々とPRを送っていたらお誘い頂きましたので、Scalatraの開発チームにお誘い頂きました。最近ちゃんとしたOSS活動ができていなかったので、良い機会と思い、参加しました。
主にドキュメントや、サンプルコードがアップデートされていない箇所を直していますが、Scalatra 2.6のリリースに向けた開発も進んでいますので、積極的に参加しようと思っています。