廃墟

本ブログは更新を終了しました。 技術的な記事のみ、有用性を鑑みて残しておきます。

「プログラマーになるにはどうしたら良いですか?」への僕なりの回答、もしくはコンピュータを軸とする僕の自伝

この記事を書くまでの経緯

というツイートを見かけた。(こういう意見は今までにもよく見て、もやもやしていた。)

触発される形でこいう感じのことを書いた。

…という感じの事を考えまして、じゃあ僕なりの「プログラマーになるにはどうしたらいいのか」を軽く記事にしておいたら数人くらいの糧にはなるかもな、と思って書き留めておく次第。

ちなみに僕のパターン自体は、この見かけたツイートに書かれている「やりたいという意欲と行動力(これ大切)があれば、必要なスキルを習得していくし、それを繰り返していくうちに「あれ、これで食っていけんじゃね?」という感じでその仕事に就く」というパターンそのものなんですが、それってどういうことなのか事実を具体的に書かないとイマイチ体験してない人には何のことか分からなそうなので、全部書いた。

注意事項

当然ですが、この記事はあくまで僕の個人的な見解です。 教師だろうと親だろうと人生を左右する決定を少数の意見だけで決めてしまうのは危険なことです。なるべく裏を取るようにしましょう。(おそらくこの読者にとって)赤の他人である僕の言うことなら尚更ですね。

ここでの「プログラマーになるには」というのは、職業としてプログラミングを中心的な生業(生活していくためのメインの仕事)にする、という意味で捉えています。

僕の話

「どうすればいいのか」をいきなりダイレクトに書くよりむしろ、僕の個人的なプログラミングに繋がったことや周辺の関係ないこと含めて書き留めた方がむしろ参考にする上で有用な気がしたので、アドバイスを交えつつ僕の個人的な体験を書き留めます。 長々としたのを読む気が起きない人は「本題」という見出しまで飛ばしてください。

お前誰?

大学を卒業して、大学院で膝に矢を受けてしまって、今はフリーランスプログラマーとして、都内でそれなりに生活できるくらいには稼いでいる人(27歳)です。

幼少期

おそらく比較的頭の良い子供として生を受けました。家は割と貧しかったです。 何故か超古いワープロがあり、小さい頃はそれを弄って遊んだりもしていました。 なんとなく、数学に繋がるようなこと、理科につながるような事が好きで得意だったようです。 ざっと言ってしまえば、少々アスペルガーっぽさのある子供だったようです。(余談ですが、そういう人をBAPと呼んだりします)

プログラミングは知的な技能なので、頭が悪いと務まりません。 あくまで生来的な適性としては、多少コミュニケーションに難があってもかまわない(もちろん得意でも構いませんよ!)けれど、論理的な思考力が欠けている人には向いていません。 向いていないだけで、訓練でどうにかなる可能性も、どこかで歯車が噛み合って秀でていける可能性も勿論ありますが、単に最初の向き不向きの話をしています。 (後述しますが、本当に社会でプログラマーをやっていくには、コミュニケーション能力がてんでダメでいいという訳ではありません)

小学校くらい

低学年は普通に遊んだり喧嘩したりしつつ過ごしていました。小学校3年生の頃に授業でパソコンに触れて、非常に面白い体験でした。 4年生の時の先生が替わった先生で、教室になかなか高機能なワープロを置いていて、僕は頻繁にお絵かきソフトなどで遊んでいました。(今見るとすごくしょぼいピカチュウの絵とかを描いてた)

そうしたら母がボーナスをほぼ全額つぎ込んでiMacを買ってくれまして、これがひとつの僕の人生のターニングポイントでした。

高学年になると、ほんのわずかですが授業でパソコンを触れたりするので、その中でFront Page Expressを触って、HTMLで「100個くらいリンクがあって一個だけアタリ」みたいな簡単なWebページを作って「宝さがし」として学内のイントラネット(…だと思う)で公開したりして遊んでいました。 クラスメイトからは今で言う「クソゲー」と言われましたが、何だかんだみんな楽しんでくれていた気もします。

中学校くらい

小学校の頃に触っていたFront Page Expressどうぶつの森のファンサイトを作って公開とかしていました。 たぶん「ホームページ つくりかた」とかで検索して、自分が理解出来る所を探したんだと思います。サーバーが必要だと知って、サーバーはお金を払ってレンタルするもので、プロバイダが貸してくれたりもする、自分が使っているぷららというプロバイダはそれを提供しているらしい。ここまで頑張って調べて親に頼んで使わせて貰いました。 いろんなサイトを見て行く中で「フレーム」という、ページを分割表示する方法があると知り、どうやらFrontPageではなく、それが内部で扱っているHTMLというものを直接弄る必要があると知り、当時なりに頑張って調べてなんとか方法を見つけて自分のサイトに反映しました。 (フレーム、最近はほとんど見ないので知らない人もいるんだろうな…)

余談ですが、当時好きだった女の子が結構こういうのが分かる子で、その子のサイトを見ると何かカーソルが可愛くなるので、どうやんの?と聞いたら「CSSってのでやるんだよ」と言われて調べたりしてました。

また、掲示板やチャットを設置したいなーと思ったら、CGIというのを設置すると出来ると知り、CGIを設置するにはFTPアスキーモードで転送してdatディレクトリをパーミッション666にする必要がある…といった情報を得て、なんとかパーミッションの概念を理解しつつ、頑張ってトライアンドエラーで設置していました。

当時、知人のおじさんから古いパソコンを貰ったりしていて、多分当時2,3万円くらいの価値だったと思うのですが、古いパソコンを譲って貰ったり、ヤフオクでおこずかいで買ったりして、Windowsも扱うようになりました。

あ、部活動は科学部に入っていましたが、当初は部長候補だったのに途中で人間関係の問題などで部活にロクに行かない期間などがあり、責任感のなさを先生に指摘され、部長にはなれませんでした。この事が1つのきっかけで「周りの人とのコミュニケーションも大事にしないとだめなんだな」という課題を自分の1つの大きな課題だと認識するようになった覚えがあります。 ただ、自分はコンピュータや物理系の研究がしたいのに、主に先生の専門だからという都合で生物系の研究をやらされていたので、それを言い訳にしていた気もします。(もちろん今では、そういう言い訳はあんまりよくないなぁ、と思います)

中学校高学年になる頃には、CSSがそれなりに書けるようになってきて、HTMLとCSSを組み合わせて作るべきものらしいというさわりくらいまで理解しつつ、受験勉強がやばくなってきたので付け焼き刃で何とかそれなりの進学校に受かりました。 95%くらい受かるのでナメてたんですけど、どうやら受験者のうち下から7%くらいだったので、運が悪かったら落ちてましたね……

この辺りで、世に公開したものを人が見てくれて、そこで貰った意見や情報を元にまた何かする、という流れが出来てきた気もします。 当時はまだインターネットもごく一部の人だけが使っているもので、今よりずっと炎上するリスクとかはない穏やかな、いわば趣味の世界の時代でした。

高校くらい

高校が随分と厳しい進学校でした。僕は興味のあることしか勉強したくないワガママ人間だったので、押し付けられる課題を色々理由をつけてやらない上、注意されても刃向かうので、かなり問題児でした。 秋田県で二番目の進学校だったはずですが、あの学校の教育方針や内容が悪いのだと、今でも思っています。 話が逸れるんですが「大人になったら分かる」という大人の発言は半分くらい本当ですが、教師の言うもののうち半分くらいはウソです。 教師は「卒業生は皆感謝している」とか言うんですけど、感謝してる卒業生くらいしか卒業後に母校を訪れるわけないんだから当たり前だろ。。。

ただ、教師にどやされている髪がボサボサでちょっと感じの悪いパソコンオタクと仲良くしたい人も中々いないので、高校時代は本当に少しだけの友達しかいませんでした。 どうやら高2くらいで何が悪かったかは分かってきたのですが、ファーストコンタクトに失敗した人たちと上手くやり直すのは僕には難しすぎたので、大学行ったらいい感じにやり直せるように、人に好かれる人はどういう振る舞いをしているのか観察して理解するように務めていた気がします。

学校が嫌だった跳ね返りと、田舎で遊びに行く場所もなかったのと、家族関係も当時あまりよくなかったのとで、連日コンピュータとインターネットに向かっていました。

自分のサイトをアップロードしている先の「サーバー」って何なんだろう?ということがふと気になったのはこの頃で、どうやらLinuxというOSで動いている場合が多く、それは無料で手に入ってCD-Rに焼くと手元のパソコンにインストールできて、DynamicDNSというのを使うと自宅サーバーをインターネットに公開することが出来る、セキュリティには細心の注意を払う必要がある、という事を知った僕は、試しに1台古めのパソコンで動かしてみました。 毎日のようにインストールや構築作業をして、いくつかのOSを試した後、VineLinuxというのが比較的日本語の情報も多くて楽だと思ったので、そのサーバーで色んなことをしました。 (今だったらUbuntuとかが楽だと思います。Vineは滅んでいるので注意してください)

とにかくその学校が嫌いだったのですが、嫌いがアイデンティティになってしまっていた僕は、変な方向に邁進して以下のような事をやりました。(よい子はマネしないように)

  • 学校の2chスレと連動する非公式サイトを自宅サーバーで立ち上げる
  • サイトをセマンティックなHTML/CSSで表現。 面倒になってきたのでPHPで携帯チェックを入れて、携帯とPCで元のコンテンツをいい感じに出し分けるようにする
  • 携帯向けに最寄りバス&電車の時刻表を見れる機能をPHPで書いて導入。URLパラメータで携帯からも簡単にチェック出来るようにしてちょっとしたアクセス数になる
  • 2chのdatをHTMLで読めるようにしたかったのでperlでdatを読み込んで表示するコードを書く。重すぎたので何回か書き直してやっと軽くなったりしてた。
  • アクセス数が気になるのでアクセス解析を導入する (確か awstats)
  • 教師の悪口を自分じゃなく皆が書いたという建前にしたかったのでWikiを立ち上げて好き放題書く(最低だ…俺って…)ちなみに言い訳しておくと、実名は伏せた上で、知っている人(生徒)が見たら誰のことか分かる、というぐらいにしていました。
  • ネットラジオに興味を持ち、ネットラジオ用途のサーバーソフトを自宅サーバーにインストールして、ネットで出来た学校の友達(意味わからんな)を家に呼んで4人でネトラジとかしてました。(センター試験の1週間前だっけ?流石にセンター試験が終わった後だったかも?)
  • 今はそのサイトはありません。

そんな中、とあるゲームはわわーっとなった僕は、ロボットの特に知能的な部分(人工知能)に関する事がやりたかったのですが、ソフトウェア周りはかなり適性があることが分かったので独学で良いかなと思い(これはあまりに物事をナメていたと後に痛感したのですが)ハードウェアとソフトウェアの両方が分かっていないとロボットは作れそうにないと思い、ハードウェアの勉強が出来そうな学部を選んで、無事入学することが出来ました。

当初は東北大志望だったのですが、地元嫌いから遠くに離れたかったので筑波に志望を変え、センター試験が終わったら学校に行かなくて良くなったのでマイペースに勉強を開始したら(図書館で勉強してました)どんどん問題が解けるようになり、模試ではC判定でしたが、運もよく受かりました。

自慢みたいになってますけれど、先生の言うことを聞いても入試の点数は上がらなくて、入試の問題を解けるようになってはじめて入試の点数が上がるのですよ。当時は大学に行けば全てが上手く行くと思っていたし、本当に何としてでも入学したかった(秋田を離れたかったという意味でもあるのですが…)ので、僕なりに最大限の努力をしていました。

大学に入ってから

動機はどうあれ、親元を遠く離れたのは正解でした。自分に欠けているものが何なのか、一人暮らしすることで改めて痛感しましたし、一人の時間が沢山取れることで、考え事に耽ったり、読書したり、勉強したり出来る時間が増えました。

前述の通り人と上手くやる方法を少しは観察から体得していたので、なるべく猫を被って上手くやろうとしていました。成功した時も失敗したときもありましたが、高校の時ほど悲惨な事にはならず、それなりに友達も出来て有意義な学生生活を過ごせました。

それまで井の中の蛙で、高校生にしては超パソコン詳しいと思っていた僕は、確かに学部(正確には学類という)の中でもトップクラスにコンピュータに詳しかったし、プログラミングの授業も授業時間に退屈しながら理解するくらい楽勝だったのですが、上には上がいることを思い知りました。

筑波大にはAC入試という、一種のAO入試というか一芸入試というか、そんな不思議な試験がありまして、情報系のAC生は特にやばい奴がいる所でした。 1年生の時から入っていた団体で同期だった彼もAC生で、当時の知識レベルは僕とは雲泥の差でした。その時点でそこまで差があった理由は僕には分からないのですが、とにかく僕より5年は少なくとも先を行っていました。 最初は精神的な幼さからそれを認められずにいたのですが、彼の度量の広さもあり、一緒にプロジェクトをこなしていく中で仲良くなる事が出来て、かなり色々なことを教わりました。

大学ではとにかく、バイタリティも能力も自分よりずっと高いヤバい人達を沢山見かけて、まだまだ頑張らなきゃ全然だめなんだなと感じました。

中だるみというか、授業が疎かになったりもしたのですが、プログラミング周りの勉強を続けつつ、一応卒業できるだけの単位と卒業研究の成果を揃え、何とか4年で卒業することが出来ました。

大学院にも進学して僕なりに頑張ったけど燃え尽きて、ロボットや人工知能の事は諦めたりしたのですが、だんだん関係なくなってくるので、一旦僕の話はここで終わりにします。

本題

で、そこからどうやってプログラマーになったのか

その後、当時だんだん流行ってきていたRuby on Railsを触ってみて、プログラミングが結構できる、くらいの立ち位置になった僕は、知り合いに誘われて、とあるベンチャー企業でプログラミングのアルバイトをしました。 その会社は滅茶苦茶で、最初はRuby on Railsという話だったのが、途中でバグだらけのiOSアプリをデバッグする仕事に変わったりしたんですが、僕は僕で面白かったのでその話をうけて、滅茶苦茶なiOSアプリのコードのバグをなるべく潰したりしました。仕様がめちゃくちゃ過ぎて、加熱された焼け石に水をかけつづけるような作業でしたが、一応の形にはなりました。 商魂たくましく、時給制だけだとダラダラやってしまうから、プロジェクトが完遂したタイミングでの成果報酬も寄越せと交渉したりして(後輩にかっこいいとこ見せたかった)、徐々にフリーランスへの片鱗を見せていた気がします。

その会社に誘われて入社したんですが9ヶ月くらいで辞めました。なるほどプログラミングが出来ても仕様や企画がダメだと何にもならんのだなと理解しはじめ、単にプログラミング技術だけではなく、企画の練り方、アイディアの作り方、ビジネスモデルの確立の仕方なども勉強すべきなのだと思うようになり、少しですが勉強するようになりました。

その他の所感

プログラミング周りの世界って、まだまだ発展途上で、免許もなくて、教育制度も確立していません。 だから、プログラミング周辺のありとあらゆることに詳しい方が仕事として成立しやすく、結果的に僕みたいに幼少期から延々とコンピュータに触れていたような人がある程度、有利です。 もちろん、大学くらいあるいは大人になってからはじめても、勉強によって追い抜くことは可能です。分野を絞って、CGだけ超詳しいとか、ネットワークだけ超詳しいとか、そういうのを目指すといいと思います。 「いろいろ知ってる」という強みには雑多なトライアンドエラーの積み重ねが必要なので、あなたがそれほど若くないなら、僕みたいな方針は無理に目指さない方が得策だと思います。年季が入ってくれば変わってきますし。

これは漫画家やイラストレーター、文筆業、作曲家といったクリエイター業にも共通するのですが、こういった業種は腕が全てなんですね。 この腕っていうのは必ずしもプログラミング技術や絵の上手さだけでなくて、交渉力やコミュニケーション能力、自己管理能力とか色んな能力が複合した能力を指して、最終的に成果を出してお金を稼ぐ能力、ということです。

新卒で入社するなら交渉とか関係ないんじゃないかと思う人もいると思うんですが、何度か転職している友人もいるので、交渉力は大事だと思います。一発で自分に合う良い会社に入れた人であっても、社内政治で上手くやりぬくのは一種の交渉力が要求されますし、全くないとやっぱり困るんじゃないかな。

進路選択がまだなら

是非、情報系の学部に進むことを進めます。

なるべく偏差値の高い大学をオススメします。やはり偏差値が高いと優秀な人の割合は高いです。 但し、受験勉強一辺倒になって入学するよりは、他の事もある程度こなした上で自分が自然に入れる大学に入るのを僕はオススメします。 無理して大学に入ると地頭が足りなくて授業についていけなくなる恐れがあるので、分相応な大学に入った方がいいと僕は思います。 また、カリキュラムもよく調べて、かならずオープンキャンパス等には一度は行った方がいいですね。一般的な大学入試のアドバイスになってくるのでこの辺で終わり。

専門学校という選択肢がどうなのかは僕は残念ながら行ったことがないので分かりませんが、どうやらゲームプログラマーとかだと結構アリみたいです。 ただ、学力的にある程度の大学に行けるのなら、大学の方がよさそうです。業界で見る優秀な人の多くは大卒だという雑な理屈なので、あなたが専門学校に行っても優秀なプログラマーになれる可能性は大いにあります。

進路選択後(別の分野の学部生や社会人など)なら

進路選択をした後でこの長ったらしいエントリを見るということは、プログラミングをどこまで勉強したらプログラマーとして就職・転職できるかが聞きたいんだと思います。

1つのルートとしては「未経験者歓迎!」と書いてあるヤバい求人に飛び込む事です。案外良いところに入れるかも知れませんし、あちらも赤字は吹きたくないので何か仕事は振ってきます。何かは身につくし、1つの選択肢と言えるでしょう。

もう1つのルートとしては、技術をまずはある程度身につける、という手があります。どういう技術をみにつけると良いかは次の段落を参照してください。

プログラマーになるなら押さえて欲しい知識

分野によっては不要なこともあるので、ここでは、Webアプリケーションやスマートフォン向けアプリケーションでは少なくとも必要な知識、と解釈してください。

  • Git でコミット、プッシュ、マージ、コンフリクトが最低限出来ること
  • 何らかのプログラミング言語で、オブジェクト指向プログラミングが出来ること。 クラス・インスタンス・メソッド・インスタンス変数といった言葉をすべて理解していること
  • ある程度、英語での読解能力があり、英語で書かれたプログラミングのドキュメントを(辞書を引いても構わない、遅くても構わないが)読むことができて、変数やメソッドを英語で適切に命名できること
  • コマンドラインインタフェースで簡単なファイル操作やミドルウェア類のインストールができること
  • エラーメッセージをきちんと読み解き、問題点を切り分けて解決できること(どんなものでもというのは難しいので、自分が専門とする分野では少なくとも出来るとよい)

雑多な分類ですが、以下のよに分類して僕が必要だなぁと思うことを書いておきました。 もちろん横断した知識があればよりよいです。 逆に、ちょっと欠けてても先輩から教わりながらで許してもらえる事もあります。(あっ…ここでコミュニケーション能力が役に立つんだな…)

Webフロントエンドエンジニア

Webサイトやシステムの表示をやる人。デザイナーの隣。もちろんバックエンドともお隣 挙げている項目が少ないですが、往々にしてデザイナー寄りもしくはバックエンドよりの知識も一緒に求められます。

  • デザイナーと会話出来る程度のデザインの基礎知識(色相・明度といった色の概念、隣接・繰り返しといったデザインの大原則、基本的なタイポグラフィ)
  • 画像形式の基礎知識(ラスタとベクタ、不可逆圧縮可逆圧縮
  • HTML, CSS でのコーディング技術
  • JavaScriptでのコーディング技術(一昔前はjQueryとかでしたが、今はAngularやReactなどに移り変わっていて、これら知識が必要だと思います。)
  • 世間一般のWebシステムを観察して得た、フロントエンドの洞察や知識

Webバックエンドアプリケーションエンジニア

Webサイトのロジックを作る人。上述のフロントと、インフラエンジニアのお隣かな。

  • そのWebサービスの仕様をまとめあげる仕様策定の能力(≒文章力+論理的思考力みたいな感じ)
  • リレーショナルデータベースの知識(「ボイスコッド正規化」が何か分かるくらいまでは勉強しよう)
  • 何らかのプログラミング言語で書かれたWebアプリケーションフレームワーク、最低でも1つに精通していること(例:Ruby on Rails, Django, Play! Framework, Laravel, Gin, Phoenix, etc ...)
  • サーバー・クライアントモデルの基礎知識
  • HTTPプロトコルの基礎知識(HTTPメソッドやステータスコードCookieなど)
  • Unixプロセスの基礎知識
  • 暗号化の基礎知識(SSLとか公開鍵暗号とか)
  • セキュリティの基礎知識(CSRF,XSS,SQLインジェクション,セッションハイジャック, etc...)
  • HTMLのコーディング技術
  • CSSとJSの簡単な理解(フロント側と会話する上で何もしらないとちょっとマズいので最低限は知ってて欲しい)
  • ブラウザの仕様についての理解(普段から使っていれば分かるようなユーザーとしての知識)

Webインフラエンジニア

Webアプリケーションが動くサーバーが安定して動くように頑張る人。 僕がそこまで詳しくないので、ちょっと足りないものや間違っているがあるかもしれませんが、足がかり程度に。

  • Unixの深い理解(プロセスと親子関係、ランレベル、メモリ、サーバー監視の手法)
  • クラウドコンピューティングの知識(ロードバランサ、ヘルスチェック、VMインスタンスという概念やスナップショット、著名なクラウドプラットフォーム固有の知識)
  • ネットワークの深い理解(TCP/IP、HTTPをとっかかりに、物理層からTCPの層まで理解しているべき、輻輳や再送制御なども知ってた方がいいはず)
  • セキュリティの深い理解(バックエンドのものに加えて様々な知識が欲しい)
  • 最近はChefが使えると良い
  • Dockerも使えると良い

スマートフォンアプリエンジニア(UI側)

求人ではロジック側と一緒の場合もあるし、両方兼ねてる方がずっといいです。半分くらいはWebフロントと被る。

  • デザイナーと会話出来る程度のデザインの基礎知識(色相・明度といった色の概念、隣接・繰り返しといったデザインの大原則、基本的なタイポグラフィ)
  • 画像形式の基礎知識(ラスタとベクタ、不可逆圧縮可逆圧縮
  • 対象プラットフォームでのコーディング技術 (iOSならObjective-C/Swift, AndroidならJava/Kotlinなど)
  • 対象プラットフォーム自体への理解(普段からスマートフォンを使っていたら気づくようなこと、push通知が来るときに事前にチェックされるとか、そういうこと)
  • 気持ちの良い動きを作れるセンス(センスは才能ではなく観察から身につけるものなので、世の中の色んなUIを触って気付いた事を糧にしましょう)
  • 対象プラットフォームのデザインルールの理解(iOSなら"iOS Human Interface Guidelines"を理解する必要あり。Androidでも似たようなのがあるんじゃないかな?)
  • 世間一般のスマートフォンアプリを観察して得た洞察や知識

スマートフォンアプリエンジニア(ロジック側)

何か項目少ないけど、アプリの種類によっていろんな知識が必要になるので一般化しにくかっただけで、実際には実務の中で覚えても良いけれど、もっと多くの知識が必要です。

  • 対象プラットフォームでのコーディング技術 (iOSならObjective-C/Swift, AndroidならJava/Kotlinなど)
  • 対象プラットフォーム自体への理解(普段からスマートフォンを使っていたら気づくようなこと、push通知が来るときに事前にチェックされるとか、そういうこと)
  • 世間一般のスマートフォンアプリを観察して得た洞察や知識
  • スレッドの概念(少なくともiOSでは必要だけどAndroidはどうなんだろ、知らない)
  • HTTPの基礎知識(サーバーと通信するアプリが多いので)
  • RDBの知識(端末内にSQLiteとかでデータを保持する事が多いので)

おわりに

筆(指だけど)が乗って結構長くなっちゃった。許して!

もう一回書くけど、僕みたいなパターンだけがプログラマーになる道ではなく、1つのパターンだよってことだから誤読しないでね。 それと、最後に並べた職種毎のスキルのリストは現場によってまちまちだし、実際には「体力と根性」が最強のスキルだったりするので、何処からやって良いか、足がかりがない人のための参考程度のものです。これだけ押さえたら完璧って事でもないし、欠けてたら役立たずって訳でもないです。

炎上防止の言い訳も終わったのでこんなところで。

cocos2d-x メモ 2016/06/02

ほぼ個人的なcocos2d-xのお勉強メモだけど、誰かの役にも立ちそうなのでブログに載せとく。

BlendFunc

BlendFuncというのを使うと、Photoshopとかにある乗算レイヤとか加算レイヤとかスクリーンレイヤとかと似たような事が出来るらしい。 そもそもがOpenGL ESのAlphaBlending機能なので、それに関する情報を漁れば色々出て来る。

# 加算
BlendFunc blend;
blend.src = GL_SRC_ALPHA;
blend.dst = GL_ONE;

# 乗算
BlendFunc blend;
blend.src = GL_DST_COLOR;
blend.dst = GL_ZERO;

# 乗算別バージョン (結果は一緒になる)
BlendFunc blend;
blend.src = GL_ZERO;
blend.dst = GL_SRC_COLOR;

ようは、srcが対象のNodeで、dstが親(+兄ノード? 事前にレンダリングされてるものだと思うんだよな)のことで、 blendfuncでの指定をそれぞれの色に乗じて和を取るってことみたい。

疑似的にはたぶん、こういうこと。

render.pixel = child.pixel * blend.src + parent.pixel * blend.dst;

RenderTexture

あらゆるNodeをスクリーンショット的に一度レンダリングして使い回せるようにするやつ。 メソッド一覧を見てたらどうやらファイルへの書き出しも出来るっぽいので、スクリーンショットSNSに投稿する機能とかにも使われてるやつだと思う。

RenderTexture *texture = RenderTexture::create(visibleSize.width, visibleSize.height);
texture1->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
texture->beginWithClear(0, 0, 0, 1);
sprite->visit();
texture->end();

visitが重要。 これでspriteのレンダリングを実行してくれる。 beginWithClearはvisit直前のキャンバスクリアみたいなやつだろう。

このtextureを使ってSpriteを作る事も出来る。

Sprite *sprite2 = Sprite::createWithTexture(texture->getSprite()->getTexture());
sprite2->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
sprite2->setFlippedY(true);

※ 手元のコード見たら setFlippedY つけてたけど、必要なのかはよく分かってないです。。

特にDrawNodeとかはそのままだと扱いにくいことがある(どうもBlendFuncと相性が悪い)ので、一度RenderTextureにしちゃってからBlendすると結構期待通りに動く。 恐らくGPUだけで完結するはずのものが一回CPUに回ってくる処理になっちゃうので、updateの中でぐりぐり動くようなのを作りたい場合はパフォーマンスに気をつけないとFPSが保てないと思う。 initの中で最初だけ作ってあとは使い回すとかなら問題少なそうだし積極的に使って行きたいな。

GLSLとsetGLProgram

まだ詳細が分かってないんだけど、C言語を拡張したようなGLSLっていう言語でシェーダプログラミングが出来るらしい。 これはWebGLを含むかなり色々な環境で動く言語のようで、汎用性が高い技術みたい。 アニメーションもヌルヌルかけるので、cocos2d-xのレイヤで書くべき部分とシェーダで書くべき部分の目利きが出来るとよさそう。ある程度は推測がつくけど、やっぱ詳細が分からないので意外な盲点がありそうな感じがする。

Xcode6.3とXcode6.2を併用してる環境でApp StoreへのSubmitが途中で止まる問題の解決策

元ネタはこちら。

stackoverflow.com

普通にXcodeからアプリをSubmitするときって、OrganizerのSubmitボタンからやると思うんですが、別な方法を使うことでこのバグ?らしき挙動をバイパスできるってことみたいです。たぶん。

  • OrganizerでExportを押下
  • "Save for iOS AppStore" からRipaファイルを生成、適当なとこに保存
  • ドックのXcodeを右クリック → Developer toolsApplication Loader
  • このApplication Loaderを使ってsubmitすると問題ない

誰かの参考になれば幸い。

Application Loaderってなんだろ。

herokuにRails4.2.0 with mongoid & angularjsなプロジェクトをデプロイ

地雷だらけで死にそうだったのでメモ

config/production.rb のjs_compressor書き換え

Angular.jsが動かなくなるのを防ぐためにmangleをfalseにしたUglifierを使う

config.assets.js_compressor = Uglifier.new(:mangle => false)

mongoid.yml の設定

以下のようにする

production:
  sessions:
    default:
      uri: <%= ENV['MONGOLAB_URI'] %>

MongoHQを使ってる場合は環境変数名が違うだけ。 production直下にuriを書けるって情報があるけど、古いようで今のバージョンでは動かない。

雑感

そこそこ使われてそうな組み合わせの割に情報あんまりないし、最近ネット上に技術メモ流す人減ってないか?Twitterに書いて満足するのやめてこの程度にはまとめて書こうな!?

参考: バージョン情報

ruby 2.1.3

Gemfile.lock

GEM
  remote: https://rubygems.org/
  specs:
    actionmailer (4.2.0)
      actionpack (= 4.2.0)
      actionview (= 4.2.0)
      activejob (= 4.2.0)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 1.0, >= 1.0.5)
    actionpack (4.2.0)
      actionview (= 4.2.0)
      activesupport (= 4.2.0)
      rack (~> 1.6.0)
      rack-test (~> 0.6.2)
      rails-dom-testing (~> 1.0, >= 1.0.5)
      rails-html-sanitizer (~> 1.0, >= 1.0.1)
    actionview (4.2.0)
      activesupport (= 4.2.0)
      builder (~> 3.1)
      erubis (~> 2.7.0)
      rails-dom-testing (~> 1.0, >= 1.0.5)
      rails-html-sanitizer (~> 1.0, >= 1.0.1)
    activejob (4.2.0)
      activesupport (= 4.2.0)
      globalid (>= 0.3.0)
    activemodel (4.2.0)
      activesupport (= 4.2.0)
      builder (~> 3.1)
    activerecord (4.2.0)
      activemodel (= 4.2.0)
      activesupport (= 4.2.0)
      arel (~> 6.0)
    activesupport (4.2.0)
      i18n (~> 0.7)
      json (~> 1.7, >= 1.7.7)
      minitest (~> 5.1)
      thread_safe (~> 0.3, >= 0.3.4)
      tzinfo (~> 1.1)
    angularjs-rails (1.3.10)
    arel (6.0.0)
    autoprefixer-rails (5.1.7)
      execjs
      json
    binding_of_caller (0.7.2)
      debug_inspector (>= 0.0.1)
    bootstrap-sass (3.3.3)
      autoprefixer-rails (>= 5.0.0.1)
      sass (>= 3.2.19)
    bson (2.3.0)
    builder (3.2.2)
    byebug (3.5.1)
      columnize (~> 0.8)
      debugger-linecache (~> 1.2)
      slop (~> 3.6)
    coffee-rails (4.1.0)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0, < 5.0)
    coffee-script (2.3.0)
      coffee-script-source
      execjs
    coffee-script-source (1.9.1)
    columnize (0.9.0)
    connection_pool (2.1.1)
    debug_inspector (0.0.2)
    debugger-linecache (1.2.0)
    erubis (2.7.0)
    execjs (2.3.0)
    globalid (0.3.3)
      activesupport (>= 4.1.0)
    hike (1.2.3)
    i18n (0.7.0)
    jbuilder (2.2.8)
      activesupport (>= 3.0.0, < 5)
      multi_json (~> 1.2)
    jquery-rails (4.0.3)
      rails-dom-testing (~> 1.0)
      railties (>= 4.2.0)
      thor (>= 0.14, < 2.0)
    json (1.8.2)
    loofah (2.0.1)
      nokogiri (>= 1.5.9)
    mail (2.6.3)
      mime-types (>= 1.16, < 3)
    mime-types (2.4.3)
    mini_portile (0.6.2)
    minitest (5.5.1)
    mongoid (4.0.2)
      activemodel (~> 4.0)
      moped (~> 2.0.0)
      origin (~> 2.1)
      tzinfo (>= 0.3.37)
    moped (2.0.4)
      bson (~> 2.2)
      connection_pool (~> 2.0)
      optionable (~> 0.2.0)
    multi_json (1.10.1)
    nokogiri (1.6.6.2)
      mini_portile (~> 0.6.0)
    optionable (0.2.0)
    origin (2.1.1)
    puma (2.11.1)
      rack (>= 1.1, < 2.0)
    rack (1.6.0)
    rack-test (0.6.3)
      rack (>= 1.0)
    rails (4.2.0)
      actionmailer (= 4.2.0)
      actionpack (= 4.2.0)
      actionview (= 4.2.0)
      activejob (= 4.2.0)
      activemodel (= 4.2.0)
      activerecord (= 4.2.0)
      activesupport (= 4.2.0)
      bundler (>= 1.3.0, < 2.0)
      railties (= 4.2.0)
      sprockets-rails
    rails-deprecated_sanitizer (1.0.3)
      activesupport (>= 4.2.0.alpha)
    rails-dom-testing (1.0.5)
      activesupport (>= 4.2.0.beta, < 5.0)
      nokogiri (~> 1.6.0)
      rails-deprecated_sanitizer (>= 1.0.1)
    rails-html-sanitizer (1.0.1)
      loofah (~> 2.0)
    railties (4.2.0)
      actionpack (= 4.2.0)
      activesupport (= 4.2.0)
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rake (10.4.2)
    rdoc (4.2.0)
      json (~> 1.4)
    sass (3.4.12)
    sass-rails (5.0.1)
      railties (>= 4.0.0, < 5.0)
      sass (~> 3.1)
      sprockets (>= 2.8, < 4.0)
      sprockets-rails (>= 2.0, < 4.0)
      tilt (~> 1.1)
    sdoc (0.4.1)
      json (~> 1.7, >= 1.7.7)
      rdoc (~> 4.0)
    slim (3.0.2)
      temple (~> 0.7.3)
      tilt (>= 1.3.3, < 2.1)
    slim-rails (3.0.1)
      actionmailer (>= 3.1, < 5.0)
      actionpack (>= 3.1, < 5.0)
      activesupport (>= 3.1, < 5.0)
      railties (>= 3.1, < 5.0)
      slim (~> 3.0)
    slop (3.6.0)
    spring (1.3.2)
    sprockets (2.12.3)
      hike (~> 1.2)
      multi_json (~> 1.0)
      rack (~> 1.0)
      tilt (~> 1.1, != 1.3.0)
    sprockets-rails (2.2.4)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      sprockets (>= 2.8, < 4.0)
    temple (0.7.5)
    thor (0.19.1)
    thread_safe (0.3.4)
    tilt (1.4.1)
    tzinfo (1.2.2)
      thread_safe (~> 0.1)
    uglifier (2.7.0)
      execjs (>= 0.3.0)
      json (>= 1.8.0)
    web-console (2.0.0)
      activemodel (~> 4.0)
      binding_of_caller (>= 0.7.2)
      railties (~> 4.0)
      sprockets-rails (>= 2.0, < 4.0)

PLATFORMS
  ruby

DEPENDENCIES
  angularjs-rails
  bootstrap-sass
  byebug
  coffee-rails (~> 4.1.0)
  jbuilder (~> 2.0)
  jquery-rails
  mongoid
  puma
  rails (= 4.2.0)
  sass-rails (~> 5.0)
  sdoc (~> 0.4.0)
  slim-rails
  spring
  uglifier (>= 1.3.0)
  web-console (~> 2.0)

Angularが悪いんじゃなくて使い方が間違ってるんだという話

最近いろんな案件や記事でAngular.jsを耳にしますが、結構「あれ使いにくいよね」などという話もちらほら。 実際ぼくが使っていてもなんだか使いにくく感じることがままあります。

多少触ってみたり考えてみたりして、僕なりの結論めいたものが見えてきたので記事にしてみようとおもいます。

サーバーサイドレンダリングとクライアントサイドレンダリング

perl, PHP全盛期

古来(?)、perlPHPの時代、多くのWebページは手打ちのHTMLで出来ていました。 この中で、フォームなどの機能をちょっとだけ追加したい、などの要請から、HTMLに直接ちょっとだけコードを埋め込めるPHPが一斉を風靡しました。

Rails全盛期

PHPによるWebアプリケーションが盛んになってくると、そのプログラムに重複する部分が多いことや、設計・実装をパターン化することで効率化が図れることがわかってきて、Ruby on RailsなどをはじめとするMVCフレームワークが登場しました。

大事なのは、ここまでずっと「サーバー側でHTMLを生成して、動的な要素はその中に埋め込まれていた」ということです。

Twitterの公開APIスマートフォン向けアプリの拡大、プラットフォームの多様化

TwitterAPIを公開し、サードパーティが自由に対応アプリを開発できることが、多様なアプリケーションを生むようになりました。 これとほぼ同時期にスマートフォンが普及し、そういった複数プラットフォームへの対応が要請されるようになりました。

その中では、すべてのWebでやろうという流れも強く、未だにその流れもありますが、レスポンスの悪さなどから好かれない傾向にあるようです。

補足

  • そもそもゲームとかだとRPCが当たり前のようにやられてたので、そこから輸入した考えではある
  • スマホの台頭以前からデスクトップアプリでは必要なことでしたが、やはりスマホ以後で大きくこの状況が動いたというのはあると思います。

SPAという提案 (Single Page Application)

スマートフォンアプリが発達してきたことで、Webサービスというものの捉え方は変わり、(大抵はJSON+HTTPの)APIこそがWebサービスである、という考え方が出てきました。 また、Webページより先にアプリ側を作ることも増えてきたので、じゃあどうせなら、アプリ側でシッカリ作ったAPIをWebでも使えたら、セキュリティの問題もHTMLよりは考えやすくなるし、良いことづくめじゃないか。 じゃあ、もうページの遷移すらやめてしまって、全ページをJSでレンダリングするという考え方で作ってもいいんじゃないか。 HTML/CSS/JSはクライアントサイドのもので、サーバーとはAPIで通信する。HTML/CSS/JSは静的なサーバーから配信すれば十分高速だろうし、API通信で重い部分はきちんとUIで解消していけばいいじゃん、行ける行ける!

…と、SPAが生まれるまでは、こんな流れなんじゃないでしょうか。

結論「AngularのSPA的アプローチと静的HTML生成アプローチの混在が混乱を招く」

さて、そういわけで結論にすっとばします。

Angularなどを使ったSPA的なアプローチは、バックエンドが全てJSONAPIで構成されていることを前提にしている。 だから、APIベースで考えずにviewレイヤでHTMLをレンダリングする過去のアプローチと混ぜてはいけない。 SPAで重要なのは、API側とビュー(クライアント)側が疎結合になり、それぞれ独立して開発を進められるようにすること。

わかってる人には当たり前のことなんだと思うんですけど、今のところの自分の解釈をざっと書いてみました。 この辺り、まだまだ流動性の高い部分なのでこれからも変わっていくと思います。コメントもお待ちしておりますので、いろいろ考えを深められたら、と思います。

RailsやMiddleman で自動的に目次を作るにはどうすればいいのか

せっかくなのでブログでも共有しておく。

お世話になってる先輩が泣いているのは忍びなかったので適当にサンプルコードをつくった。

考え

リポジトリにも書いたんだけど、以下の様な感じで考えて作った。何かの参考になるかもしれないので公開しておく。

目次の責任範囲はどこにある?

  • テンプレートエンジン、ジェネレータ
    • そういう考え方もある
  • h2の代わりになるタグをヘルパで定義して使う
    • Dirty! Dirty! Dirty!
    • 再利用性低すぎ!
  • レイアウトファイル
    • あ、行けそう

ということでレイアウトファイルが目次を作るのはそれなりにアリだと思います。

拡張の仕方

  • レイアウトファイルの中の処理をゴリゴリ書く
  • レイアウトファイルの中の処理をHelperに切り出す

例:ヘッダへのリンクが貼りたい

  • ヘッダにname要素やid要素をつける (どうせセマンティック的には自分でつけるべき)
  • パースした方でゴリ押し

ISUCON4 予選に出てきた

去年に引き続いて今年もISUCON4の予選に出ました。

去年は学生だったので @cnosuke , @rkmathi と一緒に出てたのですが、 今年は学生じゃないので @syu_cream , @suma90h と一緒に出ました。チーム名は「SSS」 (僕の本名、彼らのアカウント、の頭文字がすべてSなので。) 僕がタイミング悪く沖縄に出張していて、合流出来ずリモート参戦でご迷惑おかけしちゃいました。

前回はプログラムの方にいろいろとバグがあったのですが、今回はコード自体は普通に動くようにできていたという印象です。 寧ろ、改変したSQLにバグがあったりして3時間ぐらいドブに捨ててしまったのが痛かったです。 8時間って短いですねぇ、やっぱり。

mysqlのCPU負荷が異常に高かったのでインデックスを貼ってみた所で劇的に解決しました。 コードの改変より先にそっちをやれば良かったですね。

16:50時点でのスコアが4426しかなくて、こりゃあお通夜だなーと思っていたら、後半いろいろ頑張ったら結果としては25348ぐらいまで向上しました。 それほどインフラ特化じゃないプログラマーのチームとしては、悪くないんじゃないでしょうか。

主にやったこと

  • nginx チューニング
    • syu_cream がやってくれた
    • 静的ファイルはnginxで返す
    • worker_processは1で同時接続数は1024ぐらいにしてた
    • gz圧縮の話もあったけど、ベンチマークがローカルで動いていることから逆効果かなと思って止めた
  • mysql のパラメータチューニング
  • mysql へのインデックス追加
    • わりと順当に login_log の ip と user_id それぞれにインデックスを追加しただけ
  • unicorn のプロセス数と mysql の max_connections のチューニング
  • puma への変更
    • 最終的にスレッド5つ、プロセス4つに落ち着いた
  • TCP(OS)のパラメータチューニング
    • "dial tcp 127.0.0.1:80: cannot assign requested address" エラーへの対処
    • sysctl -w net.ipv4.tcp_tw_recycle=1
    • (syu_cream/suma90hがやってくれたから良く分からないけどエラーが止まった)

やってみたかったけどできなかったこと

  • MySQLのvarchar(255)になっているカラムの長さを調節
    • login_log の login とか、 (24) にすれば良かった気がする
    • booleanで良い部分が tinyint(4) になっていた所も似たような話
  • ベンチマーク直前のウォームアップ時
    • MySQLのキャッシュを暖める
    • MySQLのコネクションをあらかじめ貼っておく
  • きちんとボトルネック解析
    • 結局、せいぜいtopを見る程度で、細かくボトルネックを解析できなくて、場当たり的でした

感想

去年も言ったけど、こういうパフォーマンスチューニングも面白いですねぇ。 勉強になるので、来年も参加したいなーと思っています。

一緒に参加してくれた @syu_cream さん、 @suma90h さん、ありがとうございました!