読者です 読者をやめる 読者になる 読者になる

エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

TypescriptでのEmitterの付き合い方

きっかけ

TypeScriptをやるようになって、EventEmitterでどうも引っかかりを覚えた。
どうするべきか悩んだ挙句、やっと答えっぽいものが見えてきたので、まとめる。

TypescriptでのEmitterの付き合い方

環境

まずは、環境情報

> npm -v
4.0.5

> ver
Microsoft Windows [Version 10.0.15063]

ちなみに、エディターは、VisualStudioCode使ってます。
コードの参照先の検索や、定義に飛ぶのが他のエディターより楽だったので、コイツに落ち着きました。
できれば、リファクタリング機能が増えてくれると嬉しい。

Visual Studio Code - Visual Studio

package.json

{
  "name": "emitter",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^7.0.13"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": false,
        "sourceMap": false
    }
}

本題

よくある紹介記事

下記の内容の紹介をよく見かけると思う。

import { EventEmitter } from "events"

class EmitSample extends EventEmitter {

    constructor() {
        super();
        this.on("onTest", () => {
            console.log("on event");
        })
    }
}

const es = new EmitSample();
es.emit("onTest");

この例では、EventEmitterを継承して、コンストラクタで"onTest"イベントを監視する。
インスタンス作成後、emitでイベントを発火させている。
当然、コンパイルして実行すると下記のようになる。

> tsc EmitSample.ts
> node EmitSample.js
on event

しかし、これだと、開発していくうえでかなり問題がある。
それは、どこからでもemitできる点。
これを許していると、イベントを消したいときなんかは、grepをかけて検索する必要があります。
あと、許容される範囲がデカすぎて、Typescriptで想定される大規模開発をしていると、すぐにカオス化する。
いわゆるスパゲッティコードが簡単に出来上がる。
コンパイルで気づけないの点も非常に厄介です。
Typescript使っているから、コンパイルで気づけるって思っていても、コンパイルエラーにならないので、あとで爆発する。
今まで積み上げてきた努力の時間が無に帰る。
キラークイーンのバイツァ・ダストぐらいの威力があるに違いない。

対策としては、公開範囲を極小化すること。
具体的には、下記のようにする。

import { EventEmitter } from "events"

class EmitSample {

    private emitter: EventEmitter;

    constructor() {
        this.emitter = new EventEmitter();
        this.emitter.on("onTest", () => {
            console.log("on event");
        })
    }

    onTest() {
        this.emitter.emit("onTest");
    }
}

const es = new EmitSample();
es.onTest();

継承しなくなったことで、直接emitが呼び出せなくなる。
また、こうすることで、インスタンスに対する操作を提供する形になり、呼ばれたらどうなるのか明確化して、ある程度コントロールができるようになる。
不正なイベント呼び出しもできなくなるので安全に開発ができるようになる。
イベントが不要になったら、関数を削除するので、コンパイルでキチンと弾かれる。

これは、EventEmitterでよく再現されるObserverパターンでも導入可能。
なるべく公開範囲が小さくなるように作るのがコツだと、最近感じ始めた。

以上、終了。
最近は、Typescriptでオーバーロード使うべきか悩んでいる。
あと、ジェネリックスの適用方法も。
もう少し考えがまとまったら投稿予定。

TypeScript関連記事

suzaku-tec.hatenadiary.jp

suzaku-tec.hatenadiary.jp

suzaku-tec.hatenadiary.jp

suzaku-tec.hatenadiary.jp

suzaku-tec.hatenadiary.jp

平成29年度春季データベーススペシャリストの受験後の感想

午前

たぶん、大丈夫。
分からん問題は2,3問くらいやったし。
過去問も8割近い正答率になってたから大丈夫だろう。
ちなみに、午前Ⅰは免除でした。

午後

Ⅰ、Ⅱ、共に壊滅的。。。
まず、問題が意味分からん設問がいくつかある。
「これには問題がある」その問題とはなにか?って意味が分からん。
問題出す側が問題を聞いてくるってどういうこと?って思ってしまう。
指摘するからには、問題わかってるんじゃねーの?って気になる。
時間が足らずに最後は、適当に書いたわ。。。
6割ギリギリいけるかどうかだと思う。

反省

反復して学習ができてなかった。
特に午後問。
過去問を一回目を通して終わってた気がする。
午前は、そのかわりしっかりやってたな。
回答方法が簡単だからかもしれないが。。。
午後問って、専用の回答容姿がないと回答が書きづらいんだよね。。。
その問題があって、なかなか問題やろうって気にならなかった。

あと、推移的関数従属と部分関数従属をよく理解してなかった。
問題にあって、結構詰まった。
逆に、隔離性水準は完璧に覚えて追った。
利用できる箇所が1回あった気がする。
次回は、正規化、関数従属についてよく復習しておこう。

次回に向けて

試験対策ブログの充実と対策サイトに目を通す!

データベーススペシャリストドットコム

suzaku-tec.hatenadiary.jp

Macで各種バージョン確認まとめ

なるべくMac固有のバージョン確認のみ載せる。
ブログとかで環境情報を載せる場合は、下記のコマンドで確認したほうがいい。

種類 コマンド
OS SW_VERS
Swift swift -v
ターミナルモードが起動してしまうので、:exitで抜け出す。
Xcode xcodebuild -version
Homebrew brew -v
Java java -version

SwiftでWebViewアプリ

きっかけ

Swiftでいろいろアプリを作っているが、なかなか言語が覚えられない。
ネイティブ系のエンジニアではないからかもしれない。
WebViewを使えば、楽できるのではないかと思い、実施に至る。

環境情報

$> SW_VERS
ProductName:    Mac OS X
ProductVersion: 10.12.3
BuildVersion:   16D32

$> swift -v
Apple Swift version 3.1 (swiftlang-802.0.48 clang-802.0.38)

$> xcodebuild -version
Xcode 8.3
Build version 8E162
igarashitoshio-no-MacBoo

Xcodeのバージョンによっては、実施方法に差が出るので、一応載せとく。

やり方

プロジェクト作成

兎にも角にもプロジェクト作成が最初の仕事。

  1. Xcodeを起動して、Create a new Xcode projectを選択。
  2. Single View Applicationを選択してNext
  3. Languageをswiftにして、後はテキトーに入力
  4. 保存するディレクトリを選んでcreate

StoryBordの削除

SwiftはStorybordを使って、部品の配置を決める。
しかし、WebViewは部品一つしか必要ないので、あっても意味が無いので削除する。
※とくに削除しなくても問題ないので、飛ばしてもいいかも?

  1. Xcodeのサイドバーの"Show the Project navigator"を表示
  2. 一番トップにある、プロジェクト名のファイルを選択
  3. General > Develop Info > Main Interface の内容を空にする
    こいつで参照するStorybordを決めている。
  4. Main.storyboardを削除

ViewController呼び出し

storybordを削除したので、自前で呼び出す処理が必要らしい。
AppDelegate.swiftファイルを下記の通り編集する。
※コードは一部抜粋

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var navigationController: UINavigationController?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow(frame: UIScreen.main.bounds)
        
        let viewController: ViewController = ViewController()
        window!.rootViewController = UINavigationController(rootViewController: viewController)
        window!.makeKeyAndVisible()
        return true
    }

やっていることメモ

  1. ベースとなるウィンドウのインスタンスを生成。
  2. ベースとなるViewControllerを生成。
  3. 1.で作成したwindowの一番上位のViewConntrollerにUINavigationControllerを指定。
    さらに、そのUINavigationControllerの一番上位のViewConntrollerに、2.で作成したviewControllerを指定
  4. 1.で作成したwindowを有効化

WebViewを全画面表示

import UIKit

import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    let webview: WKWebView = WKWebView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        webview.frame = view.bounds
        webview.navigationDelegate = self
        view.addSubview(webview)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

viewにwebviewのインスタンスを生成したものを埋め込む。
やる際は、WebKitのインポートをお忘れなく!
なんでビルドエラーになるのか分からず、1時間くらい時間を浪費するハメになった。。。

完成

上記をやれば、とりあえず実行するとwebviewが全画面で表示される。
ただし、真っ白だけど。。。

htmlを表示してみる

やりたいのは、ローカル保持しているHTML表示
外部のモノを参照することもあるだろうけど、やりたきことは別なので、やってみる。

配置場所の作成

まずは、htmlを配置する場所を作る。
Resourcesにhtmlなどを置こうと思う。
Xcodeだと、ディレクトリとは呼ばずにGroupと呼ぶらしい。
なぜだかは知らないけど、かなり迷う。
File > New > Group を選択して、Resourcesを作成

HTML作成

作ったResources内に、index.htmlを作成する。
File > New > Fileから、htmlファイルを作る(emptyを選んでindex.htmlという名でファイルを作る)
作ったら、ファイルを以下の内容にする。
今回は表示させたいだけなので、別になんでもいい。

<html>
<head>
</head>
<body>
test
</body>
</html>

htmlファイルのロード

作ったindex.htmlをwebviewに読み込ませる。

import UIKit

import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    let webview: WKWebView = WKWebView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        webview.frame = view.bounds
        webview.navigationDelegate = self
        view.addSubview(webview)
        
        let url = Bundle.main.url(forResource: "index", withExtension: ".html")!
        let request = URLRequest(url: url)
        webview.load(request)
        
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

実行

実行すると、index.htmlの内容が出力されるはず。

感想

htmlの表示ができたので、あとはWebの知識とJS・CSSの考えを流用すれば行けるハズ。
デフォルトOptionalが有効なのが、違和感ありすぎて辛い。。。

特に、xcodeが全て英語なので、英語に慣れてないと拒絶反応が出る。
あと、デリゲートって何?おいしいの?
デリゲートの意味が未だに理解できない。
調べはするが、それってinterfaceとか使って呼び出すメソッドを決めておき、処理は宣言しているところで書くのと同じなんじゃ。。。って思う。
これは、いわゆるFacadeなのだろうか?
いままでプログラミングしてきて思うに、Facade使って上手くいったパターンがほぼないのだが、検討違いだろうか?
愚痴っぽくなってしまったので、ここでおしまい。

WebViewを使ったアプリには、可能性を感じる。
ネイティブ側の問題が発生すると死にそうだけどね。。。

参考サイト

iOSでガワネイティブ - Qiita

swift - How to add a navigation bar to WKWebView? - Stack Overflow

SwiftでWKWebViewを使ってみた - Qiita

npmにインストールしたものの確認

インストールしたものの確認方法

下記コマンドで確認できる

npm list

もしくは、ailiasが設定されているので、listの箇所は、ls, la, llが使える。
ailiasの確認がしたい場合は、npm list -hとすると下記のような記述がでる。
もちろん、ここのlistも置き換え可能。

npm ls [[<@scope>/]<pkg> ...]

aliases: list, la, ll

多すぎる

npm listで表示したものは、依存関係も含めて表示される。
そのため、インストールしているものが多すぎると、ネストが深くなったりして、確認したい一覧が見えない。
なので、依存関係を見たい場合以外は、下記のコマンドで事足りる。

npm list --depth=0

こうすることで、トップレベルのインストール物を確認できる。

グローバル環境を確認する

今まで紹介してきたものは、全てローカル環境の確認方法。
グローバル環境にインストールしたものではない。
確認したい場合は、ご察しの通り、-gオプションを付ければいい。

npm list -g

もちろん、これにも--depth=0は使える。
やり方が、統一感があるので、覚えやすいはず。

Macのターミナルのカスタマイズ

ターミナルの右側の文字列のカスタマイズ

ターミナルの$前の出力フォーマットは、環境変数のPS1で設定されている。

現状の設定内容を確認したい場合、下記のコマンドで確認する。

echo $PS1

意味は下記の通り。

意味
\h ホスト名(最初の.まで)
\H ホスト名
\t 時間(24h)
\u ユーザー名
\w 現在のディレクトリまでのパス
\W 現在のディレクトリ名

値の設定

{変数名}={出力フォーマット} で設定可能
例は下記の通り。

PS1=\W

ただ、上記のやり方だとターミナル再起動で元に戻ってしまうので、~/.bashrc などに記載する。
やり方は、以前の記事を参照。

suzaku-tec.hatenadiary.jp

参考サイト

www.yoheim.net

OSのバージョン確認方法

きっかけ

ブログやっていると、環境情報を乗せる必要がある。
そのため、OSのバージョン確認方法を知っておくと楽なのでメモる。

確認方法

エンジニアなので、コマンドで確認する。
当然、OS毎に違いがでるので、それぞれ記載する。
出力された情報を貼り付ければ、実施しているOSの情報は十分なハズ。

Windows

コマンドプロンプトで下記コマンドを打つ

ver

そうると、下記のような情報が出力される。

f:id:suzaku0914:20170402111509j:plain

Mac

ターミナルで下記のコマンドを打つ

sw_vers

下記のようなバージョンが出力される。

f:id:suzaku0914:20170402112434p:plain