備忘録。金額表示などでよくあるカンマで3桁ずつ区切るアレ。正規表現で実現できることを知りました。便利なのでメモ。
"123456789".replace(/(\d)(?=(\d{3})+$)/g, '$1,'); //=> "123,456,789"
現場からは以上です。
備忘録。金額表示などでよくあるカンマで3桁ずつ区切るアレ。正規表現で実現できることを知りました。便利なのでメモ。
"123456789".replace(/(\d)(?=(\d{3})+$)/g, '$1,'); //=> "123,456,789"
現場からは以上です。
この note の記事、なかなかおもしろいので未読の方はぜひ読んでみてください。
これ読んでてふと思ったけど、プログラミングはできるのにデバッグが下手なひとっているよね https://t.co/HoqyqJbUa8
— kntmr (@knt_mr) 2019年1月5日
狭い観測範囲で恐縮ですが、このようなひとの特徴を考えてみました。
問題の切り分け、どこまでが正常でどこからが異常なのか、対象を絞り込むスキルが必要です。絞り込む際、過去の経験からすぐに思い当たることもあれば、調べる範囲を絞りつつ問題の所在を探すこともあります。
また、大局的には切り分けられるけど、局所的に調査できないひともいる気がします。このようなひとは、debugger を使ったり、(原始的ですが) print debug しながらロジックを追うことをしていないように見えます。あと、ログ (スタックトレース) を見てない。
問題はここにあるという思い込みを捨てて、まずは現状をできる限り正確に把握することが大事です。
仮説を立てて検証することは、デバッグというかトラブルシューティングの基本かと思います。
仮説を立てるにはある程度の経験や動作原理の理解が必要で、最初のうちは愚直に調べるしかないかもしれないけど、「XXのときはYYになる」のように、条件と想定する結果を書き出して1つずつ検証するのがよいかと思います。
あと、個人的に重要だと思うのが、
特に2点目については、副次的に別の事象が発見される可能性があるので、水平展開としてやっておくとよさそう。
手当たり次第ではなく、順序立てて体系的に分析することが大事です。
個人の思い込みによって推測にバイアスがかかることがあるような気がします。仕組みや原理を理解不足もあるかもしれない。下手にあれこれ推測するくらいなら、まずは手元の環境で事象を再現させるところから始めた方がいいと思います。
前述の2点と重複しますが、切り分けと仮説&検証のプロセスを繰り返すことで、推測の確度を高められるのではなかろうかと思われます。
ここまで書いておいてアレだけど、人間というものは気持ちに余裕がないと冷静に判断できなくなりがちで、ついつい「思い込み」に走ってしまうもの。
年末&元日は帰省先で賑やかに過ごし、三が日が過ぎた今は自宅でマターリ。
2017年のふりかえりと2018年のこと - kntmr-blog
というわけで、基本的に何か目標がないとだめだめマンみたいなので、今年は英語勉強の目標として TOEIC で600点あたりを目指してみようかな。あと、どこかで Java 9 と Spring 5 は腰を据えて学ばなければ。現場からは以上です。
これのふりかえりと2019年のことでも書いてみようかと。
2018年前半は進捗ゼロで、結局 TOEIC は受けられず。が、夏頃から『スタディサプリENGLISH』のプレミアム会員に登録し、通勤時間を利用して1日30分程度勉強しています。課金駆動学習。今年は1日1時間程度は勉強できるようにしたいところ。
Java や Spring の新しい機能はなかなか試すことができず。ただ、Java のリリースモデルについてはそこそこキャッチアップできました。仕事で使わずとも新しいバージョンの情報は収集していきたいところ。特に、クラウド (サーバーレス) 関連の機能やフレームワーク/ライブラリはウォッチしておかねば。
普段、仕事でクラウド関連のサービスを使う機会がなく、なかなか手付かずの状態だったのですが、2018年は AWS のオンラインセミナーを受けたり、無料枠でいくつかのサービスを試してみました。可能であれば仕事を通して AWS や GCP などのクラウド関連のスキルを身に付けたいところですが、引き続き、基礎的なところは自己学習で補おうかと。ついでに認定でも目指してみようかな。
あと、全然たいしたものではないのですが、初めて GitHub で PR や Issue を投げてみました。
とりあえず、2019年は英語の勉強を中心にしようかと。まずはリスニングとリーディング。その他は必要に応じて。
最近、Vue.Draggable を使う機会があったのですが、ドラッグ&ドロップで要素を並び替えたときにどのような順序でイベントハンドラが呼ばれるのか気になったので調べてみました。とりあえず、以下に記載されているイベントハンドラを対象にします。ちなみに、move
イベントは SortableJS の move
プロパティを利用するようです。
サンプルコードはこちら。
呼び出しの順序は以下の通り。右端の数字は操作の番号と対応する。
1) クリック ⇒ 2) ドラッグ ⇒ 3) 入れ替え ⇒ 4) ドロップ
1) クリック ⇒ 2) ドロップ (※ドラッグなし)
1) クリック ⇒ 2) ドラッグ ⇒ 3) ドロップ (※入れ替えなし)
1) クリック ⇒ 2) ドラッグ ⇒ 3) 入れ替え ⇒ 4) 戻す ⇒ 5) ドロップ
1) クリック ⇒ 2) ドラッグ ⇒ 3) 入れ替え ⇒ 4) 入れ替え ⇒ 5) ドロップ (※2行移動)
調べてはみたけど、Sortable の README.md などを読めばなんとなくイメージできるかもしれないですね...。
現場からは以上です。
GraphQL Advent Calendar 2018 の18日目です。
最近、GraphQL を試しに触り始めてみたという程度です。普段は Java や Spring を使っています。というわけで、今回は Spring Boot で試してみたときの備忘録シリーズの第3弾となります。第1弾と第2弾はこちら。Query と Mutation を試してみたときの備忘録です。が、本当に触ってみた程度の内容です...。
今回は Subscription を試してみます。相変わらず触ってみた程度の内容ですが、サンプルコードはこちら。
kntmr/playground/graphql-spring-examples - GitHub
以下、備忘録。
Subscription の Resolver からは Publisher<T>
を返す。取り急ぎ、Spring WebFlux を追加。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
スキーマに Subscription の IF を定義。
// ... (略) type Subscription { added(id: ID!): ToDo }
Subscription の場合は、GraphQLSubscriptionResolver
インタフェースを実装する。今回は EmitterProcessor<T>
で Publisher<T>
を返すことに。また、引数で指定された ID で filter することで、Subscribe したユーザーごとに Subscription を返すようにする。
@Component public class TodoSubscriptionResolver implements GraphQLSubscriptionResolver { private TodoEmitterProcessor processor; public TodoSubscriptionResolver(TodoEmitterProcessor processor) { this.processor = processor; } public Publisher<ToDo> added(int id) { return processor.getProcessor().filter(todo -> todo.getUserId() == id); } }
EmitterProcessor<T>
を持つクラス。
@Component public class TodoEmitterProcessor { private EmitterProcessor<ToDo> processor; public TodoEmitterProcessor() { processor = EmitterProcessor.create(); } public EmitterProcessor<ToDo> getProcessor() { return processor; } public void sendMessage(ToDo todo) { processor.onNext(todo); } }
Mutation で更新するときに EmitterProcessor#onNext
する。
// ... (略) ToDo newTodo = new ToDo( ... ); todoDao.add(newTodo); processor.sendMessage(newTodo); // 追加
アプリを起動するとコンソールに以下のログが出力されている。
Registering ServerEndpointConfig: ServerEndpointRegistration for path '/subscriptions': class graphql.servlet.GraphQLWebsocketServlet
というわけで、今回は GraphiQL ではなく、WebSocket で /subscriptions
にリクエストする。
const ws = new WebSocket('ws://localhost:8080/subscriptions') ws.onopen = (e) => { console.log('ws opened.') ws.send(JSON.stringify({ query: `subscription { added(id: 1) { // ★ id, content, completed } }` })); } ws.onmessage = (e) => { console.log('ws message.') var resp = JSON.parse(e.data); // ... (略) } ws.onclose = (e) => { console.log('ws closed.') ws.close(); } ws.onerror = (e) => { console.log('error!!') ws.close(); }
GraphiQL などから Mutation でデータを更新すると、ws.onmessage
でイベントが通知される。Resolver 側で ID で filter しているので、他ユーザーのデータを Mutation に投げた場合はイベントは通知されない。
まだまだあやしいところはありますが、ここまでで Query / Mutation / Subscription の3機能をざっくり試してみました。今後はもう少し実践的な内容を調べていきたいと思います。特に、自動生成などの開発ツール周りを調べたい。
とりあえず、以下のドキュメントをもっと読み込んでみようかと。
先日の JJUG CCC 2018 Fall で GraphQL のセッションがありました。
www.slideshare.net
デモのリポジトリはこちら。
JJUG CCC 2018 Fall に行ってきました。簡単に所感をまとめます。
セッション資料は以下で公開されると思います。
GitHub - jjug-ccc/slides-articles-2018Fall: JJUG CCC 2018 Fall 登壇資料まとめ
今回は午後からの参加だったのですが、GraalVM とか午前のセッションでいくつか気になるものがあるのであとで見てみようと思います。
今回参加したセッションは以下の通り。メモから抜粋。
www.slideshare.net
参加者が多くて人気のあるセッションでした。改めてアーキテクチャ設計の難しさを感じました。定期的に読み直したい資料です。冒頭で紹介されていた起業クエストはこちら。
吉祥寺.pm16で発表した「起業クエスト」を公開しました!
— :craftsman/kawasima (@kawasima) December 14, 2018
かなりの難度のゲームです。https://t.co/JMARTHIHxU
回線容量喰うので、おうちでお試しください!
Kotlin というより、どのように技術選定をしているのか気になって参加しました。OKR でリプレースやリファクタリングを進めるのはよさそうです。が、Key Results を客観的に判断できるように定量化するところがなかなか難しそうでキモかもしれません。ところで、Builder パターンの代わりに名前付き引数を使うというのは、なんかメリットの捉え方が少しズレてるような気がしますが、どうなんでしょう...。
www.slideshare.net
とても学びの多いセッションでした。ここまで資料がまとまってるというのは素晴らしい...。要復習。
www.slideshare.net
今回、最も聴きたかったセッション。なかなか graphql-java の話を聴くことがないので貴重でしたが、内容自体は割と基本的なところだったかもしれません。デモのリポジトリはこちら。要復習。
1番気になっている Subscription については少し触れていましたが、英語が聞き取れず...。悲しい。
英語ムズすぎィィィ
— kntmr (@knt_mr) December 15, 2018
今回、海外からのスピーカーが多くて豪華でした。参加できなかったセッションの資料はあとで見てみようと思います。
あと、JJUG だけではないですか、最近、Kotlin がテーマのセッションが多くなった気がします。数年前はこのポジションに Scala がいたような。ある意味、Scala は枯れてきたと言えるのかもしれません。先日の Spring Fest 2018 でも Kotlin サポートの話がありましたね。
Spring Fest 2018 に行ってきた #jsug - kntmr-blog
最後のセッションで、「英語の読み書きの速さの差が日本と世界のエンジニアの差」という話がありましたが、まさに直前のセッションで英語が聞き取れなかったところなので、身に沁みました...。英語の勉強をしなければ。
Windows で Micronaut を試してみたので備忘録。
一般的には SDKMAN を使うケースが多いかと思いますが、今回は Windows 環境ということでバイナリを使います。ダウンロードして Path を通す。
2.1.2 Install through Binary on Windows
初回の mn
コマンド実行時に依存解決する模様。無念にもプロキシ環境の場合は事前に設定する。
$ set MN_OPTS=-Dhttps.proxyHost=proxy.com -Dhttps.proxyPort=8080
mn
コマンドを叩いてみる。
$ mn --version | Micronaut Version: 1.0.1 | JVM Version: 1.8.0_172
無念にもプロキシ環境の場合は事前に設定する。
$ set JAVA_OPTS=-Dhttps.proxyHost=proxy.com -Dhttps.proxyPort=8080
プロジェクト作成。
$ mn create-app micronaut-examples | Generating Java project... | Application created at C:\Users\ ... \micronaut-examples
起動。
$ cd micronaut-examples $ gradlew run > Task :run [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2238ms. Server Running: http://localhost:8080
環境起因なのか、起動は思っていたほど早くない気がする...?
CLI から Controller を作成すると、Controller クラスとテストクラスが生成される。
$ mn create-controller Hello | Rendered template Controller.java to destination src\main\java\micronaut\examples\HelloController.java | Rendered template ControllerTest.java to destination src\test\java\micronaut\examples\HelloControllerTest.java
デフォルトでは 200 OK を返すコードが生成される。
@Controller("/hello") public class HelloController { @Get("/") public HttpStatus index() { return HttpStatus.OK; } }
gradlew run
で起動して、http://localhost:8080/hello
にアクセスするとレスポンスが返る。
テストクラスはこちら。gradlew test
でテストを実行する。
public class HelloControllerTest { @Test public void testIndex() throws Exception { try(EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class)) { try(RxHttpClient client = server.getApplicationContext().createBean(RxHttpClient.class, server.getURL())) { assertEquals(HttpStatus.OK, client.toBlocking().exchange("/hello").status()); } } } }
Controller のメソッドとテストを追加してみる。
@Get("hello2") public HttpResponse<String> index2() { return HttpResponse.ok("Hello Micronaut"); }
テストメソッドはこんな感じ。
@Test public void testIndex2() throws Exception { try(EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class)) { try(RxHttpClient client = server.getApplicationContext().createBean(RxHttpClient.class, server.getURL())) { assertEquals("Hello Micronaut", client.toBlocking().exchange("/hello2", String.class).body()); } } }
最初、自動生成されたテストコードを参考に HttpResponse#exchange(String)
で試してみたが、これだとどうしてもレスポンスボディが取得できない...。で、HttpResponse#exchange(String, Class<T>)
でレスポンスの型を指定してみたら無事に取得できた。
client.toBlocking().exchange("/hello2").body() //=> null client.toBlocking().exchange("/hello2", String.class).body() //=> "Hello Micronaut"
API ドキュメント にもそのような感じのことが書いてあるっぽいが、これは Reactive Streams の仕様なんだろうか...。
Returns: An Optional of the type or Optional.empty() if the body cannot be returned as the given type
以下のコマンドを叩くと、build フォルダにいろいろ生成される。
$ gradlew assemble
とりあえず、動かすことはできました。ドキュメントは割と充実しているようなので読んでみたいと思います。
User Guide - MICRONAUT DOCUMENTATION
Micronaut は、起動の早さや省メモリが特徴のようで、クラウド環境、特にサーバーレスな環境で Java アプリケーションを使うときに適しているようです。クラウド以外にも、起動が早いということからバッチアプリケーションとして使えるかもしれません。このあたり、Spring Batch と比較してみようかなー。