2014년 10월 30일 목요일

안드로이드에서 유니티 콘솔 로그 디버깅

안드로이드SDK를 설치하고, 설치폴더의 "\sdk\platform-tools"를 PATH에 추가한다.

콘솔 명령창에서 다음과 같이 입력한다.

  1. 에뮬레이터의 Unity관련 로그만 확인할 경우
    1. > adb -e logcat -s Unity
  2. 연결된 디바이스로 Unity관련 로그만 확인 
    1. > adb logcat -s Unity
  3. 연결된 디바이스 목록 확인
    1. > adb devices

2014년 10월 28일 화요일

Facebook 테스트 환경 구축하기

이 글은 테스트 계정을 만들고, 요청을 확인하는 방법을 설명한다.

테스트 계정 생성
Test Users를 참고하여 앱의 테스트 계정을 만든다. 테스트 계정을 만든 다음 Modify를 클릭해서, 사용자 이름을 변경하자. 그러면 이메일도 같이 변경되서 나중에 에뮬레이터에서 테스트할 때, 좀 더 편하게 할 수 있다. 또한, 여기서 테스트 계정끼리 친구 관계도 맺어줄 수 있다.


받은 요청 확인하기
웹 브라우저에서 테스트 계정으로 로그인 한다음, Facebook 앱 센터로 이동하면, 요청을 확인 할 수 있다. 테스트 계정으로는 Graph API Explorer에 접속할 수 없으므로 이렇게 확인하는게 편하다.


주의사항
테스트 계정은 하나 이상의 앱에 소속되어 있어야 한다. 그래서, 초대를 테스트하기 위해서는 실제 유저 계정이 필요하다.

Parse.com에 파일 올리기

파스 서버에 .unity3d나 이미지 파일들을 올려서 호스팅하는 방법을 설명한다.

파스에서 직접적인 파일 업로드를 지원하지 않는다. 대신 Cloud Code를 사용하면 임의의 파일을 서버에 올릴 수 있다. Cloud Code - Getting Started를 참고하여, 프로젝트를 설정한다.

이 튜토리얼을 따라가는 것은 어렵지 않다. 전부 다 볼 필요는 없고 "A Simple Function"에서 "$ parse deploy"까지만 보면 된다. 즉, 프로젝트를 설정하고 해당 폴더 아래서 앞의 명령어를 실행하면 알아서 파일을 서버에 올려준다.

문제는 초기에 생성된 config, cloud, public 중에 어느 폴더에 파일을 올리면 어떻게 웹으로 접근할 수 있는지이다. 파스에서 자신의 앱을 만들었고 로그인을 하고 해당 앱의 설정으로 가서, "Web hosting"탭을 클릭하면, "ParseApp Name"에 호스트 이름을 입력할 수 있다. (여기서는 yourapp이라고 하자.) 그러면 아까 public폴더 아래 your mage.jpg라는 파일이 있다면, URL은 http://yourapp.parseapp.com/yourimage.jpg가 된다.

2014년 10월 27일 월요일

WCF + MongoDB + Redis + Supersocket + PushSharp 사용 후기

출처 : http://cafe.naver.com/ongameserver/9346

정리하면
  • WCF
    • 성능 잘나옴. 
    • NuGet 잘 사용하면 생산성에 도움.
  • MongoDB
    • 안정적으로 성능 잘 나옴
    • 개발 편의성이 좋음
  • Redis
    • 엄청 빠름
  • SuperSocket
    • 코드도 깔끔하고 기능도 잘 갖춰졌음
  • PushSharp
    • 기능에 부족함 없고 잘 돌아감
    • 사용 엄청 간단함

결론은 다 잘 됨

2014년 10월 23일 목요일

Redis Desktop Manager

출처: http://redisdesktop.com/

레디스 데이터를 보기 쉽게 해주는 GUI 툴

2014년 10월 22일 수요일

Assets 폴더 패킹 유의사항

증상

에디터에서는 잘되는데 배포버전에서는 에셋을 참조하지 못한다

원인

배포 버전을 만들 때, Assets 폴더 아래있는 에셋들을 패킹한다. 이 때, 동적으로 참조한 에셋의 경우 패킹에서 빠지게 된다.

해결방법

동적 참조를 정적 참조로 바꾼다
Assets폴더 아래에 Resources폴더를 만들어서 해당 에셋을 추가한다

참고

동적 참조란, Resource.Load(), Shader.Find() 등의 함수를 사용하여 에셋에 접근하는 것이고 정적 참조란, 컴포넌트의 맴버 변수를 에디터에서 참조를 설정하는 것이다.

Assets폴더 아래에서 Resources라는 이름의 폴더를 모두 패킹한다.
Assets\
  Resources\
  Folder2\
    Resources\
  Folder2\
    Subfolder3\
      Resources\

Resources폴더는 무조건 패킹을 하기 때문에, 관리를 잘 못하면, 패키지 크기가 커진다

varchar(max) vs varchar(1-8000)


컬럼을 인덱스로 사용하거나 데이터가 8000이하라면, varchar(max)와 varchar(1~8000)의 기술적인 차이는 없는 것으로 보인다. 하지만, 모든 것이 MAX로 되어 있으면, 가독성이 떨어질 우려가 있다는 의견도 동의한다.

warning LNK4099 제거 방법

출처: warning LNK4099: 'vc90.pdb' PDB를 ... lib 또는 pdb에서 찾을 수 없습니다. 디버그 정보가 없는 것처럼 개체를 링크합니다.


PlayerPrefs에 한글(string) 넣고/불러오기

출처: http://quest3dkorea.com/viewer/11051083

기본 GUI에서 작업할때는 PlayerPrefs에 잘만 넣었다 빼고 했는데 NGUI라벨 조금 거치고하니 한글이 아예 표시가 안되서 찾아본 내용.
GUI에서는 잘됐던것이 미스테리...

base64로 인코딩
string convertTxt = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("contents"));

PlayerPrefs에 넣고,
PlayerPrefs.SetString("keyName" , convertTxt);

불러올때는 base64로 디코딩
string resultTxt = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(PlayerPrefs.GetString("keyName")));

확인
Debug.Log("contents : " + resultTxt);

Unity Life Cycle

출처: http://cafe.naver.com/unityhub/13377

유니티 내부에서 함수들이 어떤 순서로 실행되는지 잘 정리된 내용.

2014년 10월 21일 화요일

Parse 오브젝트 ACL 설정하기


현재 사용자만 접근할 수 있게
ParseObject privateNote = new ParseObject("Note");
privateNote.put("content""This note is private!");
privateNote.setACL(new ParseACL(ParseUser.getCurrentUser()));
privateNote.saveInBackground();

특정 사용자만 볼 수 있게
ParseObject groupMessage = new ParseObject("Message");
ParseACL groupACL = new ParseACL();
     
// userList is an Iterable<ParseUser> with the users we are sending this message to.
for (ParseUser user : userList) {
  groupACL.setReadAccess(user, true);
  groupACL.setWriteAccess(user, true); 
}

groupMessage.setACL(groupACL);
groupMessage.saveInBackground();

모두 볼 수 있지만, 나만 수정할 수 있게
ParseObject publicPost = new ParseObject("Post");
ParseACL postACL = new ParseACL(ParseUser.getCurrentUser());
postACL.setPublicReadAccess(true);
publicPost.setACL(postACL);
publicPost.saveInBackground();

Redmine 포트 변경하기

%redmine_root%\apache2\conf\httpd.conf
...
Listen 80
...

%redmine_root%\apache2\conf\redmine\bitnami.conf
...
NameVirtualHost *:80
...
<VirtualHost _default_:80>

80을 원하는 포트로 변경하면 된다.

레드마인과 퍼포스 연동하기

레드마인에 기본적으로 퍼포스 연동 방법이 존재 하지 않는다. 따라서 구글형님에게 물어보고 삽질을 했다.

O/S: Window7 64Bit
환경: Bitmani redmine stack 2.5.1 

방법

퍼포스 연동 코드 패치 

  1. Redmine with Perforce 를 참고하여 패치를 한다. 단) 루트 경로는 c:\bitnami\redmine-2.5.1-1\apps\redmine\htdocs 이다
  2. 저장소에서 한글 저자나 Description이 깨질 때는 app/models/repository/perforce.rb:42를 'UTF-8'에서 'EUC-KR'로 바꾼다
  3. lib/redmine/scm/adapters/perforce_adapter.rb:72 를 #cmd << shell_quote(depot) 처럼 주석처리한다
    1. 커멘드로 처리해본 결과 //depot/이 있으면 원하는 결과가 나오지 않는다

레드마인 설정

  1. 관리 -> 설정 -> 저장소에서 지원할 SCM에서 "Perforce"를 체크한다
  2. 관리 -> 설정 -> 일반 -> 첨부파일이나 저장소 인코딩에 "UTF-8,EUC-KR"을 입력한다
  3. 프로젝트 -> 설정 -> 저장소 -> 저장소 추가를 클릭한다
    1. 형상관리시스템 : "Perforce"
    2. 주 저장소 : 체크
    3. 식별자 : 적당한 이름 (추후에 저장소 페이지에서 루트로 출력됨 )
    4. P4PORT : perforceserver:1666
    5. Root directory : //depot/
    6. 로그인 : 계정
    7. 패스워드 : 암호
저장소를 클릭하면, 기존 변경 내역을 읽어와서 디비에 저장한다. 이 과정이 완료되어야 저장소의 변경 내역도 보이고 일감에서 변경내역 링크도 동작한다. 

참고자료 

  1. Redmine with Perforce
  2. additional scm support
  3. Need a way to re-sync repository history

ProSysLib - 프로세스 정보 가져오기

라이센스: CPOL(상용 사용 가능)

현재 프로세스에 대한 정보를 쉽게 얻을 수 있는 라이브러리.

http://www.codeproject.com/KB/threads/ProSysLib3.aspx

VS에서 Simian으로 코드 중복 체크하기

준비물

  1. Visual Studio
  2. Simian
  3. Java Runtime Environment: Simian 2.2.24버전 exe파일이 잘 작동하지 않아서 jar버전을 사용하기 위해서 필요함
Simian 설치

Simian 홈페이지에서 최신 버전을 받아서 자신이 원하는 폴더에 설치하면 된다.

Java Runtime Eveironment 설치

홈페이지에 가면 링크가 있다.

Visual Studio 외부 도구 설정

VS에 Tools에서 External Tools를 설정하고 다음 옵션으로 메뉴를 추가한다.

전체 솔루션 검사 (솔루션 디렉토리가 별도로 나눠져 있는 경우에는
Title: Simian - Solution
Command: C:\Program Files\java\jre6\bin\java.exe
Arguments: -jar d:\simian-2.2.24\bin\simian-2.2.24.jar -formatter=vs -language=cpp *.h *.cpp **/*.h **/*.cpp
Initial directory: $(SolutionDir)
Check "Use Output window"

현재 프로젝트 검사
Title: Simian - Current Project
Command: C:\Program Files\java\jre6\bin\java.exe
Arguments: -jar d:\simian-2.2.24\bin\simian-2.2.24.jar -formatter=vs -language=cpp *.h *.cpp **/*.h **/*.cpp
Initial directory: $(ProjectDir)
Check "Use Output window"

현재 파일 검사
Title: Simian - Current File
Command: C:\Program Files\java\jre6\bin\java.exe
Arguments: -jar d:\simian-2.2.24\bin\simian-2.2.24.jar -formatter=vs -language=cpp $(ItemFileName)$(ItemExt)
Initial directory: $(ItemDir)
Check "Use Output window"

메뉴를 클릭하여 실행하면 중복코드 결과가 Output 윈도우에 나오고, 보고싶은 라인을 더블클릭하면, 해당 파일의 위치로 이동할 수 있다.

참고자료

Simian webpage
Detecting duplicate code with Simian on Howard van Rooijen's Blog
Java webpage

CppUnitLite 단위테스트 환경설정

폴더 구조

  • sources
    • client
      • client.vcxproj
    • common
      • common.vcxproj
    • server
      • server.vcxproj
    • clientexe
      • clientexe.vcxproj
    • serverexe
      • serverexe.vcxproj
    • test
      • test.vcxproj
    • all.sln
테스트하고자 하는 로직들은 모두 라이브러리로 작성되어져야 한다. 즉, client.vcxproj, common.vcxproj, server.vcxproj등은 모두 라이브러리 프로젝트이며, clientexe.vcxproj와 serverexe.vcxproj, test.vcxproj는 어플리케이션 프로젝트들이다. 그리고, 어플리케이션 프로젝트에서는 라이브러리에 있는 클래스를 생성하고, 실행하는 간단한 코드만 들어있도록 만든다.

test에는 테스트 관련 파일이 있다.

Free UML Tool

라이세스: 비영리 공짜

http://www.visual-paradigm.com/solution/freeumltool/

명령어/쿼리 분리

명령어/쿼리 분리는 버트란드 메이어Bertrand Meyer에 의해 처음 기술된 설계 원칙으로, 간단히 말하면 다음과 같다. 하나의 메소드는 하나의 명령어이거나 쿼리여야 한다는 것이고, 두 가지 기능을 모두 가져서는 안 된다는 원리이다. 명령어는 객체의 상태를 수정할 수 있는 메소드이지만 값은 반환하지 않는다. 쿼리는 값을 반환하지만 객체를 변화시키지는 않는다.

이러한 원칙은 왜 중요할까? 여러가지 이유가 있겠지만 가장 중요한 것은 통신 때문이다. 임의의 메소드가 쿼리라면 부작용을 일으키지 않으면서 여러 번 그 메소드를 사용할 수 있을지 없을지를 확인하기 위해 그 메소드의 바디를 살펴볼 수밖에 없다.

출처: 레거시 코드 활용 전략 - 마이클 C. 페더스

책임 찾기

단일 책임 원칙

모든 클래스는 단일 책임을 가진다. 즉, 모든 클래스는 시스템에서 단일 목적을 가지고 그 클래스를 변경하는 이유는 단 하나만 있어야 한다

인터페이스 분리 원칙

큰 클래스에서는 모든 클라이언트들이 해당 클래스에 있는 모든 메소드들을 사용하게 되는 경우가 드물다. 우리는 특정 클라이언트가 주로 사용하는 메소드들을 다른 방식으로 그룹화 하는 경우를 종종 볼 수 있다. 이러한 그룹화된 것들에 대한 각각의 인터페이스를 생성하고 그러한 인터페이스들을 구현하는 하나의 큰 클래스를 가지면, 모든 클라이언트는 특정 인터페이스를 통해 큰 클래스를 볼 수 있게 된다. 이렇게 함으로써 정보를 감출 수 있고 시스템 내의 의존관계를 줄일수 있다. 이제 클라이언트들은 그 큰 클래스가 재컴파일 할 때마다 자신들도 재 컴파일해야 했던 번거로움에서 벗어날 수 있다.

책임 찾기

  1. 메소드들을 그룹화 하라
    비슷한 메소드 명들을 찾아보자. 접근 방식(퍼블릭, 프라이빗 등)과 함께 클래스 상의 모든 메소드들을 적어 보고, 묶을 만한 메소드들이 있는지 찾아보자
  2. 숨겨진 메소드들을 살펴보라
    프라이빗 메소드들과 프로텍티드 메소드들에 주의하라. 하나의 클래스가 이런 프라이빗이나 프로텍티드 메소드들을 많이 가지고 잇다면, 해당 클래스 내에 간절히 밖으로 나오고 싶어하는 또 다른 클래스가 있다고 보면 된다
  3. 변경할 수 있는 결정사항들을 찾아라
    결정사항들을 찾아야 한다. 코드 내에서 내리고 있는 결정사항들이 아니라 당신이 이미 해놓은 결정사항들을 의미한다. 데이터베이스와의 대화, 다른 객체들과의 대화 등 하드 코딩된 것처럼 보이는 작업을 수행하는 다른 방법이 있을까? 아울러 코드가 변경된다는 생각을 할 수 있을까?
  4. 내부 관계들을 찾아내라
    인스턴스 변수들과 메소드들 사이의 여러 관계를 찾아라. 어떤 메소드는 특정 인스턴스 변수를 사용하는 반면에, 다른 메소드는 그 인스턴스 변수를 사용하지 않는 것은 아닌가?
  5. 주된 책임을 찾아라
    클래스의 책임을 한 문장으로 기술하도록 하라
  6. 다른 모든 방법이 실패할 경우, 스크래치 리팩토링을 어느 정도 사용하라
    한 클래스 내에 있는 책임들을 찾아내기가 쉽지 않다면 스크래치 리팩토링을 어느 정도 사용해 보는 것도 좋은 방안이다
  7. 현재 작업에 집중하라
    지금 당장 처리해야 하는 작업에 주의를 기울여라. 어떤 작업을 수행하는 다른 방식을 제공하고 있다면 추출해야 할 책임 하나를 먼저 식별한 후에 그것에 필요한 대체를 허용하는 순으로 작업하라
출처: 레거시 코드 활용 전략 - 마이클 C. 페더스

헤더 파일에 헤더 파일 추가하지 않는 법

  1. 프리컴파일 해더에는 표준, 써드파티 또는 거의 변경되지 않는 라이브러리의 해더만 포함하자
  2. #include보다는 forward declaration을 사용하자
    1. class
    2. struct
    3. function
    4. enum 
    5. typedef
  3. value 맴버보다 reference 맴버를 사용하라
  4. inner 클래스나 enum을 만들지 마라
  5. 구현부를 숨겨라
  6. 인터페이스로 만들어라
참고자료
  1. Effective C++, 항목 31

기획이 불확실한 경우에 프로그래밍 절차

프로젝트의 기획이 명확하지 않은 경우 - 게임의 경우, 항상 그런것 같다 - 나에게는 잘 맞는 개발 절차다.

기본 철학

  1. 실용주의 - 할 일만 최소한으로 한다
  2. 빠른 피드백 루프 - 만들고, 보여주고, 수정한다 
  3. 좋은 코드 - 읽기 쉽고 요구사항을 충족한다

절차

  1. 핵심기능을  단순하고 빠르게 구현한다
  2. 피드백을 받아서 코드를 수정한다
  3. 다음 작업을 시작하기 전에 리팩토링을 한다
  4. 1번으로 돌아간다

설명

핵심기능을  단순하고 빠르게 구현한다

요구사항에 있는 선에서 최대한 빠르게 실행해볼 수 있는 구조로 코드를 작성한다. 이 때는 좋은 코드에 대해서 고민하지 않는다. 그저 적은 코드로 빠르게 테스트 하는 것에 집중한다.
좋은 코드란, 읽기 쉽고 요구사항을 최대한 충족하는 것이다. 요구 사항의 핵심 기능만 분명할 뿐, 나머지는 변경의 여지가 있다. 그래서 핵심 기능만 단순하게 구현하여 변경 사항을 확인하고 코드에 대비한다.

피드백을 받아서 코드를 수정한다

빠른 피드백 루프의 핵심을 빠른 수정이다. 빠른 수정을 위해서 가장 좋은 대비 방법은 단순한 개념과 코드다. 개념과 코드를 단순하게 유지하면, 수정하기 쉽다. 개념이 단순하면 사고도 유연해 진다.

다음 작업을 시작하기 전에 리펙토링을 한다

리펙토링을 아무런 기준없이 하는 것은 끝이 없는 일을 하는 것과 같다. 리펙토링은 좋은 코드를 만들기 위해서 한다. 좋은 코드란 읽기 쉽고 요구사항을 최대한 충족하는 것이다. 따라서, 다음 추가할 작업은 리펙토링의 좋은 기준이 된다.

1번으로 돌아간다

3번과 4번은 동시에 진행된다. 다음 요구사항을 빠르고 구현하기 위해서 리펙토링을 중간중간에 하는 것이다.

결론

리펙토링은 다음 수정사항을 목표로 코드 작성 중간중간에 해야된다. 따라서, 프로그래머에게 충분한 작업 시간을 주는 것이 무엇보다도 중요하다

10가지 Visual Studio 디버거 팁

출처: 10 More Visual Studio Debugging Tips for Native Development

  1. 예외 시에 멈추기
  2. 조사식 창에서 가상 변수(Pseudo-variables)
  3. 영역을 빠져나간 후에 힙 객체 보기
  4. 배열을 영역으로 보기
  5. 원하지 않는 함수로 한단계 들어가서 실행 안하기
  6. 코드에서 디버거 실행하기
  7. 출력 창에 프린트
  8. 메모리 누수 고립 시키기
  9. 릴리즈 빌드에서 디버깅하기
  10. 원격 디버깅하기


추상 데이터 형(ADT)

출처: Code Complete2 6.1절 요약

효율적인 프로그래머가 되기 위한 핵심 요소는 다른 코드를 작업하는 동안 무시해도 좋은 프로그램의 부분을 최대화하는 것이다
  1. ADT는 데이터와 연산의 집합이다. 그러나 "데이터"는 느슨하게 사용된다
  2. ADT를 먼저 생각하고 클래스를 두 번째로 생각하는 것은 언어로의 프로그래밍과 언어에서의 프로그래밍의 한 예이다
  3. 저수준 구현 도메인보다 문제 도메인에서 작업할 수 있는 힘을 사용하도록 하라!

ADT 예

  1. 선박제어
    1. 속력을 설정한다
    2. 현재 설정을 얻는다
    3. 이전 속력으로 달린다
    4. 사용을 중지한다
  2. 전구
    1. 켠다
    2. 끈다

ADT 혜택

  1. 세부적인 구현 사항을 감출 수 있다
  2. 변경이 전체 프로그램에 영향을 미치지 않는다
  3. 인터페이스가 보다 많은 정보를 제공하도록 만들 수 있다
  4. 성능을 향상시키기가 쉽다
  5. 외관상으로 프로그램이 정확하다는 것을 더 잘 알 수 있다
  6. 프로그램이 보다 더 스스로를 설명하게 된다
  7. 프로그램에 모든 데이터를 넘길 필요가 없다
  8. 저수준 구현 구조체 대신 실세계의 개체들을 다룰 수 있다

ADT 사용지침

  1. 전형적인 저수준 데이터 형을 ADT로  만들어라
  2. 파일과 같은 일반적인 객체들을 ADT로 취급하라
  3. 간단한 항목이라도 ADT로 취급하라

ADT와 클래스

  • 클래스에 대해서 생각하는 한 가지 방법은 ADT에 상속과 다형성을 더한 것으로 생각하는 것이다

AStyle과 Google Cpplint로 C++ 코드 스타일 자동화하기

코드 스타일을 잘 지키는 것도 중요하지만, 스타일을 지키는 비용도 중요하다. 구글 스타일 가이드를 지향하되 20/80 법칙에 따라 비용을 최소화하기 위해 절충했다.

준비물

  1. AStyle Extension
  2. Cpplint
  3. Python2.7 이상

AStyle Extension

AStyle Extension을 설치한다. Visual Studio 설정에서 AStyle Formatter를 선택하고 C/C++에서 구글 스타일 가이드에 맞는 설정을 한다.

--style=google --indent=spaces=2 --max-code-length=80 --pad-header --unpad-paren --keep-one-line-blocks --mode=c
그리고, "Format on save"옵션을 체크하면된다.

이제 문서를 수정하다가 저장하면 자동으로 포맷을 수정해준다.

Python2.7

그냥 설치하면된다.

Cpplint

Cpplint.py는 그냥 파이썬 스크립트이다. 따라서 대강 어딘가에 저장한다. - 솔수션 파일과 같은 위치 -. Visual Studio에서 자동으로 사용하기 위해서는 외부도구로 연결 시켜줘야 한다.

제목: cpplint
명령: c:\python27\python.exe
인수: cpplint.py --output=vs7 --verbose=0 --verbose=1 --verbose=2 --verbose=3 --verbose=4 --extensions=h,cpp $(ItemPath)
초기 디렉토리: $(SolutionDir)
출력 창 사용 : 체크
그리고 솔루션 폴더에 CPPLINT.cfg라는 파일을 만들고 다음 내용을 입력한다

set noparent
exclude_files=resource.h
exclude_files=targetver.h
filter=-legal/copyright.h
filter=-build/c++11
filter=-build/include_what_you_use
filter=-readability/multiline_comment
filter=-build/header_guard
filter=-whitespace/comments

각자 편한데로 설정해서 쓰면된다.