セカイモンの裏側

★毎週木曜日更新★ 海外ショッピングサイト『セカイモン』のブログです。私たちスタッフの仕事風景や日々の出来事など、     “セカイモンの舞台裏”とも言える日常を綴っていきます。

ModelをLibraryとして使う

典型的なMVCは好きではないです。

ViewとControllerを分けるのはわかるし納得ができる。

あと、古いフレームワークでDBとのクエリをModelでまとめるのも納得できる。

しかし、今時DBとの接続がフレームワークが設定されていので、あえてModelでSQLの記述と接続を記述しなくてもいいかと思います。

古いフレームワークの場合はmysql_connect()を記述してSQLも書いてとなって色々Model上で記述が多くなってくるかと思います。

しかし、最近では細かい記述はしなくてもよく

$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
   'somevariable' => $someVariable,
 ));

これでコントローラからもSQLが記述できるのでModelで記述する理由もだんだんとなくなってきているかと考えられると思います。

 

そうなってくるとMVCじゃなくてVCだけでもほぼいいんじゃないか?っていうのが考えです。

VCになると結局さらにファットコントローラの思想に行きついてしまいます。

 

とはいえ、じゃぁModelは不要って事になるので使わなくてもいいかってなるけどもライブラリとして使用することでいいじゃないかっていうのが今回のコンセプトです。

 

ライブラリとして使用するつもりが1つのコントローラからのみのアクセスになるってことよくあったり、一回きりの関数の呼び出しが他のコントローラからもModelを呼び出すってこともよくあります。

であれば初めから何がライブラリで何がModelに入れるべき処理っていうのを分けなくてもいいかと思いました。

モダンなフレームワークでのMVCについて懐疑的な意見のページを参照します。

togetter.com

ここに記載されてる事とほぼ同意です。一般的にはMVCにするときれいになるとかロジックはModelに書くべき、ロジックをModelにかけないエンジニアはまだまだ初級レベルみたいな概念がまかり通っているが、MVC自体にメリットがなければVCでもいいのではというのが個人的な意見です。

言いたいことを代替して言ってくれてるからすっきりします。

「LLのフレームワークはコードを整理してるだけ」という意見をModelとControllerの分け方を整理してるだけとくみとって解釈すると、もしコントローラで2000行ぐらいになるファイルになるのであればそれを分割してModelに分けていってもいいかと思います。

変更箇所が多そうな部分を切り出せばバージョン管理上、運用しやすくなるメリットはあるので。

共通ロジックはゴッドオブジェクトとsingle action per controllerの時にまたこの話になると思います。

 

 

 

POSTは全てAjaxで

<form>タグでpostすることを始めに覚える事かと思いますが、システムを作るうえでJavascriptからPOSTした方がいい理由がたくさんあります。

なので今では何も迷わずにPOSTをAjaxで行っています。

ではいつもの通りメリット・デメリットを記載していきましょう。

 

色々他の記事も参考にしようとしたけども、formタグとの比較でのメリットデメリットに対しての記事がなかったので参照なしに書き綴っていきます。

 

メリット

・サーバーに負担がかからない

 まぁ、これはサーバーが多少は負荷がやわらぐかもしれないけども、作り方次第ってのも大きいのと、Ajaxにしたからといって劇的に変わるわけではないと思いますが、一般的にこれが一番初めに想起させるメリットみたいです。

・バリデーションがJSで書ける

 バリデーションをJS上で書くことによってユーザーへのレスポンスをフルリロードしなくても、メッセージをエラーとしてユーザーに見せる事ができるので、ユーザーにとっても、サーバーにとっても都合がいいかと思います。中にはサーバーサイドでしか確認がとれないバリデーションとかもあると思いますが(ユーザーIDがユニークかどうか)、大部分はそうではないので大きなメリットかと思います。

・POST後の表示を考えなくてもいい

 formでPOSTするとPOST後に成功したエラーになったにかかわらずそれなりのHTMLを書いて表現しないといけないです。でも、JSからではエラー内容、通常のレスポンスもJSONで返すだけで済むのでPOSt後のデザインを考える必要もないです。

それに伴ってコントローラ名を**add,**edit, **delみたいに表示はJSON, 他はHTML表示というように分かりやすく分ける事も可能になってきます。

・formタグの位置を気にしなくてもいい?

 JSでは.POST時にどこのタグから取得するかを指定できるので、HTML上どこにタグ、データを置こうが関係なくPOSTできるようになります。hiddenタグでやればformでもできるのでメリットは薄いですが。。

 

デメリット

・コールバックを知らないといけない。

 POSTした後何かしらのサーバーのレスポンスをもとにアクションを起こしたい場合はコールバック上でアクションの関数を実行しないといけないので、慣れてない人には1ステップの障害になるかもしれません。でもコールバックは覚えないとWebエンジニアって言えないくらいですね。

・どこからの実行なのかがわかりづらい

 とんでもないJSファイルからPOSTを実行しているっていうケースもあるので、どこからどのように実行するかのルール決めをしないといけない。

・バリデーションをJS,サーバーサイド両方で記載しないといけない。

 基本はバリデーションはJSで行って、サーバーサイドではサーバでしかチェックすることができないバリデーションのみでOKかと思います。例えば、通常のユーザーの操作以外の悪意があるようなPOSTに対して「あなたは悪意があるPOSTです」ってわざわざ言わなくてもいいので適当にレスポンスは丸めておけばいいかと思います。

 

ずっとWebをやっててJqueryのPOSTでやることになんら違和感もなくやってて、それで運用も問題ないので、POSTは全てAjaxでいいという結論です。

つばめグリルでランチ会

品川駅のつばめグリルに行ってきました。

オフィスから10分ぐらいでつばめ風ハンバーグを4つ パン2つ ご飯2つでした。

 

はじめ銀紙で包まれていたので手で開けてい

 

いのか、フォークで開けていいのかわかららなかったけど、フォークであけました。

ボリュームは多かったです。

f:id:sekaimon-staff:20170609170226j:plain

f:id:sekaimon-staff:20170609170248j:plain

f:id:sekaimon-staff:20170609170305j:plain

これってスイートじゃなくてトマトでした。

 

ORMは無用の長物

無用の用と書こうとしたが、無用の用って役にたたなさそうで、役に立つっていう意味みたいなので、今回の意味とは違うようです。

kotowaza-allguide.com

本題のORMがなぜ不要かというと、ORMのメリットとデメリットを記載しました。

 

メリット

1、SQLがわからなくてもDBからデータを引っ張ってこれる

2、SQLインジェクションからORMで防げる

3、DBに関係なく同じコードで利用できる

4、バリデーションをモデルを書く事で構成が楽になる

 

デメリット

1、各フレームワークによって記述が違う

2、じゃぁこれって一体なんのSQLの実行??っていうのが直感でわからず、

DB::getQueryLogで確認しないと実際のSQLがわかりずらいって事がよくある

3、複雑なクエリに対応していない。またはいちいち調査しないといけない。

 

メリット1のSQLがわからなくてもDBからデータを引っ張ってこれるっていうメリットをよく聞くけど、そもそもプログラマーやっててSQLかけないなんてありえないというかプログラマーとして失格なんで メリットはほぼなし

 

メリット2ORMで記述している限りSQLインジェクションは防げます。

ただ、rawクエリでもplaceholderで防ぐ事ができます。 以下に例

$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
   'somevariable' => $someVariable,
 ));

なのでこれもメリットなし。

 

メリット3はDBがpostgresだろうがmysqlだろうが関係なくコードを書く事ができるという事ですが、基本的にSQLほぼDB一緒なんでこれもメリット薄 という事で

 

メリット4は過去にORMを崇拝してた事があった一番の要因です。Laravelでいうとardentというのを入れればtableを定義したmodelにバリデーションも追加できるので直感的にどのバリデーションが必要かどうかが簡単に記載できる 以下例

class Article extends Ardent {
//class Article extends Ardent {
/**
* The database table used by the model.
*
* @var string
*/
  protected $table = 't_article';
  public $timestamps = false;
  public static $rules = [
    'title' => 'required|between:1,500|',
    'body' => 'required|between:1,1000000|',
    'img' => 'between:1,1000000|',
  ];

}

コントローラで

DB::table('m_article')->insert(
array(
'name' => $_POST['title']
,'draft_name' => $_POST['title']
,'category_id' => $_POST['category_id']
,'created_at' => date("Y-m-d H:i:s")
,'updated_at' => date("Y-m-d H:i:s")
,'order_num' => $_POST['order_num']
,'draft_order_num' => $_POST['order_num']
,'full_txt' => $_POST['free_txt']
,'draft_full_txt' => $_POST['free_txt']
,'id' => $article_id
,'public' => 0
)
);

と書いても、もし文字列以上のバリデーションに引っかかるとexceptionに吐かれる。

自動でmodelで記載してるのでいちいちコントローラでバリデーションのコードを書かなくてすむ。なので、ORMはやっぱり必要と思っていました。

しかし

運用していくうちに割とあしかせになってる事がおおかった。「あれインサートできない??なぜ??あ、Modelのバリデーションで引っかかってた」という事が多かった。

あと、insertする部分を全てAJAXでpostするってなった場合はjavascriptでバリデーションするので結局JS部分でも記述が必要になった。

という2つの理由で結局使わない方がいいというのが今の判断です。

API専用のWebサービスとかであればいいかもしれないですが、バリデーションも全てモデルで結局補えないのでコントローラで書くって事に決めた方がわかりやすいかと思います。バリデーションをコントローラでモデルどっちでまとめるかっていうのも迷ってた時がありました。

detail.chiebukuro.yahoo.co.jp

今となってはFat Controllerの思想なので迷わずコントローラですね。

参考までにcodezineさんのメリット・デメリットです。

http://codezine.jp/article/detail/5858

メリット

メリット1と一緒でSQLを最小限にしたところでそれがメリットにはならない。

  • PDT(PHP Development Tools)やPHPEclipseなどの統合開発環境でメソッドの補完を行うことができるので、スペルミスやAPIを調べる手間が省ける

?? スペルミスはテーブル名とかのミスが多くてそれを防げるのであればいいけどそれは防げないかと。スペルミスがあっても実行してすぐにわかればいいかと。

  • 可搬性が上がる。データベース固有の振る舞いを吸収するので、別のデータベースに移行する際にビジネスロジックの変更を少なくできる

メリット3と一緒ですね。

デメリット

  • スキーマを変更するたびにORMクラスの再構築が必要になる場合がある
  • ORM自体を実行するオーバーヘッドが増える

 

symfonyとかであれば再構築しないときれいにORMクラスが作成されないとかはあったと覚えてます。kohanaとかは更新でORMはクラスを構築できるかと思います。

オーバーヘッドはコードが増えればそうなるかと思います。ないに越した事がないとなるとやっぱりFat Controllerが好きな理由です。

やっぱりSQLが直感で見れないのはわかりにくいわ〜。

JAVA vs PHP

現在セカイモンJAVAPHPの構成でできている。

でもなぜかフロントがJAVAで基幹・バックオフィスがPHPでできている。

まぁ色々な経緯があったからだと思いますが、なかなかいびつ構成です。

セカイモンの成り立ちがそこそこ資金があったせいかOracle RACJAVAというそこそこ工数、お金が必要な構成になっています。

そのせいでクラウドへの移植が困難状況です。

とはいえいずれかは移行はしたい思います。

そこで移行を今現時点での最適された形で移行するとどうなるかを考察してみた。

まずは言語 今現時点でJAVAPHPを使用しているのでどっちがいいのか調査。

個人的には新しいシステムではPHP, Python, Rubyなどのスクリプト言語しかないと思っていたのですがチームのメンバーに聞いてみるとJAVAも捨てがたいという事です。

 

Factors Java PHP Comment
Stability Strong Weak ・The procedural backward compatibility, no real deprecation mechanism, a mess semi platform independent libraries and functionality are just some of the issues the PHP
Java, however, has a clean platform independence and a fairly well-defined number of core libraries with appropriate quality standards
Performance Strong Weak ・While Java was formerly often described as slow, today’s JVMs are highly optimized for speed while the script languages, including PHP, still struggle with this
Existing Modules Strong Weak ・Both in PHP, as well as in Java, there is a lot of modular software, partly with free, partly with non-free licenses. However, PHP modules expose significantly more problems than those written in Java.
・For example, some PHP module developers invented own concepts (e.g. Zend Loader was created by Zend as a substitute for packages) or the modules are only optimized for a framework (like symfony plug-ins).
Java is, especially through the “complicated concepts” such as Class Loading and packages, better prepared for modularization.
・Due to better tool support (Ant / Maven, Javadoc, JUnit) Java Frameworks have easier to install, better documented and tested artifacts.
Integration Strong Weak ・There are many standards implementations in Java (it is almost an industry standard)
・If a PHP Web application should communicate with a specific protocol, the selection of libraries is rather limited (implementations are only partial or rudimentary)
・Integration of PHP applications with other services usually happens through the database layer.
Developer know-how Strong Strong ・SAL has both Java and PHP development know-how
・There are a lot of Java engineers
Overall Strong Weak Java is still one of the leading languages for building web applications (Google, Amazon, ebay, etc)
・The sekaimon web application is a large scale, complex application so security, performance, concurrency, developer productivity, scalability as a language, iteroperability and how easy it is to find engineers who are familiar with the language should be considered.

 

Which is best PHP or java for web server based applications? - Quora

blog.codecentric.de

 

Is Java equally good for creating Web applications as PHP, Ruby and Python? - Quora

softwareengineering.stackexchange.com

www.business2community.com

よくある話では、JAVAは大きぼ開発でPHPは小規模だと。しかしながらFacebookをはじめとしたとてつもなくでかいシステムでもPHPで動いているのでそういったことはないかなっと思います。

あと、セキュリティ面でPHPが懸念点があるという話もよく聞くが結局は使用するエンジニアの作り方によるもので言語によるセキュリティなんてほぼ差がないかと思います。

JAVAが安全だといっても今年のstrutusの問題もあるのでむしろJAVAの方が危険なんじゃないかって勘ぐったりします。 笑

セカイモンstrutsのバージョンが古すぎて今回のセキュリティーホールはなく問題なかったのでなんとも皮肉なはなしです。うれしいやら悲しいやら。

itpro.nikkeibp.co.jp

あと、PHPは開発は早いけど、運用コストが高いっていう話が多いけどもそれも結局フレームワークとか言語の問題よりも運用方法の方が大きく左右する話かと思います

Ruby On Railsでも運用しにくいコードの書き方なんていくらでもあるわけで。。

PHPの最大のメリットはなんといっても「簡単」につきる。

今まで他の言語ができてPHPができないプログラマーを聞いた事がない。 〇〇はできるけど、PHPはできないっと言うプログラマーはおそらくその言語もできないかと思います。

そんな簡単なPHPがなぜネット上で嫌われているのか、PHPがWebの言語としてメインストリームに入りだした頃からずーーーと嫌われてる気がします。

その理由は「簡単」すぎるからだと思います。

業務委託する時PHPプログラマーで仕事を請け負う場合は60万円っていうのが相場かと思います。しかし、Rubyとかだと65万円が相場で、JAVAになると70万円が相場です。

結局エンジニア側からするとPHPは儲からない言語なんですよ。

でも企業、サービスを運営する側からすると安いに越したことがないので絶対PHPの方がいいはず。

プログラマーの単価だけでなくJAVAと比べるとインフラの環境作り、Eclipseの環境作りで相当数時間がとられる。

しかも、Mavenのせいで運用途中で動かなくなったり。PHPでもcomposerの運用次第ではあるかもしれないですけど。

今でもEclipseの環境を作成してプログラミンできるまで最低でも4日かかっているのが現状です。PHPなら3時間で事足りのに。

laravel, struts - Google トレンド

将来的にもlaravel,strusがきれいに交差していることから、将来性でもPHPに分があると思います。

https://trends.google.co.jp/trends/explore?date=today%2012-m&q=laravel,django

https://trends.google.co.jp/trends/explore?date=today%2012-m&q=laravel,rails

ほかの言語のフレームワークと比較しても健闘していると見れるかな。rubyrailsしかないし、phtyonはDjangoしかない中でPHPは不必要にあるのでそこで伸びるっていうのはデファクトスタンダートになれやもしれません。かなりひいき目な見方ですが。。

Tomcatのバージョンも気にしないといけない分どうしても足かせになりそうなので時期バージョンはPHPでやりたいです。

NetworkManagerではまった

ディスプレイ画面付きのCentOSをインストールするとデフォルトで付いてくるらしい。

 

固定IPアドレス降っているにも関わらず書き換わってしまう。

resolve.confも書き換わってしまって????の状態が続いた。

 

調べてみたらNetworkManagerという事が判明

固定IPにしたければすぐに停止すべし

13.3.2. Network Manager の無効化 を参考

 

service NetworkManager stop

で一時的に停止して試しながら、うまくいけば

chkconfig NetworkManager off

で再起動後も停止した方がよさそう。

あと業務でよくある特異なネットワークの設定が必要でした。

 

 

f:id:sekaimon-staff:20170526091558p:plain

 

普段はこんな感じで1つのデフォルトルートだけで問題ないのでが今回の場合は

オフィスとデータセンターのルーティングが必要との事でした。

デフォルトルートだけの場合

[root@localhost ~]# netstat -rn

Kernel IP routing table

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface

192.168.181.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0

169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0

0.0.0.0         192.168.181.210 0.0.0.0         UG        0 0          0 eth0

ルーティングが2つある場合

Kernel IP routing table

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface

192.168.181.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0

192.168.9.0     192.168.181.1   255.255.255.0   UG        0 0          0 eth0

169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0

0.0.0.0         192.168.181.210 0.0.0.0         UG        0 0          0 eth0

これが必要なのでその設定方法は?

vi /etc/sysconfig/network-scripts/route-eth0

このパスに新しいファイルを作成して

GATEWAY0=192.168.181.1

NETMASK0=255.255.255.0

ADDRESS0=192.168.9.0

と設定して再起動すればOK

ここが今回つまったところ

他設定が必要なファイルをまとめると

/etc/sysconfig/network-scripts/route-eth0

/etc/sysconfig/network-scripts/ifcfg-eth0

/etc/resolv.conf

/etc/sysconfig/network

で設定は終わり。

 

MACでOracle にアクセスした時のtips

1.マックのターミナルでの話

oracleが文字化けで激しいのでというか未だにSJISなのでターミナルから入った場合、

文字列が炸裂します。

 

いつも忘れるのでここでメモ

export NLS_LANG=Japanese_Japan.AL32UTF8

マックは関係ないかも

 

2.他のテーブルを参照して更新

oracleでは update ** from ** where ** でもできなかったんで調べてみたら違うSQLのようです。

update (
select
A.ITEM_AMOUNT_DLLR A_ITEM_AMOUNT_DLLR, B.ITEM_AMOUNT_DLLR B_ITEM_AMOUNT_DLLR
from h_mypage_history A INNER join h_sales_dt_left B
on A.SALES_ID = B.SALES_ID
) set
A_ITEM_AMOUNT_DLLR = B_ITEM_AMOUNT_DLLR

 

これで違うテーブルから参照して更新できます。

「テーブル移動」「テーブル複数」って検索してもなかなか出てこなかったんでメモ