はてなキーワード: ORACLEとは
JJUG CCCというイベントで、「会場が狭い」という感想があった
それに対し、イベント関係者から感想に対する不満や、参加者を見下すような発言があった
なので、思うことを書いてみる。
1年の半分以上がデスマーチ。
仕事以外にプログラミングをしたり、技術についての情報収集する人が少ない。
(PCを家に持たない人もかなりいるのでは?)
セミナーで話す講師は報酬(お金)をもらっていて、技術力がない人でも理解できる説明をする。
結論を最初に言え。細かい説明とかはいらない。「今一番売れてるフレームワーク」を教えろ)
そもそも、JJUG=Java=Oracle関係者と思い込んでる人も少なくない。
特にナイトセミナーの会場でOracleが使われることが多いので、Oracleから金をもらって運営しているという信じている人もいるだろう。
そういう人たちにとって、企業が行うイベントで会場に不満が出ることは落ち度でしかない。
コミュニティ主催のイベントというみんなで作り上げるものなのに、ベンダーに招待された「お客様」として参加してしまっているわけである。
日本でJavaユーザーが一番多い層(SIer関係者)と乖離してきているのでは?
今までは最新のJava SEとか「辛うじて」自分たちでも手の届きそうな話だったのが、マイクロサービス・クラウドとか無縁な話が多くなってきている気もする。
「きちんとしたエンタープライズ的なセミナー」を期待している人に対して、コミュニティ活動を理解してもらうのは難しい。
Javaのエンタープライズ色が強いところも、コミュニティ活動と結びつきにくいのかもしれない。
ただ、それでもコミュニティを理解してない人たちに対して、敵愾心を煽るような発言は必要だったのか?
この規模のイベントを無料で参加できるようにするための、運営の労力が大変なのは理解できる。
ただ、運営側がだれでも見れるSNSでつぶやくとかはどうなのか?
JJUGのイベントでは聞きたいセッションについて悩むというぜいたくはない。
人気あるセッションは埋まるのとにかく早い。
前日までに部屋を決めて置き、目的の部屋の席にさっさと荷物おいてからトイレや買い出しに行くのだ。
初めてJJUG CCCに参加した後輩が「聞きたいセッションがいっぱいで残念だった、もうちょっと広い会場でできればいいのに」と言っていたところに、「運営側の苦労も知らないで文句言うな」という意見が流れてきてむしゃくしゃして書いた。
なので、あまりまとまってない。
Javaはユーザーも多く、エンプラな人の比率も高めで、コミュニティを理解せず心無いことを言う人や理解すらしようとしない人も多いと思う。
ただ、彼らをディスってもなんの見返りもないし、そもそも彼らの耳には入らない。
いい記事なのだが、いくつか反論や補足が必要だと思ったので書く。
このGPLのコンパイラとはGNU bisonやGCC(GNU Compiler Collection)について指しているのがほぼ明確なのでそれらについて書く。
確かに著作権法を元にしたライセンスは、ソフトウェアの出力結果に対してソフトウェアの著作権ライセンスが影響しないと解釈するのが妥当であるというのは正しい。
ただしこれは"著作権ライセンス"に限った話である、つまり著作権ライセンスでは不可能な制約がEULAなどでは課すことが可能であるということを意味する。
詳しくはGNUの書いた記事の"契約を元にしたライセンス"という項を読むと良い。以下に引用する。
https://www.gnu.org/philosophy/free-sw.html
ほとんどの自由ソフトウェアのライセンスは、著作権を元にしています。そして著作権によって課することができる要求には制限があります。もし、著作権を元にしたライセンスが、上記に記した自由を尊重するならば、まったく予期しない他の種類の問題があることはありそうもないでしょう(予期しないことはまま起こりますが)。しかし、ある自由ソフトウェアのライセンスは、契約を元にするもので、契約はもっと広範な制限を課することが可能です。これは、そのようなライセンスが、容認できないほど制限が強く、不自由でありうる、いくつもの形態がありうることを意味します。
わたしたちは、起こりうるすべてのことをあげることはできないでしょう。もし、契約を元としたライセンスが利用者を(著作権を元としたライセンスでは無理な形で)異常に制限するならば、そして、それがここで正当だと述べられていないのならば、それについて検討しないといけないでしょうし、そのライセンスは、不自由であると結論づけるかもしれません。
また元の記事の著者はGCCやbisonがGNU GPLのような強いコピーレフトで保護されたソフトウェアでも、それによって作成された著作物はGPLにならない(つまりコンパイラやパーサーのライセンスを継承しない)ことを根拠に考察しているようだが、実はbisonやGCCのGPLにはライセンスに対する例外が付属していることを考慮すべきである。
GCCやbisonの著作権保持者であるFree Software Foundationは著作権法の話をするとき、たいていアメリカ合衆国を想定しているがこれらの自由ソフトウェアが広く使われるあたって、著作権法とそれを元にしたライセンスが異なった解釈をされることがありうることをおそらく危惧している、そのため出力に対してソフトウェアのライセンスが影響しないことを確実にするためにこれらの例外を規定しているのではないか。
この二つの理由から、元記事の議論は世界中に対して広く配布するFLOSSディストリビューションでは(非常に残念ながら)鵜呑みに出来ないと私は考える。
加えて言えば、たとえフェアユースの規定が全世界的に利用できて、営利目的でなければ利用できたとしても、
自由.0: どんな目的に対しても、プログラムを望むままに実行する自由
(i.e. オープンソースの定義 6項 利用する分野に対する差別の禁止)
がある限り、そのような制限をディストリビューションは受け入れられないだろう。
またOracle vs GoogleのJavaのAPI訴訟はケースとしてはかなり特例であり、
一般に広く適用すればlibcすら当てはまるのではないかと私は思っている、
これを根拠にしてよいのならばそもそもコンピューター業界がひっくりかえるのではないか。
少なくともUbuntuのようなプロジェクトにおいて、私は断固反対である。
というのは現状ほぼすべてのWeb翻訳(例外があれば教えて欲しい)はプロプライエタリないし、それと同じ結果をもたらすSaaSSだからである。
Webブラウザを介して使う翻訳サービスはSaaSSの代表例であり、ユーザーがコンピューターの計算のコントロールを
持つべきであるという自由ソフトウェアの思想と明らかに相容れないものである。
このようなサービスを利用することの弊害として、(例えば)Google翻訳に翻訳処理の計算を依存することにより、ユーザーの入力をGoogleが常に把握することが挙げられます。
もちろんこれはあまり良いことではない。
多くのFLOSSシステムディストリビューションは自由なソフトウェアを主に入れるというガイドラインを持っている。
アーカイブのごく一部にnon-free(Ubuntuならrestricted/multiverse)なソフトウェアがあるが、
これは事実上妥協の産物であり、排除しても大した問題がないならば配布から除外することに多くのディストリビューション関係者は異論を挟まないだろう。
また例えばDebianはあるソフトウェアがDFSG(Debian フリーソフトウェアガイドライン)に適合するフリーソフトウェアであったとしても、それがガイドラインに適合しない著作物に依存する場合、contribというセクションに閉じ込めており、それは公式のシステムの一部ではないとしている。(建前ではcontrib/non-freeセクションはユーザー向けの付加サービスとされる)
Ubuntuコミュニティで新規に作られた著作物がコミュニティの哲学に反する物に依存するというのは、かなり致命的である。
たとえ奇跡が起こり、例外的にGoogle翻訳や一部のプロ用翻訳ツールがBSDライセンス(Launchpad上での翻訳用ライセンス)での出力を許したとしても決して褒められたものではない。
Ubuntuのbug#1に"Ubuntuソフトウェアは自由である。常にそうであったし、今後も常にそうである。自由ソフトウェアは万人に望むままの方法で使い、望むままの人間と共有できる自由を与える。この自由は多大な利点である。"とプロジェクト創始者であるマーク・シャトルワースが書いていることをよく考えるべきである。
https://bugs.launchpad.net/ubuntu/+bug/1
この反論を読んだ読者の中にはあまりにGNUプロジェクト寄りに思想が傾いていると思う者がいるかもしれないが、
いわゆる"Linuxディストリビューション"の中には数多くの重要なGNUソフトウェアがシステムの根幹をなす形で入り込んでおり(例えばGCC,bash,glibc etc...)
またUbuntuの派生元となったDebianの成立経緯にはやはりFSFが関わっている。
さらに言えば、システムの保守を手伝う人の中にはシステムがフリーだからボランティアで頑張っているという人もいると思う。(ほとんどではないかもしれない)
のでUbuntu周りの話に限ってはこういった観点で見てもよいと思ったので書いた。
免責: これは法律の専門家によるアドバイスではありません。この情報にしたがって行動した結果に対して責任を負うことはできません。
「Web翻訳の結果をオープンソースソフトウェア(OSS)の翻訳に突っ込んではいけませんという話」
http://blog.goo.ne.jp/ikunya/e/37e5a52e10ab26fcbd4f7ff867e9eace
この話では、「もちろん、利用規約的に問題なければWeb翻訳の結果をOSSの翻訳に突っ込んでも*ライセンス的には*問題ありません。」という追記がされてます。
ですが、プログラマの間で単にWeb翻訳をOSSに使ってはいけないんだという認識が広まってるように見えます。個人的には、この認識が広まってしまうのはいやだなと感じたのでこの文を書いています。
どういう話かというと、自分が個人で開発しているオープンソースソフトウェア(OSS)のドキュメントの日英訳をするにあたってGoogle翻訳を利用するか検討して権利まわりの情報をしらべた結果、これは白に近いグレーだろうという判断したので下訳に使ったという話です。(日英両方についてのドキュメント自体も、オープンソースのライセンスで公開しています)
念のため言っておきますが、これは元記事で問題になっている人を擁護するようなものではありません。翻訳コミュニティの人たちが自分たちのものにグレーなものを入れたくないと思うのは当然でしょうし、権利問題以外にも翻訳クオリティやその他の問題行動の話もあります。
コミュニティの思想にそぐわない人が、そのコミュニティの中で作業していくのは難しいでしょう。
もとの記事のとおり、Excite翻訳の利用規約には私的利用を超えた利用についての禁止が明記されています。こういった明確に禁止されているものについての話はここではしません。
ここでは、Google翻訳に焦点を当てた話をします。Google翻訳の利用規約はどうか?というと、Googleの利用規約については翻訳結果の利用についての記載がありません。
https://www.google.com/intl/ja/policies/terms/
記載がないということは、使用してよいのか?使用してはいけないのか?いったいどちらなのでしょうか?
機械翻訳の権利問題と似た構造の話に、GPL(GNU一般公衆ライセンス)で許諾されたコンパイラによってコンパイルした結果の利用があります。
GPLの本文には、GPLのプログラムの出力結果自体にGPLのものを含む場合にのみその出力結果にGPLが適用されることについての記述がありますが、GPLのものを含まない出力結果についてどういう許諾がされているかの記載はありません。
これについては、コンパイラによるコンパイル結果に対して、コンパイラの著作者はなんら権利を持たないと考えるのが一般的です。
https://www.gnu.org/licenses/gpl-faq.ja.html#GPLOutput
著作権法は人々があなたのプログラムとかれらのデータを使って作った出力結果の利用に関して、あなたに何の発言権も与えていません。
コンパイラと機械翻訳ツールとの違いが、対象が人工の言語であるか、自然言語かので違いしかないと考えるならば、Google翻訳の結果をOSSに利用することも問題ないということになります。
ウィキメディア財団の法務チームは、Google翻訳した文書のウィキペディア内での利用についての見解を公開しています。
https://meta.wikimedia.org/wiki/Wikilegal/Copyright_for_Google_Translations
これはアメリカの法律に基づく話ですが、CC-BY-SA 3.0やそれに類似するライセンスのコンテンツをGoogle翻訳で翻訳してウィキペディアで使用してもGoogleの著作権を侵害する可能性はとても低い(very unlikely)と結論づけています。
要点をまとめると以下の通りです。
ウィキメディア財団の見解には含まれていませんがアメリカの法律でいえば、さらにもう一つ「フェアユース」にあたるのではという話があります。これはGoogle自体がよく知っている話かもしれません。
これはAndroidのAPIにJavaのAPIが流用されていることについて、OracleがGoogleを訴訟したものです。
これについて、Java APIについての著作権が認められたものの、Androidでの使用は「フェアユース」に該当するとGoogleは主張し、カリフォルニア州サンフランシスコの地裁では著作権使用料支払いの対象にはならないという判決が下っています。
「フェアユース」というのは、アメリカの著作権法上の概念で、以下の4要素を判断指針として考えて公正な利用と認められれば、著作権の侵害とはしないと考えるものです。
ということになり、4つの要素どれをとっても、フェアユースであると認めることに対して有利に働きます。これは、AndroidのJava APIの流用と比べても、さらにフェアな利用であるように見えます。
(ちなみにGoogleの利用規約には、「カリフォルニア州の抵触法を除き、本規約または本サービスに起因するまたは関連するいかなる紛争に関しても、アメリカ合衆国カリフォルニア州の法律が適用されます。」と書かれています)
著作権情報センターのサイトに、 コンピュータ創作物についての文化庁の報告書が記載されています。
http://www.cric.or.jp/db/report/h5_11_2/h5_11_2_main.html
この報告書は、機械翻訳のユーザーが機械翻訳システムを使用するために行う原文の編集や出力の編集が創作的寄与となりうることを認めている一方で、機械翻訳の開発者が翻訳物の著作者になるということについては否定的です。
なお、原文解析等のプログラムの作成者及び汎用的な辞書データベースの作成者は、一般的に翻訳物の作成の精度、正確度等を高めることに寄与することとなるが、特定の翻訳物の作成自体にかかわっているわけではないので、その著作者とはなり得ないと考えられる。
これは平成5年とかなり昔に書かれた報告書であり、それから機械翻訳の技術は大幅に進歩しましたが、創造的個性の表現を目指して作られているもので無い機械翻訳であれば、やはり翻訳の結果の利用について問題がないようにみえます。
これにしたがえば、単純に文章をそのまま機械翻訳に投げ入れた出力結果は、原文の著作者の著作物。機械翻訳に投げ入れる前や後に十分な編集をしていれば、加えてその編集した人間の二次著作物になるということになりそうです。
これまで、どうしてGoogle翻訳の結果をOSSに使うことが白に近いと言っているかを説明してきました。
では、どうしてグレーなのかというと、新しい種類の権利問題なので判例がないからです。実際に訴えられたら負けました、ということもまったくありえない話ではないでしょう。
だいたい、ここまでが話したいことの半分です。ここからはグレーなものの良し悪しの話をします。
著作権などの権利問題についてグレーなことをやっているOSSというのはそれほど珍しいわけではありません。
有名なところでいうと、Monoが思いつきます。AndroidのDalvikがJavaのAPIを真似したものであるのと同じように、MonoはMicrosoftの.NETフレームワークを真似しています。つまり、Monoについても訴訟リスクはあっただろうということです。
しかし、OracleとGoogleが対立したのとは対照的な道をMonoはたどります。
2016年、Monoのプロジェクトを運営していたXamarin社は、そのMicrosoft自身によって買収されました。権利的にグレーだったMonoがMicrosoft公認のプロジェクトになったというわけです。
権利的にグレーだからといって、プロジェクトとして失敗に終わるわけではありません。
すこし元の記事に話をもどします。冒頭にも書いた通り、Ubuntuの日本語化プロジェクトに対してWeb翻訳の結果を突っ込むという行為は、批判されるべきだと思っています。
まずは質の問題です。現在のGoogle翻訳などは、UIの翻訳に向いていません。UIのほとんどは、意味合いが文脈に依存する単語や短文です。UIの翻訳は、実際にその機能を動かしながら、動作にあった訳語を割り当てていくべきです。
Google翻訳などを使って一括で、訳語を割り当てても良いUIの翻訳はできません。
( UIにとっての良い訳については、元記事のいくやさんがとても良い話を書いています: https://github.com/ikunya/howtotranslatelibo/blob/master/howtotranslatelibo.md#ふさわしい翻訳の考え方 )
次に、白に近かろうがリスクのあるものを入れることになるということです。Ubuntuの日本語化ローカライズであれば、すでに多くのユーザーが使用しているでしょうし、そういうものについてリスクのあるものを後から入れることになります。
そういったことを独断で黙ってやるというのは、歓迎されたものではありません。少なくとも、コミュニティに対して事前に方針を聞いたりすべきだったでしょう。
つまり、クオリティが低い上にリスクのあることを黙ってやったわけで、もちろん批判されるべきでしょう。
とはいえ、OSSには個々の事情があります。次は自分の場合の話をしてみます。
まずは質の話です。
自分のプロジェクトの場合、Google翻訳を使ったのはドキュメントです。日本語で書いたドキュメントをあたらしいGoogle翻訳に入れてみたところ、そこそこのクオリティの翻訳が出力されており、自分でゼロから翻訳するよりも、原文を翻訳しやすく修正したり結果に対して修正を加えていったほうが質と速さの両面でよいと判断したので、Google翻訳を使用しました。
次にリスクの話です。
OSSが企業に権利問題で訴訟されるということはめったにありません。OSSは公益性の高いものなので、むやみに訴えれば社会からの反感を買いますし、ほとんどの場合は訴えても大した金になりません。
訴えられるとすれば、そのOSSが十分に儲かっている場合です。もしOSSで大金が儲かったらGoogleから訴えられてしまう!どうしよう!と考えるのは、宝くじに当たったら強盗におそわれてしまう!どうしよう!と考えるのに似ています。
まず宝くじは当たらないですし、宝くじが当たったらそのお金で対策を行えば良いだけの話です。
実際Linuxでは、特許周りの対策としてOpen Invention Network(OIN)を設立しています。Linuxなどソフトウェアに対して特許を主張しないことに同意した企業から特許を買収して、そういった企業に対してロイヤルティー・フリーで許諾を行っている会社です。
これによって、Linux関連のソフトウェアに対して訴訟をしてきた、いわゆる「パテント・トロール」に対して訴訟をやり返すなどの対抗手段を得ているわけです。
権利問題で訴訟されたことによって失敗に終わったOSSというのはほとんどありません。多くのOSSは、作者が飽きたり、面倒な作業にうんざりしたり、誰にも使われなかったり、競合に勝てなかったりしたことで、フェードアウトしていきます。
結局のところ、自分の場合はGoogle翻訳をつかったところで、Googleにも、自分にも、ユーザーにも、世間にも不利益はなく、むしろドキュメントの質は上がって、Googleも翻訳を改善するためのデータを得られます。
わずかなリスクを避けるために、時間を割いた上、質を落とすというのはくだらないですし、そんなことに時間を使うくらいならコードを書いていたいものです。
結局、Web翻訳の結果をオープンソースソフトウェアで使うべきか、そうではないか?というのは個別の話でしかなく、ひとまとめにWeb翻訳の結果をオープンソースソフトウェアの翻訳にいれてはいけないとか、使うべきとかそう簡単には言えません。
質が悪いしリスクがあるのであれば単純に禁止で済む話ですが、機械翻訳が向上して、質が良いがリスクのある例が増えると話はさらにややこしくなります。
各OSSの翻訳者のコミュニティは機械翻訳の利用についてそのプロジェクトで使って良いかの方針を定めてやっていくしかなく、後からコミュニティに入っていくような人が機械翻訳を使いたい場合はコミュニティの方針を確認した上でやっていくしかないんだろうなあと思うところです。
もちろんスペシャリストがきちんとわかった上でOracleを使ってる案件は大丈夫なんだろうが、中小規模案件でOracle使ってるのにろくなのがない。
・データベースは当然のごとく正規化されてない。昔はされていたのかもしれない。
・使用されていない予約されたカラムの山。必須でない情報でもカラムを作るのでテーブルがどんどん肥大化していく。
・謎のインデックスが大量にあるが、パフォーマンス上本当に必要なインデックスはない。
・ストアドプロシージャが秘伝のタレ化。そのせいでOracleから抜けられない。
A- 日本IBM、NTTコミュニケーションズ、アクセンチュア、野村総研(NRI)
B+ NEC、日本HP、新日鉄住金ソリューションズ(NSSOL)、日本総研(JRI)、大和総研(DIR)
B NTTコムウェア、伊藤忠テクノソリューションズ(CTC)、電通国際情報サービス(ISID)
B- 三菱UFJインフォメーションテクノロジー(MUIT)、みずほ情報総研(MHIR)、
C+ JSOL、農中情報システム、SCSK、日立システムズ(HISYS)、日立ソリューションズ(HISOL)
C NECソリューションイノベータ、ニッセイ情報テクノロジー、JR東日本情報システム(JEIS)、
C- オービック、TIS、オージス総研、富士通エフサス、シンプレクス、
D+ 三菱UFJトラストシステム、三菱総研DCS、兼松エレクトロニクス、都築電気、
D 損保ジャパン日本興亜システムズ、インフォコム、セゾン情報システムズ、日商エレクトロニクス、
コベルコシステム、IIJ、ネットワンシステムズ、パナソニックインフォメーションシステムズ、
菱化システム、JRシステム、富士通システムズイースト、東芝ソリューション、富士通FIP
D- ユニアデックス、NECネッツエスアイ、日立産業制御ソリューションズ、
三菱電機インフォメーションシステムズ、MS&ADシステムズ、NTTソフトウェア、
NTTアドバンステクノロジ、JFEシステムズ、テクマトリックス、三井情報、第一生命情報システム、
ソニーグローバルソリューションズ、ワークスアプリケーションズ
E+ 富士通システムズウエスト、富士通マーケティング、三菱電機インフォメーションネットワーク、
中央コンピュータシステム、ティージー情報ネットワーク、リンクレア、ジャストシステム
E NECフィールディング、NEC情報システムズ、富士通BSC、日本情報通信、
住友電工システムソリューション、JR西日本ITソリューションズ、
E- 富士通ネットワークソリューションズ、日立公共システム、NEC通信システム、
F+ 日立ソリューションズ・クリエイト、キヤノンソフトウェア、さくら情報システム、
トヨタコミュニケーションシステム、エクサ、アイネス、TKC、CAC、CEC、SRA
F クオリカ、NSD、DTS、さくらKCS、東邦システムサイエンス、菱友システムズ、
26歳3年目 転職を考えてる。
持ってる資格
Oracle Bronze,Silver
統計検定2級
大規模構築経験あり
仮想基盤やAWS,Azureのパブリッククラウドの構築経験あり
ミドルは、bind,sendmail,samba,nginx,Apache,Zabbix,LDAPとか
麻雀(天鳳)が趣味で、牌譜の解析とかやりたかったから統計を勉強して、資格にチャレンジしてみた。ついでにpythonと数学も。どちらも業務で使うことはほぼない。
趣味Webメディア作ってたから、Wordpressサイト作るくらいなら一晩で出来る程度の能力。
http://anond.hatelabo.jp/20160703171723
それは,一言で言うと「金融緩和してもほぼ全部金融市場が吸い取ってしまい,実体経済に金が回らない」からである。
(以下は素人の私が勝手に考えたものだが,もし同じようなことを言っている経済学者がいたらぜひ教えて欲しい。まあ,素人と同じようなことを考える学者はいないと思うが。)
そもそも私がこういうことを考えるに至ったのは,1990年代終わり〜2000年代初頭にかけてのITバブルがきっかけである。その当時,IT経済を主とする"成長"は「インフレなき経済成長」と呼ばれていた。それは論理的におかしい,何か理由があるはず,と考えた結果,「これは実体経済に回るとインフレを起こすお金の大半が金融経済に回っていて,その結果金融経済が"成長"している一方,実体経済ではインフレが起きていないのでは」という結論に達した。
具体的には,当時のITバブルでは,資金がインターネット上の広告を売る新興企業に流入した。インターネット上は空間的な制約がないので,それら新興企業はほぼ設備投資をすることなく広告をいくらでも増やせる。他方,インターネット広告への期待から,それら新興企業の広告枠を買う企業が現れる。そうするとそれら新興企業の株価が上がる。株価が上がると,それを売って儲ける投資家が現れる。儲けた投資家は,またそれを新興企業に投資する。広告も一種の投資なので,広告枠を買う形で投資を行う者もいる。そうするとまた株価が上がる。
このバブルでは,対象が「インターネット上の広告枠」という無限に近い資源だったこともあり,実体経済には余りお金が回らなかった。せいぜい Sun Microsystems のサーバーが売れた程度である。ただし巨大なバブルだったので,おこぼれといっても巨大で,この後バブルが崩壊すると Sun は後遺症に悩むことになり,最終的に Oracle に買収されて消滅する。
しかしこのバブルの本質は,2次投資,3次投資,...という高次投資によって金融経済の中で資本が循環し,循環の過程で(見かけ上の)資本が拡大していった点にある,と私は考えている(バブルというのは須らくそういうものだが)。
結局このバブルは,「広告にいくら投資しても実際に広告対象の商品が売れなければ意味なくない?」ということに広告主が気づいたことで崩壊した。つまり,いくら金融経済が期待値で拡大しても,最終的に実体経済がそれに見合った成長をしなければ,それはバブルであり,バブルは必然的に崩壊するのである。
次に,この考えの傍証として私が注目したのは,金融経済と実体経済の規模の乖離である。
http://www.meti.go.jp/report/tsuhaku2008/2008honbun/html/i1120000.html によると,2006年時点で,金融資産の規模は実体経済の3.5倍であり,1990年以来の平均成長率は,実体経済が5.7%であるのに対し,金融資産は9.1%となっている。
これは異常である,と思う。
投資というのは,最終的に実体経済が拡大しないと,リターンを得られない。
ちょっと金融からは外れるが,土地転がしを例に考えてみよう。土地の値段は,循環取引的な手法を使えば,原理的には無限に上げることができる。その間,資産規模は拡大していく。しかし,それらはどこまでいっても「投資」であり,その投資を回収するためには,その土地で建物を建てて商売して利益を上げて地代を払ってくれる誰かが必要である。
もちろん投資には期間があって,5年のものもあれば,10年,20年,...といったものもあり,それらが混ざり合っている。従って,必ずしも実体経済と金融経済の規模が一致していなくてもよいが,金融経済の方が実体経済よりも速く成長するのは,やはり異常であろう。
この金融経済と実体経済の乖離は,おそらく1990年代の金融規制緩和以降に始まったのではないかと思う。この規制緩和によって,通貨以外のものを通貨と同様に扱えるようになり(例:株式交換による買収),またBIS規制の枠外で高次金融商品(金融商品に投資する金融商品)が解禁されて,金融商品を土地転がしのように転売することで金融経済が拡大することを可能にしたのではないかと思われる。
その結果,金融経済は恒常的なバブル状態になった。実体経済の成長を伴わない金融経済の成長はまやかしだが,そのまやかしがいつ露呈するかわからないので,それまでは疑心暗鬼ながらもチキンレースを続けている。まやかしだとわかっているが,実体経済よりも遥かに楽に大金をを得られるので,やめるにやめられない。それが今の状況なのではないだろうか。だから逆に,ちょっとしたことで株価が乱高下する。Volatilityが高くなってるのも,恒常的なバブルのせいと考えると個人的には納得がいく。
さて,金融緩和はここでどういう役割を果たしているかというと,このバブルを崩壊させないように金融経済に現金を注入する役割を担っているのではないかと思う。
金融緩和の恩恵を(最初に)受けるのは銀行,投資家,大企業である。
とにかく最初に恩恵を受けるのは銀行。商材であるお金が日銀から低利で借りられる=安く調達できる。
次が大規模投資家(ファンドや超がつくレベルの資産家等)や大企業。日銀から直接お金を借りるような大銀行の主要顧客になるようなところ。ここも従来より安い金利で資金を借りられるようになる。で,借りた資金を,大規模投資家はより(見かけ上の)リターンの高い金融商品(株式等)につっこむ。大企業は設備投資したり,やっぱり別な金融商品に投資したりする。銀行から借りた資金が,給与を上げる原資に直接使われることはまずないと思う。
つまり金融緩和の恩恵の大半は最初に銀行,投資家,大企業が取ってしまうし,その大半は実体経済ではなく金融経済の拡大に回ってしまう。その方が手っ取り早く稼げるからだ。残った僅かな(文字通りの)「トリクル」だけが,実体経済に回る。だから効果はゼロではないが,金融緩和の規模に比べると遥かに小さいし,また効果が出るのも遅い。設備投資が,さまざまな労働者の給与増に波及するのには,時間がかかるだろう。
近年の「異次元」と呼ばれるような金融緩和でもインフレがおきない(インフレ目標すら達成できない)のも,金融経済が金融緩和で生み出された資金を吸収し,実体経済にほとんど回ってないから,と考えると説明がつくように思う。
一番良いのは,金融規制を1990年代以前と同程度まで強化し,過剰流動性をなくすことだと思う。しかし,ここまでバブルが大きくなってしまうと,その破裂によってもたらされる実体経済への影響は,たとえもともとそれが率としてはトリクルであったとしても,絶対額が巨大なため,悲惨なことになると思われる。なので,風船が急にしぼまないよう,少しずつ空気を抜くような慎重さが必要になるだろう。
個人的には,長期投資は実体経済にとっても有益だが,短期投資(=投機)は害の方が多いので,短期投資に高い税率を課し,事実上無意味にしてしまうような政策が取れればいいのに,と考えている。株式や債券,その他の金融商品を在庫管理と同様の手法で管理し,例えば今日買った株を今日売ったら税率99%,逆に20年持ち続けた株を売った時は税率1%というようにすることで,長期投資を促すような政策は手法的には可能だと思う。
また高次投資も有害性が高いので,税率を高くする。例えば株式の売買は2次投資だから課税対象だが,配当は1次投資のリターンなので,非課税にするなど。株式はトレーディングの対象ではなく,本来の「直接金融によってリターンを売る権利&会社の支配権」の位置に戻した方が良いのではないだろうか。
最後に,これは妄想だが,金融経済と実体経済を可能な限り切り離す,というのが本当はできればいいと考えている。具体的には,金融経済はそれ専用の独自通貨を作り,その中で自由になんでもやっていい。ただし実際の通貨に交換できるのは,世界の実体経済のGDPの3%まで,とか決めておく。誰がその3%を使えるかは,金融経済の中で,専用通貨でオークションでもやって決めればよい。まあでもこれは残念ながら実現不可能だろう。
というわけで,今以上に金融緩和をしても無意味なんじゃないかな,と思ってる。
ところで,なぜ財政政策のところが「再分配(例:富裕層への課税強化&低所得層への扶助)」じゃなくて「財政出動」なんだろう?
ホッテントリメーカーで作るような煽りタイトルって、みなさんもう見飽きてると思うんですよね。
今調べたらホッテントリメーカー2008年だそうで。どうりでねー。古臭いなーと思いましたよー。
「一から学ぶJava」ってのをね、1.0にするだけでこんなに素敵なタイトルになるんだから面白いですねー。
タイトルを思いついただけだったんですけど、思いついたらやっぱりちゃんと中身も書かないと行けないじゃないですか。やだー
面倒くさいんですけどね。ちょっと1.0から学んでみましょうか。
Javaの1.0がリリースされたのは1996年1月23日ですね。発表されたのが1995年5月23日でJavaの誕生日といった場合にどちらを取るかで揉めることがあります。
かれこれ20年前なわけで、当時のパソコンというとハードウェアはCPU が Pentium 133MHz メモリ16M とかそんな感じだったかなあ。今どきの携帯電話の例としてiPhone 6sを挙げるとCPUが1.85GHz メモリ 2G ってんだから凄いですね。OSは1995年11月23日にリリースされたWindows95とかそんな時代背景です。インターネットがようやく一般に普及し始めたところでしょうか。
今から思うと相当弱いハードウェアですけども、そろそろVM方式を採用しても良さそうな、そんな時代でした。インタープリタだと流石に遅い、でもC言語のようなコンパイル言語だと"Write once, run anywhere"とはいかない、という判断もあったのだろうと思います。Javaが純粋なオブジェクト指向言語ではなくintなどのプリミティブ型を持つというのは、当時のマシンスペックを考えた場合、ある程度妥当な判断だったと言えるでしょう。これが後々苦しくなってくるわけなのですが。
Javaを作った会社はSun Microsystems(サン・マイクロシステムズ)というアメリカの会社で、2010年1月27日にオラクルにより吸収合併され今はありません。SolarisというOSとSPARCプロセッサでUNIXサーバーの販売で90年代後半までは一人勝ちのような状況だったと聞きます。当時にすでに「ネットワークこそがコンピュータ」(The Network is the Computer)というモットーを掲げてたんだからおかしい。1996年リリースのJavaが標準でネットワーク機能を備えていたのもこのあたりの思想から来ているのかもしれませんね。
当時のプログラミング言語としてC++が挙げられますが、C++でのプログラマへの負担といいますか、ヒューマンエラーの起きやすさといいますか、その辺を改善する目的で開発されたのがJavaだったわけです。
1996年の時点にこんな言語が登場したのですから革新的でした。
いろんな企業がJavaに賛同します。その中にはMicrosoftもありました。この時期、Microsoftは次期のWindows開発用のプラットフォームにJavaを据えようと考えていました。その後、袂を分かつことになるのですが……。
プログラム言語として構文などを見ると、C++を強く意識した構文なのは間違いなく、しかしポインタ演算を廃してポインタを機能を限定した「参照」に置き換えるなど簡素化が多く見られます。C++からはいろんな機能が削られています。関数ポインタ、構造体、演算子オーバーロード、テンプレート((テンプレートについては実装が間に合わなかったという話を聞きます))などなど。そのためC++の劣化であるように揶揄する人もいますが、こうしたものを捨てて言語仕様を比較的小さくシンプルに抑えた点は評価に値すると思います。しかし、今でもこうした削減された機能を愛する人からはJavaを腐す要素として挙げられてしまうのでした。
Wikipediaからピックアップすると1.1での大きな機能追加は
といったところです。当初よりJavaの内部文字コードはUnicodeで文字を表すchar型は16bitで設計されていました。Unicodeは当時それほど普及しておらず、Unicode対応のテキストエディタさえ少なかったと記憶しています。時代を先取りしていると言えますが、大きな誤算はUnicodeが当初16bitのコードポイントに世界のあらゆる文字を格納しようとしていたことで、漢字圏の我々からすると16bit=65,536程度の空間に文字が全部入るわけないだろ!というものだったが故に早々に破綻し、Unicodeは21bitのコードポイントに拡張されることになるのです。これはまた後の話。
なんにせよ、日本語が対応されたのは1.1からで、日本でのJavaの採用が始まったのはこの頃からと言えましょう。
当時のJavaのGUIはAWTというものでしたが、これを用いたGUIの開発は当時は結構行われていたイメージですね。Visual BASIC でGUIを作るプロダクトも結構あったと思います。GUIのためのオブジェクト指向言語としてJavaが使われていたイメージがありますね。JavaBeansもそのための仕様でした。件のsetter/getterの話題に繋がっていくのですが。
JDBCはJavaとデータベースをつなぐインターフェースです。RMIではあるJava VMから別のJava VMにオブジェクトを送って実行する、といったことができます。こうした機能が用意されたことで、ソフトウェアのフロントとしてのGUI、裏方の実装のためのネットワーク機能、データベース機能、さらにはソフトウェアを配布するためのJava Appletという布陣でJavaでのソフトウェア開発が加速していた時代といえます。
Microsoft Visual J++ もこの時代ですよ。
Java 1.1以降のバージョンのものは互換性確認のためにOracle Java Archiveからダウンロードすることができ、今でも入手することができます。もちろん、Java7ですら2015年4月にEOL(End of Life,サポート終了)となっているので、通常利用するのはJava8としてください(本稿執筆時点)。
当時のドキュメントを見るのも一興です。現在と比べると標準APIがかなり小さい。なお、当時のjavadocは今とはデザインが大きく異なります。
この時代であれば、全パッケージを舐めて標準APIを学ぶこともそう難しくはありませんでした。この時代から触っている人間は新バージョンが出るたびに増えるAPIを順に学んでいけたのです。しかし、現代にJavaを学ぶ場合、どのバージョンでは何があって……というのをいちいち学ぶ必要はほぼありません。Java5以前は一緒くたでいいと思いますし、一部のAPIで歴史的経緯があってねーというのを知っていればおそらく十分ではないでしょうか。
strictfpキーワードは浮動小数点演算をやる人は覚えておきましょう。JavaはパフォーマンスのためにCPUの浮動小数点演算を扱うことが許されており、そのため実行するCPUによって精度が異なることがあるんですね。まあ今時のCPUだと大丈夫だとは思うんですが。
リフレクション機能ではJavaのクラスを抽象的に扱うことができます。設定ファイルに書かれたクラス名のclassをロードして実行する……みたいなことができるんですね。フレームワーク的なものを作る場合には多用することになります。
1.2からは新しいGUIのSwingが採用されました。AWTがOSごとのGUIパーツを用いていたためデザインに違いがあったのに対し、Swingでは統一的なルック・アンド・フィールが用いられるようになりました。まぁ今ならJavaFXを使うのが良いと思います。
初期のJavaはやはりVM方式の実行速度の遅さが指摘されていました。実行時の構文解析を伴わないだけインタープリタよりは早いものの、実行バイナリを作るC/C++よりは遅い、そうした評価です。ここではサン・マイクロシステムズのVMにJIT(ジャストインタイムコンパイラ)が乗ったことが挙げられていますが、JIT自体は別の会社が先駆けて開発していたことは記しておきたいと思います。
JITコンパイラは実行時にJavaのバイトコードを環境のネイティブコードにコンパイルして動かす技術です。この後、JITコンパイラ、動的再コンパイル技術、世代別ガベージコレクションを備えたHotspotといった様にJavaVMは進化していきます。現代では実行時の最適化が進み、大きなスケールで見た場合、Javaの実行速度はC/C++での実装と比べてそれほど遅れるものではありません。遅くても倍の時間は掛からない程度といったところでしょうか。
あとは特記すべきはコレクションフレームワークです。皆が多用しているであろうjava.util.Listやjava.util.Mapといったライブラリが整備されたのがこの時なのです。それ以前はjava.util.Vectorやjava.util.Hachtableというクラスが可変長配列の機能を一手に担っていました。今ではVectorやHashtableは使うべきではありません。
Java の開発はSun Microsystems が主導していたけども、すべてがSunのものだったというわけでもなく。Javaには多くの会社が出資していてその中のひとつがMicrosoftだったわけですね。
Microsoft の Visual J++ では delegate とか独自機能拡張もありましたけど、裁判で問題になったのは J++ でコンパイルしたclassファイルはMicrosoftのVMでしか動かないという部分ですね(他社製のVMで動くclassファイルを作ることもできる)。classファイルがどこのVMでも動くの大事だろ、"Write once, run anywhere"だろ、お前何してくれてんの!と喧嘩になったわけです。当時のMicrosoftはブラウザまわりでも独自拡張がやりたい放題、標準規格?なにそれ美味しいの?みたいなスタンスをあちこちで見せていたものです。
結局、この事件でMicrosoftのJavaはバージョン1.1相当でストップ。好き勝手にやれないなら独自に言語作るわーとばかりに.NET フレームワークと C# といった方向に舵を取ります。
JavaがPC上でのUI開発の主力になろうとした勢いはここで潰えます。
Java SE とは別にこの時代に Java EEがリリースされていることは特記しておきたいですね。これ以後、それまでのCGIに取って代わって、JavaはWebサービスの開発のプラットフォームとして多用されるようになります。
2000年あたりからはJavaはGUI開発というよりは、Webサービスの開発が主流という流れになっていきます。インターネットのサービスが非常に発達していった時代、背後ではとてつもない量のJavaのプログラムが支えていたわけです。ただまあ、こうした産業利用は一般的なユーザーの目にはあまり入らないわけです。一般人からすればJavaといえばJava Appletみたいなイメージはずっと残っていたでしょうが、実体としてはJavaといえばServletという時代になっていたわけです。
企業で用いられる社内システムにもServletは多く採用されました。
理由はいろいろ挙げれると思うのですが
というのが大きな理由だろうと思います。JSPというテンプレートエンジンを用いてHTMLを整形してWebページを作り出す、というアーキテクチャはある意味では便利で簡単でした。
もっともHTMLの表現力に足を引きずられるため、GUIの機能性という点では後退したわけなのですが。それでもメリットが大きいと判断されたのでしょう。というか、まともにGUIを組めるプログラマがほとんどいないから、GUIのシステム開発がなかなか成功しないってのもあったんでしょうけどね。
2000年あたりというと携帯電話の普及も取り上げなければなりません。現代のスマホ、ガラケーに比べれば非常に機能は貧弱で、まさに携帯「電話」でした。要するに電話とメールぐらいしかできなかったんですね。
そこにdocomoのiアプリ、Jフォン(ボーダフォンを経て現ソフトバンク)のJavaアプリ、auのEZアプリという携帯電話上でちょっとしたアプリが動くよ!というのが乗るようになってきたんです。これがJavaを組込み用途にコンパクトにしたJava MEというものが土台となっていて(正確にはiアプリはちょっと違う)Servletと並ぶJava言語の大きなもうひとつの領域となっていました。
iアプリは当初は容量が10k byteまでといった制約があり、容量制限が非常に厳しかったのですが、新機種が出るたびに容量は緩和されていきました。
docomoはiアプリ含めiモードによって一世を風靡します。こうした土台を作ると、その上で商売をしたい人がたくさんやってきて、勝手にコンテンツを作ってくれる。docomoはそれらから手数料を取るので労せずして大金を稼げるというわけです。賭場の胴元というわけです。
この賭場が、将来にAppleのiPhone, GoogleのAndroidに荒らされることになります。docomoがなかなかiPhoneを出さなかったのもiモードという自前の賭場を失うことを良しとしなかったためです。金づるを失ったdocomoはSamsungと組んで独自の携帯向けOSであるTizenの開発に乗り出します。そんなTizenですが鳴かず飛ばず。噂ではインドあたりではリリースされたとか、なんとか。
話を2001年に戻しましょう。
Microsoft離反でGUIのプラットフォームとしてのJavaというものは存在感を弱めていました。この分野の復権に寄与したのはJava 1.4 (2002年2月6日)で導入されたJava Web Startです。
Java Appletがブラウザ埋め込みで動作したのに対し、Java Web Startではブラウザから起動しつつも独立したアプリとして起動するのです。
Webシステムが企業の社内システムに採用された話は先に述べたとおりですが、やはりWebシステムのGUIというのはHTMLに引きずられて貧弱だったんですね。
端的に言えば入力値が数字かどうか?みたいなチェックがなかなか難しい。HTML上でJavaScriptでやるわけなんですが、なかなか気持よく入力できるような感じにはならなかったんですね。
また、Ajaxによるブラウザのページ遷移を伴わない通信というのが出てきたのも2005年ぐらいなので、入力値に対してサーバ問い合わせするようなことはできなかった。当時だと一旦画面遷移させないとできなかったわけです。
こうした事情から、クライアントサイド、要するにPC側でもっとリッチなUIが使いたい!という要望があったわけです。Webシステム使いにくい!という不満の噴出と言ってもいい。そこで出てきたのがRIA (Rich Internet Applications)というわけです。
Javaは1.0時代のAppletからそうですが、ネットワークを介して別のPCにプログラムを送り込み、そこで動作させるという能力を持っていました。それこそまさにRIAに求められる機能性だったわけですね。
RIAの代表とされるのは
あたりです。三つ巴の戦い、どこに軍配が上がるのか!?と注目されましたが、勝利したのはHTML / JavaScriptでした。
Google MAP で注目を浴びたAjax技術、それまでブラウザでは不可能と思われていた高級なGUIをHTML / JavaScriptで実現させました。もうやめて欲しいですよね。せっかく脱ブラウザの流れが来たと思ったのにまたWebシステムに逆戻りですよ。
RIAが失速した理由として考慮して置かなければいけないのはスマートフォンの台頭です。RIAでは端末を選ばずどこでも同じアプリが動かせる点がポイントのひとつでしたが、スマートフォンではそうは行かない。"Write once, run anywhere"を破壊したのはスマートフォンだったというわけです。
しかし、先日インストールなしでアプリを実行するAndroid Instant Appsが発表されたりしまして、結局RIAの思想といいますか、要求というのは今でも息づいているのだなと思った次第です。
1.3 / 1.4 では機能追加はあっても言語構文が大きく変わることはありませんでした。大きく変わったのはJava 5です。この時からバージョニングが変わって1.5ではなく5と表記されるようになりました。
Java5の特徴はなんといってもジェネリクス。それまでjava.util.Listにデータを出し入れするのにはキャストが必須だったわけですが、ようやくキャストから開放され型の安全度がぐっと高まりました。その他に以下のような変更があります。
言語としては随分変わっったわけですが、もうかれこれ10年以上前のことですからこれらの機能が「Java5から導入された」という知識は今となってはあまり必要とされません。これらの機能が使えないJava 1.4で開発をする事案が殆ど無いからです。0ではないのが悲しいところではありますが。
Java 6 (2006年12月11日)がリリースされた後、Java 7 (2011年7月28日) が出るまでJavaは停滞してしまいます。その間にSun Microsystemsという会社がなくなってしまったためです。
Sun Microsystems の経営状況が悪化しており、ついに身売りをすることになりました。身売り先はIBMともGoogleとも噂されましたが結局2010年1月27日にオラクルに吸収合併されました。
Javaの停滞中にはJava VM上で動く非Java言語も台頭してきました。Scalaなどですね。
やや戻って2007年にAndroidが発表されます。Androidの開発言語にはJavaが採用されていますが、実行環境はJava VMではなく、ライセンス的な事情でJava(TM)は名乗らない微妙な位置関係にあります。
Java 5 以降で大きく言語仕様に手が入るのは Java 8 (2014年3月18日)です。並列処理を行うためのStream APIと、そのために簡易に関数を定義するためのラムダ式が導入された点が大きいですね。日付APIも刷新されました。
このように、Javaは1.1の黄金時代から今に至るまで利用ジャンルを転戦しながら産業の土台となって支えてきた歴史があります。ジャンルの趨勢により浮き沈みもあります。今後についても決して楽観視はできないでしょう。Javaを学ぶことはプログラミングを学ぶステップとしては意義はあると思いますが、Javaを学べばゴールというわけではありません。プログラム言語も次世代へと移りつつあります。業界動向には注視していきましょう。
ある日、たまにお世話になってるBさんからシステム構築の相談を受けた。知り合いの使ってるシステムが拡張できなくて困っている、知人に会わせるから詳しく聞いて欲しい、という事だった。このお客さんというのは過去にツーショットダイアルでしこたま儲けたらしく、金は持ってるという話だった。そういえば前に、自社でやってる出会い系サイトが重くてしょうがないんだけど助けて欲しいって相談を受けた事がある。第一世代iMacで構築してたらしく、ちょっとカブれたシステム会社にあたっちゃったんだなと思ってた。その時はまとまった時間が取れなくて手伝えなかったんだ。俺はMacは好きだけど、当時仕事ではIAサーバーにSAN繋いでOracleでDB構築とかしてたので、Mac+FileMakerでWebアプリ作ってるって聞いてひっくり返った覚えがある。
K県にあるオフィスへいった。担当者Hさんとはすぐ話が出来たが、オーナーのWさんは渋滞に巻き込まれて1時間ほど遅れて来た。Bさんからは「見た目は思いっきりヤクザだけどいい人だから」と言われていたけど、サングラスでもかけて無い限り普通に人の良さそうな叔父さんだった。日本語は上手。アクセントは中国訛りだけど、システムのことがよくわからないHさんよりよっぽど話が通じる。
内容は「コミュニティサイト」、つまり「出会い系サイト」だと言う。会員数は1万人。有料サイトで1万人はかなり凄いはず。ガラケーの待ち受け画像サイトとか手伝ってた時には、内部関係者とか無理矢理登録させて盛りに盛って5千人も行けばいい方だった。思わず口に出た「え?1万人ですか!?凄いですね」 。WさんとHさんは何故か目を合わせて苦笑いしてる。ハードウェア構成は1万人にしてはちょっとショボイかなと思ったけど、hpのDL380とMSA500の構成を打診してみた。一式200万〜くらいだけど向こうにひっくり返られて、今は数万円の自作PCでやってるって事だった。まあハードで儲ける気はないからいいけど。
出会い系のシステム構築し始めて、一番話が噛み合わなかったのが会員インポート機能だ。現行システムからの移行に使うという。そんな一回しか使わない機能、手動でコンバートするからこの機能外させてくれって何度も言ったんだがどうもこの機能にこだわる。むしろこの機能がキモだとまで言う。あ、だんだんわかってきたぞ。
こいつは有料会員が1万人もいるような優良サイトではなくて、名簿屋から買った会員情報を流しこんで会員数万人に仕立てあげるシステムだ!。俺は金に成るならマルチの管理システムでもなんでも作ったるわと思ってたからやるけど。現行サイトは女性会員として登録しても男性会員から検索できない。これは客がテストのために女性として登録してクレームをつけてくることがあるから、検索できるようにして欲しいと言われた。出会えなかったら客が残らないんじゃないですか?って聞いたら、あまり出会わせないんだと。実会員同士が連絡を取っちゃったら直メールでやりとりしてポイント消費しないから、出会えないのがいいんだと。なるほど、ワルだね!
程なくして(すったもんだあったけど)システムが完成して、同一システムで見た目だけ変えたものをいくつか作らされた。有料出会いサイト、無料の客寄せサイト、そもそも出会いとして機能してないDM送信サイトがあった。有料出会いサイトの売上は、うまくいってるサイトでも月間数十万程度なんだが、1サイトだけずば抜けて売上の高いサイトがあった。毎月コンスタントに500-600万は売り上げて、多い時は1000万を軽く超える。こんなことなら売上のパーセンテージで保守料貰えばよかったなあ。
一体どうしてこのサイトだけこんなに売上があるのかと、ちょっとサイトのメールやりとりを覗き見して青ざめた。こいつらもう出会いなんて全然エサにしてない、初めから「あなたに1000万円当たりました。振込の手続きをするので合言葉'XXXX'を送信してください」などと言ってポイントを消費させてるだけだった。この頃はまだ男性向けが圧倒多数だった気がする。後に女性向けにジャニーズを騙ったり、占いサイトと称して幸福に成るための合言葉を連投させたり、そのうちエスカレートして金の単位は億になり、あからさまに「手続きのために○○円分ポイントを購入してください」という通知になっていく。
このシステムは思いつかなかった。実はガラケーの待ち受け画像サイトやってた時もそうなんだけど、俺は基本的にケチなので「こんなのに金払う奴がいるか?いるわけねーだろ」と思ってしまう。こんなのに引っかかるやつがいるなんて信じられないのでビジネスにしようなんて思いもよらない。引っかかる人っていうのは気の毒に成るくらい頭が気の毒な人なので、「本当に振り込んでいただけるのでしょうか。子供のDSも売ってポイント買いました。振り込まれないともう本当に終わりです。」などと書き込んでいる。胸が痛んだ。このやり方は客を殺すので長続きしない。広告打つにもカネがかかるし、太客をうまく転がしてる方が効率はいいと思う。
Wさんの携帯番号末尾は0001、車のナンバーも・・・1。さすが縁起を重んじる中国人。この番号とるのにいくらかかるんだろうなあ。
OAuth ディスの記事を酒の勢いで訳してみたゾ。前半はつまらないから、「章のまとめ」か、それ以降だけ読むといいゾ。なぜか後半が切れてた。こっちだけでいいゾ anond:20160426145507 anond:20160426150324
http://insanecoding.blogspot.com/2016/04/oauth-why-it-doesnt-work-and-how-to-zero-day-attack.html
認証 (authentication: 本人確認) と承認 (authorization: 権限付与) のシステムを設計し、API を規定し、複数の異なるシステムを統合するために用いられる提案をまとめたものです。
OAuth には色々な種類があり、version 1.1a や 2、その各部の上に他の規格を乗せたものなどが存在します。世の中に出回っている数々の実装によって、具体的な利用状況は大きく異なります。
前にも OAuth について書いたことがあり、たくさんの反響をいただきました。前回の記事に対する批判の一部を避けるため、今回の記事について先に断っておきたいのですが、この記事は OAuth の使われる典型的な場面に焦点を当てており、論じられる点のほとんどは、何らかの方法で OAuth を利用する大手サービスのほとんどすべてに当てはまるということです。
言いかえると、OAuth を用いているあらゆるプラットフォームが壊れているとは限りません。OAuth にはバリエーションが多いうえに、2.0 だけに限っても 76 ページに渡るパターンがありますので、OAuth に基づいた何かに適合していながらもセキュアであり、使っても問題ないものは存在しうると言えます。ですから、あなたのお気に入りの OAuth 実装や設計が、ここで論じられる問題の一部または全部を免れていることもありえます。確率は低いですが。
また、OAuth を使っているものの中には規格を誤用しているものがあるとか、OAuth はその使い方を強制しているわけではないとか言う人もいるかもしれません。どちらにせよ、ここでは特定の OAuth ベースの規格について述べるのではなく、現状で大手が OAuth をどう利用しているかについてを、それが規格に適っているかどうかに関わりなく論じるつもりです。こうすることで、多くの読者に影響を与えることになるでしょう。危険な方法で OAuth を使っているサービスの利用者であっても、また自ら OAuth ベースのサービスを管理していて、他のみんなが作っているのを真似てプラットフォームを作ろうと思っている人だとしても関係があるのです。
この記事は長くなりますし、言ってみればほとんどの章はそれ自体でひとつの記事として十分なほどの話題を扱いますので、大まかな流れをご説明しておきましょう。
この記事は、現在 OAuth 業界でおこなわれていることを調査した結果のまとめです。OAuth を使う製品のすべてにこの記事のあらゆる点が当てはまるというのではなく、危険だったり無価値だったりするサービスの背後に見つかった慣例や根本原因を紹介する記事です。
この前書きのあとは、まず OAuth のセキュリティ欠陥を分析することから始めるつもりです。こうした欠陥の中には、セキュリティのコミュニティでよく知られていて、書籍などですでに分析されている一般原則が当てはまるものもあります。しかしこの記事では書籍化されていないケースも扱いますし、有名な欠陥についても、平均的な開発者および責任者に理解しやすく、対策の必要性がはっきりするように工夫するつもりです。
その後は、OAuth の主要素が一般的に言ってどのように実装されており、そうした普通の実装がどのようにサービスを使いものにならなくするのか、すなわちそのサービスで達成できることを極度に、不適切に、かつ意図に反して低下させてしまうのかを分析します。ごく一部のケースでは回避策の足がかりになるかもしれないテクニックについて論じますが、そういうのを実装する馬鹿らしさにも注目します。こうした記述の中では繰り返し何度も、OAuth を使う人たちがどれほど自分と自分のビジネスにとって損なことをしているのかが説明されます。
最後に、OAuth が適切に使われうる数少ない場面と、すでに利用されている OAuth の代替品を簡単に取り上げます。代替技術に関する調査の結果を提供するつもりですが、その中には Amazon のような大企業がセキュアで使いやすく信頼性の高い API を実現するために何をしているかの報告も含まれるでしょう。
いま普通に使われているかたちにおける OAuth の欠陥の幾つかを悪用すれば、大手サービスに対して強力な攻撃を仕掛けることができます。OAuth に対する攻撃は何も新しいものではありません。IBM や Oracle を含め、懸念した IETF メンバーが OAuth ベースのサービスに対する攻撃を 50 クラスも記述した 71 ページもの文書を 3 年以上前に出したように、また筆者も前回の記事でこうした点のいくつかを議論したようにです。それにも関わらず、OAuth ベースのシステムの主要なセキュリティ欠陥は非常に蔓延しています。
筆者は、いくつかの大手企業の役員や開発者に、そこの OAuth ベースシステムが抱えるセキュリティ欠陥を指摘したことがあります (そのうちのひとつは 4 年前のことです) が、全員、自社システムを修正するために一切何もしませんでした。まるで、OAuth の人気度からして、他の現実的な解決策をひとつも聞いたことがなく、それゆえに OAuth が最もセキュアな選択肢に違いないと決めてかかっているようです。どうも、OAuth のコア原則に対する攻撃のデモを文書化した情報も、聞いたことがないか、肩をすくめて無視するかしているようです。そこで、この情報をもっと広く拡散することによって、影響のある人たちの尻を蹴りとばしてあげたい、そしてサービスを設計あるいは管理している人たちにモーニングコールの役割を果たしてあげたいと願っています。
というわけで、OAuth ベースの何かを提供あるいは利用するご自分のサービスを調べて、こうした欠陥の一部あるいは全部が存在することに気づいたなら、どうぞ責任をもってこの情報を取り扱ってください。ご自分のサービスを適切にアップデートしたり、関係する問題に対応するようビジネスパートナーに適切な圧力をかけたりしてください。
ここで言及されている情報やリンクされている情報は今のところ既存のサービスに悪用できるかもしれませんが、どうぞ責任ある行動をとり、他人のものを破壊するのではなく改善することを目指してください。この記事は、自社サービスを不適切に実装している人たちへのモーニングコールのつもりで、その改善を促すために書いているのであり、悪用したがっているハッカーたちのハウツーもののつもりではないのです。
この記事では、ふたつのシナリオに注目して、その場面でどのように OAuth が組み合わされているのか、そしてなぜうまくいかないのかを検討します。記事を通して何度もこれらのシナリオに戻ってきますので、頭に入れておくことは大事です。
まず、Exciting Video Service (略して EVS) というサービスを思い描いてみましょう。ユーザが動画をアップロードしたり友人と共有したりできて、完全公開にしたりアクセス制限を設定したりできるようになっています。また EVS は動画のアップロードや削除、およびだれが視聴できるかの権限管理に OAuth ベースの API を提供しています。
ただ、例としてこの想像上のサービスに焦点をあてますが、論じられる問題はあらゆるサービスにも当てはまります。ファイルであろうと文書ストレージであろうと、カレンダー管理やオンライン会議、ディスカッション・グループ、はたまたリソース管理であろうと OAuth ベース API を提供する他のいかなるものであろうとです。また、筆者は本当にどの特定の動画サービスのことも言っていないということを覚えておいてください。問題点の一部あるいは全部は、OAuth を使っている既存の動画サービスに当てはまるかもしれませんが、EVS がそのサービスのことを指すわけではありません。どれが当てはまるかは読者への練習問題ということにしてもいいですね。
ひとつめのシナリオとして、ビデオカメラの製造会社を想定しましょう。そのビデオカメラには、録画した内容を EVS にアップロードする機能のあるソフトウェアを付属させたいと思っています。つまり、ユーザがビデオカメラを自分のコンピュータに接続して、その独自ソフトウェアを開き、ビデオカメラからアップロードしたい動画を選んでしばらくすると、それが EVS にアップロードされているというものです。
ふたつめのシナリオとしては、ある中小企業が職員用に EVS で 50 アカウントを購入し、全職員が動画をアップロードして同じ部門の職員と共有できるようにする、ということにしましょう。この会社は A Friendly Custom Platform (AFCP) というソフトウェアで職員と所属部門の管理をしており、この AFCP サービスを EVS に統合したいと考えています。望んでいるのは、管理者が AFCP を使ってだれかを営業部門に配置したら、その職員が自動的に営業部門のメンバー所有の動画すべてに対するアクセス権を取得するということです。営業部門からいなくなった人には逆のことが起こるようにもしてほしいと思うはずです。
トークンベースの認証システム (OAuth のコア) が現在よく利用されている最大の理由のひとつには、「適切に実装されれば」サードパーティのアプリやサービスに各ユーザの認証情報 (パスワード等) を提供しなくて済むという点があります。サードパーティに個人ユーザの認証情報を渡すのは、以下の理由から望ましくありません:
上記の問題点は、OAuth だけでなくあらゆるトークンベースの認証システムでも回避できます。よく OAuth の強みとして挙げられていますが、独自というわけでは全然なくて、他にも同じ強みを実現しつつ OAuth の弱点のない選択肢はあるのです。
さて、確固とした土台に基づいてはいるものの、「普通の実装における」OAuth は、上記の問題を回避しようとして以下のような手順に沿ってシステムに情報を提供します:
このトークンはユーザの認証情報ではありませんから、そしてひとりのユーザとひとつのアプリの組み合わせだけに有効で、指定された権限しか持たず、あとから破棄されるようになっていますから、きちんと前述の問題点を回避しているように思えます。しかし実際には、ちゃんとした土台を核として持っているにも関わらず、OAuth の普通の実装で使われているこのフローは、上に挙げた問題すべてに対処しているとは言えません。
この設計はそもそも危険なスタート地点から始まっています。セキュアなプラットフォーム設計の第一原則は、危険な地点から始まったものは既にダメ、逆転不可能、ということです。手順 1 のせいで、EVS 自体ではなく EVS を利用するサービスから始まっているので、ユーザは最初の一歩からして中間者攻撃を受けたような状態にあります。これは、かかってきた電話に個人情報や口座番号などを教えるようなもので、自分の使っているサービスの者だと名乗っていますが、番号が本物かどうか分からなかったり非通知だったり、という場面のコンピュータ版だと言えます。最近はこういう詐欺がたくさんありますから具体例を挙げる必要はありませんね。要点は、接続を開始する相手が信用できなければ、その接続は一切信用できないということです。EVS 自体の側から手順を始めるのでない限り、上に挙げた目標をすべて実現する API 利用のためのセキュアな認証システムは設計不可能です。
(略: 手順 2 で、それっぽいページに誘導すれば認証情報を盗める)
(略: そうした詐欺を企業自体が後押ししているような風潮もある)
(略: スタンドアロンのアプリなら、ログインを詐称する必要すらない)
この種の攻撃は前述のセキュリティ文書で「4.1.4. 脆弱性を突かれたブラウザや組み込みブラウザを使ったエンドユーザ認証情報のフィッシング脅威」として分類されています。提案されている解決策は?
クライアントアプリがユーザに直接認証情報を求めることは避けるべきだ。加えて、エンドユーザはフィッシングや良い習慣について教育を受けることもできる。良い習慣は、たとえば信用できるクライアントにしかアクセスしないことだ。OAuth は悪意あるアプリに対していかなる防御策も提供していないので、エンドユーザはインストールするネイティブアプリすべての信頼性に自分で責任を負う。
さらに
クライアント開発者は、ユーザから直接に認証情報を集めるようなクライアントアプリを書くべきではなく、システムブラウザのような信用できるシステムコンポーネントにこの役目を移譲すべきだ。
基本的に言って、OAuth のセキュリティガイドラインは、OAuth を利用する開発者がユーザを攻撃しようとすべきではないとか、悪いことをしてはならないと言っています。外部の開発者が悪いことをしないことに頼るというのは、正気のサービス設計者が依拠するセキュリティモデルではありません。
私の知る主要な OAuth ベースのサービスはほぼすべて、ここに概説した手法で攻撃可能です。
OAuth こそセキュリティの新たな金字塔だとお考えの皆さん、目を覚ましてください! 「普通の実装における」OAuth は、始まる前から負けていますよ。OAuth が存在するよりずっと前に実装された数多くのシステムはセキュアで、この問題を効率的に回避しています。残念なことに、あまりに多くのサービスが、せっかくセキュアだったのにインセキュアな OAuth モデルに移行してきました。だれかが開発者や管理者に「OAuth はもっとセキュア」「先取り思考」「将来への投資」とか何とか素敵な (しかし具体性の皆無な) バズワードを並べたてたからでしょう。ほとんどの場合、こうした変更は本当に既存の問題に対応しているのか、あるいは以前のシステムより幾らかでも良くしてくれるのかどうかをレビューすることさえなく実装されています。
OAuth ベースのサービス設計でよく見かける間違いは、ブラウザ用に、パラメータのひとつとして client_secret (あるいは同様のもの) を受け取るエンドポイントを提供することです。OAuth の client_id と client_secret パラメータは、基本的に言ってサードパーティのプラットフォーム固有の API ユーザ名とパスワードと等価ですから、EVS の API を利用する開発者だけにしか知られるべきではありません。パスワード同然のものなのですから、client_secret パラメータは「絶対に」ユーザのブラウザを通して送信すべきではありません (ヒント: パラメータ名の中に secret という言葉が入っているよ)。アプリやサービスのユーザがその client_id と client_secret を見つけることができる場合、そのユーザはそのサービスのふりをすることができ、潜在的には何かイケナイことができてしまうということになります。さらに注意すべき点として、client_secret パラメータを別の名前にするサービスもありますから、ご自分の関係するサービスをよくチェックして、他のパラメータも秘密にする必要があるのかどうかを調べてください。残念ながら、重要な変数が自分の素性をいつも表に出しているとは限らないため、この問題は意外と多く存在しています。加えて、client_id だけ使う認証フローを OAuth の上に乗せるサービスも出てくるでしょう。これには用心してください。特定の状況では、そういう client_id はまさしく client_secret 同然の働きをするのですから。
「普通の実装における」OAuth は、ウェブブラウザを使ってユーザを複数のウェブサイトに移動させるわけで、ひとつのサイトから別のサイトに client_id と client_secret (あるいは同様のもの) を送ってもらう必要があります。そうやって、たとえば AFCP と EVS の間でこれらをやりとりするわけですから、ユーザがブラウザの HTTP ログをモニタリングすれば、本当に見えてしまいます。これはアプリに組み込まれた独自ブラウザ各種でも、単に右クリックすれば何らかのネットワーク・ログ機能を持つ何らかの inspector にアクセスできてしまう場合などには可能です。
EVS と連携した AFCP にこの欠陥があると、AFCP に少しでもアクセス権限のある職員に本来の権限より多い権限を取得させてしまい、本来アクセスできないはずのところに許可が下りてしまう危険があります。別の例では、仮に Facebook が GMail 用の OAuth エンドポイントを利用しているとして、client_id と client_secret の両方がブラウザを通して送信される場合、Facebook のユーザは全員 GMail に対して Facebook そのもののふりをすることができてしまうということです。
この問題は、OAuth エンドポイントがユーザのウェブブラウザから平文で client_secret を送ってくることを期待するときにはいつも存在します。あるいはそうする必要があると誤解した API 利用者が、埋め込むべきでないところに secret を埋め込むときもです。この脆弱性が存在している可能性が高いのは、エンドポイントが client_secret (または同等品) と redirect_uri の両方を期待する (あるいはオプションとしてでも受け付ける) 場合です。redirect_uri パラメータは、今回のケースで言うと EVS がユーザをログインさせたあとでそのブラウザをどこに送るべきか指示するために使うよう設計されています。そうやって redirect_uri がエンドポイントへの転送に使われている場合、その処理はユーザのブラウザで実行されることが期待されているわけです。主要な OAuth 文書はどちらも、client_secret と redirect_uri の両方をこうした用途に使うようなケースを指示したり求めたりはしていません。
ざっと検索してみたところ、残念なことに、潜在的に違反の可能性があるそういった OAuth ベース API がたくさん見つかります。Google は OAuth の色々な利用方法を提案していますが、その中に、両方を一緒に使うことを広めるフローがひとつあります:
client_secret: 開発者コンソールで取得したクライアントパスワード (Android, iOS, Chrome アプリとして登録した場合のオプション)
Citrix もこんな間違いをしています:
(略: 以下、実際に脆弱だと確認したわけではないが、secret と redirect を併記しているサイトが列挙されている。)
Google で 2 分検索しただけでこのリストができました。皆様がもうちょっと労力をかければ、ずっと多く見つかることでしょう。ただし、上記リストは、こうしたサービスのどれかが脆弱だとか、誤用しやすすぎるということを直接に示すものではありません。色々な要素があり、たとえば Zendesk は特にこのケースでは redirect_uri パラメータをリダイレクトに使わないと明言していますし、アプリからエンドポイントを呼ぶときはフル機能版ブラウザではなく curl を使うべきだとさえ書いて、開発者が危険なことをするような誤解を極力避けようとしています。それでも、経験の浅い開発者はこうしたエンドポイントを独自ブラウザで読もうとするかもしれません。さらに、この組み合わせが世に出回っているというだけで開発者の警戒心が下がっていき、経験を積んだ OAuth ベースのサービス開発者でさえも似たような状況で潜在的にヤバイ誤用を気にせず適用するようになってきています。特に client_secret が別の名前になって、「秘密を守る」という概念が失われている場合はそうです。
サービスがこの点に関して壊れている指標となるのは、人気のある複数の OAuth ライブラリがこのサービスでうまく動かないときです。そういうサービスは一般的にいって独自の「SDK」を提供しており、サードパーティの開発者が選んだライブラリではこのフランケンシュタイン的な OAuth が使えないと苦情が来たときにはその SDK を使うよう指示します。こうしたカスタマイズは気付かれないまま進行することも多くあります。開発者の大多数は、SDK が提供されているなら、わざわざ手元のソフトで頑張らずに済ませたいと思うものですから。
この種の攻撃は前述のセキュリティ文書で「4.1.1. クライアントの機密情報を取得する脅威」に分類されています。しかしサーバがウェブブラウザを使用を要求し client_id と client_secret (または似た用途のもの) を同時に渡させるという具体的な攻撃パターンには一言も言及がありません。おそらく、その文書の執筆陣の予想では、こんな馬鹿げたサービスはだれも設計しないだろうし、その API を使う開発者もそれを独自のウェブブラウザや SDK で使ったりはしないだろうと思っていたのでしょう。こうした開発者は OAuth の規格からバラバラに取り出した要素をグチャグチャに混ぜて接着しておいて、自分のプラットフォームが OAuth 本来のセキュリティを保持していると思っています。そのツギハギのせいでどんな新しい問題が入り込むかもしれないのに、そこは一顧だにしません。残念ながら、これが近年の OAuth 業界によくあるやり方で、この既に猛威をふるっている問題は、パレードの参加者がどんどん増えて、人が使っている手法や、使っている「と思う」手法をコピーしていくことで、とどまるところを知らない連鎖になっています。
おそらく、上記のサービスを使っているシステムのうち、この問題のせいで悪用可能なものは多数あることと思います。特にデスクトップアプリでは、コンパイルされたアプリのバイナリから秘密情報がそのまま取り出せることは、サービス側で何も危険なことを要求していなくてもよくあります。Google が OAuth の使い方を多数提供しているうちで、client_secret と redirect_uri を両方受け取るエンドポイントのことが書いてあるのはたったひとつだけだというのは重要な点です。少なくとも Google の場合、redirect_uri があっても、このエンドポイントをウェブブラウザベースのアプリには推奨していません。しかし、だからといって実際に独自ブラウザでそれを使う人や、このフローを標準的なブラウザ用のエンドポイントにコピーする人が一切いなくなるはずがありません。それに加え、Google は例外なのであって、世の中にはセキュアな OAuth フローを受け入れず client_secret (や同等品) を常に渡すよう要求する愚かなサービスが今も満ちあふれており、そのフローがウェブブラウザを通るときでさえも要求しているのです。さらに悪いことに、こうしたサービスの多くはユーザのウェブブラウザを通して「しか」利用できないのですが、これは後ほど詳述します。
http://blog.livedoor.jp/itsoku/archives/47616816.html
とそのブックマーク
http://b.hatena.ne.jp/entry/blog.livedoor.jp/itsoku/archives/47616816.html
をみながら思ったんだ
要約するとアメリカは時給12万円のコーダーの仕事があるらしい
そんでとうぜんにほんじゃそんなことないという流れで
日本はハードばっかりにこだわってソフト軽視だという(まぁそうだろうね私もそういう印象あるよ)
なぜか、このスレの連中(名前からしてビジネス+)は、文系のせいにしたり大企業のせいにしたりする
このまとめをまるまる信じるとして思うことがある
一瞬なるほどそうなんですかって話になりかけたが
そしてHPやDELLなどのハードにこだわっていろいろ大変なことになってる会社もあるわけだが
なにが言いたいかって、べつにアメリカもその点では変わらないじゃんってことだよ
じゃあなにが違うのかって
理系がベンチャー立てて、googleみたいな企業立ち上げられるかどうかだよね
それだけの話だよね
そこだけが違う
理系()がベンチャーでgoogleとかほかのIT企業立ち上げたら話は終わるんだよ。amazonでもいいしoracleでもいいし、あとなにがある?あんましらないけどねw
もちろんそれが一番難しくてできないから、理系()のルサンチマン馬鹿どもは文系のせいにしたり、企業のせいにしたりしてるんだろうけどw
アメリカだって恐竜って言われてるGEとかIBMみたいな旧態然とした、大企業ってのもありつつベンチャーでITが盛り上がってるわけだからさ
アメリカ人がGEとかIBMのせいにしてるわけじゃないでしょ(まぁそもそもGEもIBMも利益率かなりいい優良会社だけどね)
ようするに能力のないバカが2chで騒いでるんだろうってことが言いたいんだけど
この2chまとめみたいにルサンチマンやってるダサい連中じゃなくもっとまっとうな理由ってないのかなって思ったわけですよ
日本にはこういう問題があるんだってのがあるんだったら教えてほしいとおもってね
そもそもなんでこの手の奴らって文系理系でわけるのかね。もっというと理系側がわけたがってるよね。お望み通り理系でわけてやったんだから理系の皆さん返信よろしく
就活の参考にしたい
20代の数年間SIで働いた。1年以上前に退職して今は別業界にいる。
今日、Evernoteを整理していたら「退職理由、SIの嫌な点」というメモが発掘された。退職直前のかなりストレスがたまっていた時期に書き殴った文章だった。学生の頃の私は絵を書いたりしていて、ものづくりで暮らしたいな〜などと思って始めたプログラミングが楽しかったので安易に受託開発業を選んでしまったが、その後悔が如実に表れていた。
一部自分でも覚えていない話もあったがコンテンツとしては面白かったし、今でもシステムインテグレーター業界で消耗する若者を減らしたいとは思うので公開してみる。
以下、同メモに加筆・修正したものなのでファンタジーだと思って読んでくれ。
受注した時点で売上がおよそ確定するので、後はその予定工数に収めて納品できれば御の字という考え方。よくある話だが、見積がおかしくても顧客と対等な関係が築けていないから追加請求もできない。時間(工数)をかければ良い成果物ができるかもしれないがそれを説明して顧客に嫌な顔をされたくないから、限られた工数の中での最善を尽くす。最善を尽くす、聞こえは良いが要は手を抜く。
つまり、どう頑張っても売上は同じなのだから、良いもの・価値を生むものを作ろうと考えない人が多い。社内で開発者と呼ばれる人間もそうだし、マネジメント層はそういうものづくり志向を持った人をリスク扱いすることもある。
これが諸問題の根源で、いかに述べるような組織・プロジェクトが出来上がっていく。
マニュアル作業の正確さをかたくなに信じてる人だらけで、ITとは何なんだと考えさせられる。
私は定型作業を効率化しようとjsやrubyでスクリプトを書いたりしていた。テストデータを開発用DBに突っ込んだり、テキスト処理して整形したり、Excelからコード生成したりするよくあるやつ。
あるとき上司に肩越しに自分の作業を覗かれて「何やってるの?」と聞かれ、そういうスクリプトを作ってると答えたら、工数とリスクの話をされた。曰く「そのスクリプト作るのに何日かかるの?工数に乗ってないよね?」「スクリプトのテストもちゃんとしないと結果が正しいって保証できなくない?」と。この時はイラッとして「30分でできる数十行のスクリプトだし自分の作業工数内で完結する。むしろ後工程や別の人でも同じことを再現性できて楽になる」とか真面目に説明してプログラムも見せたが、読もうとはせず(読めないので)1時間無駄にした。
前述したようなビジネスモデルだから、営業力と、予定工数で無難にプロジェクトを終えるマネジメント力が大事。IT企業だが開発者は自社で持たない。不況の時に待機コストが発生するリスクがあるし、自社で抱えるより単価の安い開発者が人材派遣系の企業や下請けにいっぱいいるから。
社長があるとき社内広報で「技術は買うものだ」と言っていた。文脈で明らかに技術=技術者のことだったので、使い捨ての人売り業と揶揄されていることへの自覚が無いと思う。
そういう人が集まっているor残っている組織なので開発者はほとんどいない。20〜30人ぐらいの課に1人ぐらいの割合でstaticおじさんがちらほらいるぐらい。大体20代からプロジェクトリーダーという立場をやり始め、だんだん大型の案件を扱えるようになっていき、後は出世ゲーム。部長のお気に入りが課長になり、部門長のお気に入りが部長になる。その繰り返し。
開発案件でのBP(ビジネスパートナー、委託先、派遣、下請け)比率は自分の周りだと1:5ぐらいが多い。プロパー社員一人が5人の開発を仕切る、みたいな形。案件規模によりだいぶ差があると思う。この比率が高い=マネジメント力のある組織と考える会社はこの数字を上げようと必死で、比率の低い組織は評価が下がる。
私は開発が好きだったのでエンジニアとして生きていきたい、というようなことを評価面談の度に伝えているが、その度に会社の目指す方向を説かれてモチベーションが下がる。
上述の通り、案件で接する開発者は基本的に社外の人間なのだが、彼らの技術力と意識の高さにはものすごいばらつきがある。言われたものはなんでもこなせる人、何でこの歳まで技術者やれてるんだと疑う人、このプロジェクトはおかしいと良い意味で騒ぐ人、何も意見を言わない人、CっぽくJavaを書く人、人当たりは良いが技術力がいまいちな人、すぐ休む人、バグやミスを隠す人…etc。
まぁ色んな人がいるのはどの業界のどの職種も同じだが問題は質だ。私の主観になるが本当にエンジニアとして尊敬できるレベルの人は1%いるかいないか。というのも、ほとんどの技術者は長年SIやその周辺企業と付き合ってきているので同じ体質に染まっているのだ。顧客が良いといえば良いという態度(この場合の顧客は私が所属する企業)、請負の場合は工数を超えない範囲で手を抜く姿勢、その他諸々。技術力だけをひたすら磨き続けてきたという人はごく一部だけだったし、そんな人でもGitHubアカウント持ってない・ブログやってない・OSSに貢献したことない、といった具合でクローズドな世界で生きている。
そうした技術者とやっていく中で最も厄介なのが教育コストだ。案件のあるなしで人が都度入れ替わり、新しい人が来るたびに同じシステム・技術要素の説明をして何とかやる気が出るようモチベートして、というのを繰り返すのに疲れた。私の会社固有の変なルールの説明はてきとうにしておいて、私は技術が好きな仲間が欲しかったので今のシステムの課題と技術面での改善や展望をよく話す。が、あまり食いつかれることはない。これは私の問題だが、そうした期待と落胆のループも疲弊の一因だ。
ある時、一つの課に6年近くいるというBPと一緒に仕事をする機会があった。その課にはプロパーの技術者が長いことおらず、彼がその課の技術的中心を担っているという話だった。抜けられると途端に色んなものが崩壊するからという理由で、その人の派遣元にはかなり高額の単価を支払っていたと聞いた。課員が口をそろえて「あの人はすごい」「何でもできる」というので初めはかなり期待していた。
だが、拍子抜けした。あまりにも仕事が雑なのだ。コミットされたコードはTODOコメントだらけだし、バグがあまりにも多かった。一度も実行されずにコミットされ、他の人がチェックアウトした時点で判明したバグなんかもあった。それでも声が大きく、プロパーが技術を知らないのをいいことに自分のブランディングに完全に成功していた。客先にも顔を出し、信頼を得ているらしかった。「自分は設計が得意でテスト以降の工程には興味が無い」と言っていた。確かに彼が関わった各システムには独特の概念が埋め込まれた設計があったが、その複雑な設計は保守性が低く、他の開発者が触ると容易にバグを引き起こしていた。
また、彼はJavaの有名なフレームワークであるStrutsを拡張したいわゆるオレオレフレームワークを開発しており、それの出来は悪くなかったと思う。そのフレームワークに欠けているものをうまく補うような形になっていた。だがフレームワークのバージョンを上げると壊れるというのが残念な点で負債になりかけていた。
私は異動したが、彼は今でもそこにいると聞いた。
(最低限のものしか作らないから)安くて早い!という触れ込みで売っているので、テストの工数が異常に少ないことも多い。特にテストコードを書くなんてもってのほか。そういう世界でやってきた人ばかりなので、30や40超えたマネジメント側は「テストコードって何?」状態だ。大型の改修案件が来た時にはコア機能だけでもテストを書いていこうと見積段階から社内で提案したが「顧客に『そんなメリットあるなら何で今までのプロジェクトではやってないの?』って問われるから、絶対言うなよ」と拒否された。
保守案件をやっていた頃、時間を捻出してコソコソとテストコードを書いたりしていた。その案件を離れてしばらく後、ある時リポジトリを覗いたら私が書いたテストコードがばっさり消えていて驚いた。コミットログから課内のstaticおじさん的な人が消したとわかったが、そのコミットコメントが「現在使用していないコードを削除」だった。これはもう問う気も失せて何も言えなかった。
先述したようにテストがそもそもないプロジェクトが基本なのでリファクタできないのだが、たとえテストがあったとしても勝手なリファクタは許されない。ソースコードは顧客の持ち物なので同意なしに改変することはいわば契約違反なのだ。たとえ内的品質が向上してコスト削減に繋がるとしても、そのためにお金を支払う顧客はまずいない。
私がいたどの案件にもコードレビューがなかった。リーダーと開発者数人という構成の場合、まず開発者は全員下請けでリーダーは技術の心得がない場合が多い。そうなると彼らの成果物の良し悪しを図るのは目に見えるシステムの挙動と実施されたテスト結果のExcel報告書だけになる。これが非常に非効率で、少しコードを読めばわかる明らかなバグや仕様理解の齟齬が頻発していた。特に受入試験と呼ばれるリリース直前の顧客側での最終確認や本番稼働中におけるhotfixは全機能をきちんとテストせずにデプロイされることが多く、そのhotfixがさらなるバグを引き起こしたりもしていた。
そもそもテストを書けという話だがテストが無いプロジェクトに足すのはかなり大変なので、レビューサイクルをきちんと回すだけでもかなり変わる。実際、私が入った案件ではすべてのコミットに目を通すようにし、明らかな問題は都度指摘することで品質の向上に繋がった。欲を言えば他の開発者にもレビューしてもらいたいが、下請けの彼らの工数を増やすことは嫌がられる。
無難にプロジェクトをこなすことと新しい技術を試すことの両立こそ技術者の腕の見せどころだと思っているが、ほとんどの場合それは許されなかった。新規にせよ継続にせよ案件を受注する段階で営業やマネジメント層と顧客間で「今回は過去に実績のあるこの技術でやります」という契約が結ばれているからだ。その技術(言語やフレームワーク)がいかに古く、保守性も将来性もないものだとしても受注できればよいし、その技術のサポート切れか何かの拍子で再度リプレイス案件でも受注できればさらにラッキーぐらいの考えでいる。
また横に倣えが加速してさらに悪い事に、同じアーキテクチャ・ネットワークを再利用するために既存のサーバに新システムも相乗りすればよいという発想も珍しくない。「資産の再利用によりコスト削減」という触れ込みだったが、ただでさえスケールしない低スペックのオンプレミスサーバ上で複数のアプリケーションサーバを運用した結果、予想通り耐障害性が下がった。
また、Oracleのライセンスが高いという理由で一つのDBインスタンス上に10数個のシステムが同時稼働しているなんてこともあった。1つのシステムが高負荷なクエリを投げたせいで関連する全システムが共倒れになったこともあったがOracleのバグとして報告していた。
新人の頃にOJTでstaticおじさんの下に付いたことがあった。そのとき担当したのはPerlでデータ連携用のバッチを書くという開発業務だったのだが、最悪の思い出だ。
まずプログラム構造仕様書というのを書かされた。メソッド単位でのモジュールを全てExcel上に記述し、処理の順番と内容を説明するという謎資料だった。あまりに意味がわからなかったので「UMLのクラス図を書けばよいのですか?」と聞いたら「Perlにクラスなんて必要ない。構造化プログラミングを研修でならってないのか」と返ってきた。「俺が前に書いたPerlのバッチがあるから参考にしろ」と言われ、あるリポジトリをチェックアウトして見てみると1ファイル4,000行の.plがいくつか並んでいた。その時の私は何もわかっていなかったのでそういうものかと思ってしまったが後で調べて明らかにおかしいと気づいた。
また、そのプロジェクトのメイン言語はJavaで、Eclipseを使っていたのでPerl用プラグインを入れてコーディング・デバッグをしていたらやめろと言われた。理由は「Eclipse上で動くPerlが信用できない。サクラエディタで書いてプリントデバッグすれば充分だ」と言われた。その時の私は何もわかっていなかったので、プラグインの品質が悪いとかそういう話かと思い「じゃあvimで書きます」と言ったら「サクラエディタにしろと言っただろ!」と一喝され、vim vs サクラエディタという史上類を見ないエディタ論争が起きた。
SI業界の中では高いのかもしれないが決してよくはない。4年目(たぶん25歳)ぐらいで残業込みで年収400万にやっと届いたがそこからほとんど変わっていない。30歳の先輩に聞いたところ「500万前後、残業してない場合の月の手取りは未だに20万切ることがある。残業抜きでは新婚生活が厳しい」と言っていた。いわゆる年功序列がきっちりしていてこのまま続けてもしばらくは給与が伸びないということがわかった。
個人での貢献で差がつくのは±10万程度。その程度ならいっそ無くてもいいのでは、と思う。というかそもそも生産性をきちんと評価する制度が存在しない。これはどの組織でも難しい問題だと思うが、形骸化した評価制度で上司の気に入った人間にS評価を付けているだけならいっそ止めたほうが時間の無駄にならなくてよい。
会社から貸与されるノートPCは低スペックすぎて開発には使い物にならない。なので開発者は基本的にデスクトップを使用せざるを得ないのだがこれもメモリ4G、1.2GHz程度で大したマシンでもない。本当に開発する気がない。
いつの間にかどこかで意思決定がされていて、関与する機会がほとんどない。だがほとんどの社員がそれで良いと思ってる。失敗しても自分が決めたことじゃないから上層の責任だ、そう言えるので楽だから。
情報共有をしない、というか意図的にしないようにしているとまで感じる。連絡はメールと添付ファイルベースで行っているし、共有のファイルサーバなんてのもあったが一部のフォルダは権限を持った人間しか見られない。何で他の部や課が行った過去の見積や提案資料が自由に見られないんだよ。
ソースコードのリポジトリも同様。外部に公開しないのはまだわかるが、プロジェクト外にすら基本は公開していない。別に奪われて困る大した技術もない。
会社が用意した提案資料共有サイトみたいなのもあったが、それに至ってはもっとひどい。課長以上もしくは部長から承認を与えられた者のみ閲覧可能。共有とは。
どうでもいいことを決めるにも承認や根回しや説得が必要になる。それがプロジェクトの利害関係者ならまだわかるものの、まったく関わっていない上長(課長や部長、時には部門長)を通さないと進まないという異常さ。
利益率向上のためにコスト削減ということがしきりに言われており、過剰なコスト削減対応が生産性の低下を招いている。たとえば顧客に見せる資料以外は白黒で印刷しろ、みたいなルール。色がないために情報が伝わりにくい。というかそもそも印刷せずに各自のノートPCで見ろという話だが、先述したようにノートPCは低スペックすぎるので多くの社員がデスクトップを使っている。ITとは。
本当に無駄としか思えない承認・申請フローの煩雑さに加え、使っているシステムの使い勝手も悪く、ひどい日は一日がそうした事務作業で終わる。しかもそのシステムは自社で以前開発したものだというから泣けてくる。こんな作業が定常的に発生するのでいっそ事務員を派遣で雇うべきという提案が何度もされたが、課の予算をオーバーするから無理だという回答しか返ってこない。
表向きは社員の健康促進という触れ込みで残業時間削減を全社的に取り組んでいる。残業減らせと声をかけただけでは誰も帰らないので、勤怠システムと入退館管理システムを監視し、削減できていない組織や人間の評価を下げるようになった。
その結果、サービス残業が復活した。30時間を超えると部長に説明しないといけない、50時間を超えるとその上へ…みたいなループ。表向きの残業時間削減・コスト削減としては成功したかもしれないが、社員の残業時間を管理するとかいう無駄な仕事を増やしたし、管理される社員のストレスとサービス残業に繋がったので下策だと思う。
他人の残業時間をExcelにまとめる仕事があって、そこに給与が発生してると思うと泣きたい。
そもそも無駄な作業や工数至上主義で作業効率が悪いから残業しているので、残業が少ない奴が偉いと一斉に舵取りしただけでは生産性をちゃんと評価できていないことに変わりはない。一昔前の残業多い奴は頑張ってて偉い、というのと本質レベルで何も変わっていない。
SQLServerとOracleを両方使ってるってどういうことだ・・・?
SQLServerでパフォーマンスでなかったからExadataに乗り換えたということ?
”NTTドコモがSQL Server 2014を採用、全契約回線の課金・決済システムに”
http://cloud.watch.impress.co.jp/docs/news/20150828_718454.html
原文:https://blogs.apache.org/foundation/entry/apache_commons_statement_to_widespread
原題:Apache Commons statement to widespread Java object de-serialisation vulnerability
翻訳日:2015年11月12日(午後にタイトルを日本語にしました)
----
Apache CommonsのJavaオブジェクトのデシリアライゼーション脆弱性に関するステートメント
著者:Bernd Eckenfels(コミッター), Gary Gregory(Apache Commons副責任者)
AppSecCali2015 でGabriel Lawrence (@gebl) と Chris Frohoff (@frohoff) によって発表された "Marshalling Pickles - how deserializing objects will ruin your day" は、信頼されないソースからシリアル化されたオブジェクトを受け取るときのセキュリティ問題をいくつか明らかにしました。主な発見は、Java オブジェクト・シリアライゼーション(訳注:seriarization/シリアル化/直列化=ネットワークで送受信できるようにメモリ上のオブジェクトデータをバイト列で吐き出すこと。シリアル化されたJava オブジェクトはRMIなどのリモート通信プロトコルで使用される。)を使用する際に任意のJava関数の実行や操作されたバイトコードの挿入さえもを行う方法の説明です。
Frohoff氏のツールである ysoserial を使って、Foxglove Security社のStephen Breen (@breenmachine) 氏はWebSphereやJBoss、Jenkins、WebLogic、OpenNMSといった様々な製品を調査し、(http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/) に各々の様々な攻撃シナリオを記述しています。
両者の調査活動は、開発者がJavaのオブジェクト・シリアライゼーションに信頼を置きすぎていることを示しています。認証前のシリアル化されていないオブジェクトにも。
Javaにおけるオブジェクトのデシリアライゼーション(訳注:de-serialization/非直列化=ソフトウェアで扱うことができるように、送受信されたデータを元に戻すこと)が行われるとき、大抵は想定された型にキャストされ、それによって、Javaの厳しい型のシステムが、得られた有効なオブジェクトツリーだけを保証しています。
不幸にも、型のチェックが起こるまでの間に既にプラットホームのコードが生成されて、重要なロジックは実行されてしまっています。そのため、最終的な型がチェックされる前に、開発者のコントロールを離れた多くのコードが様々なオブジェクトの readObject() メソッドを通じて実行されてしまいます。脆弱性のあるアプリケーションのクラスパスから得られるクラスの readObject() メソッドを組み合わせることで、攻撃者は(ローカルのOSのコマンドを実行するRuntime.exec()の呼び出しを含めて)機能を実行することができます。
これに対する最も良い防御は、信頼されていないピア(通信相手)とは複雑なシリアル化プロトコルを使うことを避けることです。ホワイトリストのアプローチ http://www.ibm.com/developerworks/library/se-lookahead/ を実装するように resolveClass をオーバーライドするカスタム版の ObjectInputStream を使うと、影響を制限することができます。しかしながら、これは常にできることではなく、フレームワークやアプリケーションサーバがエンドポイントを提供しているような時にはできません。簡単な修正方法がなく、アプリケーションはクライアント・サーバプロトコルとアーキテクチャを再検討する必要があるため、これはかなり悪いニュースです。
これらのかなり不幸な状況において、エクスプロイトのサンプルが見つかっています。Frohoff氏は、 Groovy ランタイムや Springフレームワーク、 Apache Commons コレクションからのクラスを組み合わせるサンプルのペイロードに gadget chains (ガジェット・チェーン)を見つけています(訳注:provided)。これはこの脆弱性のエクスプロイトのためにより多くのクラスを組み合わせられることは完全に確実なことで、しかし、これらは今日、攻撃者が簡単に得られるチェーンです。
(Twitter画像)https://blogs.apache.org/foundation/mediaresource/ce15e57e-94a4-4d7b-914c-8eb8f026659c
この脆弱性のために利用される(訳注:blamed)ことができない確かな機能を実装するクラスができ、安全性が信用できないコンテキストにおけるシリアル化を利用されないようにするような既知のケースの修正ができたとしても、少なくとも分かったケースだけでも継続的に修正していくことが要求されます。モグラ叩きゲームを始めるだけであるかも知れませんが。実際にはこれは、オリジナルチームが Apache Commons チームに警告が必要だと考えていない理由で、それゆえに比較的、活動開始が遅れました。
Apache Commons チームは InvokerTransformer クラスのでデシリアライゼーションを無効化することによって commons-collection の 3.2 と 4.0 のブランチにおける問題に対処するために、チケット COLLECTION-580(http://svn.apache.org/viewvc/commons/proper/collections/branches/COLLECTIONS_3_2_X/src/java/org/apache/commons/collections/functors/InvokerTransformer.java?r1=1713136&r2=1713307&pathrev=1713307&diff_format=h) を使っています。議論されているやるべきことのアイテムは、変化させる仕組み毎(per-transformer basis)に、プログラマティックに有効にするような機能を提供するかどうかです。
これには前例があります。Oracle と OpenJDK JRE の一部であったり、バイトコードを挿入して実行することを許したりする com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl クラスで、セキュリティマネージャーが定義されているとデシリアライゼーションを拒否します。
これはシステムプロパティ jdk.xml.enableTemplatesImplDeserialization=true とすることで無効にできます。Apache Commons Collection は、本来よりもこの実行モデルは一般化していないため、セキュリティマネージャーの存在と独立したこの機能を無効化することを計画しています。
しかしながら、明確化のために述べておくと、この便利な"ガジェット"は、唯一知られている方法でもなければ、特に未知のものでもありません。そのため、インストールされたものを強化されたバージョンの Apache Commons Collection に置き換えることが、アプリケーションをこの脆弱性に対抗できるようにするわけではありません。
このブログポストのレビューのために Gabriel Lawrence に感謝したいと思います。
Apache Commons Collection は、Java コレクションフレームワークに加えて追加のコレクションクラスを提供する Java ライブラリです。InvokerTransformer はコレクションにあるオブジェクトを(特にリフレクション呼び出しを通じてメソッドを呼び出すことで)変換するために使うことができる Transformer ファンクションインターフェースの実装の一つです。
一般のSallyによる2015年11月10日午前10字15分にポスト | コメント[1]
コメント:
私の持てる知識を絞り出してなんとか完成しました。
**************************************************************************************
完成したサイトがこちらです。
LapyNetニュース
**************************************************************************************
私は普段webとは関係ない仕事してます。なんとか休日を利用して、
メインのコードはこんな感じ
----------------------------------------------------------------------------------------------------------------------
App::uses('Sanitize', 'Utility'); class RssfeedsController extends AppController { public $helpers = array('Html','Form','Session','Number','Cache'); public $uses = array( 'Rssfeed', 'Tweet', 'Wadai', 'Rank', 'Oracle' ); ************************************************************************************** public function index() { $title_for_layout = "LapyNetニュース"; $content = "Hello World!!"; $this->set(compact('title_for_layout','content')); if(date("G")>0 and date("G") < 7){ $today = date("Y-m-d", strtotime('-1 day')); }else{ $today = date("Y-m-d"); } $params = array( 'conditions' = > array( 'and' = > array( 'Rssfeed.time' = > $today, )), 'order' = > 'tweets desc', 'limit' = > '50' ); $this- >set('posts',$this- >Rssfeed- >find('all',$params)); $paramz = array( 'order' = > 'Rssfeed.id desc', 'limit' = > '10' ); $this->set('posts2',$this->Rssfeed->find('all',$paramz)); $paramz = $this- >Rssfeed- >query('SELECT id,title FROM rssfeeds order by id desc limit 10'); $this->set('posts2', $paramz); $parapara = $this- >Oracle- >query('SELECT id,title FROM oracles order by id desc limit 10'); $this- >set('postx', $parapara); $funking = $this- >Rank- >query('SELECT id,frank FROM ranks where creation=(select max(creation) from ranks)'); $this- >set('funking', $funking); } ************************************************************************************** public function mizuno() { $parapara = array( 'order' => 'Oracle.id desc', 'limit' => '30' ); $recent_posts = $this->Oracle->find('all',$parapara); return $recent_posts; } ************************************************************************************** public function wadai() { if(date("G")>0 and date("G") < 7){ $today = date("Y-m-d", strtotime('-1 day')); }else{ $today = date("Y-m-d"); } $params = array( 'conditions' => array( 'and' => array( 'Rssfeed.time' => $today, 'Rssfeed.kubetu' => 4 )), 'order' => 'tweets desc', 'limit' => '100' ); $this->set('posts',$this->Rssfeed->find('all',$params)); $this->set("title_for_layout","2CHニュース-LapyNetニュース"); $paramz = array( 'order' => 'Rssfeed.id desc', 'limit' => '10' ); $this->set('postyy',$this->Rssfeed->find('all',$paramz)); $parapara = array( 'order' => 'Oracle.id desc', 'limit' => '10' ); $this->set('postyx',$this->Oracle->find('all',$parapara)); $funking = $this->Rank->query('SELECT * FROM ranks where creation=(select max(creation) from ranks)'); $this->set('funking', $funking); } ************************************************************************************** public function hot() { if(date("G")>0 and date("G") < 7){ $today = date("Y-m-d", strtotime('-1 day')); }else{ $today = date("Y-m-d"); } $params = array( 'conditions' => array( 'and' => array( 'Rssfeed.time' => $today, 'Rssfeed.kubetu' => 3 )), 'order' => 'tweets desc', 'limit' => '20' ); $title_for_layout = "LapyNetニュース"; $this->set("title_for_layout","ニュース-LapyNetニュース"); $this->set('posts',$this->Rssfeed->find('all',$params)); $parapara = array( 'order' => 'Oracle.id desc', 'limit' => '10' ); $this->set('postxx',$this->Oracle->find('all',$parapara)); $paramz = array( 'order' => 'Rssfeed.id desc', 'limit' => '10' ); $this->set('postsxxx',$this->Rssfeed->find('all',$paramz)); $funking = $this->Rank->query('SELECT * FROM ranks where creation=(select max(creation) from ranks)'); $this->set('funking', $funking); } ************************************************************************************** public function newnew() { if(date("G")>0 and date("G") < 7){ $today = date("Y-m-d", strtotime('-1 day')); }else{ $today = date("Y-m-d"); } $params = array( 'conditions' => array( 'and' => array( 'Rssfeed.time' => $today, 'Rssfeed.kubetu' => 2 )), 'order' => 'tweets desc', 'limit' => '20' ); $this->set("title_for_layout","エンタメニュース-LapyNetニュース"); $this->set('posts',$this->Rssfeed->find('all',$params)); $paramz = array( 'order' => 'Rssfeed.id desc', 'limit' => '10' ); $this->set('postszz',$this->Rssfeed->find('all',$paramz)); $paramz = $this->Oracle->query('SELECT id,title FROM rssfeeds order by id desc limit 10'); $this->set('postszz', $paramz); $parapara = $this->Oracle->query('SELECT id,title FROM oracles order by id desc limit 10'); $this->set('postzy', $parapara); $funking = $this->Rank->query('SELECT * FROM ranks where creation=(select max(creation) from ranks)'); $this->set('funking', $funking); } ************************************************************************************** public function top() { if(date("G")>0 and date("G") < 7){ $today = date("Y-m-d", strtotime('-1 day')); }else{ $today = date("Y-m-d"); } $params = array( 'conditions' => array( 'and' => array( 'Rssfeed.time' => $today, 'Rssfeed.kubetu' => 1 )), 'order' => 'tweets desc', 'limit' => '20' ); $this->set('posts',$this->Rssfeed->find('all',$params)); $param = array( 'conditions' => array('times > current_timestamp + interval -600 minute and Kubetu = 4'), 'order' => 'tweets desc', 'limit' => '30' ); $this->set('posts2',$this->Rssfeed->find('all',$param)); } ************************************************************************************** public function view($id = null ) { $this->Rssfeed->id = $id; //驥崎ヲ√↑荳譁・i縺励> $user = AuthComponent::user(); $TwimStatus = ClassRegistry::init('Twim.TwimStatus'); $TwimStatus->getDataSource()->setToken(AuthComponent::user()); $statuses = $TwimStatus->tweet(); $rairai = $this->Rssfeed->read(title,$id); $alcol = $this->Rssfeed->read(); $this->set('post', $alcol); $this->set('post2', $user); $this->set('post3', $statuses); $this->set("title_for_layout",$rairai[Rssfeed][title]."-LapyNetニュース"); $paramz = array( 'order' => 'Rssfeed.id desc', 'limit' => '20' ); $this->set('postszz',$this->Rssfeed->find('all',$paramz)); $parapara = array( 'order' => 'Oracle.id desc', 'limit' => '30' ); $this->set('postzy',$this->Oracle->find('all',$parapara)); } ************************************************************************************** public function add() { if($this->request->isPost()){ if($this->Tweet->save($this->data)) { $this->Session->setFlash('seikou'); $this->redirect(array('controller'=>'rssfeeds','action'=>'view',$contents11)); }else{ $this->Session->setFlash('sipai'); $this->redirect(array('controller'=>'rssfeeds','action'=>'view',$contents11)); } } } ************************************************************************************** public function delete($id = null) { $this->Rssfeed->id = $id; $this->set('set', $this->Rssfeed->read()); $this->redirect(array('controller'=>'tweets','action'=>'delete',$this->data['tweet']['rssfeed_id'])); } ************************************************************************************** public function oracle() { if($this->request->is('post')) { $user = AuthComponent::user(); $TwimStatus = ClassRegistry::init('Twim.TwimStatus'); $TwimStatus->getDataSource()->setToken(AuthComponent::user()); $contents1 = $this->request->data['Rssfeed']['contents']; $contents2 = $this->request->data; $statuses = $TwimStatus->tweet($contents1); if($this->Rssfeed->save($contents2)) { $this->Session->setFlash('成功です。'); $this->redirect(array('controller'=>'rssfeeds','action'=>'view',$contents11)); $this->redirect($this->referer()); }else{ $this->redirect(array('controller'=>'rssfeeds','action'=>'view',$contents11)); $this->Session->setFlash('失敗です。'); } } } ************************************************************************************** public function makelist() { $rssfeeds = $this->paginate(); if ($this->request->is('requested')) { return $rssfeeds; } else { $this->set('rssfeeds', $rssfeeds); } } } ---------------------------------------------------------------------------------------------------------------------- rssフィードはこんな感じです。 ---------------------------------------------------------------------------------------------------------------------- #!/usr/bin/php <?php header('Content-type: text/html; charset=UTF-8'); require_once ('/var/www/html/s/magpierss/rss_fetch.inc'); define('MAGPIE_CACHE_AGE', 60*5); define('MAGPIE_CACHE_DIR', '/var/www/html/s/cache/'); define('MAGPIE_OUTPUT_ENCODING','UTF-8'); $urls = array( '*********************************'); $items = getRssList($urls); echo '<ul>'; foreach ($items as $item) { $href = mb_convert_encoding($item['link'], "UTF-8", "auto"); $title = mb_convert_encoding($item['title'], "UTF-8", "auto"); $description = mb_convert_encoding($item['description'], "UTF-8", "auto"); $megami = mb_convert_encoding($description, "UTF-8", "auto"); ************************************************************************************** $all = 'http://urls.api.twitter.com/1/urls/count.json?url='.$href; $Rits = file_get_contents($all); $Olfe = mb_convert_encoding($Rits, 'UTF-8', 'auto'); $data = json_decode($Olfe); $tweets = $data->count; ************************************************************************************** $checkman = db_check_urls($href); $checkman2 = db_check_pr($title); $nowtimes = date('Ymd'); if($checkman == 0 &amp;&amp; $checkman2 == 0){ #$hrefs = urlencode($href); db_put_urls($nowtimes,$href,$title,$description,$tweets); echo "<li><a href=$href>$title</a><br>$megami<p>$tweets</p><p>$checkman</p></li>"; }else{ } } echo '</ul>'; ************************************************************************************** function getRssList($urls) { $rssitems = array(); foreach ($urls as $url) { $obj = fetch_rss($url); $rssitems = array_merge($rssitems, $obj->items); } return $rssitems; } ************************************************************************************** function db_check_pr($japanese){ $moji = mb_substr($japanese,0,2); if($moji == 'PR'){ return 1; }else{ return 0; } } ************************************************************************************** function db_check_urls($href){ require '/var/www/html/s/database_conf.php'; try { $db = new PDO($dsn, $dbUser, $dbPass); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = 'SELECT count(*) AS count FROM rssfeeds WHERE urls = :language'; $prepare = $db->prepare($sql); $languages = array($href); foreach ($languages as $language) { $prepare->bindValue(':language', $language, PDO::PARAM_STR); $prepare->execute(); $result = $prepare->fetchColumn(); if ($result > 0) { return true; }else{ return false; } } } catch (PDOException $e) { echo 'エラーが発生しました。内容: ' . h($e->getMessage()); } function h($var) { return htmlspecialchars($var, ENT_QUOTES, 'UTF-8'); } } ************************************************************************************** function db_put_urls($nowtimes,$href,$title,$description,$tweets){ require '/var/www/html/s/database_conf.php'; try { $db = new PDO($dsn, $dbUser, $dbPass); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sikibetu = 5; $moto = "アニゲー速報VIP"; $sql = 'insert into rssfeeds (id, time,urls,title,contents,tweets,times,kubetu,teikyo) values (?, ?, ?, ?, ?, ?, ?, ?, ?)'; $prepare = $db->prepare($sql); $prepare->bindValue(1, 0, PDO::PARAM_STR); $prepare->bindValue(2, $nowtimes, PDO::PARAM_STR); $prepare->bindValue(3, $href, PDO::PARAM_STR); $prepare->bindValue(4, $title, PDO::PARAM_STR); $prepare->bindValue(5, $description, PDO::PARAM_STR); $prepare->bindValue(6, $tweets, PDO::PARAM_STR); $prepare->bindValue(7, 'cast( now() as datetime)', PDO::PARAM_STR); $prepare->bindValue(8, $sikibetu, PDO::PARAM_STR); $prepare->bindValue(9, $moto, PDO::PARAM_STR); $prepare->execute(); } catch (PDOException $e) { echo 'エラーが発生しました。内容: ' . h($e->getMessage()); } } ?>
---------------------------------------------------------------------------------------------------------------------
**************************************************************************************
参考にした書籍
CakePHP2 実践入門 (WEB+DB PRESS plus)
CakePHP2 実践入門 (WEB+DB PRESS plus)
作者: 安藤祐介,岸田健一郎,新原雅司,市川快,渡辺一宏,鈴木則夫
発売日: 2012/09/29
購入: 5人 クリック: 165回
Webアプリ開発を加速する CakePHP2定番レシピ119
Webアプリ開発を加速する CakePHP2定番レシピ119
**************************************************************************************
一番難しいところはtwitterログインとwebサイト連結でした。
ツイート数でランキングしてます、ネットの話題を見つけられます。
ホームページビルダーを使用しています。
今のホームページビルダーは昔と違って高機能ですね。
テンプレートも何種類もあって今はすごいです。
に分かれています。
今更cakephpを使っている人は少ないかもしれませんが、
twitterアカウントあるといつでも参加できますので、
VB+Oracleのクラサバのプロジェクトのところに派遣された。
↓これみたいに、SQLを実行する前後を BeginTransaction〜commit/rollback で挟んでいるのだけど、
transaction = connection.BeginTransaction(・・・) command.CommandText = "INSERT INTO ・・・" command.ExecuteNonQuery() transaction.Commit()
↓のように、commandとtransactionを関連付けないと、トランザクション関係なく実行されちゃうよな。
transaction = connection.BeginTransaction(・・・) command.Transaction = transaction command.CommandText = "INSERT INTO ・・・" command.ExecuteNonQuery() transaction.Commit()
プロジェクトでトランザクションを使っているところを全部確認したけど、一箇所もcommandとtransactionを関連付けてるところがなかったわ。
まあ何年もまえからやってるプロジェクトで問題になってないんだから、俺が指摘して問題にすることもないかな。
あと、Oracleに接続するユーザーとパスワードが.iniに保存されていて、それもいいのかよって感じだったわ。
アプリ自体にはログイン機能とか権限によってデータのアクセス制限があるのに、アプリ経由しないで直接Oracleに接続したら全部の情報見放題になるわ。
開発現場は、派遣のPCはネットに接続させないとか生データは見せないとか情報漏洩に神経を使ってるに、実際に運用されるであろう現場ではゆるゆるっていう。