본문 바로가기

전체 글86

객체 지향 설계 - SOLID 원칙 SOLID란 로버트 마틴이 2000년대 초반 명명한 객체 지향 프로그래밍 및 설계의 다섯가지 기본 원칙을 마이클 페더스가 약어를 따서 다시 소개한 것이다. SOLID 원칙은 개발 과정에서 소스코드의 가독성을 높이고 확장하기 쉽게 하기 위해 끊임없이 리팩토링할 수 있는 지침이다. 이하 다른 포스팅에 각 원칙에 대해 정리 SRP(Single Responsibility Principle) 단일 책임 원칙: 한 클래스는 하나의 책임만 가져야 한다. https://deep-dive-dev.tistory.com/87 [클린 소프트웨어] PART 2 - CHAPTER 9 - 개방 폐쇄 원칙(OCP) 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. OCP.. 2022. 2. 15.
[클린 소프트웨어] PART 2 - CHAPTER 12 - 인터페이스 분리 원칙(ISP) ISP; Interface-Segregation Principle 인터페이스 분리 원칙은 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다. 가장 간단한 예시를 들자면, abstract class Door { abstract fun lock() abstract fun unlock() } class TimerDoor() : Door() { override fun lock() { // do something } override fun unlock() { // do something } } 여기서 TimerDoor 객체에 특정 시간이 지나면 자동으로 문이 닫히는 기능을 넣는다고 가정했을 때 Door 추상 클래스에 아래와 같이 timeout 메서드를 넣으면 안됨 👉 그러면 Door를 상.. 2022. 2. 15.
[클린 소프트웨어] PART 2 - CHAPTER 10 - 리스코프 치환 원칙(LSP) 서브타입(subtype)은 그것의 기반 타입(base type)으로 치환 가능해야 한다. LSP; Liskov Substitution Principle 1988년 바버라 리스코프(Barbara Liskov)가 처음으로 작성해서 리스포크 치환 원칙이라고 불린다. 그녀는 다음과 같이 말했다. 타입 S의 각 객체 o1과 타입 T의 각 객체 o2가 있을 때, T로 프로그램 P를 정의했음에도 불구하고 o1이 o2로 치환될 때 P의 행위가 변하지 않으면, S는 P의 서브타입니다. 이 원칙은 반대로 위반한 결과를 생각하면 더 쉽다. 어떤 함수 f가 인자로 클래스 B를 참조하고 있따고 생각해보자. B의 파생 클래스 D가 B를 가장해 f에 넘겨졌을 때 f가 의도한대로 동작하지 않는다면 D는 f에 대해 취약하며 LSP를 .. 2022. 2. 8.
[클린 소프트웨어] PART 2 - CHAPTER 9 - 개방 폐쇄 원칙(OCP) 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. OCP; Open-Closed Principle OCP를 따르는 모듈은 다음과 같은 두 가지 속성을 갖는다. Open: 확장에 대해 열려있다. 요구사항이 변경될 때, 이 변경에 맞개 새로운 행위를 추가해 모듈을 확장할 수 있다. Close: 수정에 대해 닫혀있다. 모듈의 행위를 확장하는 것이 그 모듈의 소스코드 변경을 초래하지 않는다. 하나의 변경이 의존적인 모듈에서 단계적인 변경을 초래할 때 경직성의 악취를 풍긴다. OCP에서는 이후 일어날 변경이 더 시앙의 수정을 유발하지 않도록 하라고 충고한다. 이미 제대로 동작하고 있던 원래 코드를 변경하는 것이 아닌 새로운 코드를 덧붙임으로써 요구사항.. 2022. 2. 7.
[kotlin/mockk] mockStatic 해제하기 - clearStaticMockk internal class MockkStaticTest { @Test fun `현재 시간 mock 테스트`() { mockkStatic(LocalDateTime::class) every { LocalDateTime.now() } returns LocalDateTime.of(LocalDate.of(1993, 1, 10), LocalTime.of(11, 57)) LocalDateTime.now().let { it.year shouldBe 1993 it.month shouldBe Month.JANUARY it.dayOfMonth shouldBe 10 } } @AfterEach fun clearStaticMockkLocalDateTime() { clearStaticMockk(LocalDateTime::class.. 2022. 1. 26.
[클린 소프트웨어] PART 2 - CHAPTER 8 - 단일 책임 원칙(SRP) 한 클래스는 단 한 가지의 변경 이유만을 가져야 한다. SRP; Single-Responsibility Priciple 여기서 '책임(Responsibility)'이란 '변경을 위한 이유'로 정의된다. 만약 한 클래스를 변경하기 위한 한 가지 이상의 이유를 생각할 수 있다면, 그 클래스는 한 가지 이상의 책임을 맡고 있는 것이다. 만약 한 클래스가 하나 이상의 책임을 맡는다면, 그 책임들은 결합(= cohesion이 생김)된다. 한 책임에 대한 변경은 다른 책임을 충족시키는 클래스의 능력을 떨어뜨리거나 저하시킬 수 있다. 이러한 종류의 결합은 변경을 했을 때 예상치 못한 방식으로 잘못 동작하는 취약한 설계를 유발한다. 한편, 애플리케이션이 서로 다른 시간에 두 가지 책임의 변경을 유발하는 방식으로 바뀌지.. 2022. 1. 21.
[클린 소프트웨어] PART 2 - CHAPTER 7 - 애자일 설계란 무엇인가? 애자일 팀에서는 나중의 요구사항과 필요에 대해서는 그리 오래 생각하지 않는다. 그보다는, 현재 구조에 초점을 두고 더욱 개선하기 위해 노력한다. 잘못된 설계의 증상 Rigidity(경직성): 설계를 변경하기 어려움 - 변경을 하기 위해 시스템의 다른 부분들까지 많이 변경해야 하기 때문이다. Fragility(취약성): 설계가 망가지기 쉬움 - 변경을 하면 시스템에서 그 부분과 개념적으로 아무런 관련이 없는 부분이 망가진다. Immobility(부동성): 설계를 재사용하기 어려움 Viscosity(점착성): 제대로 동작하기 어려움 Needless Complexity(불필요한 복잡성): 과도한 설계 - 직접적인 효용이 전혀 없는 기반구조가 설계에 포함되어 있다. Needless Repetition(불필요한 .. 2022. 1. 18.
[클린 소프트웨어] PART 1 - CHAPTER 5 - 리팩토링 모든 소프트웨어 모듈에는 세 가지 기능이 있다. 실행 중에 동작하는 기능: 모듈의 존재 이유이다. 변경 기능: 대부분의 모듈이 생명주기 동안 변경 과정을 겪게 되고, 가능한 한 간단하게 그런 변경을 할 수 있도록 만드는 것이 개발자의 책임이다. 변경하기 어려운 모듈은 그것이 제대로 동작한다 하더라도 망가진 것이며 수리가 필요하다. 그것을 읽는 사람과 의사소통하는 기능: 개발자가 쉽게 읽고 이해할 수 있어야 한다. 모듈을 읽기 쉽고 변경하기 쉽게 만들기 위해서는 단순히 원칙과 패턴 이상의 그 무엇이 필요한데, 바로 주의력과 훈련이다. 주의력은 어떤 그냥 동작하게 만드는 것과 올바르게 동작하게 만드는 것의 차이이고, 프로그래머가 코드의 구조에 부여하는 가치와도 같다. 리팩토링? 외부 행위를 바꾸지 않으면서 .. 2022. 1. 14.
[kotlin/mockk] mockk로 LocalDatetime.now() mock 테스트 @Test fun test() { val testLocalDateTime = LocalDateTime.of(1993,1,10,11,57) mockkStatic(LocalDateTime::class) every { LocalDateTime.now() } returns testLocalDateTime LocalDateTime.now() shouldBe testLocalDateTime }mockkStatic : makes a static mock out of a class, or clears it if it was already transformed 출처 mockk.io 2022. 1. 12.
[Java] 프로그래머스 > 코딩테스트 연습 > 해시 > 전화번호 목록 문제 설명 전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다. 전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다. 구조대 : 119 박준영 : 97 674 223 지영석 : 11 9552 4421 전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요. 제한 사항 phone_book의 길이는 1 이상 1,000,000 이하입니다. 각 전화번호의 길이는 1 이상 20 이하입니다. 입출력 예제 phone_book return ["119", ".. 2021. 4. 1.
[Kotlin] 프로그래머스 > 코딩테스트 연습 > 힙(Heap) > 디스크 컨트롤러 문제 설명 하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 요청이 들어온 순서대로 처리하는 것입니다. 예를들어 - 0ms 시점에 3ms가 소요되는 A작업 요청 - 1ms 시점에 9ms가 소요되는 B작업 요청 - 2ms 시점에 6ms가 소요되는 C작업 요청 와 같은 요청이 들어왔습니다. 이를 그림으로 표현하면 아래와 같습니다. 한 번에 하나의 요청만을 수행할 수 있기 때문에 각각의 작업을 요청받은 순서대로 처리하면 다음과 같이 처리 됩니다. - A: 3ms 시점에 작업 완료 (요청에서 종료까지 : 3ms) - B: 1ms부터 대기하다가, 3ms 시점에 작업을 시작해서 12ms 시점에 작업 완료(요청에서 종료까지 : 11.. 2021. 4. 1.
[Kotlin] 프로그래머스 > 코딩테스트 연습 > 스택/큐 > 프린터 문제 설명 일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린터를 개발했습니다. 이 새롭게 개발한 프린터는 아래와 같은 방식으로 인쇄 작업을 수행합니다. 1. 인쇄 대기목록의 가장 앞에 있는 문서(J)를 대기목록에서 꺼냅니다. 2. 나머지 인쇄 대기목록에서 J보다 중요도가 높은 문서가 한 개라도 존재하면 J를 대기목록의 가장 마지막에 넣습니다. 3. 그렇지 않으면 J를 인쇄합니다. 예를 들어, 4개의 문서(A, B, C, D)가 순서대로 인쇄 대기목록에 있고 중요도가 2 1 3 2 라면 C D A B 순으로 인쇄하게 됩니다. 내가 인쇄를 요청한 문서가 몇 번째로 인쇄되는지 .. 2021. 4. 1.
[Kotlin] 프로그래머스 > 코딩테스트 연습 > 완전탐색 > 소수 찾기 문제 설명 한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요. 제한사항 numbers는 길이 1 이상 7 이하인 문자열입니다. numbers는 0~9까지 숫자만으로 이루어져 있습니다. "013"은 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다. 입출력 예 numbers return "17" 3 "011" 2 입출력 예 설명 예제 #1 [1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다. 예제 #2 [0, 1, 1]으로는 소수 [11, .. 2021. 4. 1.
[Kotlin] 프로그래머스 > 코딩테스트 연습 > 스택/큐 > 다리를 지나는 트럭 문제 설명 트럭 여러 대가 강을 가로지르는 일 차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 트럭은 1초에 1만큼 움직이며, 다리 길이는 bridge_length이고 다리는 무게 weight까지 견딥니다. ※ 트럭이 다리에 완전히 오르지 않은 경우, 이 트럭의 무게는 고려하지 않습니다. 예를 들어, 길이가 2이고 10kg 무게를 견디는 다리가 있습니다. 무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다. 경과 시간 다리를 지난 트럭 다리를 건너는 트럭 대기 트럭 0 [] [] [7,4,5,6] 1~2 [] [7] [4,5,6] 3 [7] [4] [5,6] 4 [7] [4,5] [.. 2021. 4. 1.
[Kotlin] 프로그래머스 > 코딩테스트 연습 > 스택/큐 > 기능개발 문제 설명 프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다. 또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다. 먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요. 제한 사항 작업의 개수(progresses, speeds배열의 길이)는 100개 이하입니다. 작업 진도는 100 미만의 자연수입니다. 작업 속도는 100 이하의 자.. 2021. 4. 1.
[Java] 프로그래머스 > 코딩테스트 연습 > 힙(Heap) > 더 맵게 문제 설명 매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다. 섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2) Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다. Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요. 제한 사항 scovil.. 2021. 4. 1.