【つらつらメモ】【#2】javaが動く仕組み

メモ投稿の第2弾、javaが動く仕組みについてです。

javaはどこでも動く」という話を昔から耳にしていますが、改めてなんでどこでも動くのかについて調べた結果を書いていきたいと思います。

 

【背景】

アーキテクチャについて考えていた時に冒頭にでてきた言葉を思い出して、素直になんでjavaはどこでも動くのにほかの言語だと動かないのかということが気になって調べてみました。 

 

【結果】

結論としては、javaを動かすときに使用しているJVM(java virtual machine)が各OSの差異を吸収しています。(実際はWindows用のjvmMac用のjvmがあるみたいですが。)

なのでjavaのコード書いてjvm上で動かしさえすれば、あとはその資源をどの環境にもっていっても動作させることができます。

 

【補足】

プログラムが動作するときの仕組みについて・・

jvmについて調べている最中に「インタプリンタ型言語」、「コンパイラ型言語」という言葉が出てきたので、それらについてもこの場で触れておきます。

javaは「コンパイラ型言語」にあたり、ソースコードを一度PCが理解できるバイトコードへと変換し、その後実行するという仕組みをとります。特にjavaに関してはjvm内にJIT(Just In Time)コンパイラというものが存在し、バイトコードの実行をより効率的に行えるような仕組みが備わっています。

一方、「インタプリタ型言語」はソースコードを実行する際に1行ずつバイトコードへと変換し、実行するという仕組みをとります。一度に全コードをバイトコードへと変換する「コンパイラ型言語」と比較すると、実行速度が遅くなるというデメリットがありますが、1行ごとに実行→デバッグが可能であるというメリットもあります。

 

次回はnode.jsについて書きたいと思います。

 

【参考】

qiita.com

tech-camp.in

【つらつらメモ】【#1】アーキテクチャについて

久々の更新となります。

ここ1年かなり忙しいプロジェクトに参画しており勉強する暇がないので更新が滞っていました。今は平和なSIプロジェクトになり少し余裕ができてきたので日々学んでいることのアウトプットとして何かしら投稿していきたいと思います。

 

【背景】

現プロジェクトにて今時にしては珍しく(?)フルスクラッチ開発をすることになり、まずどいうアーキテクチャがいいんだろうかという話から始まっております。

僕は開発者としてコーディングしたことはあるのですが、どんなミドルウェアがいいとか、そもそもアーキテクチャって何だ?の状態であることにいまさらながら気づきまして、改めて1からわからないことを調べていこうと思った次第です。

 

【結果】

アーキテクチャは一言でいうとシステムの全体図です。

じゃあシステムって何だ、というと下図のようなハード、OS、ミドル、アプリの構成で作られているものだと思っています。

f:id:yoiko0328:20201103190506p:plain

 アーキテクチャはそれぞれの箱をより詳細化したもののイメージととらえています。

[アプリケーション]

ユーザの目に触れる部分、一般的にアプリと言われてイメージする部分

詳細化した場合は、アプリケーションの箱にMVCモデルやAction、Store、Stateなどの役割を表した箱を置いていくイメージです。

 

[ミドルウェア]

ミドルウェアはアプリケーションとOSの間をとりもつ存在

OSにミドルウェアがインストールされることでアプリケーションを作れるようになります。各サーバにミドルウェア製品をインストールすることでシステムを構築していきます。

-webサーバ(apacheやnginx):画面描画などの静的コンテンツを返す、APサーバから返却された動的情報の表示など

-apサーバ(tomcatなど):webサーバから来たリクエストを処置処理

-dbサーバ(postgreSQLMySQLなど):dbを入れる箱

詳細化した場合は、フロントエンドからバックエンドまでを構成する箱の下にそれぞれのサーバ上で使用するミドルウェア製品を書いていくイメージです。

 

[OS]

WindowsMacLinuxなど、PCやサーバとして動作させる基本的なソフトウェア

詳細化した場合は、使用するOSソフトウェアを記載するイメージです。

 

[ハードウェア]

サーバなどの物理的なもの

詳細化した場合は・・あまり詳細化して書くものではないような気もします。

 

以上が僕が調べたアーキテクチャについてです。

 

【補足】

調べていく中で出てきた疑問として、ソフトウェアという言葉があります。

ミドルウェアやハードウェアはシステムの構成図に表れていますが、ソフトウェアは同じような言葉なのにどこにも出てきていないと思い調べてみました。

簡単に言うとソフトウェアはハードウェアと対比される言葉でした。

つまりシステムを構成する中で物理的(ハード)なもの以外はすべてソフトウェアというとらえ方になると思います。

なのでミドルウェア製品もすべてソフトウェアになります。同じような言葉なのに使われ方が違うので混乱するときもありましたが、これで少し頭がすっきりしました。

 

【初心者】expressでwebアプリ開発をするときのフォルダ構成【node.js】

こんにちは、よいこです。

expressでwebアプリを作るときにふと正しいフォルダ構成って何なんだっけ?と思い色々調べてみました。

【背景】

node.jsを勉強するにあたってwebアプリを作りながら勉強したいと思い、単純なじゃんけんアプリをつくってみました。ただ動くものという意味合いでは考える必要はないのですが、どうせ作るならあるべき形を目指したいと考えフォルダ構成やソースコードの適切な分離をしてみました。

 【結論】

結論としては以下の構成になりました。ここに至るまでの経緯については後述しますが、ここではフォルダ構成について簡単に説明します。

トップディレクトリのsampleからserver.js (expressのmiddleware設定やその他モジュールの宣言を行う)、node_modules (npm installでインストールしたもろもろが入っている)、public (jsやcss、画像ファイルなどのクライアントで使用するファイルを格納する)、routes (httpリクエストに対して処理をするメソッドを記述したルータを格納する)、views (htmlファイル、ejsファイルなどのviewを格納する)

 sample
├package-lock.json
├package.json
├server.js

├─node_modules

├─public
│ ├─css
│ ├─image
│ └─js

├─routes

└─views

 

【ここに至るまでの経緯】

まずおおもとのフォルダ構成案としてはexpress-generatorという雛形作成ツールで自動生成したものを参考にしています。express-generatorを使用した場合は上記のフォルダ構成に加えて、./bin/www というファイルが作成されます。express-generatorでフォルダ構成を作成した場合はexpressでサーバを起動するときにまずこのwwwファイルが呼ばれ、そのあとにserver.jsが呼ばれるようです。(npm start) (自分で動きを追っているわけではないので確実にそのように動いているとは言えませんが)。一方、express-generatorを使わずに手動でファイルやフォルダを作った場合はbinフォルダが存在しないのでターミナルから直接server.jsを起動します。(node ./server.js)

もともと自分1人で作る簡単なアプリ程度ではserver.jsに全ての処理を記載しても大した量にならないため問題はないです。

ただroutesフォルダ配下に存在するjsファイル類はhttpリクエストのURLパターンが増えるにしたがって増えていくため、すべてをserver.jsに記載するよりもリクエストパターンによってファイルを分けたほうが管理やメンテがしやすいと思いフォルダを分けました。

viewsフォルダにcssやjsなどのフォルダを設置しない理由としてはexpressの公開フォルダ設定があります。server.js内に以下の記載をすることで、publicフォルダ内の資源をクライアントからアクセスできるようにしています。

app.use(express.static('public'));

以上がこのフォルダ構成に至った経緯になります。

結局express-generatorで自動生成したフォルダ構成と同じになっているのですが、ただ漫然と自動生成されたフォルダを使用するのではなく、このフォルダ構成になるに至った理由を知っておくことで、今後開発を進めていく中で資源配置に迷ったときにも正しい判断ができるのではないかと思います。

【最後に】

次回は最近は待っているfirebaseの環境構築と簡単なデモアプリ作成についてご紹介したいと思います。

使ってみて思ったのですが、firebaseというサービスは素晴らしいです。とりあえずよくわかってないけどアプリを作ってみたいんだ!という方にもお勧めできるくらい簡単に環境構築、外部への公開ができます。お楽しみに。

 

【初心者】じゃんけんアプリ作ってみた(expressとsocket.ioでセッションの共有)【node.js】

こんにちは、よいこです。

初投稿ですが、日々勉強したことを備忘録的に残していこうという思いではじめました。
今日はexpressとsocket.ioでセッションを共有する方法についてまとめたいと思います。

【背景】

最近流行ってるし、今後も続きそうだなーという思いでnode.jsを勉強しはじめたものの、ただ勉強するだけではつまらないと思いアプリを作りつつ勉強しようと思いました(ちなみにこの時点でnode.jsの知識はほぼゼロ。サーバサイドをjsで記述できるくらいしか知らない始末。。なんならjsも大してわかってない。)。

何も知らないのでHello world的な感覚でとりあえずじゃんけんアプリでも作ってみるか、と思い色々しらべていくにつれあれもやりたい、これもやりたいとなり結果つまずくことに・・・。かなり時間がかかったもののその中で学んだことをちょこちょこと書いていきたいと思います。

今回はexpressのセッションとsocket.ioのセッションを共有するよ!というお話。

【モジュール】
・express (4.17.1)
・socket.io (2.2.0)
・express-session (1.16.2)
・express-socket.io-session (1.3.5) ←※これが今回の要!
・http (expressに付属?)
・ejs (2.6.2)
・body-parser (1.19.0)

【手順まとめ】
0. 各種モジュールをプロジェクトフォルダにダウンロード (npm install --save モジュール名[ex:npm install --save express])
1. モジュールの使用宣言[ex:const express = require('express')]
2. express-sessionの設定[app.use(session)]
3. socket.ioとのセッション共有設定[io.use(sharedsession(session))]
4. 各種routerの使用宣言
※順番が重要です。この順番を適当に書いていたために一向にうまくいかず・・。

 【フォルダ構成】

 socketsample
├package-lock.json
├package.json
├server.js

├─node_modules

├─public
│ ├─css
│ │ duel.css
│ │ login.css
│ │ main.css
│ │
│ ├─image
│ │ p300x300.jpg
│ │ r300x300.jpg
│ │ s300x300.jpg
│ │
│ └─js
│ duel.js
│ index.js

├─routes
│ duel.js
│ index.js

└─views
duel.ejs
index.ejs

ソースコード

https://github.com/yoiko0328/socketsample

server.js

// モジュールの読込
const express = require('express');
const ejs = require('ejs');
const bodyParser = require('body-parser');
const app = express();
const http = require('http').Server(app);
const PORT = 3030;
const io = require('socket.io')(http);
const sharedsession = require("express-socket.io-session");
const session = require("express-session")({
    secret: "my-secret",
    resave: true,
    saveUninitialized: true,
    cookie: {
        httpOnly: true,
        secure: false,
        maxage: 1000 * 60 * 30
    }
});

// expressのテンプレートエンジンにejsをセット
app.set('ejs'ejs.renderFile);

// ミドルウェア関数使用宣言
app.use(session);
app.use(bodyParser.urlencoded({ extended: true }));

// publicフォルダの公開
app.use(express.static('public'));

// expressのsessionとwebsocketのセッションを共有
io.use(sharedsession(session));

// router使用宣言
app.use('/'require('./routes/index'));
app.use('/duel'require('./routes/duel'));

// ポートのlisten開始
http.listen(PORT, () => {
    console.log('server listening. Port:' + PORT);
});

/* websocketの処理 */
var player1 = "";
var player2 = "";
var room = "";
var selectedHand_1 = "";
var selectedHand_2 = "";
var win = 0;
var def = 0;
var draw = 0;
var duel = 0;

io.on('connection'socket => {
    /* duelページの処理 */
    // プレイヤー名のSet
    socket.on('checkUserName', () => {
        if (player1 === socket.handshake.session.userName) {
            socket.join(room);
            if(player2){
                io.to(room).emit('start'player1player2room);
                io.to(room).emit('showResult'windefdrawduel);
            }
        }

login.js

const express = require('express');
const router = express.Router();
var title;

// GETリクエス
router.get('/'function(reqres) {
    title = 'Login';
    // セッションに名前が保存されていればbattleページへ遷移
    if (req.session.userName) {
        title = 'Duel' + '(' + req.session.userName + ')';
        res.redirect('http://localhost:3030/duel');
    }else{
        res.render('.././views/index.ejs', { title: title });
    }
});

// POSTリクエス
router.post('/'function (reqres) {
    title = 'Login';
    res.render('.././views/index.ejs', { title: title });
});

module.exports = router;

【結果】

f:id:yoiko0328:20190916000453p:plain

無事にセッション情報の共有ができました!

【最後に】

これからも日々はまったポイントについて投稿していきたいと思います。

取り急ぎはexpressの使い方、socket.ioの使い方については別途記事を書いていく予定です。