M0rtercyc!e

バイクとプログラミング

ES Modulesではシビアな循環参照

タイトルの通りです。ES Modulesでどハマりしました。

DOMを所定の形式に変換して出力を行う処理を書いていましたが、その中で循環参照が生まれ二進も三進もいかなくなってしまったためメモを残します。

下記のようなファイル群を用意します。Chrome Version 74.0.3729.169で再現。

// script.js
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();
// ModuleA.js
import ModuleB from './ModuleB.js';

export default class ModuleA {
    createModuleB() {
        return new ModuleB();
    }
}
// ModuleB.js
import ModuleA from './ModuleA.js';

export default class ModuleB extends ModuleA {
}

上記のコードをHTMLから読み込むと下記のようなエラーが出ます。

ReferenceError: can't access lexical declaration `ModuleA' before initialization

まさか循環参照が悪さをしているとは知らず、直感的にはわかりにくいエラーで大変混乱しました。これは普段宣言していない変数を参照しようとすると出るエラーです。

これを解決するには、ModuleA.jsを読み込む前に、あらかじめModuleB.jsを読み込んでおく必要があります。

// script.js
import ModuleB from './ModuleB.js'; //  ここで読み込む
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();

これで問題なく読み込むことができました。

まだ理解が浅く、なぜこうなるのかを断言できないので詳しくは次回以降にメモできればいいかなと思います。

TypeScript Enumの値をオブジェクトのキーとして使う。

TLDR ブランケットを忘れるな

TypeScriptを使っているとオブジェクトのキーにEnumの値を使いたい時があります。まぁ当たり前なんですが、下のコードはコンパイルできません。

enum myStatus { int, act, typing }
const yourObject = {
myStatus.int : 5
}

TypeScript上でのEnumは要はオブジェクトなので、ちゃんとキーをブランケットで指定しないと怒られます。

enum myStatus { int, act, typing }
const yourObject = {
[myStatus.int] : 5
}


TypeScriptで動的インポート import() を使う。

自作ゲームのスキル計算の自由度を上げようと、JSONから単一クラスによるスキル情報定義に変更しました。JSONの場合、それ自体はただの文字列なので読み込むのは簡単だったのですが、TypeScriptの場合は動的インポートを使用する必要が出てきます。

動的インポートというのは、プログラムの実行時に関数やクラスをインポートすることを言います。TypeScriptやJavaScriptでは動的インポートを行なうためにimport()関数を利用します。

使い方は非常にシンプルです。import()関数は利用時にPromiseを返却します。

// ./modules/module1
export class Module1 {
constuctor() {
console.log('Hello');
}
}
// 読み込む側
import('./modules/module1')
.then((modData) => {
new modaData.Module1(); // => 'Hello'
})
.catch((error) => {
console.error(error);
});

Promiseなので、Async / Await関数でも利用することができます。

とりあえず以上です。

JavaFX CanvasでUndo/Redo

タイトルの通りです。大学の課題でJavaFXを使ったペインタを作成中です。

全体のソースはこちら。
kznrluk/4s-program-painter: ネットワークプログラミング応用演習 – 簡易ペインター

JavaFXのCanvasは他のCanvasと同じように、描写した内容を逐一保持しないため、Undo / Redoの処理には多少工夫が必要になります。

  • MOUSE_PRESSEDからMOUSE_RELEASEDまでの軌道を保持する。
  • Canvasの現時点の画像を取得して保持する。
  • Canvasのインスタンスをコピーする(実際にできるか不明)。

選択時点で軌道を保持して再描写する際にどれほどのコストがかかるのか不明だったため、Canvasの画像を取得する二番目を選びました。今考えてみると、画像で保持するのもそれはそれでコストがかかる気がしますが。

実装は比較的簡単です。履歴を保持するクラスを用意します。

JavaではArrayDequeという便利な配列があるので、それを使っています。

https://github.com/kznrluk/4s-program-painter/blob/master/src/Painter/Controller/ImageHistory.java

描写開始時に現在の描画内容を画像化して保存します。

this.canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
    WritableImage snapshot = new WritableImage(CANVAS_SIZE_X, CANVAS_SIZE_Y);
    this.canvas.snapshot(null, snapshot);
    this.history.add(snapshot);

    currentPen.mousePressed(event);
});

Undo / Redo時にスタックされている要素を取得し、キャンバスに描写します。

void undo() {
    WritableImage image = this.history.getLast(this.canvas.snapshot(null, null));
    GraphicsContext gtx = this.canvas.getGraphicsContext2D();
    gtx.drawImage(image, 0, 0);
}

void redo() {
    WritableImage image = this.history.redo(this.canvas.snapshot(null, null));
    GraphicsContext gtx = this.canvas.getGraphicsContext2D();
    gtx.drawImage(image, 0, 0);
}

描写終了時ではなく、描写開始時に履歴を作成することがポイントです。描写終了時に履歴を作成すると、Undoする場合に現在の描画内容が一度出現してしまいます。

そのうちしっかり書き直したいですが忘備録として。とりあえず以上です。

管理の続かないWordPressサイトを脱却するための工夫

タイトルの通りです。

私は以前からWordPressを使ったサイトをいくつか立ち上げ、運用したことがあります。このドメインでも、もともと`blog.anyfrog.net`というホストでブログを書いていました。

しかし、そのブログも含め基本的に運用が一年以上続きませんでした。

WordPressを自主運用すると、SaaSなどのサービスを使わない限り、物理的なサーバのヘルスケアから、仮想PC上ののOS, PHP, DB等の維持がもれなくくっついてきます。

数ヶ月経つと、”記事を書く気力はあるがバックエンドの維持管理が面倒くさい”状態となり、そのままサイトごとフェードアウトと言うことが数回、ありました。

そのため、維持管理の必要ないQiitaを気に入って使っていたのですが、先述の理由からまた個人ブログに戻ることにしました。そこで、同じ過ちを侵さぬようできるだけ管理の楽な方法でサイトを作ろうと考えました。

そのような場合、一般的にはWordPress.com等のホスティングやブログサービスを使うべきですが、独自ドメインの設定にお金がかかったり、カスタマイズが容易でなさそうなどの理由から結局自主運用のWordPressを使うことにしました。その中で選択したことをメモします。

まず、サーバサイドについて。今までは自宅サーバのWindows Server上で動いているHyper-V上のUbuntuに構築していましましたが、前述の通り物理サーバ+Windows Server+仮想Ubuntu+サーバソフトウェアの維持管理のコストが発生するため、VPSを利用することにしました。

選んだVPSはさくらVPSの1Gプラン。この点は単純にさくらインターネットに個人的な信用があるからです。石狩DCの無停電運用とか。さすがです。

一方で、このままだとOSとサーバソフトウェアの維持管理コストが発生するため、サーバ側のOSにも目を向けました。さくらVPSでは、KUSANAGIというWordPress専用仮想マシンが利用できるので、それを採用しました。

KUSANAGIについてはしばらく触ってからレビューをしようと思いますが、最適化がすでに済んでいるため非常に高速という点や、提供会社によりRPMパッケージ(ベースはCentOS)の提供が行われているためサーバソフトウェアの維持管理が楽、という点があります。

上の2つにより、だいぶ維持管理が楽になった気がします。

最後に、このブログを運用するにあたって一週間に一記事を投稿することを目標に設定したいと思います。ブログの利用を習慣づけることによって、アウトプットを活性化して、維持管理も含めたブログに対するモチベーションを高めることが目的です。

以上です。

Hello world!

WordPress へようこそ。これは最初の投稿です。編集もしくは削除してブログを始めてください !

Page 2 of 2

Powered by WordPress & Theme by Anders Norén