私はSEとして働いていますが、これまでほとんどWeb系の開発をやっていませんでした。
一応、Webサービス経由でデータを取得したりするデスクトップアプリは経験ありましたが、Webをやったという感じは一切なかったので…
そんな人間が、Web開発をやってどう感じたか、徒然と書いてみます。
あと、Java初経験でした。
概要
とあるアプリから呼び出すWeb APIを作成する
サーバー側のDB定義等も作成する
管理機能として、いくつかWebページも作成する
言語
Java 8(Play Frameworkを使用)
開発はEclipseで行うが、デバッグ等はPlayで行う
参加の経緯とか
暇だったからという、あんまりな理由です。
まあ、人手不足だったらしいので、ちょうどよかったという背景もあります。
なお、わたくし、当時はJava未経験でした。
やっぱり、暇だったから選ばれたようでした。
一応、Webの知識はざっくりあったものの、Content-Type
とかAccept
とか、HTTPヘッダーにつける項目の意味が分からない程度には素人でした。
どういうときに、レスポンスは何番を返せばよいのかも、よく分かりません。*1
Javaで苦労した点
ブログに散々書いている通り、C#が得意なので、Javaはそれほど違和感なく触れました。
それでも、苦労したので、その点残します。
文字列
もはや定番ですね。誰もが一度は通る道。
public void Search(User user) { if(user.Name == "xxx") { //何か } }
public void search(User user) { if(user.getName() == "xxx") { //何か } }
ではダメなんです!!!!
リクエストを投げて、
なぜ動かない…?
と思ったのは一度ではありません。
Javaだとこうなります。
public void search(User user) { if(user.getName().equals("xxx")) { //何か } }
これでも、オブジェクト指向はしっかり理解しているつもりで、==
ではダメな理由はわかる*2のですが、C#の優しさに触れた私は甘えていました…
プロパティ
getter、setterが忌み嫌われる理由が、よく分かりました。
エンティティ等を使うと、どうしても必要になる*3ので、我慢して使っていたのですが、可読性落ちていくのが気に入りませんでした。
リスト
List<int> values = new List<int>();
List<int> values = new ArrayList<int>();
という違いは、まあいいのですが、
int value = values[0];
int value = values.get(0);
…
あと、Javaでリストにint入れると、ボックス化とか発生してパフォーマンス的に若干不利でしたっけ?覚えていません。
時間、日付
JavaのDate
が、クソ過ぎて…Calendar
と組み合わせないといけないとか面倒です。
なお、一通り終わって気付きましたが、Java 8 からLocalDateTime
という型が増えていたそうですね。知りませんでした。*4
だったら、Date
は非推奨にしろよ!と正直思いました。
Stream API
C#、というか.NETでは、Linq
を拡張メソッド等を用いて、だれでも簡潔に利用できるよう追加しました。
Javaでは、いったんstream
に変換してから、拡張メソッドっぽい*5ものを呼び出して、Linq
っぽい処理を行います。
…使いやすいですか?
この辺りはC#が神な部分だなぁ、と思いました。
話ずれますけど、C#のLinqは、Pythonに相当影響を受けたように感じました。
Pythonのリスト周りは、標準機能だけで十分に充実してますし。
検査例外
正直、鬱陶しいと感じました。
いつ、検査例外を使うべきか、明確な指針がない*6のは、仕様として導入しておいてどうなんだ?とは思います。
Javaの良かったと思う点
DB周り
開発では、Ebean使って、コードファーストでDBを使っていました。いわゆるentity、で良いのでしょうか?
かなり簡素な仕組みであり、個人的にはなかなか使いやすかったです。*7
でも、entityを直接参照するのは、絶対に止めるべきだとも思いました。別のクラスで隠蔽すべきですね。リポジトリ等を作るべきです。
staticのfind
フィールドを用意するとか、あれは危険すぎます。
列挙型
良かった点として挙げていますが、C#に慣れた身としては、正直違和感がありました。
言語 | 扱い | 特徴 |
---|---|---|
C# | 値型 | Flagsサポート。拡張メソッドで値を紐づけられる |
Java | 参照型 | シングルトン。メソッド等で値を紐づけられる |
Javaの列挙型は参照型ですが、シングルトンだから、==
での比較が可能です。
演算子のオーバーロード、付ければよくないですかね…?
でも、メソッド等を内部に宣言できるのは、使い方次第で有用だと思います。
味をしめて、やりすぎなければ、の話ですが…
幅広く扱える
Play Frameworkもそうですし、Spring Framework などもあるので、そう思うのですが、コミュニティが活発で、新しい仕組み等を入れて、便利にしよう!という柔軟さを強く感じました。
その点、C#は鈍重な部分があると思います。
Entity Framework、便利だけど裏で何やってるか分からんよ…
Prism
難しいよ…
Web開発
気づいたらJavaばかり書いていたので、Webについても。
Play Frameworkを使っていたので、ルーティングについてはファイルに定義し、定義されたメソッドが呼ばれる、という形式です。
なので、Javaの処理を作成したら、実際にリクエスト投げる、という感じで開発していました。
Java開発は、上のような疑問はあったものの、さほど苦労はしませんでした。
始めたばかりの頃
最初に質問したのは、
これ、どうやってリクエスト投げるんですか?
でした。すると、ブラウザにURL打ち込むんです!という、とっても親切な回答が返ってきました。
なお、やってらんないと思うまでに時間はかかりませんでした。
Accept: application-json
の場合どうするんですか?には、テストページ(更新する気なし)を渡されました…
やってられないので
PowerShellでリクエストもレスポンスも確認できるの、作りました。
リクエストは、JSONで送られてきたり、フォームから来たり、URLのパラメーターで来たり、様々でした。 全部PowerShellで実現できるのですが。
とはいえ、いくつかひな型を用意して、ちょっと書き換えたらだれでも使えるようにしただけです。
まさかね、過去に自分が書いた記事が、役に立つとは…
複数ユーザーの自動登録等が必要な場合も、実際のWeb APIを通してPowerShellから呼べるようにしていました。
DBを操作すれば不要なのですが、やはり実際の流れを通したほうが、安心感は得られます。*8
これ、効率的にやれるツールとかあるんですか?あったら教えてほしいです。
PowerShell内容
流れだけですが、こんな感じでした。
- サーバーに入るための資格情報を生成(全てのリクエストに付与する)
- ログインAPIを呼び、セッションを保持する(ログアウトまで使いまわす)
- テストしたいAPIを呼び、結果を受け取って表示する
- ログアウトAPIを呼ぶ
- セッション、資格情報を破棄する
実際にブラウザを使うと、毎回ログインが必要で、非常に面倒でしたが、PowerShellだと実行するだけで良いので、楽です。
もちろんVSCodeを使いました!
リクエストごとにPowerShellスクリプトを作成していたので、呼び出しの付け替えも柔軟でしたし、とても便利でした。
…便利だって教えたのに、先任者は使ってくれませんでした。
そのせいか、途中から自分の生産性は非常に良かったです。
Webページ作成
簡単なものですが、ページの修正も行いました。
静的と動的を使い分ける感じ、なかなか勉強になりました。
とても基礎的なことがわかりました。
- Form要素の各要素は、nameで見分ける
- class要素は半角スペース区切りで複数指定できる
- submitするだけでも、JavaScriptが必要なときはある
- イベントもいろいろある
イベント多用すると、カオスになるというのはよく分かりました。
おわりに
なんか、半分ぐらい文句ですが(笑)
個人的には、Javaだけでなく、思ったより幅広い経験になりました。
なお、単体テストの状況も非常に悪かったので、必要な範囲で作っていました。
いいですね、単体テスト。便利。
JUnitで、サーバーの起動を前提にするとか、DB接続を前提にするとか、正気とは思えません。
どこでも、前提なしに実行できることが重要だと思っています。
でも、Play Framework のFakeApplication
という機能を使っていないので、使ってみたらよいかも、とは思ったりしました。
おわり