SlideShare a Scribd company logo
from old Java
to modern Java
∼ 職業プログラマに聞いて欲しいJava再入門
Acroquest Technology株式会社
JJUG / 関西Javaエンジニアの会
谷本 心 ( @cero_t )
自己紹介
•職業:
Javaトラブルシューター
(教育もやってます)
•近況:
gihyo.jpや日経ソフトウエアに
記事を書きました
ENdoSnipeというOSSの
Java解析・可視化ツールを
gihyo.jpで紹介しました
記事の検索:
endosnipe gihyo
公式サイト:
http://www.endosnipe.com
日経ソフトウエア
2013年7月号の特集記事
「そのコードは古い」の
Java編を執筆しました
同僚と一緒に
「Javaのイケてるコード、残念なコード」
を連載していました(4月号まで)
購入:
http://www.amazon.co.jp
本日のテーマ
イマドキのJava
(文法編)
Javaの文法の話
新しいAPIの話
解析ツールの話
バイトコードの話
いま、現場では
どのバージョンの
Javaをお使いですか?
(複数回答可)
もちろん
JavaSE7
既にOracleの
サポートが切れた
JavaSE6
え、まだ
J2SE 5.0ですか?
まさかの
J2SE 1.4ですか?
それより前?
大丈夫です、
今回は1.4や5.0あたりを
使っている人が
一番のターゲットです
逆に
JavaSE8?
すごいね、
帰っていいよ!
from old Java
to modern Java
∼ 職業プログラマに聞いて欲しいJava再入門
Acroquest Technology株式会社
JJUG / 関西Javaエンジニアの会
谷本 心 ( @cero_t )
Lesson1
現場で見かける
こんなコード
private List m_list = null;
private int process_file(String str_file_name) {
String str_line;
List list_lines = new ArrayList();
int i_result = read_file(str_file_name, list_lines);
if (i_result == 0) {
List list_record = new ArrayList();
for (int i = 0; i < list_lines.size(); i++) {
str_line = (String) list_lines.get(i);
Record record = new Record();
i_result = parse_line(str_line, record);
if (i_result != 0) {
return i_result;
}
list_recordord.add(record);
}
m_list = list_record;
return 0;
} else {
return i_result;
}
}
Lesson1
from C-ish Java
to Java like Java
(J2SE1.4)
private List m_list = null;
private int process_file(String str_file_name) {
String str_line;
List list_lines = new ArrayList();
int i_result = read_file(str_file_name, list_lines);
if (i_result == 0) {
List list_record = new ArrayList();
...
private List m_list = null;
private int process_file(String str_file_name) {
String str_line;
List list_lines = new ArrayList();
int i_result = read_file(str_file_name, list_lines);
if (i_result == 0) {
List list_record = new ArrayList();
...
メンバ変数だと分
かるよう、先頭に
m_ を付けよう
スネークケースの方が
読みやすいよね
変数は先頭でまとめて宣言
もちろんハンガリアン記法さ!
戻り値を複数返したい時
は、引数に戻り値相当の変数
参照を渡せばいいんだよ
関数の戻り値はもちろん0が正常、
それ以外が異常
for (int i = 0; i < list_lines.size(); i++) {
str_line = (String) list_lines.get(i);
Record record = new Record();
i_result = parse_line(str_line, record);
if (i_result != 0) {
return i_result;
}
list_recordord.add(record);
}
m_list = list_record;
return 0;
for (int i = 0; i < list_lines.size(); i++) {
str_line = (String) list_lines.get(i);
Record record = new Record();
i_result = parse_line(str_line, record);
if (i_result != 0) {
return i_result;
}
list_recordord.add(record);
}
m_list = list_record;
return 0;
下の関数でエラーが出たら
ちゃんとエラーコードを上に
伝播させないとね
正常終了はいつも
return 0;
きちんとJava風に
書き直すと・・・
private List resultList;
private List processFile(String fileName)
throws SystemException {
List lines = readFile(fileName);
List recordList = new ArrayList();
for (int i = 0; i < lines.size(); i++) {
String line = (String) lines.get(i);
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
private List resultList;
private List processFile(String fileName)
throws SystemException {
List lines = readFile(fileName);
List recordList = new ArrayList();
for (int i = 0; i < lines.size(); i++) {
String line = (String) lines.get(i);
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
メンバ変数に接頭辞や
thisはつけない
キャメルケース
エラーはExceptionで
表現して伝播させる
エラーコードではなく
普通に値を返す
変数は
使う直前
に宣言
引数に戻り値への
参照を渡さない
No ハンガリアン
before / after
で見てみると
before
private List m_list = null;
private int process_file(String str_file_name) {
String str_line;
List list_lines = new ArrayList();
int i_result = read_file(str_file_name, list_lines);
if (i_result == 0) {
List list_record = new ArrayList();
for (int i = 0; i < list_lines.size(); i++) {
str_line = (String) list_lines.get(i);
Record record = new Record();
i_result = parse_line(str_line, record);
if (i_result != 0) {
return i_result;
}
list_recordord.add(record);
}
m_list = list_record;
return 0;
} else {
return i_result;
}
}
after
private List resultList;
private List processFile(String fileName)
throws SystemException {
List lines = readFile(fileName);
List recordList = new ArrayList();
for (int i = 0; i < lines.size(); i++) {
String line = (String) lines.get(i);
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
なんということでしょう
No C-ish Java like
1
メンバ変数は見やすいように
接頭辞をつける
メンバ変数はIDEが色をつけるから
接頭辞もthisも不要
2 スネークケース 文化的にキャメルケース
3
変数は先頭で宣言しないと怒られるし
メモリ解放し忘れる
変数は使っている場所が分かるよう
使う直前に宣言する
4
関数の戻り値でエラーを表現
0を返せば正常
エラーはExceptionで表現
値が普通に返れば正常
5 引数に戻り値の参照を渡すと良い
メソッドの引数はできるだけ変更しない
(特に戻り値がある場合)
Lesson1 まとめ
Lesson2
from J2SE 1.4
to J2SE 5.0
ちなみに正式名称は
JavaSE 5.0ではなく
J2SE 5.0らしいよ
J2SE 5.0
Generics foreach
enum
static import
var args
auto boxing
... and more
イマドキのJavaの
スタンダード
before
private List processFile(String fileName)
throws SystemException {
List lines = readFile(fileName);
List recordList = new ArrayList();
for (int i = 0; i < lines.size(); i++) {
String line = (String) lines.get(i);
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
after
private List<Record> processFile(String fileName)
throws SystemException {
List<String> lines = readFile(fileName);
List<Record> recordList = new ArrayList<Record>();
for (String line : lines) {
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
private List<Record> processFile(String fileName)
throws SystemException {
List<String> lines = readFile(fileName);
List<Record> recordList = new ArrayList<Record>();
for (String line : lines) {
Record record = parseLine(line);
recordList.add(record);
}
return recordList;
}
全体的にGenericsを使って
型を明確にする
foreach文(拡張for文)で
シンプルに
ループ処理を行なう
簡単すぎたので
もう一つ。
public interface Constants {
public static final int FILE_NOT_FOUND = -1;
public static final int FILE_READ_ERROR = -2;
public static final int FILE_EMPTY = -3;
public static final int RECORD_EMPTY = -4;
public static final int RECORD_SIZE_ERROR = -5;
public static final int RECORD_BODY_EMPTY = -6;
}
public class FileProcessor implements Constants {
private List readFile(String fileName) {
List lines = new ArrayList();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
}
public class FileProcessor implements Constants {
private List readFile(String fileName) {
List lines = new ArrayList();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
}
定数インタフェースという
優れたテクニック
定数クラス名を省略して
記載できるんですよ!
あると思います
public enum ErrorCode {
FILE_NOT_FOUND
, FILE_READ_ERROR
, FILE_EMPTY
, RECORD_EMPTY
, RECORD_SIZE_ERROR
, RECORD_BODY_EMPTY
, RECODE_CODE_NOT_NUMERIC;
}
列挙するならenum
import static ErrorCode.*;
public class FileProcessor {
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
}
定数クラス名を省略して
記載できるんですよ!
static importで定数クラス
(enum)全体をimport
import staticが
1つ以上あったら * になるよう
IDEを設定しておくと良い
No J2SE 1.4 J2SE 5.0
1 Objectだけを扱うCollection Genericsを使ったCollection
2
for (int i=0; i < list.size(); i++)
while (iterator.hasNext())
for (String value : list)
3 定数インタフェースは便利 static importで定数を宣言する
4 int値を使ってコード一覧を作成 enumを使って列挙する
Lesson2 まとめ
Lesson3
from J2SE 5.0
to JavaSE 6
JavaSE 6では、
文法面はほとんど変化なし
(ツール、APIの強化のみ)
ちなみに、API変更のおかげで
native2asciiを使わなくて
済むようになったけど
native2asciiを
使う方が安全だから
結局みんな使ってる
(実際はIDEで変換)
No J2SE 5.0 JavaSE 6
1
native2asciiは面倒だからIDEの
プロパティファイル編集機能を使う
native2asciiは面倒だからIDEの
プロパティファイル編集機能を使う
Lesson3 まとめ
Lesson4
from JavaSE 6
to JavaSE 7
JavaSE 7
try-with-resources
diamond operator
nio2
multi-catch
... and more
この辺から
ちょっと理解が
怪しくなる人が多い
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
finallyでcloseしないと
リソースのクローズ漏れを
起こして大変ですよね
別に起きないし
いいよね
敢えて言えば
finallyでcloseするのは
古い定石
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<>();
try (FileReader in = new FileReader(fileName);
BufferedReader reader
= new BufferedReader(in)) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
}
return lines;
}
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<>();
try (FileReader in = new FileReader(fileName);
BufferedReader reader
= new BufferedReader(in)) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
}
return lines;
}
tryでリソースを宣言すると
tryブロックから抜ける時に
クローズされる
密かにdiamond
まぁファイル読むだけなら
private List<String> readFile(String fileName) {
try {
return Files.readAllLines(Paths.get(fileName),
Charset.defaultCharset());
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
}
}
private List<String> readFile(String fileName) {
try {
return Files.readAllLines(Paths.get(fileName),
Charset.defaultCharset());
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
}
}
NIO2で追加された
新しいファイルAPIのひとつ
これでもう
Groovyの人とかに
プギャーされなくなる
before
private List<String> readFile(String fileName) {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException ex) {
throw new SystemException(FILE_NOT_FOUND, ex);
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ex) {
// この例外は無視する?
}
}
return lines;
}
after
private List<String> readFile(String fileName) {
try {
return Files.readAllLines(Paths.get(fileName),
Charset.defaultCharset());
} catch (IOException ex) {
throw new SystemException(FILE_READ_ERROR, ex);
}
}
もう一つ、便利なAPI
before
public class Entity {
private int intValue;
private long longValue;
private float floatValue;
private String string;
private Date date;
@Override
public int hashCode() {
int result = intValue;
result = 31 * result + (int) (longValue ^ (longValue >>> 32));
result = 31 * result + (floatValue != +0.0f ? Float.floatToIntBits(floatValue) : 0);
result = 31 * result + (string != null ? string.hashCode() : 0);
result = 31 * result + (date != null ? date.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
// 省略
}
}
public class Entity {
private int intValue;
private long longValue;
private float floatValue;
private String string;
private Date date;
@Override
public int hashCode() {
int result = intValue;
result = 31 * result + (int) (longValue ^ (longValue >>> 32));
result = 31 * result + (floatValue != +0.0f ? Float.floatToIntBits(floatValue) : 0);
result = 31 * result + (string != null ? string.hashCode() : 0);
result = 31 * result + (date != null ? date.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
// 省略
}
}
自前で実装すると死ぬから
だいたいIDEで自動生成
after
public class Entity {
private int intValue;
private long longValue;
private float floatValue;
private String string;
private Date date;
@Override
public int hashCode() {
return Objects.hash(intValue, longValue, floatValue, string, date);
}
@Override
public boolean equals(Object o) {
// 省略
}
}
public class Entity {
private int intValue;
private long longValue;
private float floatValue;
private String string;
private Date date;
@Override
public int hashCode() {
return Objects.hash(intValue, longValue, floatValue, string, date);
}
@Override
public boolean equals(Object o) {
// 省略
}
}
JavaSE 7に新しく入った
Objectsのhashメソッドを利用
Java標準ライブラリも
ようやく整備されてきました
Lesson4 まとめ
No J2SE 5.0 JavaSE 7
1 finallyでcloseする try-with-resources
2 BufferedReaderでファイルを読み込む Files.readAllLines
3
Collectionの宣言は
左辺にも右辺にも型名を記載する
Collectionの宣言で
右辺の型名は省略する
4
hashCodeの実装は、間違えないように
IDEで自動生成する
hashCodeの実装は
Objects.hashを使う
Final Lesson
from JavaSE 7
to JavaSE 8
JavaSE 8
Project Lambda
Stream interface
Date and Time API
... and more
before
private List<Record> resultList;
public List<Record> getMoreThan(int min) {
List<Record> newList = new ArrayList<>();
for (Record record : resultList) {
if (record.getScore() > min) {
newList.add(record);
}
}
Comparator<Record> comparator = new Comparator<Record>() {
@Override
public int compare(Record o1, Record o2) {
return o1.getScore() - o2.getScore();
}
};
Collections.sort(newList, comparator);
return newList;
}
after
private List<Record> resultList;
public List<Record> getMoreThan(int min) {
List<Record> newList = resultList.stream()
.filter(record -> record.getScore() > min)
.sorted((o1, o2) -> o1.getScore() - o2.getScore())
.collect(Collectors.toList());
return newList;
}
private List<Record> resultList;
public List<Record> getMoreThan(int min) {
List<Record> newList = resultList.stream()
.filter(record -> record.getScore() > min)
.sorted((o1, o2) -> o1.getScore() - o2.getScore())
.collect(Collectors.toList());
return newList;
}
Listのstream処理を開始
filterで絞り込んで(引数はPredicate)
sortedでソートして(引数はComparator)
collectで結果を取り出して(引数はCollector)
filterやsortedの条件をLambdaで記述
Lambda
使いたくなったでしょ?
検索:
jdk8 download
いつ(略)
いまで(略)
Final Lesson まとめ
No JavaSE 7 JavaSE 8
1 単一メソッドの無名クラス Lambda
まとめ
日経ソフトウエア
2013年7月号の特集記事
「そのコードは古い」の
Java編を読んでね!
購入:
http://www.amazon.co.jp
大事なことなので
もう一度
ENdoSnipeというOSSの
Java解析・可視化ツールを
ぜひ使ってください!
記事の検索:
endosnipe gihyo
公式サイト:
http://www.endosnipe.com
To be continued !

More Related Content

PDF
from old java to java8 - KanJava Edition
PDF
Java SE 8 lambdaで変わる プログラミングスタイル
PDF
Javaセキュアコーディングセミナー東京第3回演習の解説
PDF
ゆるふわJava8入門
PPTX
【java8 勉強会】 怖くない!ラムダ式, Stream API
PDF
Java x Groovy: improve your java development life
PDF
Javaセキュアコーディングセミナー東京第3回講義
PPT
ジェネリクスの基礎と クラス設計への応用
from old java to java8 - KanJava Edition
Java SE 8 lambdaで変わる プログラミングスタイル
Javaセキュアコーディングセミナー東京第3回演習の解説
ゆるふわJava8入門
【java8 勉強会】 怖くない!ラムダ式, Stream API
Java x Groovy: improve your java development life
Javaセキュアコーディングセミナー東京第3回講義
ジェネリクスの基礎と クラス設計への応用

What's hot (20)

PDF
JavaのGenericsとは?
PPTX
Java Puzzlers JJUG CCC 2016
PDF
Java8のstreamをダラダラまとめてみる
PPTX
Java8勉強会
ODP
Introduction of Python
PPT
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
PPTX
PDF
60分で体験する Stream / Lambda
 ハンズオン
PDF
Javaセキュアコーディングセミナー東京第3回演習
PDF
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
PDF
社内Java8勉強会 ラムダ式とストリームAPI
PDF
Xtend - Javaの未来を今すぐ使う
PDF
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
PDF
Introduction Xtend
PPTX
DBFlute2017フェスLT資料
PDF
サーバーサイドでの非同期処理で色々やったよ
PDF
Best practice laravel
PDF
Xtend30分クッキング やきに駆動
PPTX
C# LINQ ~深く知って、使いまくろう~
PPTX
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
JavaのGenericsとは?
Java Puzzlers JJUG CCC 2016
Java8のstreamをダラダラまとめてみる
Java8勉強会
Introduction of Python
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
60分で体験する Stream / Lambda
 ハンズオン
Javaセキュアコーディングセミナー東京第3回演習
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
社内Java8勉強会 ラムダ式とストリームAPI
Xtend - Javaの未来を今すぐ使う
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
Introduction Xtend
DBFlute2017フェスLT資料
サーバーサイドでの非同期処理で色々やったよ
Best practice laravel
Xtend30分クッキング やきに駆動
C# LINQ ~深く知って、使いまくろう~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
Ad

Viewers also liked (8)

PDF
JJUG CCC 2015 Fall keynote
PPTX
日時クラスとは?
PDF
Serverlessなものを使ってサービスを作っている話
PDF
ほんとうに便利だった業務で使えるJava SE8新機能(JJUG CCC 2015 Spring)
PDF
そろそろJavaみなおしてもええんやで
PPTX
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
PPTX
U-NEXT学生インターン、過激なJavaの学び方と過激な要求
PDF
Java8移行は怖くない~エンタープライズ案件でのJava8移行事例~
JJUG CCC 2015 Fall keynote
日時クラスとは?
Serverlessなものを使ってサービスを作っている話
ほんとうに便利だった業務で使えるJava SE8新機能(JJUG CCC 2015 Spring)
そろそろJavaみなおしてもええんやで
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
U-NEXT学生インターン、過激なJavaの学び方と過激な要求
Java8移行は怖くない~エンタープライズ案件でのJava8移行事例~
Ad

Similar to from old Java to modern Java (20)

PDF
Javaセキュアコーディングセミナー東京第4回講義
PPTX
Javaプログラミング入門【第2回】
KEY
ひのきのぼうだけで全クリ目指す
PDF
たのしい関数型
PDF
Haskell で CLI
PDF
プログラムの処方箋~健康なコードと病んだコード
PDF
Rakuten tech conf
PDF
Lisp Tutorial for Pythonista : Day 3
PDF
Replace Output Iterator and Extend Range JP
PPTX
ActiveResourceが面白すぎる件
PDF
VS勉強会 .NET Framework 入門
PDF
第三回ありえる社内勉強会 「いわががのLombok」
PDF
速くなければスマフォじゃない - インターンバージョン-
PDF
知って得する標準関数の使い方
PDF
Swift 2.0 で変わったところ「前編」 #cswift
PPTX
20071030
PDF
Template method #dezapatan
PPTX
Junit4
PPTX
PHP AST 徹底解説
PPTX
pecl-AOPの紹介
Javaセキュアコーディングセミナー東京第4回講義
Javaプログラミング入門【第2回】
ひのきのぼうだけで全クリ目指す
たのしい関数型
Haskell で CLI
プログラムの処方箋~健康なコードと病んだコード
Rakuten tech conf
Lisp Tutorial for Pythonista : Day 3
Replace Output Iterator and Extend Range JP
ActiveResourceが面白すぎる件
VS勉強会 .NET Framework 入門
第三回ありえる社内勉強会 「いわががのLombok」
速くなければスマフォじゃない - インターンバージョン-
知って得する標準関数の使い方
Swift 2.0 で変わったところ「前編」 #cswift
20071030
Template method #dezapatan
Junit4
PHP AST 徹底解説
pecl-AOPの紹介

More from 心 谷本 (12)

PDF
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
PDF
Spring Bootをはじめる時にやるべき10のこと
PDF
Spring Boot + Netflix Eureka
PDF
プレゼンの技術 2 実践編
PDF
プレゼンの技術 1 考え方
PDF
プレゼンの技術
PDF
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
PDF
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
KEY
日本一細かいJavaOne2011報告
KEY
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
PDF
日本で二番目に「細かい」JavaOne2011報告
PDF
[関ジャバ]Java News 2011 Mar
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Spring Bootをはじめる時にやるべき10のこと
Spring Boot + Netflix Eureka
プレゼンの技術 2 実践編
プレゼンの技術 1 考え方
プレゼンの技術
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
日本一細かいJavaOne2011報告
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
日本で二番目に「細かい」JavaOne2011報告
[関ジャバ]Java News 2011 Mar

from old Java to modern Java