과학

자바로 프로그래밍에 입문할래요: 2.2. 라이브러리와 클라이언트 (3)

라이브러리와 클라이언트 마지막 시간.

통계를 다루는 라이브러리를 알아보고, 마지막으로 라이브러리의 중요성에 대해 소개하고 있어.

이 글에서 수학적으로 복잡한 라이브러리를 계속 소개하고 있는 이유는

프로그래머라면 응당 이런 것들을 손쉽게 만들 수 있어야 한다고 겁주기 위함은 아니야.

중요한 것은, 라이브러리라는 것이 얼마나 강력하고 우리가 클라이언트로서 이런 복잡한 것들을 얼마나 손쉽게 사용할 수 있는지 체감하는 것이지.

코드는 프로그래밍의 표현법에 불과해.

 

2.2. 라이브러리와 클라이언트 (2)

2.2. 라이브러리와 클라이언트 (1)

2.1. 정적 메소드 (2)

2.1. 정적 메소드 (1)

1.5. 입출력 (2)

1.5. 입출력 (1)

1.4. 배열 (3)

1.4. 배열 (2)

1.4 배열 (1)

1.3. 조건문과 반복문 (2)

1.3. 조건문과 반복문 (1)

1.2. 내장 자료형 (2)

1.2. 내장 자료형 (1)

0.0. 여는 글, 1.1. 첫 프로그램 만들기

 

================================

 

표준 통계(Standard statistics)

  다음은 과학 및 공학 응용프로그램에서 사용되지만 표준 자바 라이브러리에 구현되어 있지 않은, 수학 계산과 간단한 시각화 도구 라이브러리를 구성해볼까 합니다. 이는 통계 내에서 각 숫자들을 다루는데 사용되는 것들입니다. 현대 과학자들이 직면하고 있는 문제 중 하나는 자료들에 대한 분석입니다. 기초적인 자료 분석을 위해, 다음 API를 구현해 볼 것입니다.

 

자료 분석을 위한 정적 메소드들의 API

 

 

 

 

기초 통계

  N개의 수치가 있다고 해봅시다. 이 수치들의 평균(mean)은 모든 수치들의 합을 N으로 나누어서 계산됩니다. 우리는 평균을 보고 수치들을 짐작할 수 있습니다. 이렇게 우리가 갖고있는 수치 값들에 대해 평가할 수 있는 여러 함수들이 있습니다. 최솟값, 최댓값, 중간값, 분산, 표준편차와 같은 것입니다.

 

  

프로그램 2.2.4: Data analysis library

 
public final class StdStats
{
	public static double max(double[] a)
	{
		double max = Double.NEGATIVE_INFINITY;
		for (int i = 0; i < a.length; i++)
		{
			if (Double.isNaN(a[i]))
				return Double.NaN;
			if (a[i] > max)
				max = a[i];
		}
		return max;
	}

	public static double mean(double[] a)
	{
		if (a.length == 0)
			return Double.NaN;
		double sum = sum(a);
		return sum / a.length;
	}

	public static double var(double[] a)
	{
		if (a.length == 0)
			return Double.NaN;
		double avg = mean(a);
		double sum = 0.0;
		for (int i = 0; i < a.length; i++)
		{
			sum += (a[i] - avg) * (a[i] - avg);
		}
		return sum / (a.length - 1);
	}

	public static double stddev(double[] a)
	{
		return Math.sqrt(var(a));
	}

	public static void main(String[] args)
	{
		double[] a = StdArrayIO.readDouble1D();
		StdOut.printf(" min %7.3f\n", min(a));
		StdOut.printf(" mean %7.3f\n", mean(a));
		StdOut.printf(" max %7.3f\n", max(a));
		StdOut.printf(" std dev %7.3f\n", stddev(a));
	}
}

 

  해당 코드는 클래스의 일부만 발췌하였습니다. <StdRandom>과 같이, main()에서 각 메소드를 호출해 테스트를 실시합니다. 만약 라이브러리에 추가적인 메소드가 자리하게 된다면, 테스트 코드 역시 수정해 모든 메소드를 한 번에 테스트할 수 있게끔 만들어야 합니다. 관련된 내용은 코드 혹은 웹사이트를 참고해보세요.

 

 

그래프 그리기(Plotting)

  <StdDraw>는 표를 통해 숫자를 표시하는 것보다 좀 더 효과적으로 시각화를 할 수 있게 만들어줍니다. 무언가 실험을 했을 때, 해당 데이터를 단순히 표로 표현하는 것보다는 다양한 방식으로 시각화를 하는 것이 더 좋을 것입니다. 이런 처리를 신속하게 하기 위해, 일반적인 상황에서 사용할 수 있는 메소드들을 담아볼까 합니다.

 

 

프로그램 2.2.5: Plotting data values in an array

 
public static void plotPoints(double[] a) {
    int n = a.length;
    StdDraw.setXscale(-1, n);
    StdDraw.setPenRadius(1.0 / (3.0 * n));
    for (int i = 0; i < n; i++) {
        StdDraw.point(i, a[i]);
    }
}

public static void plotLines(double[] a) {
    int n = a.length;
    StdDraw.setXscale(-1, n);
    StdDraw.setPenRadius();
    for (int i = 1; i < n; i++) {
        StdDraw.line(i-1, a[i-1], i, a[i]);
    }
}

public static void plotBars(double[] a) {
    int n = a.length;
    StdDraw.setXscale(-1, n);
    for (int i = 0; i < n; i++) {
        StdDraw.filledRectangle(i, a[i]/2, 0.25, a[i]/2);
    }
}

 

  위 코드는 <StdStats>에 포함되어 있는 메소드들입니다. 각 자료값들이 있는 배열을 인자로 받아 점으로, 선으로, 막대로 시각화를 할 수 있습니다.

 

 


  <StdStats>는 여러분들에게 자료 분석을 어떤 식으로 할 수 있는지에 대해 알려주는 것일 뿐입니다. 일반적인 상황에서 사용할 수 있는 다양한 메소드들을 지원하지는 않으며, 원한다면 여러분들이 추가해볼 수도 있습니다. 

 

 

함수 그래프 그리기

  여러분은 StdStats.plot*() 메소드를 이용해 어떤 함수이든 그려낼 수 있습니다. x값의 간격을 선택하고, 그 간격에 맞게 y값을 계산해 배열에 저장 한 뒤, StdStats를 호출하면 됩니다. 하지만 그래프에 여백이 너무 많이 그려질 때가 있는데, 이 때에는 setScale 메소드들을 이용하면 됩니다.

 

  만약 여러분들이 삼각함수를 그래프로 표현하고 싶을 때, y값의 범위는 -1에서 +1 사이일 것입니다. 이를 메소드를 통해서 해결해보죠. 참고로, x값은 자동으로 그 여백을 처리해줍니다.

 

 
StdDraw.setYscale(StdStats.min(a), StdStats.max(a));

 

  배열의 크기가 클수록(점이 많을수록) 곡선은 부드러워집니다. 이전에 <StdDraw>를 통해 샘플링 해봤을 때와 동일합니다.

 

 
 

 

음파 그리기

  <StdAudio> 라이브러리와 <StdStats> 플롯 메소드는 균일한 간격으로 계산된 값의 배열으로 작동합니다. 이를 이용해서, 여러분들은 음파를 직접 그려낼 수도 있습니다. 

 

 

 

 

실험 결과 그리기

  여러분들은 여러 결과를 다른 방식으로 겹쳐 그릴 수도 있습니다. 예를 들어 남녀의 통계를 비교해야 할 때나 이론적 모델과 실제 수치를 비교해야 할 때, 두 그래프를 겹쳐서 한 눈에 확인할 수 있게 만듭니다. 다음 프로그램은, 동전을 N번 던졌을 때 앞면이 나온 횟수를 기록하며, 이를 T번 반복합니다. 이 결과를 시각화 하고, 정규(가우시안) 분포 함수와 비교합니다.

 

 

프로그램 2.2.6: Bernoulli trials

 
public class Bernoulli
{
	public static int binomial(int N)
	{ // Simulate flipping a coin N times,
		int heads = 0;
		for (int i = 0; i < N; i++)
			if (StdRandom.bernoulli(0.5))
				heads++;
		return heads;
	}

	public static void main(String[] args)
	{ // Perform experiments, plot results and model,
		int N = Integer.parseInt(args[0]);
		int T = Integer.parseInt(args[1]);
		int[] freq = new int[N + 1];
		for (int t = 0; t < T; t++)
			freq[binomial(N)]++;
		double[] norm = new double[N + 1];
		for (int i = 0; i <= N; i++)
			norm[i] = (double) freq[i] / T;
		StdStats.plotBars(norm);

		double stddev = Math.sqrt(N) / 2.0;
		double mean = N / 2.0;
		double[] phi = new double[N + 1];
		for (int i = 0; i <= N; i++)
			phi[i] = Gaussian.pdf(i, mean, stddev);
		StdStats.plotLines(phi);
	}
}

 

 

 

 

모듈화 프로그래밍(Modular programming)

  우리가 개발했던 라이브러리의 구현은 모듈화 프로그래밍의 일환입니다. 크나큰 문제를 해결하기 위해서 새로운 프로그램을 작성하는 것 대신, 문제를 작게 나누어 각 작은 작업들을 독립적으로 해결하게 만드는 것입니다. 좋은 라이브러리는 모듈화 프로그래밍을 가능케 하며, 미래의 클라이언트들에게 작업의 해결책을 제시해줍니다. "프로그램에서 작업의 단위를 나눌 수 있다면, 그렇게 해야 합니다."

 

  자바는 독립적인 별도의 파일로 디버깅할 수 있게 해줍니다. 예로부터 프로그래머들은 각자 컴파일 되고 독립적으로 실행될 수 있는 코드들을 모듈이라고 칭했습니다. 즉, 자바의 각 클래스는 모듈에 해당합니다.

 

 

  <IFS, 프로그램 2.2.3>은 각 작은 모듈로부터 만족스러운 계산을 해내기 때문에, 모듈화 프로그래밍의 좋은 예라고 할 수 있습니다. <StdRandom>과 <StdIO>, <Integer>의 메소드와 <StdDraw>의 메소드까지 다양한 모듈들을 사용합니다. 만약 모든 코드를 <IFS> 파일 단 하나에 집어넣었다면, 나중에 유지보수나 디버깅을 할 때 굉장히 많은 노력이 필요했을 것입니다.

 

  모듈화 프로그래밍을 통해, 배열을 읽는 것과 적절한 분산값을 무작위로 생성하는 작업들이 이미 잘 작동한다는 확신을 갖고 더 큰 프로그램을 작성 할 수 있었습니다. 이들은 각자 모듈로 구성 되어 있고, 각자가 테스트를 끝마쳤기 때문입니다.

 

  <Bernoulli, 프로그램 2.2.6>을 보시죠. 이는 <Gaussian>, <Integer>, <Math>, <StdRandom>, StdStats>의 클라이언트입니다. 이 수많은 라이브러리들을 우리가 아무 걱정 없이 사용할 수 있는 이유는, 이것들이 모듈로서 잘 존재하기 때문입니다.

 

 

 

 

  모듈화 프로그래밍은 현대 프로그래밍에서 필수적인 것이며, 수많은 이점들을 가졌다는 점을 기억하세요.

 

  • 아무리 큰 시스템이더라도, 적절한 크기의 프로그램들의 조합으로 나눌 수 있습니다.
  • 디버깅 역시 적은 코드로 손쉽게 할 수 있습니다.
  • 재구현 없이 재사용 할 수 있습니다.
  • 유지보수와 확장이 훨씬 간단해집니다.

 

 

적절한 크기의 프로그램(Programs of a resonable size)

  좋은 프로그램은 결코 거대하지 않습니다. 만약 여러분 프로그램의 페이지가 점점 늘어나고 있다면, 작은 작업들로 나눌 수는 없는지 다시 생각해보아야 합니다. 또 미래에 다른 클라이언트가 이 프로그램을 이용할 수 있는지에 대해 생각해보는 것도 좋겠죠. 여러분이 어떤 프로그램을 작성하던 간에, 그곳에는 굉장히 많고 작은 모듈들이 얽혀있다는 것을 알게 될 것입니다. 여러분 역시 그런 규칙을 따라야겠죠?

 

 

디버깅(Debugging)

  구문이 많고 상호작용하는 변수들이 많을 수록 프로그램을 추적하기는 어려워집니다. 100개의 변수와 그 변수들에 영향을 끼치는 수많은 구문들이 있는프로그램을 상상해보세요. 모듈화 프로그래밍에서는 이런 변수들의 스코프를 적절히 조절할 수 있게 해주고, 디버깅 역시 쉽게 만들어줍니다.

 

 

코드 재사용(Code reuse)

  우리가 <StdStats>나 <StdRandom>과 같은 라이브러리를 한 번 구현만 한다면, 이후에는 더이상 평균과 분산을 계산하고, 난수를 생성하는 데 걱정할 필요가 없습니다. 단순히 재사용만 하면 될 뿐입니다. 같은 코드를 계속 복사해낼 필요가 없다는 의미죠.

 

 

유지보수(Maintenance)

  모듈화 프로그래밍은 지속적으로 여러분의 프로그램을 향상시킬 수 있게 합니다. 모듈을 향상시킨다는 것은, 결국 해당 모듈을 사용하는 클라이언트를 전부 향상시키는 셈이죠. 가령 특정 문제를 두고 서로 다른 방법으로 해결하는 경우는 굉장히 흔합니다. 모듈화 프로그래밍을 적용한다면, 각자 모듈을 만들어 다양한 방법으로 접근해보고 독립적으로 시도해볼 수도 있습니다. 

 

  더욱 중요한 사실은, 여러분의 모듈에 버그가 발생할 수 있다는 것입니다. 모듈화 프로그래밍은 고쳐야 할 버그의 양을 상당수 줄여주게 됩니다. 모듈만 고치면, 모든 클라이언트의 버그가 고쳐지는 셈이니까요.

 

 

오래된 프로그램을 직면해본다면...

  오래된 프로그램을 보면, 상상 이상으로 긴 코드를 볼 수 있을 것입니다. 수 페이지가 넘어가는 길고 긴 구문들, 어떤 구문에서든지 접근할 수 있는 수많은 변수들이 있는 것들이죠. 이렇게 코드 어느 곳에서든지 접근할 수 있는 변수를 전역 변수(global variables)라고 합니다.

 

  모듈화 프로그램에서는 전역 변수의 사용을 최대한 피합니다. 하지만 저레벨이고 오래된 프로그래밍 언어에서는 여전히 많이 사용되고 있습니다. 전역 변수를 사용하는 거대한 모듈은 이해하기도 어렵고, 유지보수와 디버깅하기도 어렵습니다. 

 

  오래된 프로그램은 굉장히 중요한 사회 기반 시설들에서 사용됩니다. 가령 핵발전 시설이나, 은행 프로그램과 같은 것들이죠. 이것들이 여전히 남아있는 이유는 여러가지 이유가 있겠지만, 그 중 하나는 현대 프로그래머들이 현대 언어로 다시 작성하기엔 코드가 너무 난해하기 때문이기도 합니다! 여러분들은 이런 상황을 만들지 마세요.

 

 

마치며

  이번 절에서 우리는 Std* 라이브러리들을 살펴보고, 직접 사용해보기도 했습니다. 이런 간단한 수학 도구들을 소개해주는 이유는, 여러분들에게 이 도구들의 사용법을 알려주기 위함이 아닙니다. 중요한 것은, 여러분들이 이런 라이브러리들을 원하면 언제든지 만들 수 있다는 것입니다. 

 

  현대의 프로그래머가 복잡한 문제를 해결하기 위해서 던지는 첫번째 질문은 다음과 같습니다. "어떤 도구가 필요할까?". 필요한 도구들이 아직 구현되어있지 않다면, "그것들을 구현하는 것이 얼마나 어려울까?"에 대한 질문을 던져봐야 할 것입니다. 좋은 프로그래머가 되기 위해서는, 어떤 라이브러리를 사용할지 결정하는 지혜와, 원하는 소프트웨어 도구를 만들 수 있는 확신을 가져야합니다.

 

  라이브러리와 모듈화 프로그래밍 이후, 여러분들은 완전한 현대 프로그래밍 모델을 배우기 위해 한 걸음 내딛을 것입니다. 바로 객체 지향 프로그래밍(object-oriented programming)입니다. 객체 지향 프로그래밍으로 진입하기 이전에 마지막으로, 다음 절에서 자기 자신을 호출하는 함수에 대해 알아보도록 합시다.

 

2.2. 라이브러리와 클라이언트 끝.

7개의 댓글

2021.06.28

클래스, 라이브러리, API

이 3개의 차이점을 모르겠음

0
2021.06.28
@샤켓

1.

클래스는 간단히 값(변수)과 연산(메소드)의 집합이야. 객체의 설계도이고, 자료형의 확장이지. C의 구조체(값의 집합)에서 함수(연산)가 추가된 개념이라고 보면 돼. 물론 상속과 같은 복잡한 개념들도 있지만, 넘어가자구..

 

라이브러리는 메소드들을 다른 클라이언트가 쉽게 사용할 수 있도록 만들어진 일종의 모듈이야.

 

API는 인터페이스야. 좁은 의미로는 라이브러리와 클라이언트 사이에서 '이렇게 사용하세요!' 하는 설명서라고 보면 돼. API는 자연어와 함께 표현되지.

 

2.

자바에서 모든 라이브러리는 곧 클래스야. 다른 클라이언트가 특정 기능을 쉽게 사용할 수 있도록 만들어진 값과 연산의 집합이기 때문이지. 하지만 모든 클래스가 라이브러리는 아니야. 즉 라이브러리는 '재사용을 위해 만들어진 클래스' 정도로 보면 돼.

 

반면, API는 그 클래스를 사용하기 위한 일련의 '추상적' 설명서야. 이 API를 구현하는 것이 곧 라이브러리지. 라이브러리와 API는 1:1 대응하지 않아. 같은 API를 구현함에도 서로 다른 라이브러리가 존재할 수 있어. API는 추상화, 라이브러리는 구체화의 개념으로 접근하면 될 것 같아.

0
2021.06.28
@스비니

라이브러리랑 클래스는 알겠다

 

API는 컴터랑 윈도우로 소통하는거랑 비슷한거야?

내부적으로 어떻게 돌아가는지는 모르지만 결과는 준다고 하나

0
2021.06.28
@샤켓

비슷해. 중요한 것은, API가 그 결과를 생성해주는 것은 아니야. 언제까지나 소통의 창구일 뿐이고, 실제 구현은 다른 놈(라이브러리)이 하고 있는 거지.

API만 있어서는 아무것도 할 수 없어. API는 말그대로 Interface일 뿐이고, 클라이언트가 API를 사용하기 위해서는 API의 구현이 필요해.

구현이 있을 때, 클라이언트는 API의 구현 세부사항에 상관 없이 API만 가지고 결과들을 반환받을 수 있지.

0
2021.06.28
@스비니
0
@스비니
0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜
522 [과학] 한반도 형성 모델 8 白猫 4 13 일 전
521 [과학] 인류 발전은 정체되었는가? 119 월급받으며개드립하기 22 18 일 전
520 [과학] 자바로 프로그래밍에 입문할래요: 3.3. 자료형 설계하기 (4) 스비니 5 2021.08.21
519 [과학] 자바로 프로그래밍에 입문할래요: 3.3. 자료형 설계하기 (3) 3 스비니 3 2021.08.17
518 [과학] 자바로 프로그래밍에 입문할래요: 3.3. 자료형 설계하기 (2) 2 스비니 0 2021.08.15
517 [과학] 자바로 프로그래밍에 입문할래요: 3.3. 자료형 설계하기 (1) 9 스비니 1 2021.08.12
516 [과학] 자바로 프로그래밍에 입문할래요: 3.2. 자료형 생성하기 (3) 스비니 0 2021.08.11
515 [과학] 모든 멸종의 어머니 - 페름기 대량절멸 (1) 9 PorcupineTree 9 2021.08.11
514 [과학] 희귀 혈전등에 대한 아스트라제네카 코로나 19 백신 접종의 ... 18 매콤챱스 5 2021.08.10
513 [과학] 자바로 프로그래밍에 입문할래요: 3.2. 자료형 생성하기 (2) 2 스비니 2 2021.08.09
512 [과학] 엔트로피는 감소할 수 있는가? 43 Kuqi 21 2021.08.08
511 [과학] 자바로 프로그래밍에 입문할래요: 3.2. 자료형 생성하기 (1) 3 스비니 2 2021.08.05
510 [과학] 자바로 프로그래밍에 입문할래요: 3.1. 자료형 (4) 11 스비니 3 2021.08.04
509 [과학] 자바로 프로그래밍에 입문할래요: 3.1. 자료형 (3) 2 스비니 3 2021.08.02
508 [과학] SF스압) 최후의질문 / 원래는..(How It Happened) 16 기타치는고라니 15 2021.07.31
507 [과학] [양자역학 3부] 슈뢰딩거의 고양이에 대해서. 28 기타치는고라니 3 2021.07.30
506 [과학] 자바로 프로그래밍에 입문할래요: 3.1. 자료형 (2) 2 스비니 3 2021.07.29
505 [과학] (기상)우리나라 더위의 발생 형태 4가지. 51 마리괭이 20 2021.07.25
504 [과학] 자바로 프로그래밍에 입문할래요: 3.1. 자료형 (1) 4 스비니 1 2021.07.22
503 [과학] 자바로 프로그래밍에 입문할래요: 2.3. 재귀 (2) 24 스비니 5 2021.07.14