新人エンジニア向け勉強の心構え・コツ
このpostは新人/若手向け、これだけは知っとけTips25 Advent Calendar 2012の18日目です。
本日、は新人エンジニアの方に勉強の心構え・コツを伝えたいと思います。
私自身、多くの失敗もし、今も勉強中ですが、多少なりともお役に立てればと思います。
毎日勉強しよう
プロ野球選手が練習もせずに試合に臨んだら、どう思いますか?
どの職業でも同じだと思いますが、エンジニアも一緒です。
日々の勉強があった上での仕事です。
本番の仕事で使えるように、日々の勉強(練習)を行いましょう。
飲み会等で帰宅後に勉強できない日もあるとは思います。
しかし、できる限る毎日勉強しましょう。
知らないことは調べよう
知らない単語が出てきたときは、放っておかずに、調べましょう。
その日のうちに調べておくのが良いです。でないと大抵、調べ忘れてしまうことが多いです。
地味ではありますが、続けていると自分の幅を広げるのに効果が出てきます。
自分の情報源を持とう
Webサイト、twitterのタイムラインなど、自分の情報源を持つと勉強しやすいです。
興味ある分野の情報を入ってくるようになれば、ウォッチしつづけ得意分野として確立できる可能性が高まります。
ソースを読んで、動かそう
OSS全盛時代の今、気になったらソースを読んじゃいましょう。
そして、実際に動かしてみましょう。
記事を読むだけでは分からなかった情報が手に入るし、手を動かすことで理解が深まります。
選挙に行こう
ITだけに偏るより、世の中のいろいろなことに目を向けましょう。
世の中を知っていると、システムのあるべき姿が分かることもあるかもしれません。
職場の仲間やお客さんとのコミュニケーションで役立つかもしれません。
即効性はありませんが、社会人としては幅を広げるために、IT以外のことも知りましょう。
最後に
新人のみなさんは、多くの可能性を秘めています。
エンジニアとしても、一社会人としても成功して欲しいです。そのために、なんでも一生懸命取り組んで欲しいと思います。そして、取り組みをブログ等で発表すると、つながりが広がるし、他の人の役に立つかもしれません。
是非、豊かなエンジニアライフを過ごしてください。
Javaデータグリッド仕様「JSR-347」のリンク集
この記事は Java Advent Calendar 2012 の12日目です! 11日目は@kokuzawaさんでした。13日目は@zephiransasさんです。
そういえば、今日は12年12月12日ですね。皆さんは、12時12分12秒に何をしていましたか? 私はというと、、、普通に定食屋でお昼を食べてました。。。
早速ですが、JSR-347ってご存知ですか?数字で言われても、分かる訳ないですよね?
JSR-347は「Data Grids for the Java Platform」というJSRのことです。。。って名前を聞いても、普通は何を言っているのか分かりませんよね?
まず、Data Gridとは何なのか、JSR-347とは何なのか、簡単に説明します。
Javaデータグリッド仕様「JSR-347」って何?
そもそも、JSR-347以前にはJSR-107「JCACHE - Java Temporary Caching API」というものがあり、JavaのキャッシュAPIが議論されていました。ここでは、keyやvalueにJavaオブジェクトを指定して保持できるキャッシュについて議論されていました。
世の中的にはビッグデータの流れもあり、単なるキャッシュではなく、分散実行等の機能を持ったものを「Data Grid」と呼び、JavaのData Gridの仕様を決めよう。。。というのが、JSR-347です。単刀直入に言うと、メモリに乗るデータは、分散環境でメモリに乗せて実行すれば高速に処理できるよね!ということ。
さて、実際にJSR-347のGitHubにあるProposed featuresを見てみると、以下のようなものが挙げられています(もっと具体的な内容については、このポストの最後にリンク集を付けたので、そこにあるスライドをご参照ください)。
- Async API (Future based)
- Distributed code execution
- Group API
- CDI (Contexts and Dependency Injection) integration
- Transactions (JTA) integration
- Operation Mode
- Eventually Consistent API
- Configuration
- Drop-In Replacement for JSR-107 Compliant Caches
そして、これらを実際に実装しているOSSが、RedHat社を中心に開発しているInfinispanです。
InfinispanはJava(とScala)で実装されており、超簡単に言うと、In-Memoryでクラスタ環境で動作するKVS(KVSというと狭すぎますが)です。keyとvalueにはJavaオブジェクトを利用することができます。商用製品ですと、Oracle社のCoherenceが同様の機能を持っています。
そんな訳で、JavaのData Grid仕様に関する情報や、その実装であるInfinispanの情報をまとめてみました。興味が湧いた方は是非この先のリンクをご覧ください。
JSR-347関連リンク
- JSR 347: Data Grids for the Java Platform JCPのサイトにあるJSR-347のページです。このJSRの要求やSpec Leadが誰で、とか書いてあります。
- JSR 347 discussions Googleグループにある、JSR-347のフォーラムです。
- datagrids JSR-347のGitHubです。
- @JSR347 (Twitterアカウント) たまにTweetされているようですが、さびしいですね。。。
- Javaのデータグリッドの仕様:JSR-347 JSR-347のSpec Leadであり、InfinispanのLead CommiterであるManik Surtaniさんへのインタビュー記事。JSR-347やInfinispanのイメージを短時間で知りたい人が読むのにお勧めです。
- JSR-107 and a JSR on data grids Manik Surtaniさんが書いたブログ記事。JSR-107とJSR-347の違いを簡潔に書いてあります。
Infinispan関連リンク
- Infinispanのプロジェクトページ Infinispanの公式ページです。ドキュメントを見たり、ダウンロードしたりできます。
- The JBoss Data Grid or, Enterprise-grade Infinispan 先日、Manik Surtaniさんが来日した時の発表資料です。
- Infinispan Open Source Data Grid RedHatのエンジニアであるnekopさんのスライド。Infinispanが持つ機能の概要を説明しています。
- 単なるキャッシュじゃないよ!?infinispanの紹介 Infinispanの特徴や使いどころについて解説しているスライド。MapReduceの図も載っています。
- データグリッド/キャッシュサーバのInfinispanって何ができるの? Infinispanのインストールから簡単な使い方を紹介しているページ。とりあえず、動かしたい方は御一読ください。
新人向け、Eclipse便利機能(入門)
こんばんわ。
このポストは「新人/若手向け、これだけは知っとけTips25 Advent Calendar 2012」の2日目として、書いています。1日目はtoshikiさんによる「エディタのちょっとした設定」でした。
さて、2日目ですが、私が開発で利用する言語はJavaがメインのため、Javaの開発環境について書きます。
現在、多くのJavaエンジニアが開発環境としてEclispeを使っているのではないでしょうか。そこで、ここでは「新人向け、Eclipse便利機能(入門)」と題して紹介します。
ダウンロード
Eclipseのダウンロード方法は様々なページで紹介されています。例えば、「Eclipse 4.2 のダウンロード,インストール,設定,日本語化,基本操作」(長いので、以下「Javaイントロ」と書きます)には、Eclipseのダウンロード、インストール、簡単な操作方法が書いてあります。こういうページを作ってくれる方、本当にありがたいですね♪
設定
起動したら、Javaイントロにしたがって設定。好みやコーディング規約にやると思いますが、私の場合、Text Editors設定では、以下の項目にチェックを付けています。
- Insert spaces for tabs
- Show line numbers
- Show whitespace characters
Tasksビューの表示
実際するときに便利な設定がコレ。Tasksビューの表示です。メニューから「Window」「Show View」「Tasks」と選びます。
すると、画面下部に「Tasks」のタブが表示されるようになります。
コメントに「TODO」と記述した箇所の一覧がこのタブに表示されるので便利。TODOを付けておき、チェックすることで、実装漏れを防ぐことができます。
Outlienのカスタマイズ
もうひとつ、便利で手放せない機能を紹介します。
Outlineはフィールドやメソッドを一覧できる便利なビューですが、ある程度大きなクラスになると、ごちゃごちゃして見づらくなります。
私の場合、Outlineから素早く状況を掴むために、Outlineのビューでは「Sort」「Hide Fields」にチェックを付けています。
これを使うと、デフォルトでは記述順に表示されていたメソッドが、メソッド名でソートされて表示されます。また、フィールドが表示されなくなるため、メソッドのみ参照できるようになります。これにより、Outlineを素早く把握することができます。
フィールドに注目したい場合は、表示するように戻します。
リフレクションって、どれくらい遅くなるの?
「リフレクションを大量に使うときはキャッシュせよ!」とは良く聞きますが、「キャッシュしたからと言って、速いのか?」という疑問がありました。そこで、検証。リフレクションと、直接のメソッド呼び出しを10億回実行して時間を比較してみました。
メインプログラムは以下の通り。単にsetterを呼び出しているだけです。
package jp.gr.java_conf.snuffkin.sandbox.reflection; import java.lang.reflect.Method; public class TestReflectionSpeed { public static void main(String[] args) throws Exception { SampleEntity target = new SampleEntity(); Method method = SampleEntity.class.getMethod("setName", String.class); int call = 1000000000; long startTime = System.currentTimeMillis(); for (int index = 0; index < call; index++) { method.invoke(target, "test"); } System.out.println("reflection :time(ms)=" + (System.currentTimeMillis() - startTime)); startTime = System.currentTimeMillis(); for (int index = 0; index < call; index++) { target.setName("test"); } System.out.println("direct call:time(ms)=" + (System.currentTimeMillis() - startTime)); } }
呼び出しているエンティティクラスは以下の通り。
package jp.gr.java_conf.snuffkin.sandbox.reflection; public class SampleEntity { private String name; public void setName(String name) { this.name = name; } }
私が測定に使ったのは、Core2DuoのMac Book Air。いまどきのマシンと比べるとCPU性能は落ちますね。で、結果は以下の通り。
reflection :time(ms)=19054 direct call:time(ms)=44
確かに、直接メソッドを読んだ方が速いです。しかし、10億回をリフレクションを呼んでも19秒。この性能なら、大抵のアプリケーションでリフレクションを使っても性能的に問題なさそうですね。
Netty3からNetty4へのなんちゃって移植
2012/07/07追記
Netty4のAPIはその後更新され、Netty3でのAPIは残していないようです。
そのため、ここに書いた内容は現在では使えませんのでご注意ください。
2013/10/17追記
Netty3からNetty4へのちゃんとしたマイグレーション方法は「How to Migrate Netty 3 to 4 (Netty 番外編) - Taste of Tech Topics」に記載しましたので、こちらをご覧ください。
以前、Nettyのことを書いてから全然続きを書いていませんでした。その間にNettyの開発は進み、Netty3からNetty4に進化しようとしています。Nettyのgithubに行くと、開発中のNetty4のコードがあるので遊んでみました。Netty4では"next-api"と呼ばれている新しいAPIを使っているのですが、ひとまず、以前の書いたソースをNetty3からNetty4に移植してみました。すると、next-apiを使わずに、パッケージ名を変えただけでほとんど動きました。どうやら、以前のAPIも残しているようですね。
echoサンプルくらいなら、以下の2種類の修正だけで、Netty4に対応することができました(ただし、Netty4は開発中なので、APIは今後変わるかもしれません。また、使うAPIによってはNetty4でそのまま使えないかもしれません)。
- importするパッケージを"org.jboss.netty"から"io.netty"に変更する
- NioClientSocketChannelFactoryのコンストラクタ引数の変更に対応する
サンプルソースは以下の通りです。
- EchoServer
package jp.gr.java_conf.snuffkin.sandbox.netty_next.echo; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFactory; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipelineFactory; import io.netty.channel.Channels; import io.netty.channel.socket.nio.NioServerSocketChannelFactory; import io.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.frame.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * サーバ側メインクラス */ public class EchoServer { public static void main(String[] args) { ChannelFactory factory = new NioServerSocketChannelFactory( // server Executors.newCachedThreadPool(), Executors.newCachedThreadPool() ); ServerBootstrap bootstrap = new ServerBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() { ChannelPipeline pipeline = Channels.pipeline(); // Downstream(送信) pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); pipeline.addLast("stringEncoder", new StringEncoder()); // Upstream(受信) pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(8192, 0, 4, 0, 4)); pipeline.addLast("stringDecoder", new StringDecoder()); // Application Logic Handler pipeline.addLast("handler", new EchoServerHandler()); // server return pipeline; } }); bootstrap.bind(new InetSocketAddress(9999)); // 9999番ポートでlisten } }
- EchoServerHandler
package jp.gr.java_conf.snuffkin.sandbox.netty_next.echo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.MessageEvent; import io.netty.channel.SimpleChannelHandler; /** * サーバ側アプリケーションロジック */ public class EchoServerHandler extends SimpleChannelHandler { /** * クライアントから電文を受信した際に呼び出されるメソッド */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) { String msg = (String) event.getMessage(); // 受信電文を取りだす ctx.getChannel().write(msg); // クライアントに送信 } }
- EchoClient(NioClientSocketChannelFactoryのコンストラクタ引数を変えています)
package jp.gr.java_conf.snuffkin.sandbox.netty_next.echo; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import io.netty.bootstrap.ClientBootstrap; import io.netty.channel.ChannelFactory; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipelineFactory; import io.netty.channel.Channels; import io.netty.channel.socket.nio.NioClientSocketChannelFactory; import io.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.frame.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * クライアント側メインクラス */ public class EchoClient { public static void main(String[] args) { ChannelFactory factory = new NioClientSocketChannelFactory( // client Executors.newCachedThreadPool() // ★引数変えています ); ClientBootstrap bootstrap = new ClientBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() { ChannelPipeline pipeline = Channels.pipeline(); // Downstream(送信) pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); pipeline.addLast("stringEncoder", new StringEncoder()); // Upstream(受信) pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(8192, 0, 4, 0, 4)); pipeline.addLast("stringDecoder", new StringDecoder()); // Application Logic Handler pipeline.addLast("handler", new EchoClientHandler()); // client return pipeline; } }); ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 9999)); // 9999番ポートにconnect future.getChannel().getCloseFuture().awaitUninterruptibly(); bootstrap.releaseExternalResources(); } }
- EchoClientHandler
package jp.gr.java_conf.snuffkin.sandbox.netty_next.echo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelStateEvent; import io.netty.channel.MessageEvent; import io.netty.channel.SimpleChannelHandler; /** * クライアント側アプリケーションロジック */ public class EchoClientHandler extends SimpleChannelHandler { /** * サーバに接続した際に呼び出されるメソッド */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent event) { ctx.getChannel().write("Hello, World!"); } /** * サーバから電文を受信した際に呼び出されるメソッド */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) { String msg = (String) event.getMessage(); System.out.println(msg); } }
これだけで、動きました。next-apiを使っていなので、これを移植と言ってはズルイ気がしますが。。。次はもうちょっと真面目に書きます^^