二重サブミットのテストにはクリック連打ツールを用いる

Webシステムでは、同一のサブミット(リクエスト)が二重送信されることによる障害が起こり得ます。
二重サブミットが発生する原因としては、以下の3つが挙げられます。

  1. サブミットボタンを連打する
  2. ブラウザの戻るボタンで遷移元の画面に戻り、再度サブミットボタンを押下する
  3. サブミット後に遷移する画面で、ブラウザよりリロード操作が行われる

これらの原因による二重サブミットは、実装により回避することができます。
回避できているかどうかは、1~3の操作を行うことでテストすることができます。


ここで、1の操作については、手動でのクリックでは発生しないことがあるので、注意が必要です。
手動の場合は約0.1秒おきにクリックするのが限度だと思うのですが、端末やWebシステムの処理速度が早すぎる場合、手動で2回目のクリックを行う前に画面遷移が行われてしまい、二重サブミット対策の実装が行われていないのにも関わらず二重サブミットの問題が発見できないことがあります。

そこで、1の操作を試す場合は、クリック連打ツールを試すのが有効です。
クリック連打ツールであれば、0.01秒おきや0.001秒おきのクリックが可能になり、処理速度が早すぎる場合にも二重サブミットの問題をより高い精度で発見することができるようになります。

以下は、自作のWebシステムで、クリック連打ツール「連打くん」を試した結果です。
自作のWebシステムは、掲示板に文章を投稿するという簡単なものであり、クリックでは簡単に二重サブミットが発生しないほど性能は良いです。
このような性能が良いシステムに対しても、連打くんで0.01秒おきにクリックを行うことで、二重サブミットの発生を確認することができます。

・実行前

・実行後


今回の記事で使用した自作の掲示板のWebシステムは、先日、株式会社サイゼントから発売した書籍「絶対にJavaプログラマーになりたい人へ」にて解説しています。

今回の記事で説明した内容は書籍の範囲から外れた発展的な内容ですが、発展的な学習を行うための基礎を固める上で最適な書籍だと思っておりますし、書籍で作成するような簡単なプログラムが手元にあれば今回の記事で見たように技術の検証もはかどります。

また、株式会社サイゼントでは、Javaエンジニアになりたい人向けのプログラミングスクール「サイゼントアカデミー」をオープンしています!
(前述の書籍をテキストとして用いたカリキュラムとなっています)
ご興味のある方はサイゼントアカデミーのページをご確認下さい。

java:オブジェクト指向を利用する本当の理由

オブジェクト指向を利用する理由として、プログラミングの入門書には
「オブジェクト指向を用いると、現実世界をプログラミングでそのまま表現できる」
という意のことが書いてあることが多いです。
その例として

  • 犬に「ワン」と鳴かせ、猫に「ニャーン」と鳴かせる
  • 乗用車に普通に走らせ、レーシングカーに速く走らせる

といった例が用いられることが多いです。

しかし、実務での使われ方を見ると
「現実世界をプログラミングでそのまま表現する」
というのは、目的ではなく手段と言うべきものです。
実務では
「ソースコードから重複を取り除き保守性を高めるため」
という目的で使用されます。

現実世界の関係性を機械の都合に置き換えると、ソースコードに重複が発生しやすくなります。
そこで、「継承」や「ポリモーフィズム」(同じメソッド名の指定でオブジェクト毎に異なる処理をさせること)といった特徴を持つオブジェクト指向を適用することで、現実世界の関係性をそのまま記述することができるようになり、重複の発生を防ぐことができるようになります。
(同じく、オブジェクト指向の特徴として挙げられる「カプセル化」も、オブジェクト指向のルールを守らせるという意味で強力な特徴です)

目的が保守性の向上であるため、現実世界では意識されにくい「思考ルーチン」「出力機能」といったものも、クラス化されることがあります。
また、保守性の向上に繋がらないのであれば、現実世界にあるものをクラスとして記述しないこともあります。

重複を取り除くことによる保守性向上、というのはイメージしにくい所だと思いますので、以下ではJavaのサンプルコードを用いて説明していきます。


今回のサンプルコードでは、「乗り物に乗って、タイミングを見計らって、乗り物を走らせる」という処理を実装していきます。
「乗り物に乗る」という処理と「乗り物を走らせる」という処理は別々のタイミングで実行する必要があるので、別々に実装する必要があります。
また、乗り物は複数種類があり、それぞれの種類毎で異なる処理を行う必要があるとします。

オブジェクト指向を使用しない場合は、下記に示すようなサンプルコードになります。

【オブジェクト指向を使用しない場合のサンプルコード】

・OOPTestMain.java

【サンプルコードの実行結果】

「乗り物に乗る」という処理と「乗り物を走らせる」という処理は、別々のメソッドとして実装しています。
乗り物の種類毎で処理を分ける必要があり、オブジェクト指向を使用しないサンプルコードではフラグ変数により分けています。

注目するべきは、各々のメソッドの中でフラグ変数を参照していることです。
各々のメソッドの中でフラグ変数を参照しているため、フラグ変数を参照する箇所はメソッドの数だけ存在することになります。
フラグ変数の参照方法が変更される場合、例えば「自転車」を示すフラグが2から3に変更になる場合、修正する箇所もメソッドの数だけ存在することになります。
(具体的な修正箇所はサンプルコード中にコメントで示した通りで、今回の場合は2か所です)
修正箇所が増えることで保守性が低下します。具体的には、修正漏れのようなミスが発生しやすくなります。


サンプルコードにオブジェクト指向を適用すると下記のようなコードになります。

【オブジェクト指向を使用する場合のサンプルコード】

・OOPTestMain.java

・OOPTestVehicle.java

・OOPTestCar.java

・OOPTestBicycle.java

注目するべきは、ポリモーフィズムを使用することで、フラグ変数参照に相当する記述を削減できていることです。
フラグ変数の参照に相当する処理としては、クラス名の参照がありますが、クラス名に変更が発生したとしても修正箇所は1カ所に留まるため、保守性が向上します。


今回の記事は、Javaプログラマーとして活躍し始めた後に意識するべき内容であり、入門レベルよりも少し高度なものになります。
しかし、意識するのとしないのとでは、プログラムをリリースした後の保守のしやすさが変わってきます。
指示されたものを作って終わりではない、お客様からの信頼を得られるシステムを主体的に作るためには、こうした設計思想も学ぶ必要があります。

設計思想を学ぶ上では、前提知識として、プログラミング言語の基礎的の文法の理解が必要になります。
先日弊社から発売した書籍「絶対にJavaプログラマーになりたい人へ」で基礎的な文法の理解を固めることで、今回のような設計思想の話も理解しやすくなるのではないかと思います。
(興味がある方は是非とも購入のご検討を!)

Java:リテラル用の領域の確保について

Javaの変数の型は、プリミティブ型と参照型に大別されます。
そして、変数の値が同じであるかどうかを確認する場合、プリミティブ型は == で同じ値であることを確認できる(同じ値の場合はTrueになる)のに対し、参照型の場合は原則として == では確認できず、equalsメソッドを使う必要があります。

しかし、参照型の場合であっても、== で確認できる場合があります。
それは、参照型の変数にリテラル(ソースコード内に直接記述された定数値)を直接代入した場合です。

以下で、順番を追って説明していきます。

【メモリーへの値の保持の方法】

変数の値はメモリーに保持されます。
メモリーは1バイト(8ビット)ずつ細かく区分けされており、それぞれの区分けについて「アドレス」と呼ばれる値により一意に場所を特定します。
(アドレスのバイト数は、64ビットOSの場合は8バイトです)

プリミティブ型も参照型も、「メモリーに保持される」ということは変わりませんが、メモリーに保持する値は変わります。プリミティブ型変数では値そのものをメモリーに格納するのに対し、参照型変数ではメモリー上にその変数用の保存領域を確保した上で、その保存領域の場所を指し示すアドレスを変数の領域に格納します。

例として、以下のソースコードについて考えます。

このソースコードの場合のメモリーのイメージは以下です。
プリミティブ型変数の「i1」と、参照型変数の「il1」では、値の保持の方法が異なります。

【リテラル用の領域の確保】

リテラルの場合は、リテラル用の領域が別途確保されます。
そして、同じ値のリテラル値が複数の箇所で記述されていたとしても、全ての箇所において同じ領域が使いまわされます。

参照型変数でインスタンス化した(newした)場合は、仮に同じ値だとしても、インスタンス化する度に異なる領域が確保されるため、その挙動とは異なるものとなります。

例として、以下のソースコードについて考えます。

このソースコードの場合のメモリーのイメージは以下です。
リテラル値を代入した「s1」「s2」と、インスタンス化で新たに領域を確保した「s3」「s4」では、値の保持の方法が異なります。

【比較を行った場合の挙動の違い】

上記より、リテラル値を代入した場合と、インスタンス化を行った場合では、値の保持の方法が異なります。

この違いが表れるケースの一つとして、値が同一であるかどうかを確認するケースがあります。
リテラル値を代入した参照型変数同士を比較する場合は、インスタンス変数同士の比較と同じように、== で値が同一であることを確認できます。
(もちろん、equalsメソッドでも比較可能です)
しかし、インスタンス化を行った参照型変数の比較では、== で値が同一であることを確認することはできず、equalsメソッドを使用する必要があります。

また、equalsメソッドであれば、リテラル値を代入した参照型変数とインスタンス化を行った参照型変数の比較も可能です。

これをソースコードで示すと以下の通りです。
(実行結果となる標準出力はコメントで示しています)


リテラル用のメモリー領域の確保について深堀りする機会があったので、記事を書きました。

実務では、普段からString型のような参照型の変数をequalsメソッドで比較する癖をつけておけば大丈夫です。
しかし、リテラル代入と == の組み合わせで比較している場合、後の修正でリテラル代入の代わりにインスタンス化を使う箇所が現れると上手く比較できなくなるので、注意が必要です。

転職希望者向けのスクール事業を開始しました!合わせて入門書の販売も開始しました!

この度、株式会社サイゼントにて、未経験でプログラマー転職を希望する方向けのスクールを開講しました!
それに合わせ、スクールのカリキュラムを入門書としてまとめ上げ、Amazon kindleにて販売を開始しました!

今回始めたスクール事業と入門書販売は
「受託開発事業・SES事業を担う会社自ら、新入社員向けの研修をブラッシュアップして外部公開したもの」
であり
「プログラマーとして必要な実践的なスキルを短期間で身につけられる
という特徴を持ちます。

実践的なスキルを身につけることを目的としているため、取り扱うプログラミング言語も、実際の開発現場で採用されることが多いJavaとしています。

今回始めたスクール「サイゼントアカデミー」の情報は以下のページにあります。
https://academy.cyzennt.co.jp/

また、入門書「絶対にJavaプログラマーになりたい人へ」の情報は以下のページにあります。試し読みもできます!
https://www.amazon.co.jp/dp/B0D2VJ3GF2?ref_=cm_sw_r_mwn_dp_89VCZMESGWHP4AHHPEHH&language=ja_JP¤cy=JPY

ご興味がありましたら、ぜひ上記ページにアクセスしてみてください!


スクール事業と入門書販売は、社長の想いに共感した複数の社員達の協力によって、実現したものです。
「このスクールと入門書は世に送り出すべきだ」と考える私を含めた社員達が、忙しい開発業務の合間を縫って時間を捻出し、ようやく公開に漕ぎつけたものです。
また、得意分野が異なる社員達が、それぞれの知見を持ち寄ることで完成したものでもあります。
このスクールと入門書は、一人の力では決して世に送り出せなかったものです。

スクールと入門書に対する私の想いは以下のものです。
これは社長や他の社員達の想いとは異なるものかもしれませんが、そう違わないはずです。


プログラマー転職を目指すための未経験者向けのスクールは決して新しいものではなく、既に様々なスクールが乱立しています。
どのスクールも立派なカリキュラムです。カリキュラムをやりきれば、達成感と自信が生まれると思います。
未経験転職を成功させ、プログラマーとしてバリバリ活躍する、という夢を叶えられそうな内容です。

しかし、スクールで教えているスキルと、実際に実務で必要になるスキル、本当に乖離はしていないのでしょうか?
弊社にもスクール卒業生が入社してくることがあります。しかし、残念ながら、弊社の研修による学び直しが必要になってしまっています。

受託開発事業やSES事業を担う弊社では、未経験の社員に実践的なスキルを教えなければなりません。
実戦的なスキルが身につけることができなければ、受託開発事業ではお客様が望むシステムを納品できず、SES事業ではすぐに契約を打ち切られ、会社として収益を上げることができません。
また、研修期間中の社員は収益を上げることができないため、実践的なスキルを身につけるのに1年も2年もかけるわけにはいきません。

生徒からの入校料が収益源であるスクール専業の企業と異なり、弊社の場合は、お客様から支払われる開発費用が収益源です。
受託開発事業やSES事業を担う弊社には、未経験者に実践的なスキルを効率的に教える責務があり、この責務を果たすことができなければ収益を得ることはできません。
会社が設立された2011年以降、未経験者を採用して社員数を増やしながら13年間事業を継続できていることが、弊社が責務を果たしていること、そして、弊社の研修内容に競争力があることの何よりの証拠です。

そして
そのような競争力のある研修を、社員の間でだけ共有するのは勿体ないのではないか?
と考え、研修を「スクール」という形でブラッシュアップして外部公開したものが、今回開講した「サイゼントアカデミー」です。

また、スクールのカリキュラムの内容は、入門書という形で、別途販売することとしました。

スクールとして外部公開するまで、弊社の研修では、既存の入門書を使用して基礎を学んだ後に弊社独自の課題で応用を学ぶ、という形を取っていました。
しかし、実践的な内容を満遍なく身につけようと思うと、複数の入門書から必要な個所をピックアップする、という形を取らざるを得ませんでした。
これは、入門書の購入費用がかさむというだけでなく、体系的な理解を妨げたり、研修の指示や管理を難しくしたりするものでした。

そこで、研修の外部公開を機に、弊社の研修で教えていることを一冊の入門書という形にまとめ上げ、この問題を解消しました。
入門書「絶対にJavaプログラマーになりたい人へ」を読むことで、実践的な内容を一冊の入門書でワンストップで身につけることが可能になります。

本書には、Javaの基礎のみでなく、以下の内容も含まれます。

  • JUnitを含めた単体テスト技法
  • データベース操作やテーブル設計
  • 代表的なフレームワーク(JSP・サーブレット、Springフレームワーク)

本書には、「レガシー」と言われるような古い技術の内容も含まれます。例えば、「JSP・サーブレット」がそれに該当するでしょう。
しかし、これは「急がば回れ」であると考えており、最前線に立ち続けるベテランのプログラマーと同じように、古い技術から順番に土台を積み上げることで新しい技術も理解しやすくなる、と考えて残している内容となります。
また、社会のインフラを支えるシステムでは、信頼性の確保を最優先するために古い技術を採用していることがあります。そのような社会的な意義が大きいシステムの開発でも活躍することができるようになり、プログラマーとしての仕事の幅を広げることができます。

入門書「絶対にJavaプログラマーになりたい人へ」を購入して勉強するだけでも、プログラマーとしての実務で求められるスキルを効率良く身につけることができます。
しかし、未経験者にとってプログラムの勉強はハードルが高いものです。行き詰まった時にサポートしてくれる人がいた方が安心ですし、より効率的に学習を進めることができます。
また、試しにプログラムを動かしたり、課題を解いたりする中で、本当に自分が書いたプログラムは正しいのか、実務で通用するものなのか、不安になることがあると思います。この不安を解消するためには、実務経験者からのフィードバックが必要になります。

サポートしてくれる人や、フィードバックをくれる実務経験者の協力が欲しくなりましたら、是非ともスクールへのご入校を検討してください!

スクール「サイゼントアカデミー」と入門書「絶対にJavaプログラマーになりたい人へ」は、実務で通用するプログラマーの育成に貢献できるものであると確信しています。