エンターテイメント!!

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

2018/09/10週 気づきと振り返り

やったこと

  • サーバーとの疎通確認

気づき

superagent

withCreadentials() → Cookie送ってくれるやつ。
Access-Controll-Allow-Originが * のときは機能しない。

tsconfig

es5 → es2018
targetだけじゃなく、libも変える必要がある。

chromeのSet-Cookie

アクセスしているサーバーと別ドメインのサーバーからSet-Cookieが来た場合、ChromeのDevToolのNetworkタブでは見えない。

ただ、実際には設定されている。

見る方法はない。

振り返り

ChromeのSet-Cookie

疎通確認でマジ困った。
あるはずのSet-Cookieがなんでないの?って2日くらい悩んだ。
結局、Cookieは正しく設定されていて、その他がおかしかっただけだった。

Chromeで開発する場合は、Set-Cookieは最後に疑う。
そうじゃないと無駄な時間を過ごす。

もしくは、他ブラウザで試してみる。

その他雑記

ChromeのSet-Cookieで悩んだ1週間だった。。。

年を1つ取ったが、このままでいいのかにも悩んでる。

メンタルが殺られそう。
今は、購買欲で誤魔化した。
あそびあそばせ」って漫画の電子書籍買ったけど、無茶苦茶面白い。
久々に笑った気がする。
俺が最後に笑ったの、いつだっただろうか?

今は、27日の無双OROCHI3が楽しみ。
もう、それくらいしか楽しみがない。

【Software-Design-2018年9月号】書いて覚える S w i f t 入門 新しいフォーマット「SION」の紹介 メモ・感想

設定ファイルの形式

JSON形式の設定ファイルは、関与しているプロジェクトで見たことないけど、本当に流行っているのかな?
俺が古い環境に慣れすぎているかもしれないが。。。
YAMLはたまに見たことがある。大多数がXMLだった。。。
そろそろ、俺の記憶も上書きする時期かもしれない。

YAML

  • 直感的
  • 人の読み書きも楽

XML

  • 一時期は流行った
  • シリアライズが、あまりに重い
  • かさばり過ぎ

JSON

  • ECMAScript準拠
  • プログラマが書きおろすフォーマットがもとになっている
  • データ交換にも可視化にも向いている
  • コメントが使えない。
  • DateやDataがサポートされていない
  • objectのキーとして文字列(string)しか使えない

SION

JSONの欠点を保管したデータフォーマット。

サンプルを見たが、JSONに準拠しつつコメントがかけるので、フォーマットしらなくてもプログラマなら理解しやすそう。

感想

SIONの導入で終わってしまった。。。
JSONの問題点からのSIONの利点が分かりやすかった。
Swift使う機会が少ないので、触る機会があれば試してみたい。

typescriptでnpmモジュール作る時に注意したほうがいい事メモ

きっかけ

IoT向けのコードをtypescriptで書いているのだが、公開する流れになったので、そのときに受けた指摘をまとめる。

指摘事項

型を排除する

typescript使っているからかも知れないが、npmモジュールは、javascriptでも使う。
だから、型情報をできるだけ利用しない形で実装する。

継承よりイベントドリブン

前述した内容に被るが、継承はなるべく使わない。
使う側としては、継承させるより、イベントをハンドリングさせてもらうほうが楽。

Javaでもそうだな。。。
継承を否定するわけではないが、使いにくくなるのは確かにある。

dependency-cruiser を使って依存関係分離をしたメモ

きっかけ

IoT機器に載せるソフトウェア開発しているのだが、複数端末で資産流用できるようにしたいらしく、そのためにマイクロサービス化する必要があり、依存分断して構成変えられるように実施した。

その際、依存分断するのにかなり手間取ったから、依存分断するために使った方法をさらす。

準備

環境

OS

Microsoft Windows [Version 10.0.17134.165]

Node

v7.2.1

typescript

2.5.3

dependency-cruiser

4.3.1

dependency-cruiser - npm

インストール方法

  • npm install --save-dev dependency-cruiser
  • npm install --global dependency-cruiser

どっちかでインストール。

graphviz

2.38

https://www.graphviz.org/download/

binフォルダを環境変数のPathに入れる。
windowsの話

\graphviz-2.38\release\bin

↑フルパスを入れればOK。

実行

本来はJS用のものなので、typescriptをjsに変換する。 自分は面倒くさいので、前回のbrowsifyのヤツを使ってみる。

suzaku-tec.hatenadiary.jp

実行したコマンドは、下記の通り。
実行場所は、プロジェクトディレクトリ直下。

depcruise --exclude "^node_modules" --output-type dot src/ts/app.js | dot -T svg > dependencygraph.svg

そうすると、dependencygraph.svg が出来上がる。

コマンド実行して、dotが見つからない的なことを言われたら、VSCodeでやっている場合は再起動してみるといいかも。
システム環境変数が反映されてないみたいなので、自分も最初迷ったが、再起動したら問題なく動いた。

app.js から依存しているものが見えるようになる。

使って見て

助かったのは、循環参照とか、かなり深い参照していた箇所。
最初は目で追っていたけど、無理だった。。。

あと、svgで出力すると、dom操作でフォーカス当てたクラスから派生するのに色つけたりできるので、いろいろ便利。
クラス数多いと、色つけると見やすい。

とりあえず、長年、どうやって依存を発見しようか悩んでいたが、これで少しは楽になった。

browserifyの動きについての学習と依存関係の分断で悩んだことのメモ

きっかけ

brosifyの動きがよく分からなかったので、学習した内容を晒す。

browsify

browsifyとは

分かりやすそうなサイトから抜粋

このツールはNode.jsのコアモジュールやnpmのモジュールをブラウザでも利用できるようにするというのが元々の目的でしたが、モジュール間の依存解決やファイルの結合を行うためのビルドツールとして使われることが多くなってきているようです。

賢く使うBrowserify - Browserifyとは | CodeGrid

仕組み

簡単にいうと、reqwireから使うファイルをたどって言ってくれるってことですかね?

現場でも使っているみたいだけど、ここらへんの仕組みが微妙に分かってない気がする。。。
なので、実験

実験

準備

自分、JS使えないので、Typescriptで実験。
準備は下記の通り。
やるときは、任意のフォルダ内でやることを推奨。

# プロジェクト初期化
npm init -y

# globalにtypescriptを入れる
npm install -g typescript

# ビルドに必要なモジュールを入れる
npm install gulp --save-dev
npm install browserify --save-dev
npm install vinyl-source-stream --save-dev
npm install tsify --save-dev

# typescript 初期化
tsc --init

実験コード

とりあえず、下記のようなクラスを作った。
app.tsが、TestImportA.tsだけを使っている。
TestImportB.ts は、作っただけでどこからも参照していない。

期待値としては、ビルドした結果のファイルにTestImportB.tsの内容が入っていないで欲しい。

実コード
ディレクトリ構成

まずは、ディレクトリ構成から。

|--apps
|  |--js
|  |  |--app.js
|--gulpfile.js
|--package.json
|--src
|  |--ts
|  |  |--app.ts
|  |  |--TestImportA.ts
|  |  |--TestImportB.ts
|--tsconfig.json
各ファイルの実装
# app.ts
"use strict";

import TestImportA from './TestImportA';

new TestImportA().execute();
# TestImportA.ts
export default class TestImportA {
  execute() {
    console.log('call A');
  }
}
# TestImportB.ts
export default class TestImportB {
  execute() {
    console.log('call B');
  }
}
結果確認のためのビルドプロセス作成

gulpでファイル出力のタスクを書く。

// gulpfile.js
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');

gulp.task('build', function () {
  return browserify({
      entries: './src/ts/app.ts'
    }).plugin('tsify')
    .bundle()
    .pipe(source('app.js'))
    .pipe(gulp.dest('./apps/js'));
});

apps/js/app.js にビルドした内容が吐かれるので、そいつを確認すればOK

結果確認
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var TestImportA = /** @class */ (function () {
    function TestImportA() {
    }
    TestImportA.prototype.execute = function () {
        console.log('call A');
    };
    return TestImportA;
}());
exports.default = TestImportA;

},{}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var TestImportA_1 = require("./TestImportA");
new TestImportA_1.default().execute();

},{"./TestImportA":1}]},{},[2]);

うむ、ちゃんとTestImportB.tsの内容が含まれていない。

なにが嬉しいのか

エントリーポイントに依存を集中させれば、切り替えができて、かつ必要なクラスのみが入ったファイルが生成できる点が嬉しいのだろうと思う。
例えば、TestImportB.tsだけを使いたい場合は、app.ts とは別のエントリーポイントのtsファイルを作成して、ビルドタスクを書けば、資産の流用ができると思う。
もちろん、使われる側が、ちゃんと依存がエントリーポイントに寄るように作ってある必要があるけどね。。。

これの考え方を覚えるのにだいぶ苦労した。。。

学んだこと

依存はエントリーポイントに向けて集める。そうすれば、あるファイルを切り替えるだけで資産を流用することができる。

参考サイト

gulp + browserify + tsifyを利用してTypeScriptコンパイル環境を作る - $shibayu36->blog;

賢く使うBrowserify - Browserifyとは | CodeGrid

賢く使うBrowserify - Browserifyとは | CodeGrid

switch文について思うこと(Java限定)

きっかけ

現場で、switchについて近くの席から、あーだこーだ聞こえてきたので、考えをまとめたくなって書くに至る。

ちなみに、その会話に僕は入ってません。
だって、たいして仲良くないやつの会話に入っていったら、場の空気悪くする&影で口撃を受けるから。
僕の実体験だから、よく分かる。

考え

僕は、断固switch反対派。

switch反対理由

オブジェクト指向ではない

どちらかというと、手続き型プログラミングと言ったほうがいい。
上から順に処理をするのが、いかにもそれっぽい。

1caseに該当する処理が、オブジェクトに当てはまるはず。
あとは、key によって、どのオブジェクトを生成するかを判定するファクトリクラスを作れば、オブジェクト指向になる。
switchは、デザインパターンで言うところの、FactoryかStorategy、Stateに置き換えが可能なはず。
デザインパターンの適用が必ずしも正解ではないけれど、switch文はいろいろ面倒な問題を抱えるので、依存性を薄く分離できるのであれば、なるべくしたほうが無難。
と、個人的に思っている。

バグを生みやすい

switch (s) {
    case 1:
        A;
    case 2:
    case 3:
        B;
        break;
    default:
        C;
        break;
}

よく上記の使い方をするケースをよく見る。
ただ、要件が変わったときに、修正するとバグを生みやすい。
例えば、2 のときだけ、別な処理をしたいってなると、2のcaseに処理を追加してbreakすればいいと思ってしまうが、1のときの処理が変わってしまう。(A->Bの流れが途絶える。)

あと、実装していて、break忘れがよくあるので、開発コストも高いのでなかろうか?って思ってる。

拡張性が薄い

バグを生みやすい の流れと一緒。
バグを生みやすい=拡張しにくいだから、同じことを言い直しているだけかも知れないな。。。

特に、case内の処理が大きくなっていくので、switchが読みにくくなるってのも、痛い。。。

可読性が悪い

改修が何回か入ってくると、case文が長くなり、それが積み重なってswitch文が長くなり、バグを混入するという結末に至る。

雑記

書いていて思ったが、開発コストが意外に高くつくのではなかろうか?
よくやってしまう、break忘れで、「何で?」ってなることがよくある。
読み返しにくいうえ、break入れたらバグる可能性も含んでいるので、やっぱり辞めた方がいいと感じた。

誰か、switchの開発コストを測った人はいるのだろうか?
switch使った場合と、if文羅列、storategy/stateパターンを使った開発コストが気になる。

思考が偏っていると思えなくもない。
逆に、switchの方がいいケースってあるのだろうか?
それがまったく思いつかない。

VisualStudioCodeでTypeScriptのバージョンが勝手に変わっていた話

きっかけ

TypeScript使って開発しているのだが、ワークスペースの環境に指定しているバージョンが、変えた覚えがないのに変わっていたので、調べた結果を残す。

詳細

再現

package.jsonに指定しているTypeScriptのバージョンが、nodemoduleにない状態に発生する。
恐らく、自分は、gitからチェックアウトしてきたときに、npm install してないからバージョンが意図せずにズレたのだと思われる。

理由

恐らく、nodemoduleないため、vscodeのTypeScriptのデフォルトバージョンが適用されていると思われる。
※すいません、推測の域を出ません。。。

対処方法

npm install して、対象のTypeScriptのバージョンをダウンロードした後に、ワークスペースのバージョンに一致させれば、きちんと想定したバージョンのTypeScriptが使える。

意図しない変なエラーが出たら、バージョンがあっているかを見るのを、優先順位を高くして確認したほうがいいと感じた。

雑記

なんか、コンパイラのチェックが急に厳しくなったり、nodeモジュールが急にエラーになったりして驚いた。。。
TypeScriptのバージョンを合わせたら、エラーがでなくなったからいいものの、かなり迷いましたわ。。。
勝手に切り替わっているから、かなり悪質だと思いました。