PHPカンファレンス福岡2016雑感
PHPカンファレンス福岡大会 2016 に行ってきました。
今年はPHPカンファレンスが日本国内で年4回開催されるという、前代未聞の年となりました。
また、2016年は、PHP5.1.2という重要なマイルストーンのリリースからちょうど10年という時が経っています。
5.1.2というバージョン番号は、PHP5対応のOSSの多くが、最低サポートするバージョンはここだよという基準として、もっとも多く採用していたバージョンです。たしか、各LinuxディストリもここをPHPの最初の5系として動き出したような...
最初のPHPリリースからみると約20年、そう考えるともう、PHPの歴史のうちほぼ半分が、PHP5が主流だった歴史なわけです。PHP5への転換から10年の節目で、これだけPHPカンファレンスを開催したいと考える地域が増えたのは、本当にPHPが良くなっていった10年だったんだなって、感慨深くなりますね。
あーあー校長先生の挨拶でした。つづきましてー
いやまあ、そんなのもあってですね、今流行りの10年やってわかったことネタでちょっといちびってみました。タイムテーブルにはないけど確実に懇親会LTはある、と見込んで仕込んできたネタがこちらになります。
あくまで夜のやつですからね、お酒入ってからのやつですから... あ... ええ、いろいろすんません。
昼間のちゃんとしたやつはスライドまとめを見て下さい。
聴講して印象的だったのはロリポップでした。
やっぱり、PHPを積極的に採用していったレンサバの中の人はすごいって感想です。 ロリポを使う人とロリポを使わない人とロリポを作っている人の関係って、じつはPHP文化に 相似なのかもしれないな、共用やPaaSも見逃せないぞと思いました。
フレームワークについては、福岡という土地柄で、やはりCakePHPが目立ちました。 CakeはPHP4時代との互換を重視しての2へのメジャーバージョンアップがあったぶん、今っぽいMVCになるのがもっとも遅かったフレームワークと言えます。ので、以前からPHP5.1以降に登場したフレームワークを使っている自分のような者にとって、ちょっと物足りなかったかなと感じました。まあ、このタイミングだとどうしても、2までと3との違い重要なのでしょうがないんですけどね...
次回あたりは「もう全員3にしましたよね、CakePHPも他の自由にOOPできるフレームワークと足並みが揃いました、じゃあこの次はSOLIDをふまえてパッケージ原則ですが...」「私は、今のCakePHPの方が何か赤い宝石のアレよりも大規模エンプラへの耐性が高いのではないかと感じ、これが本当なら歴史的に感慨深いことで...」みたいなぶっちぎりのをやってくれるセッションが1つぐらいあってもいいかなと思います。
注目のPSR-7について思うところは、また時を改めて。
質問タイムに質問する人がいつもの面々で、それぞれ自分の担当って感じのところで質問を出してくれていいなあって反面、初参加の人ももっと質問していけたらなとも思いました。発表慣れしていない人の練習の場が大事というのはたしかで、もしかしたらそのついでに、「質問慣れをする機会」というのはあってもいいんじゃないかとか思ったり。どうやったらいいのかってアイデアはないですが。
今回の改善点:
去年は、前泊と2日目を別のホテルにしていたら、2日目のホテルのチェックインが遅れてキャンセルされ、宿がなくなる(しかもネカフェさえ満室)という事態に陥ってしまいました。今年は金曜日からの2連泊でホテル予約し、懇親会後の安心感を確保しました。
今回の課題点:
前夜祭終わりの時点では問題なかったのに、翌朝、寝る前より激しい酔いに襲われました。単純に飲み過ぎたわけではないはず、だったら夜の時点でそれはわかってるはず...と分析してみたところ、もしかしたら、新大阪を出発するとき食べた100倍カレーが、胃粘膜にバックドアを作ったのではないかという可能性が考えられました。(心理的に)再現困難なため検証できていませんので、この不具合を再現できる方がおられましたらぜひお知らせください。
ウコン重要。
反省点:
今回は自分で行こうと思ってた店には運悪くことごとく行けず、 なりゆきで行けるラーメンに流れてしまった(それはそれで美味しかったけど)のが心残りでした。
さ、次は7月16日、関西の番です。折り返しからの後半戦、盛り上がってまいりましょう。(告知)
歴史的経緯によりこのメソッドはモテない (PHPカンファレンス感想)
10月3日に行われたPHPカンファレンス2015に行ってきました。で、いいかげん蒲田グルメレポート「みんなPHPカンファレンスに行くべき、なぜならメシが美味いから」とか書かなきゃと思っていたけど、変えることにします。
スライド公開後、残念ながらとても悪い評価を集めてしまったものがありました。
PHPer女子が語る2015!こんなコードを書くヒトはモテない〜コラボ編〜@PHPカンファレンス2015 #phpcon2015
自分も、他に素晴らしい話が数多く出た中、申し訳ないけど自分の中で上位には入らないなとは思う発表でした。ただまあ、経験を積んでいってくださいというだけで、そこまで問題視すべきことじゃないと思っていました。
が、あまりにもあまりにも... 面白くないならスルーでいいのに、なんでわざわざ食ってかかるかなぁ、って Twitter を眺めてて... 当事者にとってすらそこまで必要ない勝手なアレかもしれませんが、いま蒲田グルメよりこっちの気持ちのほうが大きいので。
というわけで、モテの歴史的経緯からきちんと分析してみたいと思います。
「モテる」ネタのカンブリア爆発
オムライスが食べられない女、おぼえていますか。モテる技術ネタの第一次ブームはそこにさかのぼります。
この記事は大ブームとなり、さまざまなパロディが作られました。
- [ネタ] モテるC++女子力を磨くための4つの心得 - cimada-ism
- モテる Python 女子力を磨くための4つの心得 - 混沌脳内
- visible true: モテるAndroid女子力を磨くための4つの心得
- モテるScala女子力を上げたい人向けにScalaの本が出ます。 - ( ꒪⌓꒪) ゆるよろ日記
- モテる PHP 女子力を磨くための4つの心得 - Memo
- モテるEmacs女子力を磨くための4つの心得 - Oh! Can Not Diary
- 小野和俊のブログ:モテるプログラマー女子力を磨くための4つの心得
- モテるScala系女子力を磨くための4つの心得 - scalaとか・・・
- モテるRuby女子力を磨くための4つの心得|りんむーのブログ
- モテるPHP女子力を磨くための4つの心得 「symfony1.4を使えない女をアピールせよ」
- モテるJS系女子力を磨くための4つの心得 | tech.kayac.com - KAYAC engineers' blog
4年前、みんな若かったのかな...
当時はパロディーで、モテるという謎の価値観を積極的に否定してウケをねらうものでした。
当事者たちはすぐに飽きてやめてしまったけれど、この影響はあとでじわじわ効いてきます。
図らずも「モテる」が定着
何かと「モテる」を使って、まだ自分の技術をやっていないエンジニアに対する煽りを交えたタイトルが出現しはじめます。
- モテるAndroidアプリ開発 - Firespeed
- グラデーションできたらモテる【liner-gradient,radial-gradient】 | 指で覚えるHTML5
- Vimから3日で乗り換えた、次世代モテエディタ「Sublime Text 2」の魅力 - Hack Your Design!
- www.slideshare.net Microsoftさん...
オムライス以前から時代を先取ってきたのもありますね。
- モテる Ruby! - Ruby会議 2007 - 2nd life
- モテるアルゴリズム講座 第1回 グラフでモテたい | FLATzブログ その他 アルゴリズム|株式会社フラッツ[FLATz Inc.]
まあこのあたりは、モテるモテないといったユルいタイトルに反して、そこそこハードな内容を出すという、ギャップを楽しむものでした。
ソーシャルに浸透
そうこうしているうち、どの言語を使えばモテるといった言い方で、自分のいる泥くさい現場に比べて華やかな技術はうらやましい、不純な理由をつけてでも別の技術を学ぶモチベーションを持ちたいといった気持ちを、個人個人が個別に発するようになっています。「〇〇を使えばモテる」と。
そういうおふざけを、みんなやっているわかりやすいプロトコルとして、いわゆる非モテとセットで連想されがちなエンジニア界隈が受け入れてしまった。
といっても、それがまだ明らかに冗談であるとわかる関連付けであるうちはまだ、ギリでセンシティブな問題とは言えなかった。
が
なにか様子が変わってきます。
仮想概念「モテる」のリアリティ
まったくの男性社会、むしろ異性なんて興味ない、と言える技術の畑だからと、言う方がだんだん麻痺してしまうと、そこに接しているそれほどでもない世界に影響を与えてしまいます。
遠くの島にCSS Niteが見えます。その一つ手前にはWordCampがあります。さてそこまで来ればPHPカンファレンスは同じ会場です。
そういう意味で、プログラム言語の中でもPHPやJavaScriptには、まったく色気のない安心できる世界よりはまだ、いわゆるリア充との接点が広い文化がありました。PHPはとても大きなグラデーションで、場合によって明らかに冗談なものが、ふとしたひょうしに現実になってしまいます。
そうして、身内として過去の文脈を共有しない人にまで広がると、意味の拡大解釈が起こっても不思議ではありません。イケメンや壁ドンと同じです。モテるが100%冗談と言えなくなってしまう。まだまだネタ扱いとはいえ、モテがずいぶんと現実の側に歩み寄ってきました。
それで初心者はROMっとけはどうなのか
たしかに、空気よめない「モテる」はちょっと変な感じです。でも、これまでの歴史的経緯を知る人が、経緯も知らずに使う素人は何も言うな、というのは「初心者はROMっとけ」というのと同じです。これマサカリの中でもいちばんタチがわるいやつですね。
まあもういいかげん、ポリティカルコレクトネスがどうとか、何度かの炎上で痛い目見たとか、ドラ娘がいなくなったとか、いろいろあっておじさん連中は疲れていて、以前良かったことも今はとにかくタブーだからダメダメダメダメってなっています。けどそんなの知らない子だっているんですよね... 新しい人に対してもっともオープンなコミュニティだからこその話。
モテないはセクハラなのか?
中には「モテない」が主題になってしまったスライドを見て、セクハラだとツイートする人もいます。けれどちょっと待って下さい、セクハラというのは、たんに異性間トラブルというだけでなく、その根底には、マジョリティの無神経という本質があるものです。
そもそも、大きく男女に分けると、みなさんのいるエンジニア界隈はやはり男性がマジョリティです。男女の強弱関係ははっきりしています。
マイノリティである女性が、より強い立場の男性に対してセクハラというのは少しおかしいように思います。恋愛でいえば女性がマジョリティになることもあります。その文脈でモテないと言われれば、それは、恋愛マイノリティへの攻撃になると、みなさん肌感覚でなんとなくわかるでしょう。けれど...
それみたことかやっぱり女だ、それみたことかやっぱりPHPだ、と、スクリーンの向こうに人間がいることを忘れて、自己の承認要求を満たすために弱い方の過ちをネットで責めようとする気持ち。そのほうがむしろ、構造的にみて、ハラスメントとされる現象になります。(もちろん、適切な批判なり個人としての好き嫌いをツイートするのはこれに含みません)
マジョリティであるがゆえに、マイノリティに対するその力の大きさを自覚しなければと、自分も男性としてそう思います。
何がいけないのかポイント抽出
1
女が男をばかにした、として不愉快に思う人がいました。が、その不愉快さは、ハラスメント問題ではなく、あれよあれよと「のび太のくせに生意気だ」という暴力になりかねません。こうなることを予想して、弱者になりうる仲間を守っておく知恵が働かなかったことが残念でした。
2
「モテない」なんて言ってもそれがただの煽り脚色となるような、濃いギャップのある内容であればまだ救われました。その意味で、2014年のものは結論があったけれど、2015年バージョンは本当に言いたいことが抜けていました。お祭りを盛り上げたいと「モテネタでまたやってよ」に応えることを目的化してしまい、それを大真面目にやってしまった。自分の中の、エンジニアとしての本当の目的を忘れていたのではないかと思います。人のためにがんばりすぎやねん。
3
よくある悪ノリと同じとは言えなくなる要因がもう1つありました。LTのタイトルとして公式にパンフレットに刷り込まれていて、スポンサー企業とのコラボ企画であったこと。公式、つまりその場を仕切っている最強のマジョリティが認めたことになってしまった。こうなると、外から見たとき、ハラスメントのマジョリティー/マイノリティー関係が逆転する可能性があります。
とはいえ
エンジニアはイベントのプロではないのです。世代交代しながらイベント運営のクオリティを維持していくのは、本当に難しいです。その点は、自分も関西カンファレンスの人として、痛感します。
仲間としてぶっちゃけた気持ちを言うなら、これまだ、当日参加している人が言うならいいのですが、参加せずわかったような批判をする人には「まあ落ち着けや、おまえらPHPerちゃうし直接関係ないやろ」と。みなさん、本当の問題じゃないことを、さも問題ありかのように騒いで、楽しんでんじゃないかって感じの上司/代理店/顧客の姿を思い出してください。
どうでもいいことがふくらみましたが、ホントに言いたい社会的な視点に話を戻すと、ようは、おまえらが作ってきた道なんだから、若者が通ってしまうのは仕方ないだろ、知らんならROMっとけってのは、マサカリじゃなくて老害って言うんだぜ。ダメって言うなら歴史を検証してちゃんと伝えてあげる人が一人ぐらいいたっていいんじゃない。
今後どうすればいいか
モテで煽ったわりに面白くなかったことが良くなかったと思うので、いちばん足りていないのはおそらく登壇者のお笑いのスキルでしょう。スキルアップのために、ぜひPHPカンファレンス関西に勉強しに来てください。
勇気を出してコミュニティに参加してくれている女性エンジニアには、技術者同士として積極的に話しかけていきましょう。性別に関係なく勉強のチャンスがある、そういう気遣いをしてくれるコミュニティーには、より多くの女性が安心して参加できます。これがモテるということです。
— 田中ひさてる (@tanakahisateru) 2015, 10月 6
性役割を求めると女性エンジニアは去る。技術を向上しようという場で、上げるつもりのない女としての機能を比較されるから。性差別なく平等に参加してもらえる場だからこそ、女性のほうから自分を出していけるようになる。オシャレしてもいい、恋ネタいける、コスプレしてもいい、と。そう思うですよ
— 田中ひさてる (@tanakahisateru) 2015, 10月 6
な、おっちゃんモテそうやろ。
↑ お笑いのスキル
はやいで! つよいで! ワテらのPHP!! #phpkansai
この記事は「 PHPカンファレンス関西2015 」の リレーブログ のエントリーです。
昨日は、@aa7th さん PHPとScalaと私 #phpkansai でした。
このエントリーのタイトル、「はやいで! つよいで! ワテらのPHP!!」というのは、もしかしたら今年のPHPカンファレンス関西のテーマになるかもしれなかかった文言です。これ結局は採用されず、今年は「テーマなし」ということでボツになりました。
が、こいつが出てきたときの空気感がすごく良くて忘れたくなかったので、こうして残しておこうと思いました。関西人の冗談みたいな文言ですが、これ実は今のPHPコミュニティにとって、とても大事なメッセージを含んでいると思うのです。まじで。
- はやいで!
- つよいで!
- ワテらのPHP!!
では、ひとつひとつ解説していきましょう。
はやいで!
速いといえばPHP7ですよ。
これまでも、PHP4から5の間で、また、PHP5.3から5.6の間でも、ものすごく高速化されてきました。HHVMなんて別の処理系もあります。Wikipediaを爆速にしたことで有名ですね。実は今のPHP処理系は、インタプリタとしてはかなり速い部類になります。
とはいえ、HHVMまで行くとさすがにちょっとハードルが高かったんですが、これからは、それ相当の速度がなんと、PHP7という「ふつうのPHP」で得られるんです。
また、仮想マシンが一般的なWebの言語にあって、Phalcon という「フレームワークコードがほぼネイティブ」という速さへのアプローチもあります。ReactPHP という、Node.js のような非同期IOを実現することで、裏方の処理系のパフォーマンスを高めるアイデアもあります。
いかに早く作れるかというのもまた、PHPがこれまでWebで活躍してきた理由のひとつです。近年、エンタープライズ指向での用途にも使えるようになったとはいえ、当初 LAMP という言葉が意味していたこと、その中にPHPがいたことは、とても大事なことだと思います。
今回のカンファレンスでは、基調講演にPHP7のお話があります。Phalconのセッションも設けています。自分個人としては、開発の早さ=RAD (Rapid Application Development) の視点から、フレームワークトラックのうち1セッションを担当させてもらいます。
つよいで!
繰り返し言っていることなんですが、PHP はリクエストごとにクラス定義すら最初から読み直し、終わったら全部捨てるんですよ。それがマトモな速さで動くんです。Webリクエストはぜんぶ別のプロセス空間です。ここ、強さの秘訣ですよね。
はじめから完全分離されているということは、サーバを簡単にスケールアウトできるってことです。global使ってようが、static変数使っていようが、そいつらも分離されてるんですよ。この、ラフでもタフというのは、まぎれもないPHPの強さです。
また、ここ数年で強力なツールがどんどん登場しています。PHPUnit はもちろん、Composer, PhpStorm... ライブラリなら SwiftMailer や Guzzle、フレームワークもさまざまな用途に派生し、どんどん洗練されています。その裏には、PSR という強い実効力のある標準化機構があったりします。個人的には、型をベースに静的解析できるLLだという点で、LLで堅実なプログラムを書くならPHPは最強なんじゃないかと思っています。
セキュリティ面でも、いっときは「たとえばPHPを使わない」と言われたこともありましたが、今では、もっとも叩かれて鍛えられたセキュリティ意識を持つ文化になっているんじゃないかと、個人的に思っています。Webアプリケーションのセキュリティに関して、もっとも見識のある層の方々からの関心を集めているのは、間違いないと思うのです。
カンファレンスのセッション内容としては、フレームワークだけを特集するトラックを設けています。強力なモダンフレームワークの世界を楽しんでいただければと思います。セキュリティについてはなんと2セッションあります。CodeceptionやCI(継続的インテグレーション)の話題も楽しみですね。
ワテらのPHP!!
最先端ではどんどん速く、強くなっているPHPですが、そのいっぽうで、PHPはごく一般的なWebエンジニアから見て、けして遠い存在ではありません。Webの開発に携わる人々にとって、PHPはもっとも親しみのある言語のひとつです。
PHPは主に、Webのサーバサイドの最前面に立つ技術です。フロントエンドの人との関係もとても深いでしょう。Webデザイナーが覚えたいプログラム言語ナンバーワンかナンバーツーは、なんといってもJavaScriptとPHPですもんね。
開発とは関係のないWebのユーザーにとってもそうです。FacebookもWikipediaも、みんなPHPのおかげさまです。なんだかんだ言いながらも、みんな日々、WordPress で公開される記事を読んでいますね。いまPHPは、Webになくてはならない、みんなのPHPです。
いまだに、まだドジっ子だった頃の癖が出るかもしれません。それもまた、みんなで「あるある〜」と共感できる愛嬌ある部分なのです。ほら、配列と辞書がごちゃまぜとか、文字列を数値計算できちゃうとか、なんかかわいいじゃないですか。(で、それは案外実務で便利だったりすることの方が多い)
カンファレンスのセッションには、PHPに限定した話のほかに、フロントエンド、クラウド、アクセス解析、プロジェクト管理といった、他の分野に広がっている話題も満載です。また、PHPカンファレンス関西は参加者全員にとって、「ワテらの」カンファレンスです。上級者向けだけでなく、初心者向けセッションやIDEとGitの体験ハンズオンなども、重要なテーマとして盛り込んでいます。
ともすればそのドジっ子なところを揶揄されがちなPHPですが、そんな声はものともせず、PHPとPHP文化の「はやさ」「つよさ」を、誇りを持って「これがワテらのPHPじゃ」とアピールできる場を作りたい。そんなPHPカンファレンスを関西で提供していきたい。テーマ案「はやいで! つよいで! ワテらのPHP!!」はそんな思いから出てきました。
ま、ボツってるんですけどね(^^; いいじゃないですか、気持ちさえあれば、体裁なんて。
※ @shin1x1, @aa7th, @omoon とのミーティングと肉に感謝。
さあリレーブログでどんどんテンション上げていきましょー! 次は @slywalker さんです。 → 忍び歩く男 - SLYWALKER あしたもみてね (夏休みこども劇場)
IntelliJ でブランチ間の差分と作業ブランチ全体のコードレビュー
IntelliJ でブランチ間の差を見たいときは、まず基準ブランチをチェックアウトしてからここ
で
それぞれのコミットの diff を見て、トータルでどれだけ違うかは、Log を Diff に
これで HEAD 同士の比較です。
でも
master が他のプルリクエストをいろいろマージしていると、作業ブランチはあまり変えてないのに、master が進んでいくせいで差がどんどんできてしまいます。ここまでのスクリーンショットでもすでに README.md が master 側で進んじゃってますね。
そうなると時間が経つほどに、ブランチ HEAD 同士を比べることと、作業ブランチのコミットを累積してどんな作業をしたのかを見ることは、意味が違ってきます。数人で分担作業したものがリリース直前になると、個別のブランチよりもマージを進めている master の方が多くのファイルを変更しちゃってるなんてことが多々あります。
そこで、作業ブランチのコミットの累積をコードレビューする方法を考えます。まずは作業ブランチの base を探します。たぶんその作業は master からブランチしてますよね。じゃあ、Changes パネルのごちゃごちゃした Logs タブに master と対象作業ブランチだけを表示 (補完ありでブランチ名を2つここに書く) しましょう
それから、2つが合流する共通のコミットを探します
で、こいつをチェックアウト。この状態で最初の方法で作業ブランチと Compare すると、 作業ブランチでやった変更だけ を確認できます。
GitHub とか Bitbucket みたいな、プルリクエストのコミット群のサマリーを見ることができるサービスを使ってればいいんですが、そうでない場合、マージしたいブランチで変更のあった行がどこなのか調べるのはちょっと面倒です。まあ、GitHub の プルリクエストページでも Unified Diff になっちゃうので、ソースコードの全体像を見ながらレビューしたいと思っても難しいですね。
↑
ようは、IDE のパワーを使える状況で、かつソース全体をレビューできるこれが便利なわけですよこれが。
Yii Framework 2.0 リリース記念勉強会 資料
第19回関西PHP勉強会 Yii Framework 2.0 リリース記念勉強会 の資料はこちらです。
だいぶあおり気味なのは、一般公開を意識せずに書いているためです。その場にいる人向けに、今日はこういう勉強会なので空気読んでね、というのが入っているのをご了承ください。
Yii 2.0 とは
ベータリリース記念 第一回勉強会の資料
https://gist.github.com/tanakahisateru/cf8ef578d7ea24ea429a ※ イベントまわりでちょっとオススメじゃない書き方があります
過去の発表やブログなど
http://www.slideshare.net/tanakahisateru/phpcon-2014yii
http://image.slidesharecdn.com/yii-121012040114-phpapp01/95/yii-31-728.jpg?cb=1350032550
http://tanakahisateru.hatenablog.jp/entry/2014/06/16/040047
http://tanakahisateru.hatenablog.jp/entry/2013/12/22/030817
ユーザーガイド
http://www.yiiframework.com/doc-2.0/guide-README.html
Yii の立ち位置
開発規模の想定
開発に必要な前提知識
Symfony との類似点
- 適切なオブジェクト指向を前提にしていてIDEフレンドリー
- 設定の項目がオブジェクトのプロパティと完全に対応する
- デバッグツールを標準装備
- アセットをPHPライブラリのパッケージ内で管理、Webにパブリッシュして使う (Assetic, Laravelのpublishも似てる)
- POSTをフォーム オブジェクト で受け取りバリデーションする設計 (Laravelは5で入るあれ)
Symfony に対する大きな違い
- SymfonyのようなフルDI設計を指向せず、グローバルに参照できるサービスロケーターを良しとする
- Requestが独立したインスタンスではなくアプリケーションインスタンスと1:1になっていて、リクエストごとにメモリが全破棄される挙動に最適化されている
- アノテーション等の高度な記述をさらに高度な高速化技法で上塗りするのではなく、遅くなるならメカニズムを捨て、あくまで「ありのままで速い」ことを指向
- クラスがPOJO(?フレームワークの知識と独立したドメインモデル)であることにこだわらない
- ORMのインスタンスがフォームを兼任できる (Struts型なのがRails風になる) = ActiveRecord
- DIされないと作れない制約感 (エンタープライズでは下請けが下手しないための安全策として有効) がない
- ちょっとしたカスタマイズならクロージャでさっと済ませられる
かつてSymfonyをやめてYii2-alphaを採用した理由
Symfonyでだいぶ作っていたものを、残り2ヶ月でYii2(当時alpha)に変更してイチから作りなおしたことがありました。
- Doctrineはパッシブレコード、ただの入れ物で小さなロジックを持てるArray。そこからはSQLを実行できる層が見えない。モデルの設計が別途必要だった。
- 自力で 自由に 設計する必要があるということは、引き継いだ人のOO設計力を問われる。真似する雛形がフレームワークから与えられない
- Twigで再利用可能な部品を書くのが大変すぎる
- サードパーティー製ライブラリがないと変わったことが何もできない。その選定の負担が大きい
要するにちゃんとしようとした場合の開発コストです。
他と異なる特徴
基本
- すべてのコンポーネントが一貫して、getter/setterやビヘイビアをサポートする基底クラスを継承している
- 名前によるプロパティ参照を活かして、実装がpublicフィールドなのかgetterなのかDBのカラムなのかを区別しない
- どこにでもイベントとビヘイビアが差し込める
- イベントフックを利用していろんなものができている
- すべてのコードがPHPの文法、Yiiの基底クラスのルールを知ればいいだけ => 学習コストの低さ
- ブラウザから使えるコード生成ツールが便利 = Gii
ビュー
- ビューがPHPスクリプトである積極的な理由 = ウィジェット
- フレームワークのサポート範囲にJavaScriptを含む (jQuery等フロント側で必要なライブラリを初期インストール/パッケージバージョン管理下に)
- 削除の確認などで積極的にJavaScriptのconfirm()を使うなど
- アセットバンドルによるCSS/JSの依存順序解決
- わざわざ
artisan xyz:publish
しなくても自動パブリッシュ
ページャーフレームワーク
- DataProvider (未評価のQueryのインスタンスにorderとlimitをかけて範囲内のデータを得るオブジェクト)
- ListView (DataProviderをビューでイテレーションするウィジェット)
- 任意のSearchForm (フィルタ条件を預かりDataProviderを生成)
Laravelとの類似点 (yii2)
- ActiveRecordはEloquentとかなり似ている。クエリのしかた、リレーションのやりかた。後発なのでよりちゃんとした設計になってる。
- 世界的な人気は同クラス (どっちが強いかというよりは、今のPHPにどういうニーズが高いか)
Laravelとの相違点
まずはこれ
※ LaravelのEloquentはコンクリートなModelとBuilderの2つでできていて、生SQL用のBuilderはメソッド体系が似た別の実装になっています。つまりこの図に対応させると関係線のないクラスが3つ登場するだけ。
で、結果
$firstAdminId = (new Query())->from('user') ->where(['admin' => true])->orderBy('create_time') ->select('id')->scalar();
というコードとほとんどの内部フローを共有してこれ
$firstAdmin = User::find()->where(['admin' => true])->orderBy('create_time')->one();
が動く。ActiveRecordでのイベント/ビヘイビアとバリデーションは、ComponentとModel(フォーム)から継承している。
で、MongoDBのActiveRecordもまったく同じ継承構造。なのでこのぐらいのクエリならほぼ名前空間を変えるだけで MongoDB に切り替えられる。それでも 〜Trait とModel継承の部分は実装を共有できてて半分ぐらいは完全に同じ動きをする。
- というように、全体的に一貫したオブジェクト指向設計がある。
- 内部設計の追跡しやすさ、カスタマイズしやすさは段違い。
- ライフサイクルイベントのあるヘビーウェイトなMVC構造に見えて、実はLaravelよりも速く、キャッシュ効率が高い(PHPに素直なことへの恩恵)
CakePHPとの類似点 (yii1,2)
- 適用するプロジェクト規模がわりと近い印象
- データベースの編集画面を最速で作れる系
CakePHPとの相違
- 1.1の頃からすでにActiveRecordがだいぶ先行している
- 規約ベースで動いてないので自由な設計がしやすい
- OOP的に素直で全体の一貫性がある(ビヘイビアのサポートはより基底なクラスにあってどこでも使える)
- イベントのおかげで無理せずファットコントローラを避けられる(経験上)
- メジャーバージョンを上げるときのポリシー = 下位互換なしでいい、旧バージョンを長くサポートすればいい
特徴的なコンセプト
- コードをかっこよくするために遅くなるような選択はしない (プログラマーの満足を満たすより、PHPで適切に動くコードはどうか、という意識)
- いまどきのPHP、真面目にやれば速さは落ちない、かっこよさは結果ついてくるもの
- フレームワーク固有な記述方法 (Yamlを使ったりアノテーションを使ったり裏ワザみたいなArray記法だったり) がないのでわかりやすく、自分独自のカスタマイズも容易
- とにかくものすごくアプリケーション開発者目線。個々の部品をどういう使い方しても動くという完全性より、現場目線で「あー自分だったらこれ変えられるようにしておくのになぁ」と思ったところは、だいたい開発者の自己責任で変更できるようにしてある。
Railsと比べて何が良いか ← この視点で見るのが適切
- もっともRailsと比較されることの多いPHPフレームワーク
- PHPランタイムで動くということ。これはでかい
- PhpStormのPHPは型(docコメント)のあるLL、動的すぎない安心感
- requireとか暗黙で生まれるオブジェクトより、名前空間をuseするクラスローダーのほうが好き
- ActiveRecordのフィールドはデフォルトでホワイトリスト (デフォルトでMassive Assignmentを防げる)
- TurboLinkやらCoffeeScriptやらSassやらHamlやら、フレームワークの仕事はそういうことじゃない感
- どこに何が入っているのかが単純明解で、自分独自なプロジェクト構成も作りやすい
- 理想 (生き字引きなRubyエキスパートが現場に常駐してくれるという仮定) より現実 (普通の人がそこそこ調べたらどうにか動くものが作れること) を重視
Yii2で採用された新技術など
1 Composer
いまどき当たり前な Composer によるプロジェクト作成。
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
yiisoft/yii2-app-basic は Packagist の登録名。公開されていればどんなテンプレートからでも生成可能。
ってだけならよくある話で、アプリケーション構造はPSR-4に準拠していて名前空間で浅いディレクトリから任意のクラスをオートロード。
2 composer-asset-plugin
https://github.com/francoispluchino/composer-asset-plugin
BowerやNPMからパッケージをインストールできるComposer拡張
インストール
composer global require "fxp/composer-asset-plugin:1.0.0-beta4"
vendorの下にダウンロードされ、Yiiのアセットバンドルの機能で動的にweb公開場所にパブリッシュされます。
3 Twitter Bootstrap
Bootstrap3 拡張が最初から組み込み済み。使うか使わないかは名前空間で使い分け。
yii\widgets\*
← → yii\bootstrap\*
Bootstrapを使いたくなければ名前空間を切り替える。(Bootstrap特有のものを使っていない箇所、ActiveFormなど) これでウィジェットが吐くHTMLにbootstrapなクラスが付いたり付かなかったり。
4 SwiftMailer
SwiftMailerもBootstrapのように使い分け可能。デフォルトは組み込み済み。
Transport実装を切り替えて、SMTPなのをAmazon SESに対応したりsendmailにしたりと、ブリッジがSwiftMailerの便利さを活かすインターフェース設計になっている。
useFileTransport (bool型)という開発用のマスタースイッチが便利。
メールテンプレートのレンダラーがはじめからHTMLメールを想定している。
5 Markdown
https://github.com/cebe/markdown
1.1のときの PHPMarkdownExtra に代わって、これが採用された。すでにコアに入ってる。
- みんなおなじみのGFM (GitHub方言) モードあり
- シンタックスごとにモジュールを分割して書かれている
- Traitとして分けられたモジュールを必要なぶん結合し、自分のカスタムパーサーを作ることができる
- Traitなのでオブジェクト間のメッセージングがなく速度が出る
ベンチマーク https://github.com/kzykhys/Markbench#readme
- parsedownに匹敵する速度 (ただしparsedownは拡張性なさすぎてPHPMarkdownかというほど)
- ciconaに匹敵する拡張性 (ただしciconaは凝集度に対して誠実すぎ、もっと実行速度に最適化していいと思う)
ちなみにYiiには以前から HtmlPurifier が初期インストール済みで、デフォルトで適度に Markdown をサニタイズします。
6 最新のPHP関数とかセキュリティ
- 日時や通過などの国際化がintlベース(polyfillあり)に
- password_hash() / password_verify() (5.5〜) 推奨
- なくても互換実装あり (なんも知らんでもセキュア)
- ちなみにプロジェクト生成時にクッキー暗号化ソルトを自動生成 (なんも知らんでもセキュア)
- ちなみに何も書かなくてもフォームにCSRF対策が効いていて、わざわざ解除しないかぎり有効 (なんも知らんでもセキュア)
7 Codeception
BDD風のAcceptanceテスト(Webサーバの外からテスト)とFunctionalテスト(フレームワークのリクエスト全体をテスト)
アプリケーションの実装はだいたいが Yii::$app
が指すサービスロケーターに依存するので、だったらいっそリクエストまるごとテストする高級なテスティングフレームワークをサポートしよう。
まあSeleniumにもできるけど、デフォルトのPhpBrowserなら、PHPだけあればHTTPをサーバの外からテストできるよ。
もちろんDbUnitっぽいことが可能な単体テストもあるし、任意にPHPUnitを使ってもOK
8 HATEOASなREST
RESTfulなCRUDに特化したコントローラあり
デフォルトでActiveRecord(正確にはModel)への直接読み書きが実装済みのものあり
で、なんとこれまでSpring(Java)とBEAR.Sunday関連でしか聞いたことのなかったHATEOASをサポート http://en.wikipedia.org/wiki/HATEOAS#Implementations
レスポンスに次のアクションの選択肢リンクや現在のページャー状態などを含んで返すやつ。PHPはREST-APIに特化して、フロントはアプリやピュアなAjaxで作ってもいい。
9 その他今っぽいライブラリ
フレームワークと同時並行開発された豊富な拡張ライブラリ。ほぼ標準機能と言ってもいいです。プロジェクトによっては使わない場合もあるので composer.json
に書いていないけど。
- jQuery UI (DatePickerとか便利)
- Imagine 使いやすいGD
- Faker フィクスチャ用のでたらめなデータを自動生成
- MongoDBのActiveRecord (なんと基底が共通)
- 全文検索エンジン Elasticsearch / Sphinx
- Redis キャッシュ/セッション (ファイルベースのものと置き換えて設定するだけでOK)
- OAuthクライアントフレームワーク (Facebook, GitHub, Google, Linkedin, Twitter, ...など初期実装済み)
- 使いたい人はSmartyとTwigのレンダラーもあるよ(ウィジェット系使わないなら)
アルファ版以前から Elasticsearch の実装があるあたり、最新技術に貪欲でいいですね。
OAuthのフレームワークがあるおかげで設計迷わなくて助かりました。これは時代的にとても現実的。
10 コミュニティのライブラリ
などなど、Packagistでyii2で検索。正式リリース1ヶ月で66ページある。fuelやfuelphpで試すと1桁なので...
新しいサービスとのブリッジやウィジェットなど周辺を補助するものがやたら多い。YiiがCSS/JSを含んでのフレームワークであるというのが効いている。
逆に開発手法を変えるようなものは少ない。時期がまだ熟していないからか、それとも、だいたい yiisoft/*
以下でカバーできてるからか。
(Packagistでヒット数が多すぎるフレームワークは、それはそれで、「え、それサードパーティー製なの?!」ってなることはある)
デモに使ったプロジェクト
(追記)
Dropbox - phpkansai-19-yii2-basic.zip
.git 込みです。vendor が入ってないので、 composer install
でどうぞ。
JavaScriptはいかにしてprototypeを捨てクラスベース継承を得るのか
きっかけは、prototype
と constructor
と __proto__
の関係を再確認していたときでした。JavaScriptはこうだけど、これって、AltJSな言語の継承はどうなってるんだろうと思って試したくなりました。
ちょっと気持ち的に、なんだか宗教に入ったみたいに俺は JavaScript がわかったって声高に言う人、だいたいみんな、プロトタイプチェーンによる移譲がクラスベースの継承に束縛されていた思考のブレイクスルーなんだぜ、みたいに言うんだけど、いったいそれがどれほど素晴らしいものなんだろうと考えてしまい...
もしプロトタイプチェーンがそんなに素晴らしいんなら、npm にあるほとんどのライブラリがチェーンを活かして作られてない理由が説明できない。もしかしたら、仕組みがいくら面白くても、実際のメンタルモデルにフィットせず、実は使い物にならないんじゃないか ---- と疑ってみるところから考えなおしてみました。
TypeScript で継承したらこうなりました。
class A { public p:number; public q:number; constructor(n:number) { this.p = n; this.q = n * 10; } } class B extends A { constructor(n:number) { super(n); this.p = n * 2; // this.q = n * 20; } } var b = new B(1); console.log(b.p, b.q);
↓
var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); }; var A = (function () { function A(n) { this.p = n; this.q = n * 10; } return A; })(); var B = (function (_super) { __extends(B, _super); function B(n) { _super.call(this, n); this.p = n * 2; // this.q = n * 20; } return B; })(A); var b = new B(1); console.log(b.p, b.q);
なんだこの __extends
って。TypeScript は元のコードとわりと対応する JavaScript を吐くってことになってなかったっけ? なんで元のコードと対応しないこんな関数を作らなきゃいけないんだろう。
CoffeeScript ではどうかな?
class A constructor: (n)-> @p = n @q = n * 10 class B extends A constructor: (n)-> super(n) @p = n * 2 # @q = n * 20 b = new B(1); console.log b.p, b.q
↓
var A, B, b, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; A = (function() { function A(n) { this.p = n; this.q = n * 10; } return A; })(); B = (function(_super) { __extends(B, _super); function B(n) { B.__super__.constructor.call(this, n); this.p = n * 2; } return B; })(A); b = new B(1); console.log(b.p, b.q);
やっぱり同じようなのができた。親のクラスを参照する方法が動的か静的か違うだけで、ほとんど同じことやってる。
ちょっとまって、JavaScript のプロトタイプチェーンの教科書でこの、n
という初期化パラメータを持つオブジェクトの継承はどういうふうに実装したっけ??
function A(n) { this.p = n; this.q = n * 10; } function B(n) { this.p = n * 2; // this.q = n * 20; } B.prototype = new A(0); // とりあえずオブジェクト要る、けどこれじゃダメだ var b = new B(1); console.log(b.p, b.q); console.log(b.constructor);
おや? 伝統的な JavaScript の教科書的なプロトタイプチェーンだと、new A(0);
のところがどうしてもうまく書けないぞ。あとで (new B(1)
のときに) 初期化パラメータの値を決めたいのに、最初に何か仮に決めておかないといけない?? で、それだと b.q
の値は new B(1)
によって決定されるものと食い違う??
もっと不自然なのは、function A(n) { ... }
がコールされるタイミング。B.prototype = ...;
の時点、つまり何の実体も作られずただ定義だけしたときもうすでに、関数が呼ばれちゃってる。もし親になる A
がタイムスタンプ取得やリソースのロックみたいな責務を持っていたら...
と、ここでプロトタイプ信者になった人がいうのは、「クラスベースとは違うのだよクラスベースとは」ってことなんですが、ちょっと落ち着いて、考え方が間違っているっていう前に、TypeScript と CoffeeScript がやっていることは何なのかを、なるべく平易な JavaScript に書き換えて考えてみますね。
function A(n) { this.p = n; this.q = n * 10; } function B(n) { A.call(this, n); // ここで親の初期化プロセスを呼ぶ this.p = n * 2; // this.q = n * 20; } (function() { var tmp = function() { // プロトタイプはパラメータを持ってはいけない this.constructor = B; // __proto__の1段階目にconstructorプロパティがないJS謎仕様への対策 }; // hasOwnProperty はちょい割愛 tmp.prototype = A.prototype; // BのプロトタイプtmpはAに似た別のダミーオブジェクト B.prototype = new tmp(); })(); var b = new B(1); console.log(b.p, b.q);
- B のプロトタイプとして new されるのは A ではない
- それは A に似た別のダミーオブジェクト
- プロトタイプのコンストラクタはパラメータを持たない (
new A(0);
の件) - 親の初期化プロセスを初期化関数のように呼ぶ必要がある
__proto__
の1段階目にconstructorプロパティがないJS謎仕様への対策 ←ひどい
JavaScript でクラスベース継承で得られる恩恵を享受しようと思ったら、ユーザー側でこれだけのコードを書く必要があるんですかね? クラスベースのOOP言語でプロトタイプチェーンの真似をしたいときは、面倒だけどいちいちターゲットに移譲すれば何とかなるというシンプルさだというのに対して、あまりにフェアじゃないんじゃないですかこれ。
うーん。
そろそろプロトタイプチェーンの正義に準じて考えてみましょうか。プロトタイプチェーンは、例えていえばレストランで、無愛想な店長=プロトタイプとのやりとりしかできなかったところに、愛想のいい店員さんが入ってくれて、代わりにもっと愛嬌のある接客をしたり、お客さんのいろんな要望に答えたりしてくれる、みたいなやつですね。その実体は is-a
関係じゃなくてコンポジションによる拡張。なんでも継承で拡張しない、コンポジションを好むべきというプラクティスに合致している気がします。
気がします...
ところが JavaScript の初期設計には Java の圧力があったことを忘れちゃいけません。new Hoge();
だのコンストラクタだの、そもそもそれらは、本質的に必要なんでしょうか? なにか政治的な理由が、言語としての設計の完全性より優先したって可能性はないですか?
で、プロトタイプチェーンやるならこっちね、って最近 ECMA Script 5 で増えた、ナウなヤングに推奨な感じのやつがこれですよ。
Object.create - JavaScript | MDN
Object.create 概要 指定したプロトタイプオブジェクトおよびプロパティを持つ、新たなオブジェクトを生成します。
function Constructor(){} o = new Constructor(); // これは以下と同じです: o = Object.create(Constructor.prototype); // もちろん、実際にコンストラクタ関数の初期化コードがある場合でも、Object.create はそれを反映できません
Polyfill
if (!Object.create) { Object.create = function (o) { if (arguments.length > 1) { throw new Error('Object.create implementation only accepts the first parameter.'); } function F() {} F.prototype = o; return new F(); }; }
この代替コードの中でやってることは、AltJS系がクラスベース継承を再現したものをJSに書き下したコードにずいぶん近いですね。コンストラクタは何でもいい、要するにターゲットオブジェクトに変更安全ラッパーをかぶせた何らかのオブジェクトが作れればいいんだ。
...やっぱりね。ユーザーコードに「コンストラクタ」なんて存在、そもそも必要なかったんじゃん。ECMA 曰く、形を定義してから実体を作っていく必要なんてない、と。いきなり実体を持つオブジェクトが存在して、ユーザーはその実体に皮をかぶせたオブジェクトを、好きなときに自由に作ってそれ(=皮)をデコレーションできるよ、コンストラクタ関数の定義なんて要らないよ、というやりかたでOKだそうですよ。Java に言わされてただけなんですっ new
も constructor
もなかったことにしてください、と...?
ここ、F.prototype = o;
の o
は Constructor.prototype
ですね。クラスベース再現のほうでは、tmp.prototype = A.prototype;
に対応しますね。オブジェクト直接ではなく、あくまで、型があって、その型にプロトタイプオブジェクトが存在するという考え。
プロトタイプチェーンの信奉者は、リアルな値(実際に構造がどうなってるか予測不能)が先にあって、さてこれをどうしよう、という発想なんだけど、これどうなんでしょ? 制限された型(構造は想定の範囲内)が先にあって、それらの関係という抽象概念に対して値を投入する、という発想のほうが、ソフトウェア設計として健全なアイデアなんじゃないかと、自分なら考えますけどね...
たしかに、チェーンの先の値や関数であっても、自分が持っているプロパティのように this.foo
とするだけで読み取りアクセスできるのは楽ですが、さて、読み取りアクセスしたもを書き込みアクセス this.foo *= 2;
などすると、別の実体ができてしまいますよね。で、またそれを読むと、こんどはプロトタイプのほうにアクセスしない。えーと、これって本当に移譲って言える?
いっぽう、明示的な移譲には何の問題もなかった。さほど面倒でもないし、意図しない操作はターゲットに届かない。
class Operator constructor: (@target)-> exec: -> @target.foo *= 2 data = { foo: 1, bar: 10 } op = new Operator data op.exec() console.log data.foo # =>2
えーと、もしかして JavaScript のプロトタイプチェーンは、オブジェクト間の移譲もマトモに機能していない?
イエス!
ユーザーレベルで使えるプロトタイプチェーンとは、コピーコストをケチったクローンという用途を除いて、あらかじめ定義されたメソッドのセットを引き継ぐしかできない、単一選択のミックスインでしかないのであーる。
あれ...? んーっと、 _.extend(targetObject, myMethodSet)
っと...
// Extend a given object with all the properties in passed-in object(s). _.extend = function(obj) { if (!_.isObject(obj)) return obj; _.each(slice.call(arguments, 1), function(source) { for (var prop in source) { obj[prop] = source[prop]; } }); return obj; };
どう考えてもこっちのほうがいいですね。何個でも、何回でもいけるもん。そりゃあ Underscore も lodash も大人気なわけだ。
ユーザーの本音「あんなややこしいもん使うぐらいなら、多段な継承なんかなくてもいいよ。他に使える道具は十分揃ってるからなくても我慢できる。使えたとしても、あんなもん手出したら逆に生産性が落ちる」
かくして、JavaScript はクソの役にも立たないプロトタイプチェーンを封印し、すべて関数と単一階層オブジェクトで語れる世界で予定調和を迎えましたとさ。
いっぽうで、この隠されたプロトタイプの秘術を利用してコンパイラを作り、あろうことか邪教であるクラスベースオブジェクト指向を JavaScript 内に再現しようとするのが AltJS、という世界の流れなわけです。
いやー、そう考えるしかないでしょこれどう考えても。npm 見ても、AltJS 言語見ても。客観的に。(自分だってそんな結末は期待してなかったけど)
感想
プロトタイプチェーンという「しくみ」の魅力にハマることなく、現実世界でメンタルモデルにフィットし、かつ、実際に使える技術とは何か、ということを見失ってはいけないと思いました。あと、やっぱり JavaScript は Java の政治圧力を受けてだましだましリリースされた、ブラウザマクロのための中途半端なデザインの言語なのだというのは、いまだに重要な視点なんだなと思い出し直しました。
ウィーン ウィーン マサカリ防壁展開中...
保守性・管理性が劇的に上がるScalaのスマートなコードの書き方(ネタ)
最初に断っておくと、Scalaは初心者だからマサカリなんて怖くないもん。というわけで、ScalaになるとPHPではご法度だったいろいろが、どういうふうに解釈できるか考えてみました。
中カッコを省略する
def fizzbuzz(numbers:Seq[Int]) = { numbers.map((n) => { if (n % 15 == 0) { "FizzBuzz" } else if (n % 3 == 0) { "Fizz" } else if (n % 5 == 0) { "Buzz" } else { Integer.toString(n) } }) } println(fizzbuzz(1 to 15))
こうやる
def fizzbuzz(numbers:Seq[Int]) = numbers.map((n) => if (n % 15 == 0) "FizzBuzz" else if (n % 3 == 0) "Fizz" else if (n % 5 == 0) "Buzz" else Integer.toString(n) ) println(fizzbuzz(1 to 15))
中カッコを外すことによって、if-else
のネストが1本の式で、その中身も単一の式で、関数が単独の if
式であるということがわかるようになります。
中カッコを外してコンパイルエラーが出るようなコード、つまり何かをやるとき2つ以上のステートメントを必要とするコードは、関数型言語的でない状態を持つ可能性があります。状態がなければテストも簡単で、とても保守性アップにつながりますね。
デフォルト引数を使う
def fn(a:Int, b:Int=0) = a + b fn(1)
便利ですね。ただまあ、これでもいいですが、せっかく型があるなら、個人的にはオーバーロードのほうが嬉しいです。jQueryの引数みたいに真ん中のを省略できる、とかなっちゃっても、型をちゃんと付けてオーバーロードしてれば平気な気がします。
def fn(a:Int, b:Int) = a + b def fn(a:Int) = a // fn(a, 0) fn(1)
グローバル変数
みんな大好きグローバル変数。
object TheEarth { var population = 600000000 } TheEarth.population += 100000000 println(s"地球人口はいまや${TheEarth.population}人に")
Scalaのコンパニオンオブジェクトはシングルトンなので、入れ物の時点で完全な実体を持ったグローバル変数なところがJavaのstatic
より優れてるし、PHPみたいにいちいち関数の中で宣言しなくても import
で見えるようになります。...こわ
構造化されてない裸の変数だから悪い? 構造化されてようがされてなかろうが、グローバルなものが見えることが悪い? ちがいますね。状態の変化がテストでフォーカスしているインスタンスに閉じないことが悪いんですよね。見えるのはかまわないんですよ。
つまりけっきょく、 できるだけ var
はやめろ とくにグローバル変数、ってことですよ。犯人は var
ってこと。スコープの広さより先に、状態が変化することが問題。逆に言えば、global
でもそれは状態を書き換えない前提なら、そこまで悪くはない。
これがもし val
だったら、「式で表現された定数」ってことで、すごくいいですね。グローバル変数なのに。
文字列内に変数を展開する
あ、先やってもうた...
println(s"地球人口はいまや${TheEarth.population}人に")
展開するかしないか s"..."
で明示的に分けられるのは、LL系の言語にあまりないメリットですね。
自分を呼ぶ関数を使う
再帰アツいですね。階乗を計算して 5!
求めてみます。
def factorial(n:Int):Int = if (n <= 1) 1 else factorial(n - 1) * n println(factorial(5))
前までの階乗に今の数をかける。5! = 4! * 5
ですね。
でもこれ末尾再帰してないのでスタック使っちゃいます。なんとかしてみた。
def factorial(n:Int):Int = { def f(x: Int, s:Int): Int = if (x <= 1) x * s else f(x - 1, x * s) f(n, 1) }
これなら末尾再帰しますよ。IntelliJ IDEA ならぐるぐるマークも違うのが出てわかりやすいですね。
IntelliJ IDEAが、Scalaでメソッドを再帰にした場合に、よこにぐるぐるなマーク表示するらしいのだけど、末尾再帰最適化される場合とされない場合で「ぐるぐる度合い」が違うと話題に pic.twitter.com/YRnVd5u37t
— Kenji Yoshida (@xuwei_k) 2014, 7月 18
すごいねー...
... えーと
... ... えーと
def factorial(n:Int):Int = (1 to n).reduce((s, n)=> s * n)
なんかもんくあっか。必要以上に再帰使わなくても、畳み込の方がいいんじゃないですかね。これ末尾再帰と同じ概念の別表現なわけで、ユーザーが意識するスコープが小さくて済む。このへんのメソッドのボキャブラリーを増やすほうが、保守性高いコードになると思いますよ。
ちなみにこれ、IntelliJ 先生がこう書いたほうがいいんじゃないかと警告してくれました。
def factorial(n:Int):Int = (1 to n).product
IntelliJ 先生の添削おそるべし。
結論
中括弧なしはダメ、グローバル変数はダメ、なぜって教科書に書いてあったもん、っていうような認識で他人を批判しちゃうのは、ちょっと踏みとどまったほうがいいかも、と思いました。
で、アルゴリズムを組めることがプログラミング技術なんじゃなくて、その言語の一般的なボキャブラリーをどれだけ適切に使えるかが、保守できるプログラムを書く技術なんじゃなかなと思った次第です。なので、やっぱりその、経験すべき通過点を十分通ってないのに人様に講釈たれるのは、違うなーと...
で、まあ、自分も経験はぜんぜん足りないので、それ補うためにも、保守性の高いScalaを書きたければ IntelliJ IDEA を使うのが一番いいです。
あぁ、それと、保守性の高いPHPを書きたいんなら、同じ理由で PhpStorm をすぐに買えばいいと思いますね。