さわらブログ

さわら(@xhiroga)の技術ブログ

Webアプリの基本を整理してる

Webアプリの基本の勉強をしている。 前に20歳くらい上のエンジニアの人に基本が大事だって言われたのだけど、だんだん分かりつつあるような...

そもそもプログラムというのが何なのかしっくり来てない。 OSと自分が書いたJavaとかPythonのプログラムが物理的にどう違うのかいまいちわからん。

プロセスが何かしっくりこない。 僕の書いたPythonのプログラムはプロセス上で動いていると思うんだけど、それってOSの動作とどうやってCPUを分けあって使ってるの?とか。

一方で、Webサーバーが何なのかは地道に調べてわかって来た気がする。 まずはOSに頼んで、ソケットっていうファイル記述子の一種を払い出してもらうらしい。 この辺はAPIを叩くようなイメージだと思う!

そのあとでポートをバインドする。ポートの指定が先かと思ったけどそうではないっぽい。 で、リッスンする。これが具体的に何なのかよく分からない。そもそもプログラムが「待つ」という状態が分からない。 プログラムってズバズバ実行されるものだと思うんだけど...待つって何なんだ... どこかにファイルが書き込まれていないかを0.X秒間隔でチェックする、とかならまだ分かるんだけど。

で、このあとそれをHTTPリクエストとして読み取り、うまいこと文字列を区切ってパラメータを読み取って、処理に繋げるんだと思う。 (この辺は『Webを支える技術』が参考になった。)

www.amazon.co.jp

このあとまた分からないのがサーバーが僕の書いたコードを呼び出す仕組みなんだけど...どうやって繋ぎ込むんだろう? Tornadoとかはサーバーに直接プログラムを書き込んでる気がするんだけど、Tomcatみたいなサーバーはどうするのだろうか。

その辺は今この本で学習中。 www.amazon.co.jp

この本に限らず、基礎の勉強会とかしたいな。

Ajaxの使いどころと例外処理について考察

ぜひ意見をください( ´ ▽ ` )ノ
初めは「Ajaxが使えるぞ!」って意気揚々と調べてたんだけど、もしかしたら何にでも使うべきじゃないかも?

※親切なWeb系のお兄さんと話した内容を追記しました (2017/10/08)

そもそもの背景

現場のWebアプリでAjaxを使えることになりそうなので、新機能のうちAjaxを使えるところはそうしたい!
のだけど、Ajax/ 丸ごとリロードの切り分けとか、サーバー側で例外が起きた時の対応がよくわからない。
とりあえずは調べたことをまとめたい。

Ajaxの使いどころ

ちょっとした処理から決済まで重要度を問わずに使えるけど、DOMをゴリゴリ操作するのであれば生Javascript/JQueryはオススメできない。

2000年代の記事では以下のような必要最小限の使い方に抑えているのが多いイメージ。
1. 業務フローの本筋以外で通信が必要なところ
・チャット
SNSへのシェアや認証時のパズルなど
・検索結果など、リストに対するフィルターやソート
・自動補完
2. ダイナミックな動きが欲しいところ
インクリメンタルサーチ

その後フロントエンドのフレームワークが出てきて状況変わったってことかな?

この辺は現場のフロント事情を鑑みて決める(jspみたいなテンプレートエンジンの資産がたくさんあるなら、DOM操作にReactは導入できないよね?)のが良いと思われる。

サーバ側の例外の扱い

最初からやり直させた方がよければ例外ページ、続行させた方がよければページ内のアラートで警告

  1. 最初からやり直させた方が良いケース
    ・決済処理など重要な処理
    → エラーページにリダイレクトさせ、初めからやり直すことを促す。

  2. 続行させた方が良いケース
    ・入力補完やコンボボックスの選択肢など、表示されなくてもユーザーが処理を続けられる場合
    ・リトライしてほしい場合
    → ページ内にエラーメッセージを表示する(例:Twitterでツイートが投稿できない場合など)

参考サイト

Alex Bosworth's Weblog: 10 Places You Must Use Ajax
たくさん引用されているサイト。Ajaxを使うべき6ケースと使わないべき4ケース。ただし昔の記事。

おさかなラボ - 6 Places You Must Use Ajax
↑の記事の内容を間接的にわかりやすく引用してくれている日本語のブログ

How to use AJAX: 5 Real World Examples - Moz
割と最近のAjaxユースケース

リュックサックのファスナー修理してた

もう玉留めも怖くないぞ。はっはっは。
通勤用に使っているリュックのファスナーが外れてしまったので自前で修理した。

そもそも専門店に頼まなかったのは...

縫い目が表に出ない製法のリュック↓↓で、普通に修理すると色々裏返すとかで10000円近くかかるそうだ。
f:id:hiroga_cc:20171007145848j:plain

ほとんど新品買い直すのと同じ値段なので、自前で直すことにした。

# 雑でも安く直す方法があるはずだよね 書いてなかったけど、ファスナーが外れるのは今回で2回目。
外れやすくなっちゃってるので。 f:id:hiroga_cc:20171007150046j:plain

で、前回はファスナーをハサミで切って直した。 f:id:hiroga_cc:20171007150354j:plain

今回はもっと根元から直すよ。

裏地切ったらいい感じにファスナーはめられた。

外側から修正箇所がわかんなくていい感じだ。 f:id:hiroga_cc:20171007150551j:plain f:id:hiroga_cc:20171007150602j:plain f:id:hiroga_cc:20171007150608j:plain

ついでに玉留めもマスターした(次回また忘れてる気がする。。。)
DIYたのしー!!!

Heroku Postgresでサンプルのデータベースを用意する

練習用に手頃なデータベースが欲しくて、しかもWeb上からアクセスしたいことってないですか?
Posgres SQLのデータのリストア用コマンドがローカル以外のDBを対象に取れたので、サンプルデータを投入することができました。めっちゃ便利だ。

仕組み

PosgreSQLには、データベースの中身をテキストなどの形式でバックアップする"pg_dump"コマンドと、その結果をリストアする"pg_restore"コマンドがある。
"pg_restore"コマンドの発行時、ホストやユーザー名などにHerokuで指定された値を入れると良い。それだけ。

やり方

基本的にはこの通りに進める

www.postgresqltutorial.com

違うのは"pg_restore"の引数。

$ pg_restore -d [Herokuが指定したDB名] -h [Herokuが指定したホスト名] -p 5432 -U [Herokuが指定したユーザー名] -W ./dvdrental.tar

Herokuの指定はダッシュボードで確認可能。

f:id:hiroga_cc:20171004224039p:plain

リストアが終わったら...(私の場合は数十秒くらいでした)
¥dtでテーブルを確認。ついでに中身も確認。

::DATABASE=> \dt

                List of relations
 Schema |     Name      | Type  |     Owner      
--------+---------------+-------+----------------
 public | actor         | table | [Heroku Posgresのユーザ名]
 public | address       | table | [Heroku Posgresのユーザ名]
 public | category      | table | [Heroku Posgresのユーザ名]
 public | city          | table | [Heroku Posgresのユーザ名]
 public | country       | table | [Heroku Posgresのユーザ名]
 public | customer      | table | [Heroku Posgresのユーザ名]
 public | film          | table | [Heroku Posgresのユーザ名]
 public | film_actor    | table | [Heroku Posgresのユーザ名]
 public | film_category | table | [Heroku Posgresのユーザ名]
 public | inventory     | table | [Heroku Posgresのユーザ名]
 public | language      | table | [Heroku Posgresのユーザ名]
 public | payment       | table | [Heroku Posgresのユーザ名]
 public | rental        | table | [Heroku Posgresのユーザ名]
 public | staff         | table | [Heroku Posgresのユーザ名]
 public | store         | table | [Heroku Posgresのユーザ名]
(15 rows)

::DATABASE=> select * from actor fetch first 10 rows only;
 actor_id | first_name |  last_name   |      last_update       
----------+------------+--------------+------------------------
        1 | Penelope   | Guiness      | 2013-05-26 14:47:57.62
        2 | Nick       | Wahlberg     | 2013-05-26 14:47:57.62
        3 | Ed         | Chase        | 2013-05-26 14:47:57.62
        4 | Jennifer   | Davis        | 2013-05-26 14:47:57.62
        5 | Johnny     | Lollobrigida | 2013-05-26 14:47:57.62
        6 | Bette      | Nicholson    | 2013-05-26 14:47:57.62
        7 | Grace      | Mostel       | 2013-05-26 14:47:57.62
        8 | Matthew    | Johansson    | 2013-05-26 14:47:57.62
        9 | Joe        | Swank        | 2013-05-26 14:47:57.62
       10 | Christian  | Gable        | 2013-05-26 14:47:57.62
(10 rows)

::DATABASE=> \q

ばっちり。

DBに詳しい人なら普通に気づくのかもしれないね...。

二重送信問題について調べたことをまとめた

戻るボタンと右クリックをアプリ側で禁止にしている現場で働いている。  

ユーザーが同じ更新内容を意図せずに重複して発行しないためで、こういう問題は二重送信問題と言われるらしい。  

(Double Submit Problemって検索したらたくさん出てくるよ)

 

さすがに2017年にもなってそれはダサいと思うので、今風なやり方で二重送信問題を防ぐにはどうしたらいいのか調べてみた。

 

参考にした資料

PRGパターン(後述)について、wikipediaの記事と、その元になったTheServerSide(企業向けJavaアプリの開発者のためのポータルサイト?)の記事が参考になった。  

Post/Redirect/Get - Wikipedia

Redirect After Post

また、NTTデータの「TERASOLUNA(テラソルナ)」というフレームワークのドキュメントが、RPGパターンを含めた対策について網羅的にカバーしている。  

http://terasolunaorg.github.io/guideline/5.3.0.RELEASE/ja/TERASOLUNAServerFrameworkForJavaDevelopmentGuideline.pdf

 

調べたこ

二重送信にはこんな種類がある。

  • 更新完了後にブラウザ側で画面を再読み込み

  • 更新完了後、戻るボタンを押してから再度更新リクエス

  • 更新リクエストを送信後、レスポンスが返ってくるまでに送信ボタンをもう一度押してしまう

  • 更新リクエストを送信するページがブックマークされてしまい、画面遷移が正しくないためにデータの不整合が生じる

 

以下の対策が挙げられる。

  • PRGパターン

  - POSTリクエストを受け取ったら、更新完了などのページにリダイレクトする。

  • 送信ボタンの非活性化

  - 送信ボタンが一度押された時点でisClickedフラグを立て、レスポンスが返ってくるまでボタンが押せなくする。

  - 更新リクエストを送信できる画面を返す際、サーバー側でトークンを発行しておく。クライアントは送信リクエストにそのトークンをくっつける。サーバー側で保管しておいたトークンと一致すればトランザクションを通す。一度使ったトークンはその場で破棄する。

  - 更新リクエストのタイムスタンプとテーブルの最終更新日時を比較し、テーブル側の方が新しければ更新しない。

 

誤りなどのご指摘があればぜひお願いします。

 

考えられること

サーバー側の不整合の防止と、クライアント側で誤って二重送信しないための工夫を分けて考えられそう。

トランザクショントークンでリクエストを検証することは必須とし、ユーザーが誤って更新しないようにボタンの非活性化やPRGパターンの導入をする・・・など。

 

まだ分かっていないこと

  • PRGパターンでブラウザバックが防げるのかわからない。資料によって言っていることが違う。ブラウザごとの挙動の問題?

  • PRGパターンを実装する上で、リダイレクトには実装方法がいくつかあるらしい。ページに埋め込む、httpのヘッダーに埋め込むなど・・・後者の方が良さそうだけど、どうなんだろう?

無料かつWindows対応のデスクトップ版が存在するBootstrapエディター、Pingendo

f:id:hiroga_cc:20170930150920p:plain

レスポンシブWebデザインな感じでサイトのプロトタイプ作ってみたら大変だったので、エディタの導入を検討中。

調べるとWebアプリだったりMacのみ対応だったりなんだけど、現在無料で使えてマルチプラットフォーム対応のPingendo(ピンジェンド)というのがあるようだ。 Electron製のため、Mac/Windows/Linuxをカバーしている。その上Web版もある充実っぷり。

ちなみに名前の由来はラテン語の"Painting"から。Twitterで尋ねたら教えてくださった。気さくだ...!

価格とライセンス

Bootstrap4対応の最新版はbeta期間中は無料とのこと。3系対応の旧版もWebで公開されており、自由に使えるとある。
ライセンスはインストール時に確認可能。無償のベータ版であり、サポートも保証しないことに同意することが使用条件とある。

Pingendoで作ってみた

  • フォームなど、一部の部品はPingendoで生成したものではないです。 gist.github.com

あくまで個人的に、手書きに比べて効率4~5倍くらい?
bootstrap初心者・レスポンシブWebデザイン初心者として手書きでHTML作成→1日(11時間49分)
Pingendo導入後、初回のHTML作成→2時間20分

導入のメリット

  • (他のエディタにも共通して言えるが)HTMLを編集しながらプレビューが見られるため、開発効率が上がる。
  • コンポーネントにマウスオーバーすると当該のソースがハイライトされるので、bootstrap初学者の学習効率が上がる。
  • 既存のコンポーネントや別のページのコンポーネントをコピペできるため、コードの品質が上がる。
  • 画面で編集してHTMLをエクスポートするのではなく、HTMLをそのまま編集→表示できる。
  • よって、HTMLを自分で編集しても問題ない。

導入のデメリット

  • 現状bootstrap以外のフレームワークには対応していない。
  • デフォルトの部品の種類が少なく、結局自分で書くことになる(その場合でも、一度書いたらコピペができるのは良い)
  • GUIで部品を削除すると、不要なdivタグが残っているのに気がつかないことがある。

自分のレスポンシブWEBデザインの何が盲点だったのか

いきなりマルチデバイス対応のWeb画面のサンプルを作ることになったのですが、とりあえず作ってみたらすごく疲れた。 (もっといいやり方あるだろコレ...)と思いながらやってた。いくらか原因がわかったので棚卸し。

問題

グリッドデザインのためのクラス(col-md-12, とかのことを言いたい)を宣言する時に、divタグがやたら多くて疲れた。 ヘッダーのロゴ画像とかタイトルとかがうまくヘッダーに収まってくれず、一部人力で高さや幅を指定してしまった。

仮説

ヘッダーは、専用のクラスがある気がする。 divタグ以外に要素を表すタグを使うべきだったんじゃないだろうか。

結論

グリッドデザインの組み方が悪い。PC用の表示をする時に、1行の中の箱要素の中身まで横に崩す必要はなさそうだ。 ヘッダーは、ナビゲーション関連のクラスを使うのが良さそうだった。

参考にしたサイト

bootstrapのチュートリアルをじっくりみた。 www.tutorialrepublic.com

気がついたこ

ヘッダーについて - 便利なクラスがたくさんある。 - ページのタイトルとかをトップに張り出す時には"navbar-header"。スマホ表示の時にヘッダーを右端に寄せてくれる -