[펌] 분개할 수 밖에 없는 미국산 소고기 수입..

미국산 소고기가 실제로 위험하지도 않고, 광우병은 단지 지나친 우려일뿐일지라도.. 그 무엇하나 분명하지 않은 이 시점에서… 분명하지 않다는 것은 위험하지 않다도 아니고 위험하다도 아닌 것을 말하는 것입니다. 이런 시점에서 소고기 개방은 너무나도 위험한 것입니다. “일단 저질러 놓고 보자. 누군가 죽어 나자빠지면 분명해지지 않겠는가?” 라는 저질 발상 정책이라는 점은 자명한 사실입니다.

아래는 그 내용의 진위 여부를 떠나 대한민국국민이라면 한번쯤 읽어보고, 스스로 생각해봐야할 글이기에 퍼온 글입니다.

[펌 글의 시작]

광우병 글만 뜨면 무슨 도배글이라고 귀찮아하고 넘기고 무슨 공산당이 책동글이라도 쓴듯이 짜증나 하는 분들. 제발 정신 좀 차리고 한국 국민들이 어떤 위험에 처해 있는지 한번이라도 제대로 읽어보세요.

해외교포가 뭣땜에 이런 짓을 하냐구요? 제발 좀 나라가 어찌 돌아가는지 관심 좀 가져주세요.
제발 광우병의 심각성을 아직도 모르시는 분은 좀 찾아서라도 읽어주세요.

한우만 먹는다고 채식만 한다고 끝이 아니예요. 그 소에서 나온 피가 식수를 오염시키고 각종 소 부산품 (젤라틴과 같은)이 생리대, 기저귀를 비롯한 엄청난 수의 생필품에 사용되며, 야채의 비료로 사용되어 다시 우리 밥상에 올라옵니다. 아이들의 학교 급식에, 곳곳에 자리잡은 패스트푸드에, 우유, 치즈, 버터, 라면 스프, 쵸코파이에 들어가는 마쉬멜로우, 끝이 없습니다.

타액으로도 감염되므로 연인과의 키스로도 감염될 수 있습니다. 좁쌀만한 소고기로도 광우병에 감염되고 100% 사망이며, 예방책도 치료약도 없습니다.

잘 익혀먹으면 될까요? 광우병 인자는 600도의 열로 가열해도 파괴되지 않으며, 소의 피가 섞인 물은 정화조를 거쳐도 프리온이 그대로 남아있습니다.

미국산 소고기 매일 먹는 미국사람들도 멀쩡한데 우리도 뭐 별 거 있겠어? 하시는 분들. 정신 차리세요. 그렇게 호락호락한 문제가 아닙니다. 그 쇠고기와 우리가 수입할 쇠고기는 1등급과 쓰레기 정도로 틀립니다.

미국인들의 유전자형은 광우병에 감염될 확률이 30% 정도인데도 최근 알츠하이머 발병이 9000% 늘었다는 보고가 있죠. 그 대다수가 알츠하이머로 위장된 광우병이라고 하며 부검도 하지 않으며 쉬쉬한다고 합니다. (이 부분은 정확한 검증이 필요한 대목입니다)

한국인의 유전자형은 광우병에 걸릴 확률이 말도 안되게 높은 95%입니다. 미국인들은 20개월 미만의 (광우병 발생은 대부분 30개월 이상의 소에서 일어남) 소고기만 먹으며, 그것도 원산지가 정확히 표시되어 유통되는 소고기만 먹습니다.

즉, 그들은 광우병 발병이 높은 30개월 이상의 소는 접할 일도 없으며, 광우병이 발생한 적이 있는 지역에서 나는 소를 가려내며 먹을 수가 있습니다. 그리고 유전자 특성상 발병률이 상당히 저조합니다. 그런데도 저렇게 광우병 발생률이 높습니다.

광우병 발병률이 높은 30개월 이상의 소, 특히 발병률이 높은 뼈, 내장까지 수입하게 된 우리나라. 미국이 돈주면서 쓰레기 처리해달라고 해도 딴 나라들은 다 마다할 일을 독이 든 쓰레기를
제 값 다주면서 사오게 될 우리나라. 그 쓰레기를 그냥 버리는 것도 아니고 여기저기 숨기고 위장해서 싫다는 국민에게도 어떻게든 섭취시킬 우리나라.

소 가공품이 든 생리대, 과자, 라면, 기저귀를 사용하면서 전혀 위험한지 안위험한지 판별할 수 없을 우리나라 국민들. 전세계 유일하게 말도 안되는 소고기 수입 조건을 병시ㄴ같이 받아들여 세계 유래가 없이 전국민을 상대로 광우병의 실험장이 될 나라.대한민국.

이게 대체 말이나 됩니까. 600만 유태인 대학살과 같은 일이 우리나라에서 벌어질지도 모릅니다. 그것도 나중의 일이 아니라 지금 코 앞에 왔습니다. 3일이면 미국산 쇠고기 무분별하게 들어올 겁니다.

이번 FTA 협상에서는 미국산 쇠고기 수입으로 한국에서 광우병이 발병하더라도 우리는 수입을 중단할 수 없다는 조항이 첨가되었으며 또한 우리가 광우병에 걸린 소고기인지 아닌지 검사할 권한도 없습니다. 말이 됩니까 이게?

국민을 광우병 실험용 마루타로 내모는 정부만 욕하고 한탄할 일이 아닙니다. 무지하고 무관심한 국민들이 더 문제입니다. 남탓하고 남욕한다고 해결될 일이 아닙니다.

프로그래밍 문제 해결 체크 리스트

오랜만에 포스팅 합니다. 이곳을 방문하시는 분들 중에 소수의 분들은 아시겠지만, 제가 결혼을 하고 지난주 월요일에 신혼 여행을 다녀온 후에.. 외부 프로젝트에서 열심히 작업에 한창인지라, 블로그에 글 하나 올릴 여유가 없는듯합니다.

고로… 다시금 블로그에 글을 올리기 위한 동기 마련을 위해 금주 월요일, 오늘 글을 하나 올려 보려고 합니다. 딱히 요즘 작업에 여념이 없어, 새로운 학습이 없어 올릴만한 주제가 없긴한데요.. 그래서 요즘 개발하고 있는 컴포넌트에 대한 오류의 디버깅을 하던 차에.. 문제점 해결을 위해 이렇게 하면 좋겠구나 하는 제 경험적인 내용을 간단히 정리하려고 합니다.

먼저 문제점이 발생했을 경우, 그 문제점에 대한 현상을 구체적이고 정확히 서술 해줘야합니다. 그 다음으로 이 현상을 발생시켰던 사용자의 행위를 단계별로 정리해야 합니다. 물론 사용자의 행위가 없는 경우가 있습니다. 예를 들어… 프로그램이 가만이 있는데, 다운된다거나 하는 등.. 그리고 다음으로는 문제 현상을 발생시키는 프로그램 코드의 위치를 파악해야 합니다. 그리고 현상과 사용자의 행위 그리고 문제가 되는 코드를 힌트로 해서 문제점의 원인을 추정해 봅니다. 일단 추정이므로 추정 원인은 여러개가 나올 수 있겠습니다. 이 추정 리스트를 통해서 확인해 가면서 맞아 떨어지는 추정을 해결하면 문제점이 해결되겠지요. 여기서 중요한 것은 해결방법을 최종적으로 구체적으로 정리해서 추후에 동일한 문제점이 발생했을때 동일한 실수를 범하지 말아야한다는 점입니다.

정리해보면, 프로그래밍 문제 해결 체크 리스트 항목으로…

  1. 문제점에 대한 현상
  2. 문제의 현상을 일으키는 사용자 행위
  3. 문제가 되는 프로그램 코드 위치
  4. 문제점의 원인 추정
  5. 추정에 대한 해결방법

이번주는 프로그램에 대한 버그 수정에 곯머리를 앓을것같아서, 막무가내로 버그를 잡지 말고 체계적으로 해결해자는 취지에서 이 글을 올려봅니다. 물론, 오랜만에 블러그에 글을 포스팅하는 이유도 있지만 말입니다.

선과 점 사이의 최소 거리 구하기

원문은 http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ 입니다.

지금 진행하고 있는 프로젝트에서 필요한 알고리즘인데, 어디 이미 구현된 소스 코드 없나… 찾다가 발견한것입니다. 찾고보니, 무척 오래전에 봤던 글이네요. 그런데 그때는 소스 코드를 제공하지 않았는데… 여하튼, 다시 복습하는 겸해서 번역해 올립니다. 예전과 다르게 그림도 깔끔해서 그 그림을 그대로 올리겠습니다. 물론 변역이기는 하지만, 나름대로 내용을 보충해서 올렸습니다. 내용 시작합니다~

P1(x1, y1)과 P2(x2, y2)를 지나는 선분의 공식은 아래와 같다.

P = P1 + u(P2P1)

점 P3(x3, y3)는 P1과 P2를 지나는 선분에 인접한 점이다. P3를 선분까지 수직으로 연장한 길이가 바로 우리가 구하고자 하는 값, 즉 최소 거리이다. 수직으로 연장해서 만나는 점을 P라고 하자. 즉, P는 선분 상의 점이 되겠다. 그렇다면, 벡터P3->P와 벡터 P2->P1를 정의할 수 있을 것이고, 이 두 벡터의 내적(Dot Product)는 0이다.

(P3P) dot (P2 P1) = 0

위의 식의 P에 처음에 언급한 선분의 식(P에 대한)을 대입해보면…

[P3P1 – u(P2P1)] dot (P2P1) = 0

위의 식을 u에 대해서 풀어보면,

이 u 값을 다시 처음의 선분의 방정식(P1과 P2를 지나는)에 대입해 교점P에 대한 x, y에 대해 풀어보면…

x = x1 + u(x2x1)
y = y2 + u(y2y1)

그렇다면… 이렇게 구한 P와 P3의 거리가 바로 우리가 구하고자 했던 최소 거리값이 된다.

기능추가에 대해서.

잘 이해하고 있으며 잘 정립된 코드에 대해 어떤 새로운 기능을 추가할때 소요되는 시간. A를 목적으로 만들어진 프로그램에 목적 A와 연관된 기능을 추가할때 소요되는 시간.

내 경험으로, 위의 두가지 상황에서 하나의 기능을 추가하는 시간은 최대 2일을 넘지 않아야 한다.

만약 넘긴다면 제대로 정립되지 못한 코드이거나, 제대로 이해하지 못하고 있거나, 앞서 말한 A라는 목적과는 전혀 연관 없는 기능 추가에 대한 상황이라고 생각해도 좋지 않을까…

내가 앞으로도 이 말에 대해 책임을 질 수 있을까?

OOP 설계원칙 – SRP편

원문에 대한 링크는 http://www.gisdeveloper.co.kr/attachment/1154452764.pdf 입니다. 저작권은, 원본 문서를 작성한 분의 동의를 구하지 않고 번역한지라.. 제가 없고, 원저작자에게 있습습니다. 내용상의 오류 발견하시면 거침없이 하이킥 한방.. ^^; 그럼 내용 나가십니다…

SRP : The Single Responsibility Principle
“하나의 클래스를 수정해야 한다면, 그 수정 이유는 오직 한가지여야만 한다.”

6장의 볼링 게임 시스템을 다시 상기해보면, Game 클래스는 2개의 분명한 책임을 처리해야 한다. 현재 게임 화면을 추적하는 책임과 점수를 계산하는 책임이다. 끝에서, 이 두개의 책임을 2개의 클래스로 나눠서 처리해다. Game 클래스는 게임 화면을 추적하는 책임을… Scorer 클래스는 점수를 계산하는 책임을.

음… 두개의 책임을 각각에 대한 두개의 클래스로 분리하는것이 왜 중요할까? 이유는 각 책임이 변경의 이유이기 때문이다. 시스템에 대한 변경요구가 들어오면, 클래스들에 속한 책임에서의 변경을 통해 이뤄지게 된다. 다소 좀 설명이 철학적인데… 흠.. 여하튼, 만약 어떤 클래스가 하나 이상의 책임을 가지고 있다면, 변경요구에 대한 이유 역시 하나 이상이 될 것이다.

만약, 클래스가 하나 이상의 책임을 가진다면, 그 책임들이 서로 관계를 맺게 될 것이다. 하나의 책임에 대한 변경은 다른 하나의 책임 때문에 엉키거나 변경 자체가 불가능하게 될 수 있다. 책임들에 대한 이런 관계 맺음은 변경요구 시 예상치 못한 어려운 상황을 발생시키는 설계로 치닿게 될 것이다.

예를들어보자. 그림9-1의 설계를 보면, Rectangle 클래스는 2개의 매서드를 가지고 있다. 하나는 화면에 사각형을 그리는 것. 또 하나는 넓이를 계산하는 것.


2개의 서로 다른 어플리케이션이 이 Rectangle 클래스를 사용한다. 하나의 어플리케이션은 Computational Geometry이고, Rectangle 클래스의 넓이를 얻어오기 위해 쓰일 뿐, 화면에 그리는 일은 하지 않는다. 다른 어플리케이션은 그래픽컬한 것으로 앞의 어플리케이션 처럼 클래스의 넓이도 얻어오고, 화면상에 그리기위해 Rectangle 클래스를 사용한다.

이 설계는 SRP를 위반하고 있는데, Rectangle 클래스가 2개의 책임을 갖고 있기 때문이다. 하나의 책임은 넓이 계산. 두번째 책임은 그리기. SRP 위반은 여러가지 추잡스러운 문제를 유발한다. 첫째로 반드시 Computational Geometry 어플리케이션에 쓰지도 않는 GUI 관련 모듈을 포함해야한다. 쓰지도 않는데 말이다.. 찝찝해… 두번째는, 하나의 어플리케이션에서 Rectangle를 어떤 이유때문에 변경했을때,  또 다른 어플리케이션에 영향을 미친다는 것이다. 이런.. 이런..

더 나은 설계는 그럼 9-2처럼, 두개의 완전히 독립된 클래스에 각각 하나씩의 책임을 분리하는 것이다. 이 설계는 Rectangle의 클래스의 넓이 계산 책임은 GeometricRectangle 클래스를 만들어 넣는다. 이대로라면, 사각형을 표시하는 기능이 Compution Geometry 어플리케이션에 영향을 미치지 않는다.


책임이라는게 무엇인가?

SRP 즉, 단일책임원리에서, ‘변경의 이유’로써 ‘책임’을 정의했다. 클래스를 변경해야할 하나 이상의 이유를 생각할 수 있다면, 그 클래스는 하나 이상의 책임을 갖고 있다는 의미이다. 우리는 책임을 그룹 단위로 생각하려는 경향이 있다. 예를들자면, 리스트 9-1에서와 같이, Modem 인터페이스를 살펴보자. 대부분의 사람들에게는 Modem 인터페이스는 완벽하게 보인다. 즉, 4개의 함수는 분명히 Modem의 기능이 틀림없다.


그러나, 여기에는 2개의 책임이 존재한다. 첫번째 책임은 연결관리이고, 두번째 책임은 데이터 통신이다. dial과 hangup 함수는 모뎀의 연결을 관리하고, send와 recv는 데이터 통신 함수이다.

이 2개의 책임을 분리해야하는가? 대부분의 경우, 확실하게 그래야만 한다. 이 2개의 함수셋(dial과 hanup 함수셋, send와 recv 함수셋)은 “공통점”을 가지고 있지 않다. 이 2개의 함수셋의 변경 이유는 서로 다르다.

더욱이, 이들을 사용하는 어플리케이션의 부분 역시 완전히 다르다. 마찬가지로 이러한 다른 부분들은 서로 다른 이유로 변경될 것이다.

그래서, 그림9-3이 더 나은 설계이다. 2개의 분리된 인터페이스에 2개의 책임을 나눴다. 최소한 이 방법은, 2개의 책임이 서로 결합함으로써, 변경에 방해가 되는 것으로부터 어플리케이션을 보호해줄 것이다.


그러나……. 결국에는 ModemImplementation 클래스에서 두 책임이 재결합하고 있다는 점이다. 이것은 바람직하지 않은 것이지만, 어쩔 수 없는 경우일지도 모른다. 그러나, 이들의 인터페이스를 분리함으로써, 이 두 책임을 분리시켜야 한다.

ModelImplementation는 못쓸 클래스처럼 보일지도 모른다. 그러나, 모든 의존성들이 이 클래스로인해 제거 된다는 점. 어느 무엇도 이 클래스에 의존할 필요가 없다는 것이다. 어느 무엇도 main을 제외하고 이것의 존재를 알 필요가 없다는 점이다. 그러니까.. 쉽게 말하면 Modem 관련 기능을 위해 우리가 알아야할 클래스는 ModemImplementation이 아니고 앞서 2개의 인터페이스 DataChannel, Connection 이다. 이것이 ISP가 아닌가….
ModemImplementation는 단지 OS나 하드웨어에 따라 달리 구현되는 구현부일 뿐이다. 인터페이스와 구현의 분리가 완벽하게 이뤄지고 있다는 것이다. 그래서, 우리는 우리는 울타리 뒤에 흉직한 것들을 놓는 것이다. 즉, 울타리는 앞서 2개의 인터페이스이고 흉직한 것들은 ModemImplementation이다. 흉직하다라는 표현을 한 이유는 변경사항이 발생할때마다 변경해야할 곳이기에 개발자의 수고가 가장 많기 때문이다. 이것으로 인해, 어플리케이션의 나머지 부분 역시 오염되는 것을 최소화 할 수 있다.

결론
SRP는 가장 간단한 객체지향 원리 중에 하나이면서 옳바르게 사용하기가 가장 어려운 것중에 하나이다. 책임의 결합은 우리가 은연중에 하게 되는 습관인듯하다. 이러한 책임을 찾아 분리하는 것이 소프트웨어 설계의 아주 많은 부분이다. 사실, SRP 이외의 다른 객체지향원리도 SRP의 원리가 적용된다.