Let's write β

プログラミング中にできたことか、思ったこととか

GoogleMapのスタイルギャラリーSnazzyMapsのスタイルを適用したGoogle Static Mapの作成

GoogleMapのStaticMapを作るときに、スタイルをカスタマイズしてアプリケーションのテーマと雰囲気を合わせたいなという場合があります。 GoogleMapのスタイルはカスタマイズできるのですが、個別の項目を1からカスタマイズするよりは、 おしゃれな既存のテーマを見つけて、そこから微調整するほうがらくですよね。

そんな既存のテーマが大量にアップロードされている

snazzymaps.com

というありがたいページがあります。 このサイトはユーザーがカスタマイズしたスタイルを投稿してくれていて、ライセンスCCで公開されており、自由に使うことができます。

このサイトで、たとえば

Apple Maps-esque - Snazzy Maps - Free Styles for Google Maps

のようなスタイルページを開くとJS用のスタイルコードをJSONでダウンロードできるのですが、 このJS用のスタイルをStaticMapで利用するためには少し変換してやる必要があります。

具体的にはfeature:<featureType>|element:<elementType>|<StylersのKey Valueを:で繋いだもの>という形式に変換して それぞれ個別にstyleパラメータとして指定してやる必要があります。 また、カラーコードは#で始まる形式ではなく、0xから始める形式に変換してやる必要があります。

なので、SnazzyのページのURIを指定すると、そこからHTMLを解析してスタイルのJSONを取得して、 上記の変換をした上でStaticMapのURLを生成してくれるRubyスクリプトを書いてみました。

require 'json'
require 'open-uri'
require 'nokogiri'

SNAZZY_URL = '<Snazzy style page url>' # 'https://snazzymaps.com/style/42/apple-maps-esque'
GOOGLE_MAP_API_KEY = "<Google Map Api Key>"

if __FILE__ == $0
    baseURL = "https://maps.googleapis.com/maps/api/staticmap"
    # Default Parameters
    parameters = [
        {"size": "400x400"},
        {"scale": 2},
        {"maptype": "roadmap"},
        {"key": GOOGLE_MAP_API_KEY}
    ]

    # Retrieve Style from Snazzy
    charset = nil
    html = open(SNAZZY_URL) do |f|
      charset = f.charset
      f.read
    end
    page = Nokogiri::HTML.parse(html, nil, charset)
    styleJSONStr = page.search('pre#style-json').text
    styleJSON = JSON.parse(styleJSONStr)
    styleJSON.each do |entry|
      style = []
      featureType = entry["featureType"]
      if featureType
        style.push("feature:#{featureType}")
      end
      elementType = entry["elementType"]
      if elementType
        style.push("element:#{elementType}")
      end
      entry["stylers"].map { |styleEntry|
        k, v = styleEntry.first
        if k == "color"
          v = "0x#{v[1..-1]}"
        end
        style.push("#{k}:#{v}")
      }
      parameters.push({"style": style.join("|")})
    end

    # Markers
    src = "label:S|color:blue|渋谷駅"
    dst = "label:G|color:red|六本木一丁目駅"
    parameters.push({"markers": "#{src}"})
    parameters.push({"markers": "#{dst}"})

    # Add Polyline
    parameters.push({"path": "color:0x5BB2FFFF|weight:4|enc:omsxEystsYMo@Kw@GgACa@??EqBGo@GaAC_@Ek@KmG?iBCwAIwEUgFGwAWsFSuEGeBGmBKgBI}BAOCo@IeBG{@OwDWmGOkDGkAKeA??KkGIsC??CeABwAIsAYuCS}AKo@]{AmCcLm@{Ba@qAc@uAw@qB_@aAQc@s@iBwBiGyA}D_E}JYu@qAyCkBqE??k@wAo@yAWo@Mk@G[EUAW?[@SBODQDK"})

    # Generate QueryParameter
    queryParameter = parameters.map {|entry|
      k,v = entry.first
      "#{k}=#{v}"
    }.join("&")

    # Generate & Open URL
    url = "#{baseURL}?#{queryParameter}"
    puts url
    system "open '#{url}'"
end

このスクリプトを実行すると以下の画像のようなStaticMapへのリンクが生成されます。

f:id:Pocket7878_dev:20170725135121p:plain

無事ギャラリーのスタイルが適用されたStaticMapを取得することができました。

独学でプログラミングしてきてよかった本まとめ

良いコードを書きながら速くチームで成し遂げたい

ビジネス的には、ビジネスの機運を適切につかむためにも速くリリースすることが必要である事が多く、 一方で出来合いのコードで速くリリースし続けると負債となって溜まっていってしまいます。

そういうジレンマを解消するために日々「良いコードを書きつつチームとして速くプロダクトに落とし込む」 練習をしているのですが、その過程で読んだ中で良かった本などをまとめてみました。

コンピュータの理論

job_suugakusya.png

コンピュータは物理的な物体としての「電子計算機」であるという側面とともに、 理論的な「計算モデル」によって成り立っているという側面があります。

そのためには、コンピュータの数学的な背景から学ぶと理論的な視点からコードの良し悪しを見られるようになると思います。

良かった本

アルゴリズム

論理、計算論、数学

量子コンピュータ

Tips: ひとが物事をやる時のやり方を見る

日々小さなことでも、人が物事をやるときにどのようにしてこなしているか 観察していると、いろいろなアイデアをえることができたりしました。 特に、人々が共同で作業を分担して行っている組織の仕組みややり方は自然にマルチエージェント型のシステム構成になっていることが多く、 また、人々が空間的に広がって作業している場合の情報交換の仕組みや、 時間軸上で広がっているときの情報交換の仕組みから、 分散ハードウェアやマルチスレッド処理のアルゴリズムの素描となるようなものを見ることができて面白かったです。

コンピュータのハードウェア的側面

computer_single_board.png

一方でコンピュータは目の前に実在する物体でもあるので、 具体的なハードウェア(CPU、キャッシュ)、その上で行われているOSの仕組み等を見てみると、 ハードウェアを意識したコードを書けるようになると思います。

  • 規則装置の電子的な仕組み
  • CPUの仕組み
  • キャッシュ階層の構造
  • OSのメモリ管理
  • OSのハードウェア管理

良かった本

プログラミング言語

コードを書くときには特定のプログラミング言語を使ってプログラムを書くことになるので、 プログラミング言語は人とコンピュータとのインタフェースの役割を担っていると思います。

そのため、プログラミング言語の言語的特性や各機能やパラダイムのメリットデメリットや、 言語設計の上での課題でのアプローチの方針を見てみると、より言語の機能を適切に使ったコードを書けたり、 広い視野で課題への良いアプローチを考えることができるようになると思います。

  • さまざまな言語のパラダイム
  • 型理論
  • 様々な言語の持つ機能とそのプロコン
  • 様々な言語の字面上の認知特性
  • 言語の設計思想(大規模開発にたいしてこの言語はどのようにアプローチをしているのか?..etc)

個人的にやってみて視野が広がったプログラミング言語

ハードウェア

  • Nasm
  • X86 (32bit, 64bit 両方だとなおよし)

手続きプログラミング

  • C
  • Rust (分類はここで適切?)

オブジェクト指向

スタック型言語

  • Forth

関数プログラミング

論理型言語

LL言語

分散処理

言語の勉強は大好きなので、他にも良い言語があったら是非教えてください。

良かった本

型理論

関数プログラミング

オブジェクト指向

その他

大規模なプログラムの組み立て方

一人で、短期間にコードを書き上げるのなら比較的力技でもなんとかなりますが、 ある程度の時間をかけてチームで開発をしていくに当たっては、プログラム全体のアーキテクチャを適切に 組んでいくと、よりコード全体が読みやすいコードになっていくと思います。

良かった本

Tips: 違和感を感じたら整理してみる

プログラムを書いているときに、「なんだかごちゃごちゃしてきちゃったな」って感じる時がありました。 そういうときは、その違和感がどこから来るのか整理してみて、どこからその違和感が来るのか、どうやったらそれがなくなるのか、 どういう問題点があるんだろうというのを整理してみました。 すると、異なる視点から構造化してみるとコードがかなりシンプルになってスッキリしたケースがかなり有りました。 違和感を感じたら、その場で直せなくてもどこかにメモをして時間のあるときにまとめてみると良いかもしれません。

チーム開発の知見

business_akusyu.png

プロダクトやチームの編成も視野に入れて適切なプロジェクト管理の手法を選べると 開発時の人的な衝突や、プロジェクトの炎上の危機を未然に防げるかもしれません。

コードも適切にテストのフローを入れておくことで、 余裕を持ってしてデグレのチェックや仕様変更への柔軟な対応もできるようになりました。

  • プロジェクト運営の様々な手法(ウォーターフォール、XP、アジャイル..etc)
  • チーム開発の知見(自己組織化、リモートワーク..etc)
  • いろいろな開発手法(TDD, DDD, 静的解析ツール)
  • チームビルディング(リーダーシップ、自己組織化, 心理的安全性)

良かった本

メンタルや考え方の生産性を上げる

atama_taisou.png

より抽象的な問題へのアプローチや脳の本来持つ問題解決力をうまく活かしたり、 作業中の身体への健康の不安などを減らせるとより集中したり安心して作業に取り組めます。

良かった本

おまけ: 歴史を知る

作業をしているとどうしても体力的に疲れてしまったり、辛いことと言うのは必ずどこかで出会うことになるので、 そういう時エンジニアの歴史や、かっこいいエピソードなどを読んでエンジニアという職業をもっと好きになりました。 エンジニア界隈のコミュニティーとかについても読み物として読むのは楽しいと思います。

好きな本

rlwrapがMacでの子プロセスのディレクトリの追跡をサポートしたようです

前回の記事でも触れましたが最近はplan9portのrcをつかって生活をしています。
rcではヒストリ機能はサポートしておらず、readline系のなんかを使うと良いんじゃないかみたいなアドバイスがされています。

そんなときに便利なのはやっぱりrlwrapです。任意のコマンドを readlineで囲むことができます。

github.com


rlwrapの仕組みとしては、引数としてもらったコマンドを子プロセスとして把握していて、入出力の処理をするという仕組みになっています。

また、その一貫としてファイル名の補完というのがあり、子プロセスのカレントディレクトリ(a.k.a CWD)を見て、ファイル名を保管してくれるというのが有ります。

この機能、元々は/procファイルシステムを持つUNIX系システムでしかサポートされておらず、Macではrlwrapを最初に立ち上げたフォルダの中身がいつまでも保管されるようになっており不便でした。

macでもlibprocというものがあり、

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libproc.h>

int main (int argc, char* argv[])
{
        int ret;
        pid_t pid;
        char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
        struct proc_vnodepathinfo vpi;

        if (argc > 1) {
                pid = (pid_t) atoi(argv[1]);
                ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf));
                if (ret <= 0) {
                        fprintf(stderr, "PID %d: proc_pidpath ();\n", pid);
                        fprintf(stderr, "    %s\n", strerror(errno));
                        return 1;
                }
                ret = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi,
                                   sizeof(vpi));
                if (ret <= 0) {
                        fprintf(stderr, "PID %d: proc_pidinfo ();\n", pid);
                        fprintf(stderr, "    %s\n", strerror(errno));
                        return 1;
                }
                printf("%s\n", vpi.pvi_cdir.vip_path);
        }

        return 0;
}

こんな感じのコードでPIDを指定してそのプロセスのcwdを取得することができました。

これをMacで有効にしてくればいいのになと思っていたら、

github.com

そんなPRが二年前にすでに提出されていました。提出されていたのですが
libprocというファイルが存在するだけでは、実際に上記のMacのようなコードがサポートされているか不明瞭なので、autoreconfでの判定をもう少しちゃんとしないとねというところで止まっていました。

僕としてはぜひ取り込まれてほしいので、止まってるけどどんな感じとつついてみたところ、作者がさくっと取り込んでくれたようです。

これで、mac環境下でもrlwrapをつかっていて子プロセスのCWDが変わったときに適切にファイル名の補完が追従されるようになったようです。

rbenvをPlan9portのrcに対応させるPRを送った

plan9の標準シェルrcを最近メインで使い始めたのですが、ヒストリー機能がないとかそういうのは自前でやるとしても rbenvなどの普段使っているツールが動かないのは辛いです。

rbenvなどは、rbenvからshell scriptを出力しそれをシェル側でevalする形で環境変数を設定したりPATHを設定したりしています。 例えばbashでrbenvを使うときに

eval $(rbenv init -)

のようにすると思いますが、これは

export PATH="/Users/pocket7878/.rbenv/shims:${PATH}"
export RBENV_SHELL=bash
source '/Users/pocket7878/.rbenv/libexec/../completions/rbenv.bash'
command rbenv rehash 2>/dev/null
rbenv() {
  local command
  command="$1"
  if [ "$#" -gt 0 ]; then
    shift
  fi

  case "$command" in
  rehash|shell)
    eval "$(rbenv "sh-$command" "$@")";;
  *)
    command rbenv "$command" "$@";;
  esac
}

というスクリプトがrbenvから出力されこれがevalされてrbenv関数をシェル内に定義する形で行われています. 幾つかのサブコマンドも同様の方法でシェルが操作されているのですが、rcシェルはshシェルとは文法が異なるので そのままでは動きません。

同様の問題を抱えていそうなfishシェルについては既にpatchが取り込まれていたので、ソースコードをざっくりとfishで検索して 対応する箇所を大まかに絞って幾つかのサブコマンドにrcへの分岐を組み込みました。

github.com

特にrcではシングルクオートとダブルクオートの扱いが変わっていたりするのでそのあたりの考慮が大変でした。

AirPodsが届いた

昨年末に注文していたAirPodsが今朝方届きました。

f:id:Pocket7878_dev:20170106131807j:plain

意外と思っているよりも箱が重たかったのが印象的でした。

f:id:Pocket7878_dev:20170106131954j:plain

箱を開けてみるとなかに小さなガムの容器のようにケースが入ってました。

このケースがしっかりした感覚の重さでした。(充電器として使えることを考えると当然かもしれませんが)

そのケースを開けると2秒ほどでiPhoneにペアリング用の画面が表示されて、ペアリングをしたら無事ペアリング完了です。

イヤホンの装着感ですが、元々EarPodsをつかっていて外れたことはまったくなかったのでAirPodsも同様
非常に安定した装着感で普通に作業していて外れる気配は全くありません。

ダブルタップでSiriを起動できるのも便利ですし、発信して、着信側で受話するのもこちらで切断するのもダブルタップでデキるようだったので使い所は色々ありそうです。

音量を上げるのにSiriに話しかけるのは少し面倒ですが、そもそも音量は基本変更することもないですし、
気にするほどではないかなと思います。

もう少し使ってみて充電などを確かめてみたいと思います。

競プロ勉強進捗

f:id:Pocket7878_dev:20170105134541p:plain

競技プログラミングをちゃんと勉強しようというのが今年の目標でも合ったので とりあえず必ず1日一歩ずつでもいいから進めようと思う。

とりあえず、一昨日あたりからはじめてABCの残っていたA&B問を全問といておいた。 A&Bはすんなり解けるのを確認した。C++を最近触っていなかったので標準ライブラリで曖昧なところが最初は合ったが 後半になるに連れて基本的に使うライブラリは固定化されてきたので頭に入ったと思う。

計算量見積もって総当りでいいならそれでざっくり解いてしまうのも大事だなと思った。

2016年振り返り & 2017年のやってみたいこと

Github

f:id:Pocket7878_dev:20170104132758j:plain

比較的よく働いたと思う。 ただしこれはプライベートリポジトリも含めたもので、会社のプロダクトをGithubで管理しているので 思いに会社のプロダクトのRails, iOSあたりを毎日なにかしら書いているので、ほぼ埋まっているのは 当たり前かもしれない。

来年はオープンソース周りにも手を出していきたい

OSS

コントリビュート

the-rust-programming-language-ja

Rustの公式ドキュメントの翻訳プロジェクトκeenさんが始めてらして宣伝なさってたのでRustに丁度 興味を持っていた時期だったので参加した。そこそこ訳したように思う

f:id:Pocket7878_dev:20170104133326p:plain

コミット数では一応2位ということになった、行数とかで言うとそうでもない気がする。 一旦の1.6の翻訳が終わってからはあまり手を付けられていない.

github.com

Plan9PortはPlan9 OSのツールをモダンOSに移植したツール群であるが、 僕はこのPlan9Portのツールが大好きで、よく使っていた(Acme, Sam, 9Term)あたりだけだが、 日本語入力をサポートしていない(キーボードのコードをそのまま入力している)ので、それを つけようともがいていて、一応それらしいものがついた。

poketo7878-dev.hatenablog.com

今のところ余りにも日本語入力という目的のために非効率なことをしている部分もあるし、UseCaseとしては特殊だと思うのでPRは送っていない。

github.com

GooglerのサイドプロジェクトとしてRustをバックエンドにつかったエディタが開発されてるぞというのをみて 興味がある時に初期のプロジェクトが有るという機会はあまりないと思って使ってみたところこちらでもMacIMEをサポートしていなかったので plan9portにつけたときと同じ要領で日本語入力をサポートするPRを送った

github.com

こちらのほうが、plan9portとは違ってプログラムが直接文字を扱っているので実装しやすかった。 一方でやはり変換まわりはバックスペースを送りまくって置き換えるという怪しげな実装なので、 そのうち範囲リプレースをバックエンドでサポートしたら置き換えるべきだと思う。 Xcode8には事情により対応しないようなので、僕のローカルで環境を整えるのが大変でそれ移行あまりテストできていないのが悔しいが 人生初のGooglerとのPRのやりとりになった。丁寧にレビューしてくださってありがたかった。

その他は仕事でつかっている幾つかのライブラリにCarthageのアップデートやら、Cocoapod対応やらのPRを送った。

個人プロジェクト

github.com

上でも触れたがPlan9Portのエディタが大好きで使っていたのだが、 どうしても日本語入力をサポートしたとは言えネイティブのエディタには追いつけないので、 個人的に良いと思った機能を模倣したテキストエディタCocoaのNSDocumentをつかって実装している。 https://pocket7878.github.io/ec/

MouseChoordsの機能はサポートしていないが、右クリックに依るジャンプや、 中ボタンによるコマンドの実行などの機能は実装済みである。 また、ネット上でAcmeやSamにほしいと言われていた幾つかの機能も追加機能としてつけている (ドキュメントにはまだ乗せていないが、設定ファイルベースでインデントの仕様やカラーリングを設定でき、 ファイルパスベースでそれらのフラグを個別対応したりするのも検討している)

2016で一番作ってよかったのはこのエディタだともう。会社でRailsアプリケーションを書いているときも、個人でプログラムを書いているときも ドッグフーディングしている。いい面でも悪い面でもAcmeとSamの両方からいいとこ取りをしようと思っていて、 つけていない機能はある意味で「AcmeにはあるけどSamにはないし、あまり僕には必要ないので」と割り切っている。

読んだ本

めぼしいところはコレくらいだった。業務のほうが諸々忙しくあまり読書に時間をかけられなかったのが心残り。

今年は色々読むべきとされてる本の読めていないものたちをを読みたいとおもう。

学んだ言語・技術

  • Rust
  • Golang
  • RxSwift
  • Kotlin
  • Clean Architecture

業務の方は今のところ主にRails, Swift, Javaあたりで済むし、今年の頭あたりはプロダクトの忙しい時期でも合ったので とりあえず作らなければという形で技術というよりは、アーキテクチャをまっとうに組むという感じでやってきたが 年の後半になってプロダクトが落ち着いてきたので、色々と長期的なことを考える時間が取れた。

その中で関数型言語としてRustを学んで勉強会に顔を出したり、 すこしまだ様子見とおもっていたGolangもある程度導入事例が増えてきたので学んでみた。

肌感としてはGolangはまだ仕様に納得行かない部分もあるが(VendoringとかAliasとか)それでも、その納得行かない部分がコミュニティでも 確かに議論の対象にはなっているようだったので雲行きは怪しくないだろうと思って今後プロダクトに導入を進めることにした。 手始めに一部のサーバーサイドの機能をgRPCで分割して導入した。

RxSwiftやKotlin, Clean Architectureについては、 モバイルアプリケーションのリファクタリングをすすめるにあたって大きな方針として検討し、導入を開始した。

今年の目標

競技プログラミングの勉強

競技プログラミングはなかなか手を出しづらく、学生時代になんどか取り組んだがそのままにしていたが 今年はちゃんと取り組みたいと持っている。

ブログをちゃんと書く

ブログをちゃんと書こうともう、と言うかそもそもブログのネタがちゃんと見つかるように色々とやりたい

WebVR

A-Frameあたりをちゃんと触ってWebVR周りに触れていきたいと思う。

僕が働いているAzit.incでは一緒に働けるエンジニアを募集しています!
採用情報 — 株式会社アジット|Azit Inc.