技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

情報処理技術者試験対策「VR・AR」

最近の情報処理技術者試験では、VRとARの違いを知らないと答えられない問題が出題されることがあります。
 
詳しい知名度は以下の通りなのですが、VRという用語に比べて、ARという用語は比較的知名度が低いです。
 
VR認知度は87.6%、ARは34%。『VRビジネス調査報告書2018』が発売 - VR Watch
https://www.watch.impress.co.jp/vr/articles/news/20180124_vrbusiness.html
 
情報処理技術者の試験勉強でARという用語を始めて知ったという方も少なくないかもしれません。
また、このテーマは10年ほど前の情報処理技術者試験では問われなかったテーマなので、昔に受験してそれっきりの方は今でも知らないかもしれません。
 
簡単に言うと、VRとはゴーグル等の機器を装着して仮想現実の中での疑似体験を提供するシステム、ARとは現実世界の中に情報を付与するシステム、という違いがあります。
イメージしやすい例を挙げると、「Pokémon GO」はARです。鳥取砂丘に出向き、スマートフォンのカメラで映し出した砂丘の中にレアポケモンを出現させて、スマートフォン上のスワイプ操作で捕まえる。これがイメージできれば、ARの言葉の意味は一発で覚えられると思います。
 
レガシーなシステムを昔から保守している技術者にとっては関係の無い話に思えるかもしれませんが、レガシーシステムが提供するAPIを通して最新鋭のシステムと連携する、という例は少なくなりません。
将来的にVRやARと連携することもあるかもしれませんので、システムの提案や社外との打ち合わせに備えて、言葉の意味だけでも覚えておいて損はないと思います。
 
----------------------
 
なお、2021年時点では情報処理技術者の出題範囲外だと思いますが、VRやARの他にMRという用語もあるので、こちらも覚えておくと良いでしょう。
MRは、VRとARを組み合わせたようなものです。
現実世界の上に情報が付加されているARとは異なり、VRと同じように機器を通して視覚や触覚による体験を行うことができます。
また、全くの仮想世界での体験となるVRとは異なり、ARと同じように現実世界をベースとした体験となります。
 
----------------------
 
情報処理技術者試験に関する記事の目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

情報処理技術者試験対策「静的解析ツール・動的解析ツール」

情報処理技術者試験では、「静的解析ツールとは何か」「動的解析ツールとは何か」を問う問題が出題されます。
この記事では、これらのツールは何か、何のために使うのか、といったことについて簡単に書いていきます。
 
【静的解析ツールの説明】
静的解析ツールとは、実行しない状態でソースコードのチェックを行うツールです。
コンパイル前に、コンパイルエラーや実行時エラーとなる箇所、若しくはエラーになる可能性が高かったり可読性が低下したりする箇所を見つけ、警告を出してくれます。
エラーや可読性低下につながる箇所を最速のタイミングで見つけることができ、また人間によるソースコードレビューと異なり見落としが出ることもないので、静的解析ツールを適切に使うことで品質が向上しやすくなります。
 
EclipseJavaソースコードを書く時に、未使用のインポートや変数が存在する時に黄色の波線が出た経験はないでしょうか?
静的解析ツールは、その機能をよりリッチにしたものと考えて良いです。
Eclipse自体も静的解析ツールの機能を含んでいると考えて良いと思っています)
Javaの場合、「FindBugs」や「SonarQube」といったツールが代表的な静的解析ツールとして挙げられます。
 
【動的解析ツールの説明】
動的解析ツールとは、実行時にプログラムの実行状態を解析するツールです。
変数の内部状態の表示や、プログラムの呼び出し回数・実行時間の計測、プログラムの命令や分岐の網羅率の計測、アサーションチェック(変数状態等が期待結果と一致していることの確認)等を行います。
単純に実行結果を見るだけでは分からない情報を見ることができるので、バグの調査やテストの実施状況確認、テストの実行結果の確認といった作業を効率良く行うことができるようになります。
 
Eclipseデバッグ機能を使うと、各ステップ毎で変数の内部状態の変化を見ることができます。
Eclipseがサポートするこの機能も、動的解析ツールと呼べるものです。
 
----------------------
 
目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

Base64の説明とjavaでのエンコード・デコードの例

Base64とは、テキストデータやバイナリデータ(画像ファイル、PDFファイル等)を表現する方式の一つです。
以下の64種類の文字と末尾のパディング文字(=)を用いて表現するのが特徴です。
・アルファベット(a~z, A~Z)
・数字(0~9)
・一部の記号(+, /)
 
この表現方式は、一部の文字しか使用できないプロトコルでデータの送受信を行いたい場合に有用であり、ASCII文字しか送受信できないプロトコルでもデータの送受信が可能になります。
有名な所で言うと、電子メール(SMTP)でBase64が使われています。
また、APIでのデータ送受信でも良く使われます。
 
ここで、Base64エンコード・デコードをイメージしやすくするため、2バイト文字(日本語)を Java8 の java.util.Base64https://docs.oracle.com/javase/jp/8/docs/api/java/util/Base64.html)を用いてエンコード・デコードしてみます。
 
【サンプルコード】
・Base64Test.java
import java.util.Base64;

public class Base64Test {

  public static void main(String[] args) {

    // 元の文字列(2バイト文字)
    final String orgStr = "こんにちは!";

    // Base64へのエンコード
    String encodedStr =
      Base64.getEncoder().encodeToString(orgStr.getBytes());

    // Base64からのデコード
    String decodedStr =
      new String(Base64.getDecoder().decode(encodedStr));

    System.out.println("元の文字列      : " + orgStr);
    System.out.println("Base64へのエンコード : " + encodedStr);
    System.out.println("Base64からのデコード : " + decodedStr);

  }

}
 
【実行結果】
元の文字列      : こんにちは!
Base64へのエンコード : 44GT44KT44Gr44Gh44Gv77yB
Base64からのデコード : こんにちは!
 
----
 
なお、今回の記事では触れませんが、バイナリファイルを1バイトずつエンコード・デコードすることで、バイナリデータにも対応できます。
また、Base64エンコード・デコードの方式は公開されており、人気の言語ではライブラリも存在しているので、他の言語でも実装可能です。

Vue.jsに出てくるコロン(v-bind)とアットマーク(v-on)について

Vue.jsのコードに時折コロン(:)やアットマーク(@)が出てきて戸惑う人がいるかもしれませんが、これは省略記法です。
それぞれ、v-bind、v-onを指しています。
 
Vueオブジェクトの変数や関数をHTML側から参照するために、v-bindやv-onを使用します。
 
以下、サンプルコードです。
 
【サンプルコード(v-bind)】
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
 <title>Vue.js - Hello world!</title>
</head>
<body>

<div id="app">
 <!-- 属性では{{ }}構文は使用できない。代わりにv-bindを使用する -->
 <input type="text" v-bind:value="message1"><br>
 <!-- 省略記法 -->
 <input type="text" :value="message2">
</div>

<script src="https://unpkg.com/vue"></script>
<script>
 var app = new Vue({
  // elで指定した値はdivタグのidと対応
  el: '#app',
  // 変数の初期値定義
  data: {
   message1: 'Hello World 1!',
   message2: 'Hello World 2!'
  }
 })
</script>
</body>
</html>
 
【実行結果(v-bind)】
以下のように、Vueオブジェクトの変数の値とHTMLを結びつけることができます。

f:id:akira2kun:20210307200811j:plain

 

 
【サンプルコード(v-on)】
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
 <title>Vue.js - Hello world!</title>
</head>
<body>

<div id="app">
 <!-- v-onによりボタン押下時のベントハンドラ実行が可能になる -->
 <button v-on:click="btnClicked">ボタン1</button><br>
 <!-- 省略記法 -->
 <button @click="btnClicked">ボタン2</button>
</div>

<script src="https://unpkg.com/vue"></script>
<script>
 var app = new Vue({
  // elで指定した値はdivタグのidと対応
  el: '#app',
  // 変数の初期値定義
  data: {
   message: 'Hello World!'
  },
  // 関数定義
  methods: {
   btnClicked(){
    alert(this.message);
   }
  }
 })
</script>
</body>
</html>
 
【実行結果(v-on)】
以下のように、Vueオブジェクトの関数を呼び出すことができます。
これは、ボタン1とボタン2の両方で同じ動きになります。

f:id:akira2kun:20210307200826j:plain



JavaScriptのasync・awaitのサンプルコード

JavaScriptでは、通常は非同期処理となり、重い関数が終わるまで待つということをせず、次の関数に先に制御が移ってしまいます。
そのため、API呼び出しやIO(ファイルの読み書きやDBの読み書き)を伴う関数を呼び出した後に、その結果を元に次の処理を行う、というフローを行うためには一工夫必要です。
 
これを簡単に書くために、JavaScriptにはasync/awaitという文法が用意されています。
この記事では、非同期処理のサンプルコードと、async/awaitを用いて同期処理にするサンプルコードを用意しているので、そのサンプルコードを読めば使い方は理解できると思います。
 
async/awaitを使う上での注意点として、promiseやresolve/rejectとセットで使う必要があるという点があります。
これをセットで使用しないと、同期処理にならない、待った後の処理が実行できない、等のバグになります。
async/awaitはpromiseオブジェクトを簡単に扱うための文法でもあるので、promiseについては別途調べるとより理解が深まると思います。
 
【サンプルコード(非同期処理)】
// すぐ終わる処理
function lightTask() {
 console.log("light");
}

// 1秒かかる重い処理
function heavyTask() {
 const procedure = () => {
  console.log("heavy");
 }
 setTimeout(procedure, 1000);
}

// JavaScriptは通常は非同期なので、heavyTaskの終了を待ってくれない
function exection() {
 heavyTask();
 lightTask();
}

exection();
 
【処理結果(非同期処理)】
C:\tmp>node sample.js
light
heavy

C:\tmp>
 
【サンプルコード(同期処理)】
function lightTask() {
 console.log("light");
}

function heavyTask() {
 // awaitで呼び出される関数ではpromiseオブジェクトを返す必要がある
 return new Promise((resolve, reject) => {
  const procedure = () => {
   console.log("heavy");
   resolve(0); // returnではなくresolveで戻す(これを忘れると制御が戻らない)
  }
  setTimeout(procedure, 1000);
 });
}

// awaitを使用する関数にはasyncをつける
async function exection() {
 let result = await heavyTask(); // awaitで呼び出すことで処理が終わるまで待つ
 // console.log(result); // 0
 lightTask();
}

exection();
 
【処理結果(同期処理)】
C:\tmp>node sample.js
heavy
light

C:\tmp>

Chromeの拡張機能を使用した文字列置換

以前の記事で、URLからJavaScriptを読みこむことでブラウザに表示される文字の変換を試みました。
しかし、URLから読み込ませる方法だと、大量の文字列置換はできません。
 
そこで、今回はChrome拡張機能を使用した文字列置換を試みました。
以下、サンプルコードです。
 
manifest.jsonは、「https://developer.mozilla.org/ja/docs/Web/JavaScript」にアクセスした際に「content.js」が実行される記述としています。
最小限の記述であるため、実際に配布する際には説明を入れたりアイコンをつけたりすると良いでしょう。
 
【構成】
test┳manifest.json
  ┗content.js
 
【サンプルコード】
・manifest.json
{
 "name": "test",
 "version": "1.0.0",
 "manifest_version": 2,
 "content_scripts": [{
  "matches": ["https://developer.mozilla.org/ja/docs/Web/JavaScript"],
  "js": [
   "content.js"
  ]
 }]
}

 
・content.js
document.body.innerHTML=document.body.innerHTML.replace(/JavaScript/g,'[JavaScript]');
document.body.innerHTML=document.body.innerHTML.replace(/ECMAScript/g,'[ECMAScript]');
 
【動作確認】
1.Chromeを開き、下記から「拡張機能の管理」を選択

f:id:akira2kun:20210302230333j:plain

 

2.「デベロッパーモード」をONにし、「パッケージ化されていない拡張機能を読み込む」を選択

f:id:akira2kun:20210302230354j:plain

 

3.サンプルコードが存在するフォルダを選択

f:id:akira2kun:20210302230420j:plain

 

4.manifest.jsonに記述したサイトにアクセスすると、自動で文字列置換が行われる

f:id:akira2kun:20210302230439j:plain

 

5.取り込んだ拡張機能の削除は、「Chromeから削除」を選択することで行う

f:id:akira2kun:20210302230504j:plain

JavaScript:thisの挙動と用途

JavaScriptの初心者を悩ます文法の一つとして、thisが挙げられます。
thisが何を指しているのか、どのような場合に使われるのか、なかなかイメージが難しいと思います。
 
この記事では、その疑問について答えていきたいと思います。
 
今回の記事では、サンプルコードの実行はNode.jsで行います。
また、非Strictモード('use strict'を宣言したりexport句でStrictモードに変更したりしない場合)を前提とします。
(Strictモードの場合は、thisによりグローバルオブジェクトを参照しようとした場合にundefinedになります)
 
----
 
1.thisキーワードの説明
「this」の説明の前に、JavaScriptとオブジェクトの関係について簡単に説明します。
JavaScriptは、必ずオブジェクトの中で実行する必要があります。
実行環境(ブラウザやNode.js)は「グローバルオブジェクト」と呼ばれるオブジェクトを用意しており、自分でオブジェクトを定義しない場合はグローバルオブジェクトから各々の処理が実行されています。
(ブラウザの場合のグローバルオブジェクトは「window」、Node.jsの場合のグローバルオブジェクトは「global」となります)
 
「this」キーワードは、記述箇所を動かしているオブジェクトを参照します。
自分で定義したオブジェクトから記述箇所を呼び出している場合はそのオブジェクト、そうではない場合はグローバルオブジェクトを返します。
 
【サンプルコード】
function func1() {
 console.log(this); // 関数を呼び出しているオブジェクトを参照
}
func1(); // グローバルオブジェクトの関数を実行
let obj = {}; // 独自のオブジェクト定義
obj.func = func1; // 独自のオブジェクトに関数を定義
obj.func(); // 独自のオブジェクトの関数を実行
 
【実行結果】
・1回目の関数呼び出し
Object [global] {
 global: [Circular],
 clearInterval: [Function: clearInterval],
 clearTimeout: [Function: clearTimeout],
 setInterval: [Function: setInterval],
 setTimeout: [Function: setTimeout] {
  [Symbol(nodejs.util.promisify.custom)]: [Function]
 },
 queueMicrotask: [Function: queueMicrotask],
 clearImmediate: [Function: clearImmediate],
 setImmediate: [Function: setImmediate] {
  [Symbol(nodejs.util.promisify.custom)]: [Function]
 }
}
 
・2回目の関数呼び出し
{ func: [Function: func1] }
 
2.callやapplyを用いて関数呼び出しした場合のthisの参照先
関数をメソッドチェーンで「call」や「apply」と繋ぐことで、呼び出される関数の中でthisが参照するオブジェクトを指定することができます。
オブジェクトの指定は「call」や「apply」の第一引数で行います。
 
また、「call」や「apply」は第二引数以降も指定が可能です。
第二引数以降では、関数呼び出しの際の引数を指定することができ、呼び出される関数の中では「arguments」キーワードでそれを受け取ることができます。
「call」は第二引数、第三引数、第四引数…といった具合に変数を一つずつ定義し、「apply」は第二引数に配列形式でまとめて変数を定義します。
 
【サンプルコード1】
function func1() {
 console.log(this);
}
let obj = {hoge: "hoge"};
func1.call(obj); // this=objと結びつけることができる。
func1.apply(obj); // 同上
 
【実行結果1】
・1回目の関数呼び出し
{ hoge: 'hoge' }
 
・2回目の関数呼び出し
{ hoge: 'hoge' }
 
【サンプルコード2】
function func1() {
 console.log(this);
 for (var i = 0; i < arguments.length; i++) {
  console.log(arguments[i]);
 };
}
let obj = {hoge: "hoge"};
func1.call(obj, "Hello", "World!"); // 引数を1つずつ指定
func1.apply(obj, ["Hello", "World!"]); // 引数を1つの配列で指定
 
【実行結果2】
・1回目の関数呼び出し
{ hoge: 'hoge' }
Hello
World!
 
・2回目の関数呼び出し
{ hoge: 'hoge' }
Hello
World!
 
3.bindを用いたthisの参照先変更
関数をメソッドチェーンで「bind」と繋ぐことで、thisの参照先を強制的に結びつけた新たな関数を定義できます。
結びつけるオブジェクトは第一引数で定義します。
 
【サンプルコード】
function func1() {
 console.log(this);
}
let obj = {hoge: "hoge"};
let func2 = func1.bind(obj); // thisを強制的に結び付けて新たな関数を定義
func2();
 
【実行結果】
{ hoge: 'hoge' }
 
4.アロー関数で関数定義した場合のthisの参照先
アロー関数で関数を定義した場合は、thisの参照先は固定になります。
関数を定義した時点のオブジェクトを指すようになります。
 
【サンプルコード】
let func1 = () => { // アロー演算子で関数を定義
 console.log(this); // この場合は、定義時点の呼び出し元オブジェクトでthisを決定
}
func1(); // グローバルオブジェクトから呼び出してもthisは空のオブジェクトを指す
let obj = {};
obj.func = func1;
obj.func(); // 独自のオブジェクトから呼び出してもthisは空のオブジェクトを指す
 
【実行結果】
・1回目の関数呼び出し
{}
 
・2回目の関数呼び出し
{}
 
----
 
thisは、どのオブジェクトから呼び出されたかによって挙動を変えたい時に使用することが多いです。
ポリモーフィズムを実現するために使用する、と言った方がわかりやすいかもしれません。
また、今回の例では取り上げていませんが、関数を定義したオブジェクトを渡せばコールバック処理も可能です。
 
以下のサンプルコードは、呼び出したオブジェクトの名前を参照する例であり、どのオブジェクトから呼び出したかによって挙動を変えることができています。
 
【サンプルコード】
function func1() {
 console.log(this.name); // 呼び出したオブジェクト毎で違う名前を表示
}
let obj1 = {name: "hoge"};
let obj2 = {name: "fuga"};
func1.call(obj1);
func1.call(obj2);
 
【実行結果】
・1回目の関数呼び出し
hoge
 
・2回目の関数呼び出し
fuga