내 입사 동기들은 항상 kotlin 스러운
에 집착한다.
kotlin을 사용한지 4개월정도 된 지금 시점에서, kotlin 스럽다
에 대해 적어보고자 한다.
JAVA vs Kotlin 을 통해 두 언어의 차이점을 들어보자.
이런 간단한 학사 정보 시스템이 있다고 하자. (실제로 학사 관리 시스템은 무척 복잡하다.)
학생들의 정보는 students : List<Student>
로 저장된다.
방방대학교는 평균 점수가 가장 높은 학생에게 장학금을 지급하고자 한다.
학생 정보 :
김철수 (C언어: 100점, 컴퓨터구조: 80점)
김영희 (C언어: 80점, 자료구조: 80점)
김민수 (C언어: 80점, 대학글쓰기: 90점, 이산수학: 90점)
Student maxStudent = null;
for (Student student : students) {
if (maxStudent == null) {
maxStudent = student;
} else if (maxStudent.getScoreAvg() < student.getScoreAvg()) {
maxStudent = student;
}
}
또는
Student maxStudent = Collections.max(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getScoreAvg().compareTo(o2.getScoreAvg());
}
});
val maxStudent = students.maxByOrNull { it.scoreAvg }
(Java 코드가 약간은 억지스럽긴 하지만) Java코드에 비해 Kotlin에서는 1줄만에 해결된다.
두 코드 모두 김철수의 Student객체가 반환된다.
민수가 대학글쓰기의 점수가 마음에 안들었던 모양인지, 이의제기를 신청했다.
(다행히도) 채점에 문제가 있던걸 발견한 교수님은, 민수의 대학글쓰기 성적을 100점으로 올려주었다. (잘못 채점했군요. 민수 학생의 점수는 70점입니다.)
학생 정보 :
김철수 (C언어: 100점, 컴퓨터구조: 80점)
김영희 (C언어: 80점, 자료구조: 80점)
김민수 (C언어: 80점, 대학글쓰기: 100점, 이산수학: 90점)
이제 철수와 민수의 평균은 90점으로 동일하다.
철수와 민수 중 누구에게 장학금을 지급할지 고민하던 학교는, 이수한 과목 수가 더 많은 학생에게 장학금을 지급하고자 한다.
Student maxStudent = null;
for (Student student : students) {
if (maxStudent == null) {
maxStudent = student;
} else if (maxStudent.getScoreAvg() < student.getScoreAvg()) {
maxStudent = student;
} else if (maxStudent.getScoreAvg().equals(student.getScoreAvg())) {
if (maxStudent.subjects.size() < student.subjects.size()) {
maxStudent = student;
}
}
}
또는
Student maxStudent = Collections.max(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if (o1.getScoreAvg().equals(o2.getScoreAvg())) {
return o1.subjects.size() - o2.subjects.size();
} else {
return o1.getScoreAvg().compareTo(o2.getScoreAvg());
}
}
});
val maxStudent = students.sortedWith(compareByDescending<Student> { it.scoreAvg }.thenByDescending { it.subjects.size })
.firstOrNull()
kotlin도 아까보단 지저분해진 감이 있지만,, java코드에 비해서는 덜 지저분해졌다.
위 예시는 정말 빙산의 일각이고, Java/C# -> Kotlin 으로 넘어온 경험자로써, Kotlin은 (잘만 쓰면) 정말 없는거 빼고 다있는
간단한 언어라고 생각한다.
내가 생각하는 kotlin 스럽다의 정의는 아래와 같다.
함수형 프로그래밍 언어에 대한 이해와, kotlin에서 지원하는 기능/메소드를 적절하게 사용하는 것
프로그램의 상태와 상태 변경을 시키는 '구문'의 관점에서 연산을 설명하는 방식
그래서, 너가 하고싶은걸 '어떻게' 해결할건데!
어떤 방식(How)가 아닌 무엇(What)과 같은지를 설명하는 방식
그래서, 너가 '무엇'을 할건데!
// 일반 함수
var num: Int = 0
fun add(param: Int) {
return num + param
} // add()를 수행하면 num의 값이 변경되므로 순수함수가 아니다.
// 순수 함수
fun add(param1: Int, param2: Int){
return param1 + param2
} // 인자만 받아서 값을 반환하므로, side-effect가 없는 순수함수이다.
위 기준은 내 기준이라 절대적이지는 않을 수 있다.
이미 구현된 메소드로 '무엇을 할 지'만 명시하면 되기 때문에, 로직을 별도로 짤 필요가 없다.
또한, 로직을 별도로 짜지 않아도 되기 때문에 (적어도 비즈니스 로직 단은) 코드가 가벼우며,
코드가 곧 주석이 되는 느낌이 있어 가독성이 높아진다. (실제로 우리 실무 코드에는 주석이 거의 없다.)
물론 순수 함수를 짜는 것은 힘든 일이다. 분명 나는 제일 작은 단위로 쪼개서 순수함수를 만들었다고 생각하지만, 그 순수함수를 더 쪼갤 수도 있는 상황이며, 어디까지 쪼개야 할지도 큰 고민이다.
하지만, 코틀린은 확장 함수 (Extension Function)을 지원하기 때문에, 이러한 부분이 어느정도는 해소될 수 있다고 생각한다.
코틀린 서적을 정독하는 것은 아주 큰 도움이 될 것 같다.
코틀린스럽게 짜고 싶지만, 어떤 기능이 있는지 잘 모르는 것이 '코틀린 스럽게 짜는 것'의 가장 큰 장벽이라고 생각한다.
보통은 내가 원하는 기능을 검색하면 나오기는 하지만, 가끔은 '이런거는 없겠지' 생각하며 자바처럼 구현하곤 한다. (forEach 돌리면서..)
근데 (놀랍게도) 알고보면 kotlin에 기본적으로 있는 메소드이다 ㅋㅋ.
그래서 나는 앞으로 Kotlin In Action
책을 정독하면서 블로그에 내용을 정리해볼까 한다.
여담이지만, 하도 Kotlin에 익숙해지다보니 이전에 쓰던 Java와 C#이 어색해졌다. 더 어색해지지 않게 계속 사용하겠지만, Kotlin 스러우면
그만큼 사용하기 편리하다.
Reference :
함수형 언어 : https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D
명령형 프로그래밍과 선언형 프로그래밍 :
https://okayoon.tistory.com/entry/프로그래밍-패러다임명령형-프로그램절자적-객채지향-선언형-프로그램함수형의-정의-특징-비교를-간단히-알아가자
함수형 프로그래밍이란? : https://jongminfire.dev/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EB%9E%80
함수형 프로그래밍 :
https://velog.io/@thms200/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D