※ Keep in mind
본 내용은 웹개발과정의 강의 중 내용을 복습을 위해서 메모한 것에 불과한 것입니다. 이러한 연유로 강의내용을 오인한 나머지 오기재 및 불기재가 있을 수 있으니 '참고'만 해주시길 바랍니다. 저의 경우에도 본 내용을 단순히 읽은 것이 결코 저의 것이라고 생각하지 않습니다. 본 내용은 복습를 위한 초기 내지 중간 과정에 불과한 것이고, 이후에 내용을 보충 후 인출 및 설명하기 과정이 있어야 비로소 복습의 단추가 어느정도 마무리 되어간다고 볼 수 있습니다.
따라서 당초에 본 내용은 비공개였습니다. 그럼에도 불구하고 본 내용을 공개한 점은 함께 공부하는 동료들과 나눔을 바탕으로 배움과 성장의 공진화라는 소기의 목적을 달성에 어느정도 도움이 될수 있기 때문이라고 생각합니다.
I. INTRO : 오전 문제풀이
II. 함수
프로그래머란 절차를 만드는 사람
코딩을 할수록 길어지는것, 중첩해결, 차원늘어나는것 해결해야한다.
우리가 감당할 수 있는 낮은 중첩으로 만들어야한다.
이것을 도와주는 것이 함수임
나누면 끊어진 단위가 있고 이것이 엮여지면서 모양이만들어진다.
이 순간 구조가 나오고 구조화된 코드라고 한다
1. 코드(절차)의 구조화
자바프로그래밍 > 구조적프로그래밍 > 객체지향프로그래밍
구조적 프로그래밍 key : 자르는 방법을 이해하기
(1) 프로그래밍은 절차이다.
1) 함수 소개
코드를 자르는데 자른다는 것은 무엇? 함수로 자름
자르고 이후에 이어붙일 수(함수호출 : Function call) 있다
반환은(retrun) 흐름을 돌아올 때 받는값이기 때문에 부름
구조를 만드는 것은 Top-down,bottom-up 이 있다.
2) top -down
구조를 먼저 생각하고 구현을 나중에 하는 것이다.
가장 바람직함 먼저 생각을 하고 구현함
그러나 입문자에게는 어렵다. 입문자는 구조보다 돌아가는게 급하다.
이미 해본사람들은 이게 쉽다.
처음에 bottom-up(돌려보기) 한 후
나중에 비슷한거 할때 그대로 top-down 식으로 이용가능하다.
3) bottom-up
책쓰고 목차잡기
구조를 나중에 하기
처음에 돌려보기
(2) 절차를 자르는 도구로써의 함수
1) 함수가 가지는 능력2 : 코드를 잘라낼 수 있다.
함수를 이용하면 : (나재차집 : 나재영의 차와집)
--코드의 직접 사용을 '차'단할수 있다(구현코드를 숨길 수 있다.)
얘를 가져다 써도 다른 나의 코드에 영향을 받지 않는다.
즉 인터페이스 역할
--코드를 작게 '나'누어서 만들 수 있다.
--코드를 '집'중화할 수 있다.
코드작성 양이 줄어든다.
해당함수를 수정할 시 해당 함수를 사용하는 다른 함수에도 영향을 미침
--코드를 '재'사용할 수 있다.
다음에도 또 쓸수있다.
(3) 자바에서 함수를 정의하는 방법
static int power(int x) { .... return }
static : 일단 써두기
int : return 값 자료형
(int x) : 인수 자료형
return : 반환 값
1) 매개변수 없이
public class BasicFunction {
static int f1() {
return 3+4*23;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = 3+4*23-23+345-23;
System.out.printf("result is %d\n",result);
result = f1()-23+345-23;
System.out.printf("result is %d\n",result);
}
}
간단하게 f1()함수 구현 함
결과 두개의 값이 동일 함
static int add() {
return 3+4;
}
result = f1()-23+345-23+add();
System.out.printf("result is %d\n",result);
위와 같이 add()로 7을 추가로 값을 받을 수 있다.
- 함수는 만드는과정에서 자르는 이유를 찾아야한다
왜 잘라? 할때 4가지 중에서 생각해야한다.
2) 매개변수 있게 (call by value)
static int add(int x, int y) {
return x+y;
}
result = f1()-23+345-23+add(3,4);
System.out.printf("result is %d\n",result);
함수에 int x, int y 는 매개변수의 이름을 자유롭게 설정이가능하다
이 경우 하고자하는 용도에 맞게도 이름을 넣을 수 있다.
이 경우 매개변수가 설정되면 반드시 값을 주어야한다
static void printSum(int x) {
System.out.println(x);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
result = f1(4)-23+345-23+add(3,4);
System.out.printf("result is %d\n",result);
printSum(add (4,5)); //4,5 > add > printSum 이 순서로 진행된다
}
printSum(add (4,5)); //4,5 > add > printSum 이 순서로 진행된다
3) 기존 코드 함수화
static void printNum(int [] nums) {
for(int i = 0 ; i < nums.length ; i ++) {
System.out.printf("%d",nums[i]);
if(i < 14)
System.out.print(",");
}
System.out.println();
}
main 함수 내 산개되어 반복된 배열출력하는 코드들을 한곳에 합침
4) 매개변수 안쓰는방법(전역변수를 이용)
강의장 지역이 아니라 강의장지역을 벗어난 전역으로 이용이 가능하다.
static int [] nums = new int[15]; //전역변수로 선언
static void printNum() { //매개변수없음
for(int i = 0 ; i < nums.length ; i ++) {
System.out.printf("%d",nums[i]); //바로 영향받음
if(i < 14)
System.out.print(",");
}
System.out.println();
}
이 경우 static을 써서 전역으로 nums배열을 선언하고 매개변수 없이 이용이 가능하다.
하지만 바람직한 방법은 아니다.
왜냐하면 서로 영향을 받게되어서 결합력강해지기 때문이다.
함수는 고립화 되어있어야하는데, 즉 함수 안에서자만 자라면 외부가 어떤일이 있어도 영향이없어야한다
만약 바깥에 문제 발생해서 영향을 받으면 고립화가 안되고, 누군가와 결합된 형태가 된다.
즉 함수는 고립화 및 결합력을 낮게
그러므로 전역은 안좋다. 전역적으로 결합해서 전역적으로 보아야해서 코드작성시 신경쓸것이 많다
그래서 가급적 전역변수를 안쓰도록해야한다. 지역변수를 쓰자 그래야 고립화 & 결합력 낮게
(4) 함수 이름 짓기 (카멜표기)
함수는 기능을 담당하는 녀석이다. 즉 행위 (~하다 의 단위)
행위로 이름짓기
로또번호생성 -> 생성로또번호 [gen_Lotto()] (기능 / 재료)
로또번호출력 -> 출력로또번호 [print_Lotto()]
로또번호정렬 -> 정렬로또번호 [sort_Lotto()]
가운데 _ 구분자를 써서 가능함 (하지만 언어나 플랫폼에 따라 다르다. - 자바 : 카멜표기)
-카멜표기 : 첫글자 소문자 이후 시작부분대문자 / -파스칼 표기 : 첫글자 대문자 이후 카멜처럼
초기에는 절차만들기가 어려운데, 결국 어려운건 절차명, 함수명 등을 짓기가 어려울수가 있다.
(4) 함수화 실습 (오목게임)
1) 보드 초기화
출력도, 프린트도 아니므로 최초 init_Board로 해준다.
static void init_Board(char [][]board) {
//지역화 1
for(int y = 1 ; y <= 10 ; y++) {
for(int x = 1 ; x <= 10 ; x++)
board[y - 1][x - 1] = '┼';
}
//위칸 마감
for(int y = 1 ; y <= 10 ; y++) {
for(int x = 1 ; x <= 10 ; x++) {
board[0][x - 1] = '┬';
board[9][x - 1] = '┴';
}
board[y - 1][0] = '├';
board[y - 1][9] = '┤';
board[0][0] = '┌';
board[0][9] = '┐';
board[9][0] = '└';
board[9][9] = '┘';
}
}
함수 왔다갔다 하기 힘드니까 호출함수에다가 F3 누르면 함수코드로 간다
함수코드에다가 alt + 화살표하면은 호출함수로간다
2) 보드 출력
static void print_Board(char [][]board_args) {
for(int y = 1 ; y <= 10 ; y++) {
for(int x = 1 ; x <= 10 ; x++)
System.out.printf("%c", board_args[y - 1][x - 1]);
System.out.println();
}
}
3) 보드 좌표 입력
static int number = 0; //전역으로 하지만 바람직하지않음
static int input_OmokBoard() {
Scanner scan = new Scanner(System.in);
int ox = 1 ; int oy = 1;
if(number % 2 == 0) // 홀수번째
System.out.printf("%c 백돌차례",'○' ); //x랑 y 위치 휴먼관점에서!
else //짝수번째
System.out.printf("%c 흑돌차례",'●' ); //x랑 y 위치 휴먼관점에서!
System.out.println(" 놓고 싶은 위치에 넣기");
System.out.println("X Y : ");
ox = scan.nextInt();
oy = scan.nextInt();
return ox, oy;
}
값이 원시형(기본형변수)은 공유가 안된다 전달되어도 값이 직접가지만
참조형 변수는 다 공유가 된다 개별적인 사번이 들어갈수있다 (무조건 공유)
2. 함수호출과 스택
함수가 있을 때 스택이라는 개념이 있다.
1 )
프로그램 실행할 때 메모리를 쓴다
코드가 올라가는 곳 (코드영역 : text 영역)
데이터가 올라가는 곳(데이터영역 : Data영역)이 있다
데이터 영역에는 Heap 과 Stack 영역으로 나누어진다.
stack 은 함수의 지역변수를 마련하는공간
heap 은 동적으로 형성되는 것을 마련하는 공간
2)
코드부분은 실제로는 컴파일된 이진코드로 올라간다
프로그램이 메모리에 올라가 실행 된 것을 process라 한다
(사실 프로그램은 올라가지않음, 프로그램 자체는 죽은상태)
(프로그램이 down 됐다기 보다는 process가 멈춘거임)
올라간 코드 실행 시 메인함수 실행된다는 것은 연산자가 실행되는 것임
가장먼저 실행되는 것은 = 등인데 코드안에 선언된 것이 미리 준비물이 마련된다
본 이미지에 있는 변수의 개수는 4개이다 (args 포함)
선언된 애들은 stack에 준비되고 잠기고, 딱 알맞는만큼 메모리에 공간이 할당된다. [예약]
보라 : 참조변수 저장 / 연두 : 값 저장
이런것들을 예약석이라고한다.
이 경우 new연산자로 갑자기 필요한 입석인 Heap 에 객체가 마련된다.[예약X]
그리고 exam() 괄호 때문에 heap에 0으로 값이 초기화된다.
이후 = 때문에 heap에 마련된 객체에 0으로 초기화된 곳에 exam이라는 참조변수가 가르킨다.
3)
input()함수 실행을 위해서는 공간이 마련되어야한다
이 경우에 Stack에 마련된다.
메인함수에 필요한 공간을 잠깐 홀드하고, 메인함수 위에 적재한다.
exam, test, kor를 적재한다.
이 경우 exam이 참조하고있는것이 누구인지 가르킨다. [heap 은 참조가 2개]
순서대로 함수가 실행되고 반환 시 함수가 실행했던 지역변수 등은 돌려주어야한다.
더이상 필요가 없어서 stack영역에서 사라진다.
함수호출되면 main 위에 쌓였다가 없어지는 방식이다.
4)
엄밀히 말하면 Stack과 heap이 뚫려있다. 구분되어있는것이아님
누가 더 크냐 보다는 위아래에서 각자 쌓아가는것이다.
가운데서 만나면 메모리공간이 부족한 것이고 프로그램을 실행할수 없게되는 것이다.
5)
main함수도 끝이 되면 return 되는것이고 stack에 메인함수도 사라지는 것이다.
이는 프로그램이 load되고 하는등에서 메모리 사용하는 것을 볼수있다.
stack이 사라져도 Heap에 여전히 있다.(참조되지않은 객체) 이를 메모리 누수라고한다.
2. 재귀함수
함수가 따로 있는게 아니라 반복을 위한 반복이 있다.
(1) 수열의 n번째까지 합을 구하는 함수를 작성하시오
sum() 함수가 sum()함수 계속 호출하면 스택에 계속 쌓인다.(재귀함수)
자기가 자기를 두번이상 호출하는 방식은 스택에 부담, CPU에 부담이 된다.
이후 수업 구조체, 캡슐화 할 예정
1. 보충
(1) 함수호출할 때 스택화 힙에 대한 관계이해
별도로 강의를 3번정도 보니 이해가 되었다.
큰 틀은 stack에는 예약 후 main함수를 중심으로 다른함수가 이용되는지에 따라 stack의 크기가 달라지고
heap에는 main함수 외 new등으로 새로 마련된 객체는 예약되지않은 것으로서 이 크기에 따라 heap의 크기가 달라진다
다만 이 경우 stack에 있는 참조형변수는 heap에 있는 객체를 가르키게 되는방식을 이용하기도한다.
(2) 원시형(기본형) 변수 참조형변수의 차이
변수는 두가지가 있다.
기본형과 참조형이있다. 기본형은 '값'그 자체를 저장하는 변수이고, 참조형은 객체의 이름(주소)를 저장하는 변수이다.
이 경우 새로운 클래스를 선언하는 것은 참조형을 추가하는것과 동일하다고 볼수 있다.
클래스에 대한 객체를 선언하는 것은 참조형변수가 추가되는 것이기 때문이다.
함수에서의 경우 기본형변수는 값 그자체가 가는것으로서 '공유'가 될수없다.
그러나 참조형변수는 참조변수 즉 가르키는것이 가는것으로서 '공유'가 가능하다.
2. 회고
(1) 구조적 프로그래밍에 대한 flow 이해를 하게되었다
앞서 언급한 함수의 필요성에 대한 흐름을 읊으면
프로그래밍이란 절차를 작성하는 것인데, 이 경우 절차가 복잡해 지거나 중첩될 수있다.
이러한 복잡성을 줄이기 위해서 절차 끊어내는 역할로서 함수가 대두하게 된다.
이 경우 절차를 끊는 기준은 4가지 기준(나재차집)을 생각하면 가능하다.
(2) 함수이용의 이점 4가지가 있다 : 나재차집
코드를 나눌수있고, 재사용이 가능하고, 다른영향으로 부터 차단이 가능하고(인터페이스), 코드를 집중화가 가능하다
(3) 함수를 이용시 전역변수 이용을지양해야함
지양해야하는 이유는 함수의 이점이 코드의 직접사용에 차단이 용이하다인데,
전역변수를 이용하면 다른코드에 영향을 미칠수 있기 때문에 바람직하다고 보기는 어렵다
(결합력은 상승, 고립화는 하락)
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 15번째- 221219 [12-3-월] (1) | 2022.12.19 |
---|---|
TIL : 14번째- 221216 [12-2-금] (2) | 2022.12.16 |
TIL : 12번째- 221214 [12-2-수] (0) | 2022.12.14 |
TIL : 11번째- 221213 [12-2-화] (0) | 2022.12.13 |
TIL : 10번째- 221212 [12-2-월] (1) | 2022.12.12 |