2017년 5월 24일 수요일

[python] 파이썬으로 twilio써보기

twilio는 SMS/MMS를 보내는 서비스이다. 모듈을 받아서 바로 그냥 쓰기만 하면 된다.(아니 물론 회원가입을 하고 인증키를 받은 후)
서비스는 아주 잘 되는 것으로 보이나 문제점은 한국에서 지원이 안된다. (아주 치명적이다.)
그래도 어떻게 쓰는지는 한 번 적어놔야겠다.
from __future__ import unicode_literals
from twilio.rest import Client

account_sid = "AC...내가 받은 아이디"
auth_token = "273 내가 받은 인증코드"

client = Client(account_sid, auth_token)

message = client.messages.create(
    body="Hello, I'm Younghwan Nam. I love you All. See you.",
    to="+8210000000",
    from_="+13399999999"  # 발급받은 twilio 번호
    )

print message.sid

2017년 5월 17일 수요일

[java][bitwise] 자바 비트연산에 대해서...

분명 학원에서 비트연산이라는 건 배워본 적이 없다. 연산이라하면 더하기, 빼기, 곱하기, 나누기, 그리고 모드(%) 뿐이었다.
비트연산을 쓴 적은 자바스크립트를 사용할 때 써본적은 있지만 서버에서 써본 적은 없다.(물론 알게 모르게 자바에서 네트워크 통신같은 것을 할 때 쓰고 있을 것이다.)
비트 연산은 나름 중요해 보인다.
알아두고 가끔씩 써봐야 나중에 남이 만든 코드를 보았을 때, 읽을 용기가 생긴다.
그렇지 않으면 "아 난 안되는가보다." 하고 다른 소스를 찾게 되는 자신을 바라보면서 언제까지 이러면 안되겠다는 생각을 했었다.
static void bitwiseTest4() {
  int seven = 7; // 0000 0111
  int nineteen = 19; // 0001 0011

  // & : and 연산
  // 0000 0111
  // 0001 0011
  // ---------
  // 0000 0011 ->  2 + 1 -> 3
  System.out.println(seven & nineteen);

  // | : or 연산
  // 0000 0111
  // 0001 0011
  // ---------
  // 0001 0111 -> 16 + ( 4 + 2 + 1 ) -> 23
  System.out.println(seven | nineteen);

  // ^ : xor 연산
  // 0000 0111
  // 0001 0011
  // ---------
  // 0001 0100 -> 16 + 4 -> 20
  System.out.println(seven ^ nineteen);

  // ~ : 보수(반전)
  // 0000 0111 -> 1111 1000 -> 1(부호) 111 0000 -> -128 + 64 + 32 + 16 + 8 ->
  System.out.println(-128 + 64 + 32 + 16 + 8);
  System.out.println(~seven);
}

output: 
3
23
20
-8
-8
이걸로 뭘 할 수 있을까? 그건 나중에 알아보기로 해야겠다. 일단 시프트 연산부터 정리를 해야겠다.
시프트 연산은 비트들을 왼쪽 오른쪽으로 움직이면서 노는 것이다. 처음에는 이게 뭐지 싶지만 익숙해지면 괜찮을 것이다. (아마 그럴 것이다. 나는 초보니까 익숙하지 않다.)
static void bitwiseTest5() {
  //시프트 연산
  int ten = 10; // 0000 1010
  int m_ten = -10; // 1
  System.out.println(Integer.toBinaryString(ten));
  System.out.println(Integer.toBinaryString(m_ten));
  // signed right shift : 오른쪽으로 한칸 이동 이전 맨 왼쪽의 숫자에 따라 새로 생성되는 숫자가 정해진다
  // ten : 0000 1010 -> 0000 0101 -> 5
  // m_ten : 1111 0110 -> 1111 1011 -> -1 - 4 = -5
  System.out.print((ten >> 1) + " " + (m_ten >> 1) + "\n");
  // unsigned right shift : 맨 왼쪽 숫자에 상관없이 0으로 통일한다
  // ten : 0000 1010 -> 0000 0101 -> 5
  // m_ten : 1111 1111 1111 1111 1111 1111 1111 0110 -> 0111 1111 1111 1111 1111 1111 1111 1011
  // -> 2147483647(Integer 최대값) - 4 -> 2147483643
  System.out.print((ten >>> 1) + " " + (m_ten >>> 1) + "\n");
  // left shift : 왼쪽으로 이동하는 것이다 right shift의 반대라고 생각하면 된다.
  // 여기서 주목해야 할 점은 right shift는 2배로 줄어들고 left shift는 2배로 커진다는 것이다.(이진수니까 당연한 것이겠지만)
  // 그래서 10번 움직인다면 2의 10승 1024가 곱해진다.
  System.out.print((ten << 10) + " " + (m_ten << 10) + "\n");
  System.out.println((ten << 1) + " " + (m_ten << 1) + "\n");
}

2017년 5월 9일 화요일

[java][design pattern]비지터패턴은 왜 쓰는 것일까? - 2

자 이제 비지터 패턴을 이용하면 무엇이 변하는지 공부하자.
  • Visitor가 Hair들을 방문할 수 있도록 VisitableHair 인터페이스를 만들자.
  • Hair들이 VisitableHair를 구현하도록 하자. (BoldHair, BushyHair, CurlyHair, HairyHair)
  • VisitableHair를 방문할 HairShopVisitor 인터페이스를 만들자.
  • 실제로 방문해서 일을 할 헤어디자이너들을 구현하자. (Barber, Hairdresser, Stylelist)
public interface VisitableHair {
  void accept(HairShopVisitor visitor);
  //아직 HairShopvisitor가 없어서 에러가 남
}
public class BoldHair implements VisitableHair {
  @Override
  public void accept(HairShopVisitor visitor) {
    System.out.println(this + " 아무렇게나 해주세요");
    visitor.visit(this);
  }
  @Override
  public String toString() {
    return "I have a bold Hair";
  }
} 

public class BushyHair implements VisitableHair {
  @Override
  public void accept(HairShopVisitor visitor) {
    System.out.println(this + " 아무렇게나 해주세요");
    visitor.visit(this);
  }
  @Override
  public String toString() {
    return "I have a bushy Hair";
  }
}

public class CurlyHair implements VisitableHair {
  @Override
  public void accept(HairShopVisitor visitor) {
    System.out.println(this + " 아무렇게나 해주세요");
    visitor.visit(this);
  }
  @Override
  public String toString() {
    return "I have a curly Hair";
  }
}
public class HairyHair implements VisitableHair {
  @Override
  public void accept(HairShopVisitor visitor) {
    System.out.println(this + " 아무렇게나 해주세요");
    visitor.visit(this);
  }
  @Override
  public String toString() {
    return "I have a Visitable Hair";
  }
}
이제 HairShopVisitor를 만들자.
public interface HairShopVisitor {
  void visit(BoldHair boldHair);
  void visit(BushyHair busyHair);
  void visit(CurlyHair curlyHair);
  void visit(HairyHair hairyHair);
}
HairShopVisitor를 구현해서 사용하려면 저 위에 있는 모든 객체를 구현 해놔사 사용할 수 있다.
일단 하나를 구현해보자.
public class HairShopBarberVisitor implements HairShopVisitor{
  @Override
  public void visit(BoldHair boldHair) {
    System.out.println("나는 이용사입니다. boldHair 군요. 면도해드릴게요\n");
  }
  @Override
  public void visit(BushyHair busyHair) {
    System.out.println("나는 이용사입니다. busyHair 군요. 밀어드릴게요\n");  
  }
  @Override
  public void visit(CurlyHair curlyHair) {
    System.out.println("나는 이용사입니다. curlyHair 군요. 밀어드릴게요\n");  
  }
  @Override
  public void visit(HairyHair hairyHair) {
    System.out.println("나는 이용사입니다. hairyHair 군요. 밀어드릴게요\n");  
  }
}
이렇게 하면 방문자로서 하나의 로직이 추가된 것이다. 2개를 마저 만들자.
public class HairShopHairdresserVisitor implements HairShopVisitor{
  @Override
  public void visit(BoldHair boldHair) {
    System.out.println("미용사입니다. boldHair 군요. 파마(?)해드릴게요\n");
  }
  @Override
  public void visit(BushyHair busyHair) {
    System.out.println("미용사입니다. busyHair 군요. 파마해드릴게요\n");
  }
  @Override
  public void visit(CurlyHair curlyHair) {
    System.out.println("미용사입니다. curlyHair 군요. 파마해드릴게요\n");
  }
  @Override
  public void visit(HairyHair hairyHair) {
    System.out.println("미용사입니다. hairyHair 군요. 파마해드릴게요\n");
  }
}

public class HairShopHairStylelistVisitor implements HairShopVisitor{
  @Override
  public void visit(BoldHair boldHair) {
    System.out.println("스타일리스트입니다. boldHair 군요. 스타일있게 해드릴게요\n");
  }
  @Override
  public void visit(BushyHair busyHair) {
    System.out.println("스타일리스트입니다. busyHair 군요. 스타일있게 해드릴게요\n");
  }
  @Override
  public void visit(CurlyHair curlyHair) {
    System.out.println("스타일리스트입니다. curlyHair 군요. 스타일있게 해드릴게요\n");
  }
  @Override
  public void visit(HairyHair hairyHair) {
    System.out.println("스타일리스트입니다. hairyHair 군요. 스타일있게 해드릴게요\n");
  }
}
이제 테스트를 해보자.
public static void main(String[] args) {
  VisitableHair[] variable_hair = { new BoldHair(), new BushyHair(), new CurlyHair(), new HairyHair()};
  HairShopVisitor[] artists = {new HairShopBarberVisitor(), new HairShopHairdresserVisitor(), new HairShopHairStylelistVisitor()};
  
  for(HairShopVisitor artist : artists) {
    for (VisitableHair hair : variable_hair )
      hair.accept(artist);
    }
  }
답은?
I have a bold Hair 아무렇게나 해주세요
나는 이용사입니다. boldHair 군요. 면도해드릴게요

I have a bushy Hair 아무렇게나 해주세요
나는 이용사입니다. busyHair 군요. 밀어드릴게요

I have a curly Hair 아무렇게나 해주세요
나는 이용사입니다. curlyHair 군요. 밀어드릴게요

I have a Visitable Hair 아무렇게나 해주세요
나는 이용사입니다. hairyHair 군요. 밀어드릴게요

I have a bold Hair 아무렇게나 해주세요
미용사입니다. boldHair 군요. 파마(?)해드릴게요

I have a bushy Hair 아무렇게나 해주세요
미용사입니다. busyHair 군요. 파마해드릴게요

I have a curly Hair 아무렇게나 해주세요
미용사입니다. curlyHair 군요. 파마해드릴게요

I have a Visitable Hair 아무렇게나 해주세요
미용사입니다. hairyHair 군요. 파마해드릴게요

I have a bold Hair 아무렇게나 해주세요
스타일리스트입니다. boldHair 군요. 스타일있게 해드릴게요

I have a bushy Hair 아무렇게나 해주세요
스타일리스트입니다. busyHair 군요. 스타일있게 해드릴게요

I have a curly Hair 아무렇게나 해주세요
스타일리스트입니다. curlyHair 군요. 스타일있게 해드릴게요

I have a Visitable Hair 아무렇게나 해주세요
스타일리스트입니다. hairyHair 군요. 스타일있게 해드릴게요
몇 번 더 만들어보면 손에 익지 않을까 싶다.

[java][design pattern]비지터패턴은 왜 쓰는 것일까? - 1

비지터 패턴을 쓰는 이유가 뭘까?
왜 방문을 해서 로직을 추가하는 걸까? 그냥 해당 클래스에 로직을 넣어서 쓰면 안될까?
해당 클래스를 바꾸지 못할 때 쓰는 것일까? 해당 클래스들의 자료구조는 변화하지 않을 것이고 로직은 계속 추가될 것이라면 비지터가 좋을 것 같기도 하다.
여기 머리를 자르기로 하자.
곱슬, 직모, 탈모, 대머리, 금발의 긴머리, 뽀글뽀글 등등 여러가지의 머리가 있다. 이들은 모두 미용실에가서 이렇게 말한다.
어울리게 잘라주세요
이제 미용사 성향 / 머릿카락에 따라 머리를 자를 것이다. 구현은
  1. Hair, HairShop 인터페이스 생성
  2. 각 인터페이스의 구현체 생성(BoldHair, BushyHair / Barber, Hairdresser)
  3. 그리고 테스트
// 1. 인터페이스 생성
public interface Hair { }
public interface HairShop {
  void cut(BoldHair boldHair);
  void cut(BushyHair busyHair);
  void cut(Hair hair);
}
이제 인터페이스를 구현하자.
// 2. 구현체 생성
public class BoldHair implements Hair{ }
public class BushyHair implements Hair{ }

public class Barber implements HairShop {
  @Override
  public void cut(BoldHair boldHair) {
    System.out.println("Barber : boldHair");
  }
  @Override
  public void cut(BushyHair busyHair) {
    System.out.println("Barber : BusyHair");
  }
  @Override
  public void cut(Hair hair) {
    System.out.println("Barber : Hair Interface... ");
  }
}

public class Hairdresser implements HairShop{

  @Override
  public void cut(BoldHair boldHair) {
    System.out.println("Hairdressor : BoldHair");
  }

  @Override
  public void cut(BushyHair busyHair) {
    System.out.println("Hairdressor : BushyHair");
  }

  @Override
  public void cut(Hair hair) {
    System.out.println("Hairdressor : Hair Interface... ");
  }
}
이제 테스트를 해보자.
public class Test {
  public static void main(String[] args) {
    Hair[] hairs = {new BoldHair(), new BushyHair()};
    HairShop[] artists = {new Barber(), new Hairdresser()};
 
    for (Hair hair : hairs)
      for (HairShop artist : artists)
        artist.cut(hair);
  }
}
콘솔을 확인
Barber : Hair Interface... 
Hairdressor : Hair Interface... 
Barber : Hair Interface... 
Hairdressor : Hair Interface...  
이렇게 된다. 결국 머릿카락의 정보는 가질 수 없다. 왜냐하면 자바는 싱글디스패치이기 때문인데 자세한 내용은 더블디스패치관련 글을 읽어보기를 바라면서...
여하튼 비지터패턴은 해당 클래스를 변경하지 않고 Visitor들을 추가해서 일을 할 수 있게 한다.
Visitor만 새로 만들면 hair들은 새로운 로직을 추가하지 않고 로직을 추가할 수 있게 된다.
출처:
https://dzone.com/articles/design-patterns-visitor https://sourcemaking.com/design_patterns/visitor/java/1 https://www.tutorialspoint.com/design_pattern/visitor_pattern.htm

2017년 5월 5일 금요일

[java] CSVWriter사용하기 (그리고 쌍따옴표 없애기)

CSV는 참으로 많은 곳에서 사용한다. 데이터를 저장할 때 사용하는 아주 기본적인 포맷이 아닌가 싶다.
CSV에서 오는 간결함은 그것을 만드는 사람마저 간결함을 추구하게 하는 힘이 있다.
콤마으로 나눠진 값들(CSV, Comma Separated Values)은 그 간결함 속에서 더욱 확장되어왔다.

자바에서는 CSV를 만들기 위한 Writer를 따로 만들어주고 있지 않지만, 사람들이 애용하는 라이브러리는 존재한다.
그중 하나 opencsv을 사용해보자.
/** CSVWriter 사용해보기**/
public class CSVTest {
  static List makeFileValues() {
    List list = new ArrayList();
    for(int i = 0; i < 10 ; i++) {
      list.add(new String[] { String.valueOf(i), String.valueOf(i+i), String.valueOf(i+i+i)});
    }
    return  list;
  }
}
실행해보자.
public static void main(String[] args) throws IOException {
  String Path = "C:/ynam/";
  String Name = "CSVTEST";
  
  try (CSVWriter writer = new CSVWriter(new FileWriter(Path+Name + ".csv"))){
    writer.writeAll(makeFileValues());
  }
}
실행해보자.
"0","0","0"
"1","2","3"
"2","4","6"
"3","6","9"
"4","8","12"
"5","10","15"
"6","12","18"
"7","14","21"
"8","16","24"
"9","18","27"
이렇게 나왔다.
이 현상은 사실 우리 회사에서 벌어지던 일이었다. 이 따옴표가 문제는 아니다. 하지만 이 내용을 그대로 다시 디비에 넣고 다시 빼낸다면?
"""0""","""0""","""0"""
"""1""","""2""","""3"""
"""2""","""4""","""6"""
"""3""","""6""","""9"""
"""4""","""8""","""12"""
"""5""","""10""","""15"""
"""6""","""12""","""18"""
"""7""","""14""","""21"""
"""8""","""16""","""24"""
"""9""","""18""","""27"""
처음부터 우리가 원하는 그 값 자체만을 담고 싶다면? 생성자에 추가하나만 하면 된다.
CSVWriter writer = new CSVWriter(new FileWriter(Path+Name + ".csv"))
여기를
CSVWriter writer = new CSVWriter(new FileWriter(Path+Name + ".csv"), ',', CSVWriter.NO_QUOTE_CHARACTER)
이렇게 바꾸고 다시 해보자.
  public static void main(String[] args) throws IOException {
    String Path = "C:/ynam/";
    String Name = "CSVTEST_without_qoute";
  
    try (CSVWriter writer = new CSVWriter(new FileWriter(Path+Name + ".csv"), ',', CSVWriter.NO_QUOTE_CHARACTER)){
      writer.writeAll(makeFileValues());
    }
}
자 실행해보면 어떻게 나올까
0,0,0
1,2,3
2,4,6
3,6,9
4,8,12
5,10,15
6,12,18
7,14,21
8,16,24
9,18,27
단순하다.