エンターテイメント!!

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

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の方がいいケースってあるのだろうか?
それがまったく思いつかない。

ヤフーあの講演の件で思ったこと

発端・顛末

「女性エンジニア少ない問題」を解決するために、機械学習で男性エンジニアを女性に変換する - ログミーTech(テック)

女性エンジニアが少ないとやる気が出ない問題で批判「懲戒解雇されてほしい、エンジニアやめろ」一方、過敏に反応しすぎの声も - Togetter

各社の対応

ヤフー

当社社員の講演における不適切表現のお詫び - ヤフー株式会社

サイバーエージェント

Battle Conference U30

所感

問題点

問題とされているのは、技術点なところではなく、「女性エンジニア=コンパニオン」みたいな思想が根底にあるような書き方だった点だと思う。

女性エンジニアが少ないから男性エンジニアのやる気がでないというところは、疑問を持つね。。。
脱線しそうなので、後術する。

恐らくだが、社内発表でネタ的な意味合いで書いた気がする。
どうしても男性エンジニアが多い業界なので、男性の目を引く記述をしてしまったのだと思われる。

問題への対応

ヤフーとサイバーエージェントは、ただ謝っているだけですね。。。

なぜ炎上したのかの分析が書かれていないので、謝罪になっているのか、ものすごく疑問。
本当に理解しているのか、ことの経緯を把握しているのかに疑問を感じる。

障害やバグの内容を報告するときもそうだが、対応内容だけ書かれても、意味ないと思う。
対応することは重要だけど、その対応が適切であるのかの判断材料がないってのは、対応の是非を疑う。
今回の件は、それと同じ。
炎上してしまったから、謝ってしまおうと受け止められても仕方ないと思う。

やる気について

やる気は、自分で出すものであって、周囲の環境で左右されてはダメだと思う。
モチベーションもそうだが、そういうものは自分で出すものであって、周囲にそれを求めてはいけないと、個人的に思ってます。
プロのエンジニアなのだから、周囲に影響されずに求められた質を出し続けるのは、責務であると同時に義務でもあると思う。

あと、やる気ってなんだろうね?
推し測れないものだから、それが必要なのかが分からない。
合理的思考を阻害する要因になるのではないか?と最近思うようになった。
どうやって的確に早く終わらせるかという観点より、楽しんでやるという観点になっていくような気がしてならない。

分からなくもない

今回の件、分からなくもない。

ハッキリと言って、SEになる男は、モテない人が多い印象がある。
かくゆう俺がそうだから、そう思っているだけかも知れないが。。。
女性と話すとテンションは上がるのは、大抵の男なら感じるでしょう。
俺でもテンションは上がるし、気持ちが高ぶってしまうと思う。
ちょっと優しくされたら、即落ちると思う。

ただ、そのテンション上昇は、仕事のやる気とは、あまり関係ないと思うがね。

どうあればよかったのか?

おそらく、動機がまずかったと思う。

たぶん、問題提起を、「男性エンジニアのやる気」ではなく、「組織における男女比」にすれば良かった気がする。
そうすれば、男女比を調整するために男性→女性のように振る舞わせるための機械学習ってのが使えたのと、比率を調整した結果の報告は、事実の報告で、思想の批判にはならなかったと思う。

雑感

株価

この件を受けてなのか知らないが、ヤフーの株価が。。。
ヤフーの株を持っているので、言及しづらい。。。
当分、この影響は出そうな気がする。。。

ちゃんと分析して、対応策と再発防止策をちゃんと考えて欲しいとは思う。

最近の学習意欲について

徒然なるままに書く

きっかけ

最近、どうも学習意欲が減退している気がする。。。
日々の情報収集はしていて、深掘り調査したいことはいくつかあるのだが、調査に至る前に諦めていることがおおい。

理由の考察

個人的に理由を考えたが、おそらく、知っていると思っているからやらないのではなかろうか?と思われる。
いわゆる知ったかぶりってやつ。 そういう考えは、技術力の低下と慢心を生むことを、分かってはいるのだが許容してしまう自分がいる。 対策を考えてはいるのだが、なかなか思いつかない。
考えたのは、学習を習慣化させるか、誰かと一緒に学ぶか。
前者は、どっちにしろハードルが高い。少しでも満身があれば、簡単に習慣から外れそうな気がする。
後者は、なんというか嫌だね。他人に自己の能力向上を委ねるのは、危険な気がしてならない。
真剣さがどこか抜けているから、こんな状況になっているのではないかという考えもある。
もしかしたら、フリーランスになったほうが、学習する環境になるのではないかという考えもある。

もう一つ理由があると思っている。
それは、環境構築の面倒くささ。
それは、dockerで対応できそうなので、少しづつ勉強してはいるが、windows環境だとツライものがある。
あと、イメージのダウンロードが異様に時間がかかるのもツライ。。。
もしかしたら、macに移行すれば、解決しそうな気がしないでもない。

あと、時間がないってのもあるかも知れない。
帰ってから就寝まで2~3時間。起床してから家出るまで1時間。
有りはするんだけど、別のことに割いているだけって事かもしれないが。。。
どうしても、家に帰ると娯楽を楽しみたくなってしまうのも問題だな。
だからと言って、カフェで勉強とか、恥ずかしくてできない。
近くのマックやカフェで勉強している輩を見るが、俺からしたら、正気の沙汰とは思えない。
よく人に見られて勉強なんかできるな~って、毎回思う。
絶対、「勉強している俺すごいでしょ?」って思っていると感じる。

雑感

考え抜いたが、最終的には世間が悪いって考えになってしまいますわ。。。
世間がもっと俺を甘やかしてもいいと思うんだよね。