ActionScript 코드 최적화 항목

이번 핑거아이즈의 속도 개선을 위한 전반적인 코드 리팩토링 시에 고려했던 최적화 항목입니다. 위의 항목중 2/3정도만 반영되었고.. 나머지는 반영하지 못했습니다. 코드 최적화 작업 시간을 따로 마련해 놓지 말고.. 코드 작성 시에 미리 미리 고려해 적용해 놓아야한다는 당연한 진리를 새삼 깨닫게 되었습니다.

  1. 가능하다면 Sprite 대신에 Shape 사용하기
  2. cacheAsBitmap 적절히 사용하기
  3. 라벨에 대해 TextField 보다는 FTE(Flash Text Engine) 사용하기
  4. 가능하다면 mouseChildren, mouseEnable을 false 지정하기
  5. Array 대신 Vector. 사용하기
  6. 드로잉 API(drawPath, drawGraphicsData, drawTriangles) 사용하기
  7. object cache 전략 사용하기
  8. 폴리곤 내부 판정은 hitTestPoint보다 직접 구현해 사용하기
  9. 파생될 일이 없는 클래스는 final로 지정하기
  10. floor, ceil은 int 형변환으로 대체하기(floor(1.5) -> int(1.5), ceil(1.5) -> int(1.5)+1)
  11. abs보다는 직접 -1을 곱하는 방식으로 처리하기
  12. for 반복문 대신 for each 문 사용하기

여하튼… 위의 최적화 코드등을 통해 기존 속도 대비 10%정도 향상된듯합니다만… 체감하기는 어려운 향상인지라 다소 아쉬움이 많이 남습니다.

[GIS] SHP와 SHX 파일 해석(파싱)시 주의할 점

SHP의 레코드 헤더와 SHX의 레코드 헤더는 각각 Content Length와 Offset, Content Length라는 Integer 타입의 값이 있습니다. 물론 SHP와 SHX에 대한 Content Length는 동일합니다. 여기서 주의할 점은 이 값이 BYTE 개수가 아닌 WORD 개수라는 점입니다. 예를 들어서 Content Length가 100이라고 할때 레코드 내용의 길이가 100 BYTES가 아닌 2배 길이인 200 BYTES라는 것이지요.

사용자 삽입 이미지
ESRI에서 제공하고 있는 문서에.. 잘(?) 나와 있네요.  길이니 당연히 BYTE 개수겠지 하고 술렁 술렁 넘어갔더랬는데.. 이런 복병이.. 대학원 다닐때 SHP 파일 해석하는 것을 구현했던 적이 있었는데.. 그땐 문제없이 잘했더랬는데.. 초심자의 마음으로 문서를 정밀하게(?) 읽고 구현했던 시절이였으니 지금의 실수가 없었겠지 않나 싶습니다. 여튼.. SHP파일 파싱할때 요점 주의하시기 바랍니다.. 초심의 잃지 말아야한다.. 라는 각오를 새롭게 다져봅니다.

[GIS] JTS Geometry Class Diagram

JTS는 자바로 잘짜여진 지오메트리 공간연산 기능을 제공하는 오픈소스입니다. 세상에 나온지 수년이 지났고 워낙 잘짜여진터라 C언어로도 포팅되졌습니다. 위의 UML을 그려본 이유는 최근에 자바언어로 ESRI의 SHP 파일과 DBF 파일을 읽고 쓸 수 있는 라이브러리를 오픈소스 차원에서 개발할때 JTS에서 제공하는 Geometry 타입을 사용하기 위함입니다. 자바언어로 SHP와 DBF 파일을 읽는 오픈소스를 찾아보았으나 너무 다른 라이브러리에 깊이 관계를 맺고 있어 최적화시켜 사용하기가 제겐 부담이 되어 이번 기회에 새롭게 만들어 오픈소스 형태로 공유해볼 생각입니다.

[GIS] GeoTools를 이용해 SHP, DBF 파일 읽기

GeoTools(http://www.geotools.org)는 자바 기반의 GIS 시스템을 구축할 수 있는 다양한 기능을 갖춘 오픈소스입니다. 제가 처음 GeoTools에 관심을 가졌던 이유는 SHP 파일을 읽기 위한 자바 라이브러리가 필요해서 였는데요. 이 기능을 파악하기 위해 테스트로 작성했던 코드를 공유해 봅니다.

먼저 SHP 파일에서 좌표를 읽어 들이는 코드입니다.

import java.io.IOException;
import java.net.MalformedURLException;

import org.geotools.data.shapefile.shp.ShapefileException;
import org.geotools.data.shapefile.shp.ShapefileReader;
import org.geotools.data.shapefile.shp.ShapefileReader.Record;
import org.geotools.data.shapefile.ShpFiles;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;

public class ShapefileReaderTestMainEntry {
    public static void main(String[] args) {
        ShapefileReader r = null;
        try {
            ShpFiles shpFile = new ShpFiles("G:\\__Data__\\dong.shp");

            GeometryFactory geometryFactory = new GeometryFactory();
            r = new ShapefileReader(shpFile, true, false, geometryFactory);

            while (r.hasNext()) {
                Record record = r.nextRecord();
                Geometry shape = (Geometry)record.shape();
                Point centroid = shape.getCentroid();
                System.out.println(
                    "(" 
                    + centroid.getX() 
                    + ", " 
                    + centroid.getY() 
                    + ")"
                );
            }
            r.close();
        } catch (MalformedURLException e1) {
            e1.printStackTrace();   
        } catch (ShapefileException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        };
    }
}

다음으로는 DBF 파일에서 값을 읽어 들이는 코드입니다.

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;

import org.geotools.data.shapefile.ShpFiles;
import org.geotools.data.shapefile.dbf.DbaseFileHeader;
import org.geotools.data.shapefile.dbf.DbaseFileReader;

public class DbaseFileReaderTestMainEntry {
    public static void main(String[] args) {
        DbaseFileReader r = null;
        try {
            ShpFiles shpFile = new ShpFiles("G:\\__Data__\\dong.shp");
            r = new DbaseFileReader(shpFile, false, Charset.defaultCharset());
            DbaseFileHeader header = r.getHeader();

            int numFields = header.getNumFields();
            for(int iField=0; iField < numFields; ++iField) {
                String fieldName = header.getFieldName(iField);
                System.out.println(fieldName);
            }

            while (r.hasNext()) {
                Object[] values = r.readEntry();
                for(int iField=0; iField < numFields; ++iField) {
                    System.out.println(values[iField].toString());
                }
                System.out.println("---------------");
            }

            r.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }  
    }
}

에자일 프랙티스

Agile Practice (원문 cafe.naver.com/gisdev에서 김지윤님)

1. 비난은 버그를 수정하지 못한다.
손가락질 하는 대신, 가능한 해결책을 제시하라 중요한 것은 긍정적인 결과이다.

2. 땜질식 수정에 빠지지 말자
깔끔하고 모든 것이 드러나도록 코드에 정력을 쏟자.

3. 사람이 아니라 아이디어를 비평하라.
누구 아이디어가 더 나은지를 입증하는 것이 아니라 해결책에 도달하는 데에 자부심을 가져라

4. 올바른 일을 하라
정직하라. 그리고 진실을 얘기할 용기를 가져라. 때론 이렇게 한다는 것이 어려울 수도 있지만 그렇기 때문에 용기가 필요한 것이다.

5. 기술 변화를 따라가라.
모든 분야에서 전문가가 될 필요는 없지만, 업계가 어디로 가는지 알고 있어야 하고, 그에 맞춰서 계획을 세워야 한다.

6. 여러분 자신과 팀에 대한 기대치를 높여라
도시락 회의를 통하여 모든 사람의 지식과 숙련도를 올리고 사람들이 화합하게 하자. 즉, 팀이 흥미를 보이는 기술이나 프로젝트를 이롭게 할 기술을 도입하자.

7. 새로운 기술을 배우고 예전 기술을 버려라
새기술을 배울 때, 여러분을 방해 할 낡은 습관을 버려라. 결국 구형차보다 새차가 훨씬 낮다.

8. 계속 왜냐고 물어보라
여러분이 들은 얘기들을 액면 그대로 받아 들이지 마라. 쟁점이 되는 내용의 핵심을 이해할 때까지 계속 질문하라

9. 일이 쌓이기 전에 부딪쳐라
사건들 사이에 꾸준하고 반복적인 간격을 유지해야 일상적으로 되풀이 되는 일을 해결하기 쉽다.

10. 고객이 결정하도록 하라.
개발자, 관리자, 비즈니스 애널리스트가 비즈니스에 치명적인 결정을 내려서는 안된다. 사업주가 이해할수 있는 언어로 세부 내용을 설명하고 사업주가 결정할 수 있도록 한다.

11. 좋은 설계는 지도다.
설계는 바른 방향으로 인도한다. 그것은 허물 수 없는 경계가 아니다. 특정한 방식을 강요 해서는 안된다. 여러분은 설계(혹은 설계자)에게 인질로 잡혀서는 안된다.

12. 필요에 따라 기술을 택하라
먼저 무엇이 필요한지 정하라. 그리고나서 특별한 문제에 기술 사용 여부를 판단하라. 어떤 기술의 사용에 결정적인 질문을 하고 진실하게 답해 보라

13. 프로젝트를 항상 릴리즈 가능하게 하라
프로젝트를 항상 컴파일 할 수 있고, 실행할 수 있으며, 테스트 하고 당장에 배치 할 수 있게하자.

14. 일찍, 자주 통합하라.
코드 통합은 주요 위험요인이다. 이 위험을 완화 시키려면, 일찍 통합하고 규칙적으로 계속 통합해야 한다.

15. 시작부터 어플리케이션을 자동 배치하라
의존성 테스트를 위해 다양한 구성의 머신에 어플리케이션을 설치 할 때, 자동배치를 사용하라. 품질보증은 어플리케이션 뿐 아니라 배치를 테스트 해야 한다.

16. 분명히 보이게 하라.
어플리케이션이 개발도중 항상 눈에 띄게 하고, 고객이 마음에 들게 하라. 고객과 접촉하고 매주 또는 2주에 한번씩 데모를 사용하여 피드백을 미리 구하라

17. 점진적으로 개발하라
최초의 유용한 기능단위로 묶어서 제품을 릴리스 하라. 각 추가 기능의 개발에 1~4주 정도의 반복주기를 사용 하라

18. 실제일을 기초로 해서 견적하라.
실질적인 견적을 내기 위해 팀이 현재 프로젝트를 고객과 함께 수행하도록 하라. 고객이 기능과 예산을 조절하도록 하라.

19. 자동화 된 단위테스트를 사용하라
좋은 단위 테스트는 문제를 즉시 경고한다. 견고한 단위 테스트가 자리 잡지 않았다면 설계나 코드 변경을 하지 말자.

20. 만들기전에 사용하라.
테스트 주도 개발을 설계툴로써 사용하자. 테스트 주도 개발은 여러분을 더 실용적이고 더 간단한 설계로 인도할 것이다.

21. 차이는 결과를 만든다.
지속적 통합 툴을 사용해서, 지원하는 플랫폼과 환경의 조합마다 단위테스트를 실행하자. 문제가 여러분을 부르기 전에 능동적으로 문제를 찾자.

22. 핵심 비즈니스로직에 해당하는 테스트를 만들자.
고객이 이러한 테스트를 격리해서 검증하게 하고, 일부러 이러한 테스트를 자동적으로 시험하게 하자

23. 얼마나 많은 일이 남았는지 측정하라.
현실성이 떨어지는 측정 기준으로 자신이나 팀을 기만하지말자. 해야 할 작업의 백로그를 측정하자

24. 모든 불평은 진실을 담고 있다.
진실을 찾아, 진짜문제를 해결하라

25. 독창적이지 않고, 명확하게 코드를 작성하자.
코드를 읽는 사람에게 의도를 명확하게 표현하자. 읽기 쉽지 않은 코드는 독창적이지도 않다.

26. 이야기하는 주석
잘고르고, 의미 있는 이름을 사용해서 코드를 문서화 하라. 메서드의 목적과 제한조건을 설명하는 주석을 사용하라. 좋은코드를 대신하려고 주석을 사용하지말자.

27. 능동적으로 트레이드 오프를 평가하자
성능, 편의성, 생산성, 비용, 적시 릴리스를 고려하자. 성능이 적당하면, 다른요소를 향상 시키는 데 집중하자. 하찮거나 미미한 성능이나 우아함을 위해서 성능을 복잡하게 하지 말자.

28. 짧은 수정/빌드/테스트 주기 안에서 코드를 작성하자.
긴 주기동안 코딩을 하는 것보다 짧은 주기에서 코딩을 하는 편이 더 낫다. 유지보수 하는 데 더 명확하고 간단하면 쉬운코드를 만들 것이다.

29. 동작하는 가장 단순한 해결책을 만들자
패턴, 원칙, 기술을 사용해야 하는 부득이 한 사정이 있을 때만 패턴, 원칙, 기술을 포함하자

30. 클래스에 집중하고 컴포넌트를 작게 유지해라.
커다란 클래스나 컴포넌트 혹은 다방면에서 잡다한 클래스를 만들고픈 유혹을 피하라.

31. 묻지말고, 말해라
다른 객체나 컴포넌트의 일을 떠맡지 마라. 객체나 컴포넌트에 무엇을 하는지 알리고 , 자신의 일에 충실해라

32. 코드를 교체해서 시스템을 확장하자
인터페이스 계약을 존중하는 클래스를 교체해서 기능을 추가 하거나 강화하자. 위임은 언제나 상속보다 바람직하다.

33. 문제와 해결책의 로그를 보존하자.
문제를 해결하는 일의 일부는 나중에 해결책을 찾고 적용할 수 있도록 해결책의 상세내용을 보존하는 것이다.

34. 경고를 에러처럼 다루자
경고가 있는 코드를 체크인 하는 것은 에러가 있는코드나 테스트에 실패한코드를 체크인한 만큼 나쁘다. 체크인한 코드는 빌드툴에서 어떤에러도 만들어서는 안된다.

35. 문제를 격리해서 공격하라
문제를 해결할 때 문제를 주위와 분리시켜라. 특히 큰 애플리케이션의 경우에 말이다.

36. 모든 예외를 처리하거나 전달하라
예외를 덮어두지말자. 임시라도 말이다. 코드가 실패할 수 있다고 생각하며 작성하자

37. 유용한 에러 메시지를 제공하자
에러의 상세 내용을 알아내기 쉬운 방법을 제공하자. 문제가 생겼을 때 문제에 대해서 할 수 있는 많은자원과 관련된 상세정보를 제공하라, 그렇지만 이 정보와 함께 사용자를 파묻지 말자

38. 스탠드 업 미팅을 사용하자.
스탠드 업미팅은 팀을 같은 곳에 둔다. 회의를 일상적이면서 짧고, 집중적으로 유지하자

39. 좋은 디자인은 활동적인 프로그래머로부터 진화 한다.
진짜 통찰력은 활동적인 코딩작업에서 나온다. 코드를 작성하지않은 아키텍트를 기용하지말자. 시스템의 현실을 알지 못하는 아키텍트는 설계를 할 수 없다.

40. 코드 공동소유를 강조하자
개발자들을 순환시켜 전체 시스템의 다른 영역에 있는 서로 다른 모듈이나 테스크를 교차해서 개발 시키자.

41. 멘토가 되자
아는 것을 공유하는데 즐거움이 있다. 얻은 만큼 베풀어라 더 나은 목표를 달성하기 위해서 다른 사람을 자극하자. 팀의 전체적인 역량을 향상시키자.

42. 다른 사람에게 문제를 해결할 기회를 주자.
다른 사람에게 해결책을 주는 대신에 올바른 방향을 알려주자. 그 과정에서 모두 먼가를 배울 수 있다.

43. 준비되었을 때만 코드를 공유하라
다른 사람이 쓸 수 있도록 준비 되지 않은 코드는 절대 체크인 하지 마라. 컴파일이 안되거나 단위테스트를 통과하지 못한 코드를 체크인 하는 것은 프로젝트의 범죄적인 태만 행위로 간주해야 한다.

44. 모든 코드를 리뷰하자
코드리뷰는 코드 품질을 개선하고 에러를 낮추는데 매우 가치 있는 것이다. 코드리뷰를 올바르게 했다면, 리뷰는 실용적이고 효과적 일 수 있다. 다른 개발자로 하여금 작업이 끝날때마다 코드 리뷰를 하게 하자

45. 다른 사람에게 계속해서 알리자
여러분이 조사한 좋은자료나 자신의 상황. 아이디어를 발표하자. 다른 사람이 일의 상황을 물을 때까지 기다리지 말자