2013년 7월 8일 월요일
Scala 와 Java 의 자료구조 변환 문제를 쉽게 해결합시다.
이런 Scala의 장점을 Java에서 사용하기 위해서 단순한 작업 두 가지만 해주면, Scala 의 강력한 자료구조를 쉽게 사용할 수 있습니다.
첫째는 maven으로 java와 scala 코드를 동시에 빌드할 수 있는 환경을 만드는 것이고,
둘째는 Java 자료구조와 Scala 자료구조를 쉽게 변환할 수 있도록 하는 것입니다.
첫째는 링크를 따라가시면 쉽게 환경을 구성할 수 있으니 생략하구요,
자료구조의 변환에 대한 코드만 보여드리겠습니다.
물론 제가 만든 게 아니라 Scala 에서 기본 제공하는 JavaConversions 라는 Object 를 사용하는 것입니다.
Java2Scala Object 를 보시면 모든 메소드가 implicit 로 정의되어 있습니다. 암묵 변환(implicit conversion) 이 되서, 개발자는 Object 를 import 하는 것으로 끝납니다.
Java2Scala.scala
java 코드에서 scala 메소드를 사용할 때, java 의 list 나 set 을 전달하면, 알아서 scala 의 ArrayBuffer 나 HashSet으로 변환하여 작업한 후 결과도 java 의 자료구조 형식으로 변환합니다.
scala 의 implicit 기능을 사용하면 엄청난 유연성이 생깁니다.
2013년 5월 27일 월요일
Time Period Library for JVM
특히, 일반적인 산술적 계산이 아니라 주말, 공휴일, 개인 휴가 (반차 포함), 팀 공가 등등을 고려한 작업 계획을 작성하려면 좀 복잡한 계산이 필요합니다.
이런 걸 일반적으로 Company Working Calendar 라고 하는데, 기간별 투입시간 등의 리소스 관리에 많은 기법이 동원됩니다.
예전 회사에서도 이 문제로 여러번에 걸쳐 발전시켰습니다만, 워낙 좋은 라이브러리가 있어서 이 넘의 forking 해서 사용했습니다.
원본 : Time Period Library for .NET
원본을 보면, 제가 원하는 기간 계산이나 최종일 계산등이 아주 구조적으로 할 수 있도록 구성되어 있습니다.
제가 여기에 몇가지 기능을 추가해서 사용했었는데요. .NET의 TPL 을 이용한 병렬 처리가 가장 기억에 남습니다.
올 1월에 scala 공부 겸 해서 scala 로 제작해 보자 해서 porting 을 수행하였습니다.
1. Time Period Library by Scala
뭐 Scala 로 제작했으니 JVM에서 돌구요. Scala의 Collection 지원과 여러가지 기능 (curry 등) 을 사용하였으니, scala 공부 시에는 도움이 될 듯 합니다.
문제는 제가 이넘 제작하다가 테스트 코드를 많이 못 만들어 버그가 많을 것이라는 것입니다^^
다음은 java 로 porting 한 소스입니다.
2. Time Period Library by Java
이넘은 debop4j 라이브러리 내에서 개발한 거라 debop4j-core 를 사용합니다.
기능은 위의 두 개와 같구요. java 코드라 좀 지저분하다는 점이 단점이지요^^
이 글을 빌어 원작자에게 감사드리며, 허락도 받지 않은 상태라 걱정도 되네요.
2013년 1월 21일 월요일
Java Byte code 생성을 이용하여, Reflection 대체하기
다음 코드는 DynamicAccessor 를 생성해주는 Factory입니다. 굳이 factory를 만든 이유는 DynamicAccessor 생성 비용이 일반 클래스의 생성 비용에 비하여 상당한 비용이 들어가므로, Cache 를 이용하여, 재활용하자는 의미가 큽니다. Cache는 google guava의 LoadingCache 를 사용한 이유는 Cache 자체적으로 항목들을 관리할 수 있어, 코드량 및 실수가 적어지는 것이 장점입니다.
마지막으로 DynamicAccessor 를 테스트하는 코드입니다. (reflectasm 에 성능 측정 코드가 있어 굳이 만들지 않았습니다)
2013년 1월 20일 일요일
Google Guava 소개 자료
제가 본 것 중에 가장 정리가 잘 되어 있고, 발표자료지만 머리에 쏙쏙 들어오게끔 예제 코드도 잘 만들어진 소개자료 들입니다.
1. Google Guava & Eclipse Modeling Framework - Mikael Barbero
2. Guava by Example
다른 자료들도 많고, Guava 공식 사이트 Wiki 에도 많은 자료가 있습니다.
Java의 부가적인 코드량을 많이 줄이고, 좋은 품질의 Java 코드를 작성할 수 있는 Guava 를 많이 썼으면 합니다.
2013년 1월 10일 목요일
특정 코드를 병렬로 수행하기 - Java
그래서 Java 로 유사하게 Data 처리를 병렬로 수행할 수 있도록 하는 코드를 구현해 봤습니다.
private static int getPartitionSize(int itemCount, int partitionCount) {
return (itemCount / partitionCount) + ((itemCount % partitionCount) > 0 ? 1 : 0);
}
다음과 같은 절차로 수행됩니다.
- ExecutorService 생성 - 논리적 CPU 갯수만큼의 작업스레드를 가지게 한다.
- 입력 데이터 컬렉션인 elements 를 Process 갯수로 나눈다. (partitions)
각 Process 별로 작업할 컬렉션을 분할합니다. ( Process 가 4개이고, elements 수가 100개라면, 0~24 : 0 CPU, 25~49 : 1 CPU ... ) - partition 별로 작업을 정의한다.
- 모든 작업을 ExecutorService에게 실행시킨다.
- 작업 결과를 취합하여 반환한다.
위의 코드가 아주 제한적인 기능이지만, 입력값 별로 특정 로직을 수행할 때에는 유용합니다. 기본적으로 CPU가 4개라면, 최대 4배까지 빨라집니다. 물론 부가 작업이 있으니 약간은 떨어지겠지요.
만약 집계 기능의 경우는 위의 3, 4 번에서 소계를 수행하는 코드와 마지막 집계하는 코드가 더 필요할 것입니다.
테스트 코드는 다음과 같습니다. 십만번 호출 작업을 하는 테스트 코드 블럭을 100번 반복할 때, CPU 갯수 만큼 나눠서 수행하도록 합니다.
* 소스 중에 컬렉션 관련 메소드는 Google Guava 13.0 을 사용했습니다.
2013년 1월 6일 일요일
Scala 와 Java 의 가변인자(varargs)를 가진 메소드를 상호 호출하는 방법
void javaPrint(String: format, Object... args)
Scala 에서는 다음과 같이 표현합니다. 물론 AnyRef* 보다 Any* 를 사용하면 primitive type 들도 가능합니다.
def scalaPrint(format:String, @varargs args: Any*)
먼저 Java에서 Scala 로 만들어진 scalaPrint() 를 가변인자 형식으로 호출하게하기 위해 @varargs를 지정하게 하면 됩니다.
그럼 Scala 언어에서 Java 로 만든 javaPrint 를 호출하려면 다음과 같이 해야 합니다.
@varargs
def wrappingJavaPrint(format:String, args: Any*) {
javaPrint(format, args.map( _.asInstanceOf[AnyRef]) : _* )
}
로 호출하면 java 의 가변형식을 호출합니다.
"_*" 를 붙이는 이유는 Scala compiler 에게 가변인자로 호출함을 명시적으로 알려주게 됩니다.
Scala 2.8에서는 이런 문제가 좀 많았는데, 그 후로는 이런 방식으로 정착된 것 같습니다.
전 위의 방법을 몰라서, 좀 헤맸습니다^^
2012년 12월 26일 수요일
Java 와 Scala 코드를 동시에 사용하기
생각해보면 C# 과 VB.NET 또는 J# 을 한 프로젝트에서 사용한 적이 있긴한데, 거의 실험용이였고, J# 이 도태되고, C# 이 발전하는 바람에 C# 으로만 개발을 했습니다.
Java 개발을 시작하고, Scala 도 알게되고, Groovy 도 알게 되었지만, 순수 Java 코드로만 개발을 했다.
물론 Scala 는 따로 프로젝트를 만들어서 공부하거나 실험하면서 기존 Java 로 된 라이브러리를 잘 사용했습니다만...
Java 개발 시에 Scala 코드나 라이브러리를 사용할 생각은 잘 못했습니다.
이번에 C# 코드를 Java 로 포팅하면서, Default Parameter 지원같이 코딩량을 줄일 수 있는 Scala 가 필요했는데, Java 와 Scala 코드를 동시에 사용하는 코드 개발 방법을 몰라 포기 했었죠.
몇번 시도 했는데, 상호 교차 참조 시에는 문제가 생기더군요... 쩝...
오늘 제대로 된 정보를 얻어 따라해보니 상호 교차 되어도 문제없이 컴파일과 실행이 되는 군요. ㅎㅎ
우선 Java 와 Scala 를 동시에 사용하여 개발하기는
http://www.codecommit.com/blog/scala/joint-compilation-of-scala-and-java-sources 를 참고하시면 됩니다.
전 maven 으로 개발하므로, maven 코드를 그대로 복사해서 사용했습니다.
그 전에도 비슷하게 만들어져 있었는다. compiler plugin 순서를 scala , java 순으로 해야 하더군요 ㅠ.ㅠ
요렇게 한 다음
ValueObjectBase.java
public abstract class ValueObjectBase implements IValueObject {
//private static final long serialVersionUID = 5546630455380910528L;
@Override
public boolean equals(Object obj) {
return obj == this ||
(obj != null &&
getClass() == obj.getClass() &&
hashCode() == obj.hashCode());
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public String toString() {
return this.buildStringHelper().toString();
}
/**
* {@link ValueObjectBase#toString()}을 재정의하지 말고, buildStringHelper를 재정의 하세요.
*/
protected Objects.ToStringHelper buildStringHelper() {
return Objects.toStringHelper(this);
}
}
TimeVal.scala
class TimeVal extends ValueObjectBase with Comparable[TimeVal] {
var time: DateTime = _
def this(duration: Duration) {
this()
this.time = new DateTime().withMillisOfDay(duration.getMillis.toInt)
}
def this(moment: DateTime) {
this()
this.time = new DateTime().withMillis(moment.getMillisOfDay.toLong)
}
def this(hourOfDay: Int, minuteOfHour: Int = 0, secondOfMinute: Int = 0, millisOfSecond: Int = 0) {
this()
time = new DateTime().withTime(hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond)
}
def datetime: DateTime = this.time
def hourOfDay: Int = time.getHourOfDay
def minuteOfHour: Int = time.getMinuteOfHour
def secondOfMinute: Int = time.getSecondOfMinute
def millisOfSecond: Int = time.getMillisOfSecond
def millis: Long = time.getMillis
def getDateTime(moment: DateTime): DateTime = moment.withTimeAtStartOfDay().plus(millis)
def getDateTime(date: DateVal): DateTime = date.getDateTime(this)
override def hashCode(): Int = HashTool.compute(time)
protected override def buildStringHelper() =
super.buildStringHelper()
.add("time", time)
def compareTo(other: TimeVal) = {
Guard.shouldNotBeNull(other, "other")
time.compareTo(other.time)
}
}
object TimeVal {
def now: TimeVal = new TimeVal(DateTime.now())
}
TimeVal 사용 예
public static DateTime TimePart(DateTime dateTime) {
return new TimeVal(dateTime).datetime();
}
Scala 언어로 된 TimeVal가 Java 클래스를 상속 받고, Class 를 사용하는 것은 당연하지만, 동시에 Java 코드에서 Scala 클래스와 Object를 사용하게 되었습니다.
이로서 코드량을 확연히 줄이거나, Scala 코드로 구현하는 것이 더 효과적일 때에는 자유스럽게 사용하게 되었습니다.
한손잡이보다 양손잡이가 더 좋겠죠? (물론 코드의 품질의 충분조건은 아닙니다^^)
2012년 12월 23일 일요일
Friends of Guava
원본 : http://code.google.com/p/guava-libraries/wiki/FriendsOfGuava
Friends of Guava
- Caliper - we use it to benchmark our code
- Glazed Lists - observable collections
- GSON - read and write JSON
- Guice - a mature dependency injector
- Dagger - a high-performance dependency injector.
- Google Web Toolkit - we support it
- ICU4J - unless all your users live in the same place
- Joda-Time - do not use JDK date/time libraries!
- JUNG - graphs done right
- MOE - this is how we keep our internal and external codebases in sync
- ProGuard - shrinker/bundler/obfuscator/optimizer
- Mockito - Googlers' favorite mocking framework
Joda : Java용 Date 관련 라이브러리
1. 연산자 overriding 이 됩니다 ( 사칙연산이 되니 코드가 간단해 집니다 )
2. 열거, 필터링 관련 작업은 LINQ가 있어서 엄청 편합니다.
Java 에서는 두 가지 모두 안돼죠 ㅠ.ㅠ
어쩔 수 없이 기본 java.util.Date 와 subclass로 C#으로 된 소스를 포팅하려고 했는데, 기초적인 코드부터 다 만들어야 해서, 어떻하나 하다가 다음과 같은 라이브러리 도움으로 쉽게 해결 할 수 있었습니다.
1. Date 관련 연산은 Joda Time 라이브러리를 이용
2. LINQ 까지는 안되도, 열거, 필터링, 변환 작업을 수행하는데에는 Google Guava 의 Iterables, Lists 등 Helper class 를 활용했습니다.
C# DateTime 연산 예
public static DateTime EndTimeOfHalfyear(this DateTime dateTime, int yearStartMonth = TimeSpec.CalendarYearStartMonth) {
return
dateTime
.StartTimeOfHalfyear(yearStartMonth)
.AddMonths(TimeSpec.MonthsPerHalfyear)
.Add(TimeSpec.MinNegativeDuration);
}
Java 로 Porting 한 예 (Joda Time Library 사용)
public static DateTime endTimeOfHalfyear(DateTime moment, int startMonthOfYear) {
return
startTimeOfHalfyear(moment)
.plusMonths(TimeSpec.MonthsPerHalfyear)
.minus(TimeSpec.MinPositiveDuration);
}
JDK만으로는 할 수 없는 Date관련 API를 Joda 가 상당히 많이 제공하네요^^
포팅이 다 되고 나면, 리팩토링을 하면서 좀 더 효과적인 코드로 변환이 가능할 것 같습니다.
열거, 필터링 관련된 LINQ에는 비할바는 못되지만, Guava 에서 어느정도 지원해주고, 더 필요한 것은 되는 대로 만들어서 추가하니, 포팅 속도가 예상외로 빨라졌습니다.
올해 안에 Time, Period, Calendar, Working Day 등을 지원하는 라이브러리를 선보일 수 있을 것 같습니다.
앞으로는 가능하면 github 를 공개헤서 거기서 소스를 참고 할 수 있도록 하겠습니다.
2012년 11월 10일 토요일
요즘 공부하고 있는 Scala 라는 언어 소개 자료
java 야 기본 중에 기본이라, 말하면 잔소리고,
groovy는 동적 언어로서 간단한 프로토 타입이나 테스트 코드 작성에 유용하고, Solution에서 동적 script 가 사용될 때, groovy 를 표준으로 삼게 되면, 많은 잇점이 있습니다. 같은 JVM에서 돌고, 동적인 Script를 class 로 빌드해서 재 사용이 가능하여, 속도면에서도 상당한 장점을 가지게 됩니다. 또한 기존 java 라이브러리를 활용하게 되면, 더욱 강력한 기능을 제공할 수 있습니다.
groovy의 단점이라면, 동적언어로서 숙명적으로 실행 속도가 문제가 됩니다...
java 와 비교해서 같거나 더 뛰어난 성능을 가지면서, 여러가지 발전적인 기능을 가진 언어는 없을까 고민 중에 회사 동료들이 Scala에 대한 정보를 알려줘서 알게 되었습니다.
Scala는 OOP + 함수형 언어 특성 모두를 가지는 다방면의 기능을 가진 언어입니다.
만약 새로운 서비스를 만들게 된다면, Java 보다는 Scala 를 주요 언어로 선정하고 싶을 정도입니다.
다음은 제가 본 Scala 관련 소개 자료 중 유용한 자료라 생각됩니다.
한번 보시고, 괜찮다고 생각되신다면 공부해 보시길...
2012년 10월 21일 일요일
비동기 프로그래밍 by Netty and Scala
공부를 계속하다보니, Scala 가 눈에 들어오네요^^
같은 JVM에서 수행되고, Java, C# 보다 더 유연하고, 편하고, 빠르고...
물론 Ruby, Groovy, Python 같은 Dynamic 은 아니니 유연성은 좀 떨어지고, 컴파일 속도가 좀 느린 단점이 있긴 합니다.
요런 발표 자료를 보시면 이해가 좀 더 잘 될 듯...
혹시 Java 진영에서 개발하시는 분 중에 Scala를 모르시는 분들은 관심 가져 보시기 바랍니다.
2012년 2월 29일 수요일
[책] Thinking In Java 4th Edition
아마 Java 개발자라면 한 권정도는 가지고 있을 바이블에 해당하는 책이라 할 수 있겠죠. 저도 2nd Edition을 소장하고 있고, 이번에 4th Edition을 구매했습니다.
Bruce Eckel 이란 분의 탁월한 사상과 프로그램 언어에 대한 통찰이 돋보이는 책입니다.
개인적으로는 Java 라는 언어도 프로그래밍 언어이므로, 프로그래밍에 대한 기본이 없다면, 어떤 프로그래밍 언어든 어렵기는 매한가지이고, 도구로서 사용하기 어려울 것입니다.
다만, 이 책은 Java 라는 프로그래밍 언어를 통해, Software 프로그래밍에 대한 본질을 잘 설명했다고 평가하고 싶습니다.
이런 통찰력 및 기본적인 이론에 대해 이해하기 쉽고, 자세히 설명한 글은 찾아보기 힘듭니다.
아쉽게도 Thinking in C# 이라는 책도 기획되고, 진행 중이었는데, 중단된 것 같습니다. PDF 형태로 다운로드 할 수는 있습니다만, 중간 중간 집필이 안된 부분이 많군요…
C# 개발자라 하더라도, 차라리 Thinking In Java 번역서를 읽으시면, 더 이해가 잘 될 것입니다. Java 나 C#이나 환경적인 부분은 많이 다르지만, 프로그래밍 언어로서는 크게 다르지 않기 때문에, 기본기를 다지는 데에는 더 없이 좋은 책이라 볼 수 있습니다.
예전에 본 책이지만, 거의 5년여를 Java와는 인연이 없었으니, 다시 보니 새롭네요. 다시 한번 이론 정리도 되구요.
더군다나 Eclipse 도 더 빨라지고, 좋아져서, VS.NET 보다 더 속도감이 있는 건 SSD 때문일까요? 흠…