Labo288

プログラミングのこと、GISのこと、パソコンのこと、趣味のこと

2022年度の振り返り

前回

kiguchi999.hatenablog.com

TL;DR

  • エンジニアリングマネージャーになった(=チームリーダー)
  • エンジニアチームの再設計に携わった
  • FOSS4Gのグローバルカンファレンスに参加した
  • PyConJP 2022へ登壇した
  • 単著「位置情報エンジニア養成講座」を出版した
  • MapLibre User Group Japanの設立に関わった

職位の変更:メンバーからエンジニアリングマネージャーへ

所属企業では、2022年度に開発チームを構築、いわゆる職能別チームで、自分は「GISチーム」のリーダーを仰せつかった(ほかにフロントエンド・バックエンドがある)。人数の変動はありつつ、1年通して平均で5人程度のメンバーがいるチームで、リーダーをしつつ適宜開発メンバーにもなる、いわゆるエンジニアリングマネージャーとなった。それまでは社内に明示的な役割がなく、新設である(プロジェクト単位でチームを編成していた、プロジェクトリーダーの経験はあった)。なお年度末にはテックリードQGIS)にもなっている。

それまでは実務者としてコードを書く・顧客折衝・設計…など技術で価値を発揮できていたと思うので、この立場になる際には不安があり、実際技術にかける時間は減少した。開発者(またはIndividual Controbutorともいうのだろうか)としてある程度パフォーマンスが出るとが管理側になる…のは日本企業に限った話ではないのかなと、下記の本からすこし察したが、実際どうなのだろう。

エンジニアリングマネージャーのしごと ―チームが必要とするマネージャーになる方法 | James Stanier, 吉羽 龍太郎, 永瀬 美穂, 原田 騎郎, 竹葉 美沙 |本 | 通販 | Amazon

ちなみにこの本はすごく良くて、マネージャー職になった人は全員が読むべきだと思う(エンジニアじゃなくても価値があるのでは)。マネージャーを1年やった感想としては、不安に思うほど悪いものではなかった。1人が発揮できる出力には限界があるので、チーム全体をバフする役割…というのは実際楽しいこともあった(新規メンバーが自走していくのは嬉しい)。

ところで「1人の出力には限界があるのでチーム全体をバフする…」これは正論だが正直全面的には同意できなくて、10x Programmerなんて言葉もあるように、エンジニアの生産性はバラつきが大きいため、高い人たちの出力を最大化する施策のほうが重要だと思う。これは、高くない人たちを底上げするのは容易ではなく(経験則)、高い人の出力を「下げない」方がやりやすいと思うから。

このように、新しい職位になって面白いと思うこと・そうでないことが色々ありつつも、それなりにやっていけそう…と思っていたのだが、さいきんは世間の技術者のレベルに対してかなり危機感を持っている。新たにジョインしたメンバーや、世間の動きを見ていて、自分が遅れていることがハッキリとわかる。ただでさえ実務から離れ、貯金とビジネステクで食う人間に近づいているなか、蓄積も実は足りていないのでは、と気付かされたわけである。

levtech.jp

そんな悩める自分には、上記が良い記事だった。

チームの再設計

2022年度中盤から2023年度へかけて、チーム構成の再設計に携わった(というより問題点・解決策を提言して採用された)。というのも、職能別チームでは増加し続けるメンバーに対しスケールしないことが目に見えていたからである(1チームが10人を超えると厳しいだろう)。兼任も多くリソースのコントロールも困難であった。 また、各エンジニアが関わる技術分野が、各チームが担う「職能」に閉じてしまうことも問題であった。組織が成熟するほど分業は進むし、各人が専門領域を持つことはとても大事だと思う。しかし、フロントエンドを専門とするエンジニアであってもバックエンドのことはある程度知っているものだと思う(たぶん強い人ほどそう)。これは、ソフトウェア開発は、フロントエンド(またはバックエンド)だけの知識だけでは完結しないため、経験が長くなるほど専門外の技術に触れるからだと考えている。職能別チームはこの機会を奪ってしまう(=フロントエンドが得意な人・バックエンドが得意な人、でチームが構成され・分業される)。

下記のブログは非常に参考になった。順序的には、上記の検討したうえで事例を探したところ下記の記事を見つけ、正しそうであるとわかった。なので参考になったというより、やりたいことと同じことを言っている人がいて安心した、が正しい。

mtx2s.hatenablog.com

ただし、そんなに難しいことはしようとしていなくて(それほど人数も多くない)、職能別チームから、そのチーム内でソフトウェア開発が完結する体制へ変更しただけ(いわゆる事業部制組織?)。そうすれば人数が増えたらチームを増やせば(大体10人が上限だろう)、チームの機動性は維持したまま人数増加に対してスケールする。

良いことだけではなかったが、いずれ必要になる施策なので早めに手を打てたのはよかった。

FOSS4G 2022への参加

イタリアはフィレンツェで開催されたグローバルカンファレンスに初めて参加した(会社経費)。発表はなかったが、とても刺激になった。

2023のコソボにも参加予定(会社経費)。発表もあるよ。

PyConJP 2022登壇

docs.google.com

大きめのイベントへ登壇する機会が得られたのは幸運でした。

「位置情報エンジニア養成講座」を出版

amzn.asia

書籍を出せたということ自体が、幸運でしかないのですが、世間で一定の評価を頂いているようで、大変うれしい限りです(発売前はタコ殴りになったらいやだなとか本気で考えてた)。実は発売後1ヶ月以内に増刷が決まった。

なおお金の面については世間にたくさん情報があるので私から新たに提供する情報はありませんが、それほど儲かるものではないです。

MapLibre User Group Japanの設立

私はほとんど何もしていないですが、設立メンバーの2名のうちのひとりです。月1でTwitterスペースでおしゃべりしています、これまで3回やったところ。MapLibreのプロダクト群はとても魅力的で、ウェブ地図を引っ張っていく存在になればいいなと思っています。

Cloudflare Workers + Honoを試したメモ

以下をなぞって、かんたんなAPIの作成、デプロイ、KVを試した

zenn.dev

Cloudflare Workers

  • wranglerを使えばデプロイ・KVの追加など非常にかんたん、これがDXが良いってやつか〜
  • KVは結果整合というやつで、リアルタイム性が求められるデータには無理。キャッシュと、静的ファイルの配信に使うものっぽい
    • Durable Objectは強整合、リアルタイムなやつはこっち(チャットアプリのバックエンドとしての公式デモがある)

Hono

  • Honoはとてもよくて、Expressを書いたことがあればあまり頭使わずにエンドポイントを生やせる
    • (Workersの仕様にもよるのだろうが)とても薄い「ように見える」ので好き(=特殊なお作法があまりない)。こういうライブラリを書けるようになりたいものです。
  • JSXを書けるのも、もしかしたらすごい面白いのかもしれない
  • ミドルウェアがとても便利、認証・CORSなどが公式でそろってる、簡単に使える
    • 3rd partyでFirebase Authenticationもあったけど、使い方よくわからなかった

Cloudflare Workers + Honoのユースケースは、SSR、ちょっとした認証つきウェブサイト・プロキシサーバー、WebSockerサーバーとか? D1を使うともっと本格的なアプリケーションサーバーを構築出来る気がするけど、まだベータ(アルファ?)のステータスなので先の長い話な気がする。でも有識者の情報を見ているととてもワクワク出来る。

GDALがGTFSをサポートしたので試してみた

はじめに

gdal.org

GDAL/OGRがGTFSをサポートした。2023年5月リリース予定のv3.7から利用できるようになる。 リポジトリのupstreamには既にコードが反映されているので、どんな挙動か試してみる。 なお使ったのはおなじみ拓殖バスさんのGTFSデータ。

www.takubus.com

ogrinfo

apps/ogrinfo GTFS_regular_line.zip

INFO: Open of `GTFS_regular_line.zip'
      using driver `GTFS' successful.
1: agency (None)
2: calendar (None)
3: calendar_dates (None)
4: fare_attributes (None)
5: fare_rules (None)
6: feed_info (None)
7: routes (None)
8: shapes (Point)
9: stops (Point)
10: stop_times (None)
11: translations (None)
12: trips (Line String)
13: shapes_geom (Line String)

v3.7ではogrinfoが-jsonオプションをサポートするのでやってみる。なるほど、layerという単位で情報を出力出来るのは便利そう。

apps/ogrinfo GTFS_regular_line.zip -json
{
  "description": "GTFS_regular_line.zip",
  "driverShortName": "GTFS",
  "driverLongName": "General Transit Feed Specification",
  "layers": [
  //行数多すぎるので一部抜粋
    {
      "name": "stops",
      "metadata": {},
      "geometryFields": [
        {
          "name": "",
          "type": "Point",
          "nullable": true,
          "extent": [
            142.82196521759,
            42.891557,
            143.295466714286,
            43.4601089766615
          ],
          "coordinateSystem": null
        }
      ],
      "featureCount": 906,
      "fields": [
        {
          "name": "stop_id",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_code",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_name",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_desc",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_lat",
          "type": "Real",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_lon",
          "type": "Real",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "zone_id",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "stop_url",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "location_type",
          "type": "Integer",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "platform_code",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        },
        {
          "name": "parent_station",
          "type": "String",
          "nullable": true,
          "uniqueConstraint": false
        }
      ]
    },
  ],
  "metadata": {},
  "domains": {},
  "relationships": {}
}

ogr2ogr

ここからが本番。

apps/ogr2ogr output GTFS_regular_line.zip -lco ENCODING=UTF-8

とすると、outputフォルダ内に4種類のシェープファイルが生成される。

ls output
agency.dbf              feed_info.dbf           shapes_geom.dbf         stops.shp               trips.shx
calendar.dbf            routes.dbf              shapes_geom.shp         stops.shx
calendar_dates.dbf      shapes.dbf              shapes_geom.shx         translations.dbf
fare_attributes.dbf     shapes.shp              stop_times.dbf          trips.dbf
fare_rules.dbf          shapes.shx              stops.dbf               trips.shp

出力をディレクトリにすると、レイヤー別にシェープファイルが生成されるのはGTFSに限らない以前からある挙動。

なお、GeoPackageなどの形式で出力しようとするとエラーが発生した。まだリリース前の機能なので、単にバグだと思われる。

apps/ogr2ogr output.gpkg GTFS_regular_line.zip stops
Warning 3: Cannot find tms_NZTM2000.json (GDAL_DATA is not defined)
Segmentation fault: 11

上記のシェープファイルQGISで表示してみる。

  • stopsは単に停留所の位置と属性なので、わかりやすいデータ。
  • tripsは、trip単位でラインが生成されるので、同じルートで複数のtripがあると、同じラインが重なることになる。また、このラインはstop同士を直線で繋いだ線分。
  • shapesは座標で、shapes_geomはそれらを繋いだライン、意味のある属性はない。

終わりに

GDALがサポートしたので、じきにQGISにも反映されるでしょう。QGISがデフォルトでGTFSを読めていたら、GTFS-GOというプラグインを開発することはありませんでした。ようやく時代が追いついてきたな…! 基本機能が充実していくのは喜ばしいことですし、GTFS-GOもGDALの実装を参考に改善していくことができます(頻度集計機能もあるし)。

github.com