개발을 하다보면 여러가지 아키텍쳐와 라이브러리를들 보고 써보게 된다.
그 중 자주 등장하는 용어들이 있는데, 항상 사용법만 알고 싶어 검색하는 경우가 많아 이 용어들의 뜻은 지나치는 경우가 많다.
이번에는 제목의 용어들이 정확이 무엇을 뜻하는지 알아보는 시간을 가져보려 한다╰(°▽°)╯
얘랑 유지 보수는 한자어라 느낌은 왔었다.
프로그래밍에 있어 재사용이라는 뜻은 한 모듈을 여러가지 코드?에 얼마나 자주 사용할 수 있는지를 뜻한다.
이에 대해 대표적인 것들을 보자면
등 다양하다. 이들은 모두 다양한 코드 속이나 프로젝트에 녹여들어 자신의 기능을 뽐내는 데 쓰인다. 메서드로 예를 들자면
public class mClass() {
public void print(String str) {
String msg = "내가 하고 싶은 말은: " + str
println(str)
}
public void sayMyName() {
print("나는 원빈")
}
public void sayYourName() {
print("닌 오징어")
}
}
위 코드의 print메서드는 파라미터로 들어온 값을 다른 형태로 변환시켜 콘솔창에 출력하는 기능이다. 그리고 sayMyName과 sayYourName이라는 메서드에서 사용되고 있는데, 이렇게 여러군데에서 사용할 수 있는 것이 재사용성이다.
흔히 MVVM의 ViewModel과 View의 관계는 1:N이라고 하는데 이는 하나의 ViewModel이 여러 View에서 사용할 수 있단 뜻이고,
위 코드는 하나의 print메서드가가 여러 say~Name메서드에서 사용할 수 있는 경우다.
재사용성을 높인 코드는 불필요한 중복코드가 없어져 라인수가 줄어들어 가독성이 증가하고, 한 기능을 맡는 모듈이 버그가 있거나 개선을 해야하는 상황이 있고 이 모듈이 여러기능(재사용)에서 쓰이고 있다면, 이 모듈만 수정하면 되니 유지보수도 편한 장점이 있다.
어 유지 보수?
얘는 지금보니 졸라 이해하기 쉬워보인다. 하지만 초창기 나는 이것마저 왜 자꾸 용어를 갖다 쓰는지 몰랐다ㅋ.
유지 보수의 뜻도 코드로 함 보겠다. 이번 코드는 kotlin으로 하는데 이유는 java까먹음..
class tomato {
fun myProfile() {
print("현재 나는 26살입니다.")
}
fun yourProfile() {
print("현재 너는 62살입니다.")
}
}
이런 클래스가 있다고 해보자. 어느 날, 개발팀에서 회의가 나오고 tomato 클래스의 프린트 문구를 "현재"에서 "조만간"으로 바꾸라는 내용이 나온다. 뭐 위 코드는 2개의 메서드에서 1번씩만 바꾸면 되지만 만약
class tomato {
fun myProfile() {
print("현재 나는 26살입니다.")
}
fun myProfile() {
print("현재 나는 졸립니다.")
}
fun yourProfile() {
print("현재 너는 62살입니다.")
}
fun yourProfile() {
print("현재 너는 자고있습니다.")
}
...
}
이렇게 수십개의 메서드가 있다고 하면 욕이 자연스레 나올 것 이다. 이는 중복된 사항을 변수로 빼놓지 않아서 발생하는 문제고, 이런 것이 유지보수가 안 좋다는 의미이다. 바꿔보자
class tomato {
private val prefix: String = "현재"
fun myProfile() {
print("$prefix 나는 26살입니다.")
}
fun myProfile() {
print("$prefix 나는 졸립니다.")
}
fun yourProfile() {
print("$prefix 너는 62살입니다.")
}
fun yourProfile() {
print("$prefix 너는 자고있습니다.")
}
...
}
위는 전역변수 prefix만 "현재"에서 "조만간"으로 바꾸면 회의 내용이 바로 적용된다. 이래서 중복 코드는 바로바로 변수나 메서드 처리를 해줘야한다.
이 외에도 유지 보수라는 용어는 다양한 의미를 포함한다.
유지: 코드를 추후 다른 개발자에게 인수인계
보수: 코드를 수정
정도로 보면 대충 어떤 느낌으로 코드를 짜야할 지 알 듯하다.
얘는 확실히 몰랐다. 느낌도 안 왔었다. 지금도 자주 출장가신다.
코드에서 두 모듈 간의 연결 또는 관계라고 할 수 있다. 둘 중 하나가 다른 하나를 어떤 용도를 위해 사용하는 경우인데 코드로 보자
class A() {
val classB = B()
classB.print()
}
class B() {
fun foo() {
print("가나다라마바사")
}
}
위 코드는 class A가 class B에게 의존성이 생긴 경우이다. 말 그대로 의존하다는 건데, A는 B가 없으면 기능을 수행할 수 없고 B 클래스가 삭제되면 컴파일 에러까지 발생하게 된다. 또한 B 클래스의 내용이 바뀌면 의존한 A 클래스까지 변경이 이루어진다.
사실 개발 초보단계에서 이런게 뭐가 문제고 저렇게 의존성 발생을 제한한다면 다른 클래스를 써올 방법이 없다. 문제가 생기는 경우는 유닛 테스트를 할 때인데, 유닛 테스트란 하나의 모듈을 테스트 모듈로 교체한다음 실행시키는 테스트 법이다.
만약 B 클래스에 대해 테스트를 진행한다면 의존성이 있는 A 클래스는 B()라는 부분을 고쳐야한다. 물론 이도 코드가 적어서 별거 아닌것 처럼 보이지만 프로젝트가 커지면 당연히 의존성이 걸려있는 경우가 늘어나게 된다.
이러한 의존성을 제거하려는 노력으로 MVC, MVP, MVVM과 같은 디자인 패턴들이 만들어지게 된다.
MVVM 포스팅에서도 말했듯이 ViewModel은 View에 대한 어떠한 참조값도 없어 의존성이 하나도 없다. 이러한 경우 유닛 테스트를 진행하게되면 ViewModel을 통째로 들어 교체할 수 있기에 장점이 생긴다. ViewModel에서 context를 참조하지 말라는 경우도 물론 메모리 관련 문제도 있지만 테스트할 때 지옥이라 한다. 아 난 아직 유닛 테스트를 해본적이 음슴.
이 외에도 의존성을 없애는 방법중 의존성 주입이라는 기법이 있다. Android에선 대표적으로 Koin이나 Hilt를 사용하는데 해본적이 음슴.
의존성 또한 유지 보수와 관련된 내용이다. 개발자들은 결국 얼마나 프로젝트의 유지 보수성을 극대화 시킬 수 있는지 역사를 보면 답을 알 수 있는듯 하다.~