The King's Museum

ソフトウェアエンジニアのブログ。

『ワークシフト』を読んで

ワークシフトを読みました。8月の読書。

ワークシフトは2011年に書かれた本。 未来の働き方、具体的には 2025 年の働き方について予測し、そこで起こっているであろう<シフト>について書かれている。 筆者は働き方において、これから 3 つのシフトが起こるだろうと述べている。

  1. ゼネラリストが評価される時代が終わり、高い専門性を持つスペシャリストが求められるようになる
  2. 人的関係に基づいたコラボレーションによるイノベーションが重要になる
  3. 経済的な成功と消費を求める画一的なキャリアゴールから、やりがいを求めるキャリアを築く必要がある

これら 3 つのシフトの具体例として筆者が想像した悲観的なストーリーと楽観的なストーリーが語られる。 悲観的なストーリーはこれらのシフトにうまく適応できなかった人々のストーリー、楽観的なストーリーはこれらのシフトにうまく適応できた人々のストーリだ。 そして、これらの想像上のストーリーを踏まえて 3 つのシフトをうまく乗りこなす術が書かれている。

ゼネラリストエンジニア

3 つのシフトはそれぞれ「確かにその通りだ」と感じたが、中でも特に気になったのが 1 つ目のシフト。

第一に、ゼネラリスト的な技能を尊ぶ常識を問い直すべきだ。 世界の50億人がインターネットにアクセスし、つながり合う世界が出現すれば、ゼネラリストの時代が幕を下ろすことは明らかだと、私には思える。

どうやらゼネラリストの価値は下がっていく一方のようだ。 反面、高い専門性を持つスペシャリストが求められるようになる。

省みて自分のキャリアはどうだろうか。 自分はプログラマー/エンジニアだと思っているが、世間的には技術職にあたるわけだしある程度の専門性がある職業だと思う。

でも、ソフトウェアエンジニアとして専門性の高いスペシャリストではないと最近感じる。 職業人生はそろそろ 10 年を迎えるが、何か一つの領域を長くやってきたわけではない。 Java の GUI を書き、C++ で HPC のミドルウェアを書き、Android もやったし Web のフロントエンドもそこそこやった。 サーバーサイドもそれなりにいじれるし、インフラ構築もそれなりにできる。 フルスタックエンジニアとポジティブに呼ぶこともできるが、端的にいえばソフトウェアエンジニアの世界でのゼネラリストなのかもしれない。

ゼネラリストの価値は下がっていく。 さて、自分のキャリアは大丈夫だろうか? でも、この本にはこんなことも書かれている。

新しい時代には、本書で提唱する「専門技能の連続的習得」を通じて、自分の価値を高めていかなくてはならない。 未来にどういう技能と能力が評価されるかを知り、その分野で高度な技術を磨くと同時に状況に応じて柔軟に専門分野を変えることが求められるのだ。

専門性は高めていかなければならないが、専門領域も時代に合わせて変化させていく必要がある。 なるほど。専門性を維持しつつ求められている専門領域にキャリアを常にシフトさせていく、というのは説得力がある。

自分のキャリアをポジティブに捉えるのならば、ずっと「ソフトウェア開発」には携わってきたわけで、それを軸にして時代に合わせた技術を習得すればよいのではないか。 勉強を続けなければいけないことは大変といえば大変だけど、この仕事は今でも楽しいと思えるのでそれほど苦にはならなさそうだ(能力的な限界が先にくるかもしれないが)。 ただ、どの能力・技術が評価されるかを見極めるのはとても難しく、常にアンテナを高く立てておく必要はあるだろうし、経験を思い切って捨てるようなキャリアを選ぶ柔軟性も必要になってくるだろう。

そうやって、自分のキャリアを見つめ直した一冊だった。

『リーダブルコード』を読んで

『リーダブルコード』を読みました。7月の読書。

内容はかなり初歩的で特に目新しいことはなかったかな。 ただ、これを実践できてるかは別で、書かれていることを意識してコード書いていきたいと思った。

日々、コードはシンプルで分かりやすくなるように気をつけているけど、他者からの視点を意識するというのは少し抜け落ちてた気がする。

最近、まとまったコード書いてなくてあまり良くないな〜と思う今日この頃…

『エンジニアのためのマネジメントキャリアパス』を読んで

『エンジニアのためのマネジメントキャリアパス』を読みました。

「今年は毎月本を読む」と決めていたので五月中に読み終えたかったけど、五月中は忙しくて読み切ったのは六月。 けっこうボリュームがあったっていうのも一因だけど。

インターンのメンターから CTO まで

この本はその名の通りエンジニアのマネジメントキャリアパスについて書かれた本。 インターンの監督(メンター)から始まり、CTO に至るまでのエンジニアのマネジメント職について幅広く書いてある。 エンジニアの管理職のキャリアラダーを登り始めた人にはとても役に立つ本だろう。

印象的だったのは、エンジニア求められるスキルとはまったく違うスキルが必要だという点。 言われてみれば当然なのだが、テックリード、技術部長や CTO に至るまで、エンジニアの延長線上にあるように見えていて実はまったく違った役割が求められる。 その上、エンジニアとしての技術力は必要とされており(コードを直接書くことは求められていないが)、そのことがより一掃これらの職位のハードルを高くする。

それぞれの職位の役割がかなり詳細に書かれているので、その職位に就いたときには参考書としてとても役に立つ本だと思う。 仕事についてかなり細かく具体的に書いてあるし、ありがちな失敗や筆者自身の経験などが書かれていてとても親切だ。 たとえば、技術部長になって複数のチームを管理するようになったら「手一杯で何も成果があげられていないように感じるのが普通」というようなことも書かれている。 きっと新米の技術部長はこれを読んで少し安心するのではないだろうか。(逆に手一杯だと感じない場合は、仕事がちゃんとできてない可能性があるとも書かれているが)

いつか CTO になったら

最初に「読み切ったのは六月」と書いたけど、実はこの本全部読んでない。 後半の四割くらいは斜め読みして飛ばしてしまった。

とても細かく仕事について書いてあるけど、通して読むには記述が細かすぎて読み物として飽きてしまった。 翻訳の問題なのか、一部の文がすごく長ったらしいのもあって少し読みにくかった。 もう少しエッセンスを抜き出して書かれているとうれしかった。

より経営に近い職位については今の自分の立場とはレイヤが違うし、あまり頭に入ってこなかった。 それでも、そのレイヤの職位のあるべき姿みたいなのがぼんやりとは見えて勉強にはなった。 加えて、自分の上司やさらにその上の上司がどのような役割で働いて、どういう部下だったら嬉しいか?みたいなところを考えるきっかけになった。

自分がもし CTO になるようなことがあったらまたこの本に手を伸ばそうと思う。 今はそんな予定ぜんぜんないけど。

Cousera: Architecting with Google Kubernetes Engine Specialization の Course 1 & 2 を修了した

Architecting with Google Kubernetes Engine Specialization の前半を修了した。

f:id:hjm333:20200712134852p:plain

f:id:hjm333:20200712134840p:plain

Course 1 は Kubernetes というよりも GCP の概要を演習つきで学習。 Course 2 は Container と Kubernetes の基礎、というか表面だけさらっと流した感じ。

正直、身になってる感じがあまりしないな。 演習もほとんど自分で考える要素がないし。 やっぱり自分でいろいろ試行錯誤して構築する経験を積まないと身につかない気がするな~。

残りは 2 コース。どうなることやら。

Kubernetes を勉強するよ

今更ながら Kubernetes を勉強しようと思う。

とりあえず公式のチュートリアルをやったけど、まだまだ理解できないことばかり。 理解できなくてもどかしい感じは居心地が悪いけど、何か新しいことを学ぶときには必ず通る道だからと自分に言い聞かせる。

チュートリアル終わって何をやろうかなと思っていたところで、Coursera の Specialization を見つけた。

www.coursera.org

Google 公式のコースだしまぁきっと間違いないでしょう。 他にも似たようなコースがあったけど、今まで AWS しか触ったことなくて GCP も少し触ってみたかったし Coursera の方をやろうかな。 有料だけど多少はお金がかかったほうがいいプレッシャーにもなるし。

Coursera のコースはたくさん受講してきたけど、基本的に外れがないので安心感がある。

継続とは何か(2)

継続について考える第二弾。

前回の記事では、足し算と掛け算という単純な例を用いて継続について考えた。

www.thekingsmuseum.info

今回は再帰での継続渡しスタイルについて考えて、継続についてさらに理解を深めたい。

累乗を計算する

再帰を用いて 1 から n までの累乗を計算する関数は次のようになる。

(define (fact n)
  (cond [(= n 1) 1]
        [else (* n (fact (- n 1)))])) 

n=1 の時は 1 を返し、それ以外の時は、n に n - 1 までの累乗を掛け算する。

実行すると次のとおり。

(fact 6) ; => 720

ここまではいつも通りの計算だ。

継続渡しスタイル

累乗の計算を継続渡しスタイルにするとどうなるだろう。

まずは n=1 の時を考える。 1 の累乗は 1 なので、これを関数 col に与えてやればよい。

(define (fact&co n col)
  (cond [(= n 1) (col 1)]
        [else ...TODO...]))

次は n が 1 より大きい時だ。

簡単なところから一歩ずつ考えていこう。

継続スタイルでは col に計算の結果を与えてやる必要があった。 だから、col に対しては n の累乗の結果を与えてやればよい。 x を n-1 までの累乗とすれば、n の累乗は (* n x) だから、col にはそれを与えることにする。

(col (* n x)) ; => ただし、x は n-1 までの累乗

こうすれば継続スタイルの約束を守れる。 問題は x すなわち n-1 までの累乗はどうやって得られるかという点だ。

n-1 の累乗を再帰的に fact&co を使って定義する。 fact&co はそれ自体が累乗を計算して col に計算結果が渡ってくるのだから、次のように計算すればよい。

(fact&co (- n 1) (lambda (x) x)) ; => x は n-1 までの累乗の値が入る

上の lambda の中の x を使えば n-1 までの累乗の値が取得できる。 これを、さきほどのパーツを合わせれば n が 1 より大きいときの計算が得られる。

(fact&co (- n 1) (lambda (x)
                   (col (* n x)))) ; => n の 累乗を計算して、col に与えている

これで else のケースもそろったので fact&co は次のように定義できる。

(define (fact&co n col)
  (cond [(= n 1) (col 1)]
        [else (fact&co (- n 1) (lambda (x)
                                 (col (* n x)))) ]))

実行は次のとおり。

(fact&co 6 (lambda (x) x)) ; => 720

展開してみる

理解を深めるため n=3 として、fact と fact&co の関数適用を展開してみる。

fact は展開すると次のようになる。

(fact 3)
=>
(* 3 (fact 2))
=>
(* 3 (* 2 (fact 1)))
=>
(* 3 (* 2 1))

これは簡単。 ちなみにどの時点でも評価可能で、どの時点の評価も 6 になる。

fact&co は展開すると次のようになる。

(fact&co 3 (lambda (x) x))
=>
(fact&co 2 (lambda (a)
             ((lambda (x) x)
              (* 3 a))))
=>
(fact&co 1 (lambda (b)
             ((lambda (a)
                ((lambda (x) x)
                 (* 3 a)))
              (* 2 b))))
=>
((lambda (b)
   ((lambda (a)
      ((lambda (x) x)
       (* 3 a)))
    (* 2 b)))
 1)

少し複雑だが、順を追って見てみる。

  • (fact&co 3 ... ) は、(fact&co 2 ... ) の結果の a に対して 3 をかけたものを col に渡す。
  • (fact&co 2 ... ) は、(fact&co 1 ... ) の結果の b に対して 2 をかけたものを col に渡す。
  • (fact&co 1 ... ) は、1 を col に渡す。

末尾再帰

こうやって眺めると、その関数の計算が終わったあとにやるべき計算をクロージャにして col に渡していることが分かる。 例えば (fact&co 2 col) には「計算結果に 3 をかけて (lambda (x) x) に渡す」というクロージャを渡している。 これはやはり「これから行われるであろう計算をパッケージ化したもの」だ。

もう一つ気づいたのは、継続スタイルでは関数が末尾再帰になってる。 本来(?)の末尾再帰だと即値で計算した結果を引数に渡してるイメージだけど、継続スタイルではやるべき計算がクロージャとして col に渡されていく。

通常の再帰では「2 までの累乗の結果に 3 をかける」という計算は、関数呼び出しのスタックにつまれて保存されている。

(* 3 (fact 2)) ; → 3 をかけるという計算 (* 3 []) はスタックに積まれて保存

一方、継続渡しスタイルではスタックには積まれずクロージャとして計算を保存している。

(fact&co 2 (lambda (a)
             ((lambda (x) x)
              (* 3 a))))
; => 3 をかける計算はクロージャに保存されている              

また、通常の呼び出しでは見えづらい「3 をかける計算」が継続渡しスタイルでは明示的な計算((* 3 a))になっている。

少し継続がつかめてきた。 次回はさらに複雑な再帰の継続渡しスタイルについて見ていく予定。

『カードミステリー』を読んで

4月の本は『カードミステリー』。珍しく小説を読んだ。

この本は小学生の時に読んだことがある本。 いつかまた読み直したいと思っていたけどずっと本棚で眠っていた。 まぁ、だいぶ前に自炊して PDF にしたから本棚で眠ってたというのは比喩なのだけど。

パパと息子が二人で旅をしながら、家出したママを探しにギリシャのアテネに向かう。 その途中、小さな村で息子は不思議な小さな本(豆本)を受け取る。 豆本にはトランプのカードが人物化した不思議な島の物語が書かれている。 そして、息子はその物語と自分の不思議な関係性に気づいてく。

著者は『ソフィーの世界』を書いたヨースタイン・ゴルデル。 ヨースタイン・ゴルデルは哲学の教師だったこともあって、この本でもよく哲学的な問いが投げかけられる。 パパと息子が旅をしながら哲学の話をするというのは『禅とオートバイ修理技術』の影響を受けているのかな。

思い出の本を読み直すのはとてもノスタルジーな感覚だった(エモい?)。 パパが話す哲学談義や豆本の中の不思議な島の話、人物化したトランプ達やママとの再会、そしてジョーカー。 読み進めていくと忘れていた記憶がすっと蘇ってきたりしてちょっと感動したり。

ただ、パパの小難しい話は今の自分にはあまり響かなくなってしまっていた。 当時はパパの哲学の話にとても影響を受けたんだけど。

子どものうちは、自分のまわりをゆっくり見る能力があった。 けれど、やがて世の中に慣れてしまう。 成長するということは、感覚の経験に酔っ払ってしまうことなのかもしれない。

まさにこのとおり。 もう成長してしまって感覚の経験に酔っ払ってしまったんだろう。 小学生の頃はずいぶんと読むのに時間がかかった気もしたけど、今回はあっという間に読み終わった。 そういう意味でも大人になったんだなぁと感慨にふけった。

そういえば、この本にはトランプの「ジョーカー」が出てくるが、それに影響されて JOKER というハンドルネームを使っていた黒歴史が…。

(c) The King's Museum