日記
調べたこと
- mockito
- verify()
- メソッドが呼び出された回数を検証する
- doAnswer()
- メソッドの引数を使って返値を設定できる
- verify()
- eclipse local history
- 半日かけて書いたコードをEclipse上で消してしまった。
- ゴミ箱にはいかずに消えていた。
- Local Histryを使うと復元できる!
やったこと
- mockitoのverify()とTheoryでドハマりした。
- Theoryで複数パターンをテストするとき、verify()で使う呼び出し回数はリセットされない。
- reset()でMockをリセットしてやらないといけない。
- デバッグで変数追いかけまくってやっとわかった…
考えたこと
Theoryはデバッグしづらさがある
TheoryとFixtureを使ったテストは最高に簡単に書けるので大好きだったのですが、デバッグしにくいのが難点かもしれませんね。何回目の呼び出しでバグったかわかりにくいし、コンディショナルブレークポイントを刺さないといけないし…
ラムダ式を深く追いかけたい
仕事中、ブレークポイントを刺してバグを見つけることは多いですが、あまり時間をかけられません。で、よく気になるのがラムダ式。なんかよくわからないところに飛びまくるんですよね。時間があるときに深追いしよう。
Springアノテーション地獄
アノテーションはおまじないになりがち。アノテーションがやってくれている処理にたどり着くまでが遠いんですよねぇ。これも時間があるときに深追いしよう。
日記を書くのはいいことだ
一度アウトプットしておくと、頭の中が空っぽになったかのような気分で次の新しいことを学べる。(気がする) 自分の学習の傾向を後から振り返って作戦を立てるなんてこともできますわよ。
今日は30分で書きました。内容がうすい~。
日記(トピック: JavaのflatMapがちょっと気に食わない)
調べたこと
- systemdのsystemctl stopの挙動
- guava
- GitHub - google/guava: Google core libraries for Java
- Javaのユーティリティ系ライブラリ
- 冗長な記述を短くできる。特にCollectionが使いやすくなる
- ImmutableMapは非常によく使う。ImmutableCollectionsExplained · google/guava Wiki · GitHub
- gatsby
guava使ってみた。ImmutableMap便利スギィ!https://t.co/47zTSxBeeB
— ytnk (@__ytnk__) 2018年8月8日
やったこと
考えたこと
Java.util.StreamのflatMap()はなんか微妙
flatMapの引数はStreamを返す関数。
てことは、リストのリスト(e.g. List<List)を得るみたいなありがちな処理は以下のように書くことになる。
注目してほしいのはこの部分。
List<Integer> list = listOfList.stream()
.flatMap(List::stream) // .flatMap(l -> l.stream())でもいい
.collect(Collectors.toList());
flatMapは、streamに対して関数を適用して、そこで得られたstreamをすべてくっつけて一つのstreamにします。 てことは受け取ったstreamの中身はリストなので、それをstreamに変換してくっつけると、リストの中身を取り出すことになるわけですね。
いやしかし私はflatMapの引数がstreamを返す関数というのがどうも気に入りません。
単にくっつけるときのstreamの中身を返すだけにしてしまうと、
streamへの変換を行わなければいけないくてそれを自動でやるのは難しいというところでしょうか。
それで、どのように変換するかはプログラマに任せないといけないという事情だと思います。が、どうになならないのかなーと思いました。
というか、その問題を解決しているライブラリがありそうなので調べてみます。
ファイルの重複行を削除するアルゴリズムってどうなってるんだろう
- メモリに全行読み込む系
- ハッシュテーブルを使えば、重複の検出は素早く済みそう
- メモリに全行読み込まない系
- ファイルをチャンクに分けて少しずつ見ていって、↑に書いたやつをメモリに書く代わりにファイルに書きながら進める
- 一度ソートしてファイルに書く⇒次の行が同一か見るならいけそう
- じゃあどうやってメモリに全行読み込まずにソートするんだろう問題
i18nのこと、そろそろちゃんと考えたい
記事のテーマ:i18n(ソフトウェアの国際化対応)は、単に文や時間(タイムゾーン)を差し替えれば済むような簡単なものじゃない。自分たちの文化にはない決まりにしたがって文ができていることがある。場合によっては、そのためのロジックを加えなければ対応できない。そのような対応が必要になるような文化を数多く持った国家で育つと、i18nに対応したプログラムを特に意識せずに書くことができるようになるのではないか。
今の仕事では、英語のUIを持ったサービスを作っているけど、ユーザーの使用言語は3つある。 ので、そのうちi18n対応をすることになりそうな気がしている。 とても興味深かった、というか、そのうちまたお世話になりそう
これからやること
今日は一時間20分くらいで書きました。
書くことに慣れたいので目標を考えました
毎日いろいろ調べてはいるけど記事にしようと思うと手が止まります。 調べて発信する力は非常に役に立つ力だと思うので、目標を決めて取り組みます。
目標
3か月後、未知の技術を調べる~記事にするを2時間でできる。
1カ月後の目標
記事を書くのにかかる時間を予想できる。
2か月後の目標
未知の技術を4時間で調べる~書くまでできる。
ねらい
記事の質にはこだわらず、書くことを習慣化することに重点を置きました。 100点のものを作ろうとして手が止まってしまうことがよくあるので、まずは記事を公開するという行為への心理的ハードルを下げられれば良いなと思っています。
目標達成のためにやること
- 毎日記事を書いて公開する。
- 調べたこと
- 考えたこと
- やったこと
- 週に一回、一週間学んだ中で特に気に入ったものについてまとめてQiitaで公開する。
- 今日の分は達成⇒次は8/15
↓書いたもの qiita.com
Object.equals()とObject.hashCode()のデフォルト実装
java.lang.Objectのequals()とhashCode()の実装について調べました。
Object.equals()
JDK 8 での実装は下記の通り、参照値を比較しているだけです。
public boolean equals(Object obj) { return (this == obj); }
jdk8u/jdk8u/jdk: a71d26266469 src/share/classes/java/lang/Object.java
参照値とはすなわちオブジェクトへのポインタなので、Object.equals()は同一のインスタンスであるときだけtrueを返します。
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.
参照値(単に参照とも)はオブジェクトへのポインタまたはnullです。nullはオブジェクトを参照しない特殊な参照値です。
Object.hashCode()
hashCode()はJVMの実装に依存します。
こちらの記事でとても詳しく説明されていました。 結局のところ
- OpenJDK 8, OpenJDK 9
- スレッドごとに持つ値をXorshiftした数
- OpenJDK 7, OpenJDK 6
- 乱数
とのことでした。 XorShiftは、排他的論理和とビットシフトのみで(高速に)疑似乱数を生成できるアルゴリズムです。 hash codeは一度生成されるとObject Headerと呼ばれるインスタンスごとに持つ領域に記録されます。 二回目以降のhashCode()の呼び出し時には、Object Headerに記録されたhash codeを返します。
OpenJDK8でhash codeを生成するコードは次の通りです。
// Marsaglia's xor-shift scheme with thread-specific state // This is probably the best overall implementation -- we'll // likely make this the default in future releases. unsigned t = Self->_hashStateX ; t ^= (t << 11) ; Self->_hashStateX = Self->_hashStateY ; Self->_hashStateY = Self->_hashStateZ ; Self->_hashStateZ = Self->_hashStateW ; unsigned v = Self->_hashStateW ; v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ; Self->_hashStateW = v ; value = v ;
jdk8u/jdk8u/hotspot: 87ee5ee27509 src/share/vm/runtime/synchronizer.cpp
スレッドのメンバ変数_hashStateX
と_hashStateW
を使ってハッシュコードを生成します。
xor-shiftのアルゴリズムは理解できていないのですが、hashStateX, hashStateY, hashStateWをアルファベット順で一つ前の名前を持つ変数に値を移し、hashStateWを生成したハッシュコードにすることで、次の呼び出し時にもユニークな値が生成できるようにしています。
_hashStateはスレッド生成時に次のように初期化されます。
_hashStateX = os::random() ; _hashStateY = 842502087 ; _hashStateZ = 0x8767 ; // (int)(3579807591LL & 0xffff) ; _hashStateW = 273326509 ;
jdk8u/jdk8u/hotspot: 87ee5ee27509 src/share/vm/runtime/thread.cpp
Spring BatchのReaderである程度複雑なことをする
やりたいこと
Readerである程度複雑なことをしたい。 ある程度複雑なこととは、例えば
などです。
Readerでできること
Readerは、ItemReaderインターフェースの実装クラスです。 よく使いそうなItemReaderの実装クラスはSpring Batchで17種類提供されていますが、一回の読み込みで複数回クエリを発行するようなReaderやREST APIを叩くはものはありません。
このため、複雑なReaderは自分で実装しなくてはいけません。
ItemReader
Readerはreadメソッドが呼ばれるたびに新しいデータを一つ返します。 これは、一回のクエリ発行で一つのデータが返るような処理をすればいいということではありません。 read()はnullを返すまで実行されるので、そのようなクエリを発行したら無限ループしてしまうことになるからです。 ということは、簡単に言うと次のような実装が必要になります。
public class MyItemReader<T> implements ItemReader<T> { private List<T> data; private List <T> getData() { // なんか複雑な処理でデータをとってくる return data; } T read() { if (data == null) { data = getData(); } if (data.size() < 1) { return null; } return data.remove(0); } }
Spring Batchはリスタート機能も備えているのですが、このままでは外部からReaderを再開してあげる方法がないので、このクラスはリスタートに対応していません。
AbstractItemCountingItemStreamItemReader
リスタートできるように、どこまで読み込んだとかの管理をうまくやってくれるクラスはないのかなー。ありました。
抽象クラスAbstractItemCountingItemStreamItemReaderは、Readerが返している要素の数と返せる要素の数(最大値)を管理してくれます。 Readerで読み込んだ要素の管理は自分でしないといけませんが… JdbcPagingItemReaderなどは、この抽象クラスを継承して実装しているので、参考になるでしょう。
public class MyItemReader extends AbstractItemCountingItemStreamItemReader<T> { private List<T> data; private List <T> getData() { // なんか複雑な処理でデータをとってくる return data; } @Override protected void doOpen() throws Exception {} @Override protected Employee doRead() throws Exception { if (results == null) { data = getData(); } return results.get(getCurrentItemCount() - 1); } @Override protected void doClose() throws Exception {} }
実はこのままだと、やっぱりdataを復帰させる方法がないので、やはりリスタートには対応していません。近いうちにリスタート対応版を追記します。
React + Reduxをさっくりと覚えた
こんなのつくりました
(さっくりと)覚えたこと
- SVG
- JavaScript
- React
- Redux
動機
- フロントエンドのコードを読みたい
- 障害の原因調査が捗りそう
問題
- 読めない
- [...array1, ...array2]
- { key1 } = object
- {...object1, ...object2}
- なにやってるかわからない
- 階層化されたコンポーネント
- イベントを処理する流れが追いかけられない
- reducerとかいう謎の単語
さっくりと覚えていく
React
動的なUIを宣言的に書ける。
やったこと
- 公式サイトのチュートリアル
- create-my-react-appで作ったテンプレートをいじくる
- ソートするやつを作る
メモ
- DOMコンポーネント
Redux
stateを一か所に集めて、stateの更新と反映を行えるようにする。
Observerパターンのちょっとマッチョなやつ。
Reducerというコンポーネントにロジックをまとめられる。
やったこと
- ビデオ Getting Started with Redux
- https://egghead.io/lessons/react-redux-react-todo-list-example-adding-a-todo
- Redux単体からreact-reduxまで
- 平均5分くらいの動画が30本
- ES6のよく使うシンタックスも教えてくれる
- 公式のBasicsあたり
- Qiita Redux入門【ダイジェスト版】10分で理解するReduxの基礎
- なんか複雑な絵が描いてあって気がめいった
メモ - dispatcherで生成したアクションをreducerで受け取って新しい状態を計算する - stateをsubscribeして画面を再描画する
Recat-Redux
propsにstateとdispacherを渡せるようにする。
状態の更新⇒再描画のための儀式がゴッソリ消える。
ReactDOMコンポーネントはビューを返すためだけに使えるようになる⇒スッキリする
やったこと
- Reduxの流れで一緒に学習
- ソートするやつをリファクタ
新しい発見
- コンパイルエラー相当の静的解析はしてくれる
- トランスパイルするから当たり前なんだけど盲点だった
- 環境構築めっちゃラク
- ライブラリごとに使うメソッドの数が少なかったので、あんまり覚えなくてよかった
- 画面で動くの楽しい
つまづいたところ
- 当初、Reduxを使うことにあんまりメリットを感じなかった
- とりあえずReactコンポーネントで状態管理してみた
- ⇒カオスになった(Reduxを使うまではそこまでカオスだとも思ってなかった)
- Presentational ComponentとContainer Componentの構成
- どうやってState Treeを構成すべきか悩ましい
- Presentational Componentにどれだけロジックを入れるか悩ましい
- SVGのアニメーションむずい
- sleep()ないんですか
つまづかなかったところ
- npm
- gradleとだいたい同じ
- Reduxの概念
- 純粋関数
今後
- テストしたい
- reduxで副作用したい⇒redux-saga
- アニメーションしたい
reactのstateがごちゃつき始めるくらいまで使ってみた。
stateがごちゃついてなんかつらいなこれ…ってなり始めるくらいまでreact.jsを使ってみました。 初心者なりにつらかったところを記録しておきます。 react.jsの環境構築や使い方については、初心者向けの記事は良い記事がたくさんあるので、そちらにお任せします。
つくったもの
ソートするやつをつくりました。 0~99までの100個の数値を、バブルソートでソートします。
もっとちゃんとしたやつをどこかで見たことがるって?はい、私も見たことがあります。いいのです。学習用なので、これでいいのです。
herokuにデプロイしてみました。
https://evening-brushlands-42735.herokuapp.com/
https://github.com/ytnk531/react-tutor
ソースコードも公開しています。ただしフロントエンドド素人が作ったものであるため、くれぐれもお手本にはしないように( ´∀` )
reactのコンポーネントで状態管理するのはつらい?
下記の記事では、reactのコンポーネントの状態管理はreduxに任せてしまおう、と言っています。
qiita.com
reactのコンポーネントはstateと呼ばれるプロパティを持っていて、通常はこのstateプロパティを変化させてコンポーネントの状態を変更します。
reduxは、コンポーネントごとに状態を持つのはやめて、reduxを使うことで一か所で管理してしまおう、というライブラリです。こういったライブラリが推奨されるということは、コンポーネントで状態管理することに辛さがある、ということが示唆されているわけですが、いまいちそのつらみが理解できませんでした。
つらくなるまでやってみた
reactを使うならreduxと一緒に使いなさい!と教えていただきましたが、いまいち嬉しさがわかりませんでした。reduxで状態管理する嬉しさがわからないというよりは、reactで提供されているstateを使って状態管理する困難さがわからなかったのです。
ということで、ある程度つらくなるまで使ってみました。
フロントエンドは経験も知識ありませんでしたが、react自体は難しい物じゃないのでわりとすんなりと使えるようになりました。
作るのに必要だった知識
子要素は筆者の事前の理解度や利用経験。
- HTML
- JavaScript
- 基本的なシンタックスとconsole.logとアロー関数がわかる程度。
- Greasemonkeyで簡単な自動入力スクリプトを書いたことがある
- SVG
- ベクターの画像だよね?
stateで状態管理するつらさ
stateの更新がめんどくさい
stateを操作するときは、以下のように記述します。
// value1を1増やす this.setState(prevState => ({ value1: prevState.value1 + 1 });
状態を変えるたびにこれをやるのはしんどいってもんですね。
stateの反映されるタイミングが謎
setState()は非同期で呼ばれます。いつstateが更新されるかは定かではないのです。
例えば、下記のコードは無限ループします。
'''javascript
// finishの初期状態はfalse
while(this.state.finish) {
this.setState({finish: true});
}
'''
やっぱり散らばるのはよくない
コンポーネント間で共有したい値があったりします。 stateを外部から参照する方法があるにはあるのですが、とてもやりづらいうえに非推奨だそうです。
各コンポーネントの状態が、変更されているかわかりにくくなってしまうのは、確かに悪いことに感じます。 状態がいつ変更されているのかを追跡する手段が用意されていなければ、バグを見つけにくくなってしまうでしょう。 一つのクラスの中にstateが留められていたとしても、それはやはり同じでしょう。
結局つらかったか
すみません、stateを持ったコンポーネントを一つしか作らなかったので、そんなにつらくなかったです。
というか、stateもったコンポーネント同士で親子関係を作ると値の変更がしにくいので、子コンポーネントは状態を持たずにpropsで渡した値が状態になるような作りにするほかなかったです。
つまるところ、規模が大きくなってくると、一つのコンポーネントでたくさんの状態を管理したり、コンポーネント間で値が伝搬していくように作らなければならないように思います。
これがコンポーネントで状態を管理するつらさ…で…いいのか…な…。
つまづいたところ
コンポーネントをループで生成する h3poteto.hatenablog.com