728x90
def solution(num_list):
    answer = [0,0]
    for n in num_list:
        answer[n%2]+=1
    return answer
728x90
728x90
def solution(array, n):
    answer = array.count(n)
    return answer
728x90
728x90
def solution(slice, n):
    return ((n - 1) // slice) + 1
728x90
728x90

 

def solution(my_str, n):
    return [my_str[i : i+n] for i in range(0, len(my_str),n)]
728x90
728x90
def solution(M, N):
    return (M * N) - 1
728x90
728x90

개인적으로 어려웠던 스프링의 원리과 사용기술을 학습하기 위하여 작성한 글입니다~! 김영한 강사님 최고..!!

🔥 개요
- 스프링이란?
스프링 프레임워크는 자바 진영의 웹 프레임워크이다. EJB라는 겨울을 넘어 새로운 시작이라는 뜻으로 시작된 스프링은 현재는 다양한 생태계를 구축하고 있다.
- 개발자로 활동하며 스프링을 사용하는 입장에서 스프링이 제공하고 있는 다양한 기능을 당연하게 사용해왔지만, 정작 스프링을 왜 사용하는지? 사용되는 기술이 무엇인지? 핵심원리를 파악하지 못하고 스프링을 사용해왔다.
- 그래서 스프링 프레임워크는 왜 만들어졌는지, 핵심개념은 무엇인지 알아보고 그 내용을 정리하기 위하여 이 글을 작성한다.

=> 스프링은 자바 언어 기반의 프레임워크이고, 자바는 객체 지향 언어이다.

그렇다면 좋은 객체 지향 프로그래밍이란 무엇일까?

  • 객체 지향 프로그래밍(OOP)

- 객체 지향 프로그래밍(Object Oriented
Programming)은 컴퓨터 프로그래밍의 패러다임 중 하나이다.
- OOP 는 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위인 객체들의 모임으로 파악하고자 하는 것이다.
- 각각의 객체는 메시지를 주고받고 데이터를 처리할 수 있다.
- 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.

유연하고 변경이 용이하다?

- 그렇다면, 유연하고 변경이 용이하다는 표현은 어떤 뜻일까? 내가 좋아하는 레고는 매우 유연하고 변경이 용이하다. 블럭(객체)을 조립하여 하나의 레고 완성품을 만드는 것처럼, 프로그래밍에서는 컴포넌트를 유연하게 변경하면서 개발하는 것을 의미한다고 생각한다.

핵심개념은 무엇일까?

- 객체 지향 프로그래밍은 추상화, 상속, 다형성 등이 있으며 추가적으로 다중 상속 등의 특징이 존재한다.
- 그 중 OOP 의 핵심 개념인 다형성(Polymorphism) 에 대하여 알아보겠다.
- 유연하고 변경이 용이한 좋은 객체 지향 프로그래밍을 하기 위해서는 다형성이 매우 중요하다. 왜 다형성이 중요할까?

역할과 구현

다형성을 쉽게 이해하기 위해 실세계에 비유하여 생각해보자.

- 자동차에 비유하여 생각해보자. 자동차의 종류는 매우 다양하다. 하지만 운전자는 자동차 사용방법에 대하여 알고 있다면 자동차를 운행하는데 아무런 지장이 없다.
- 자동차(역할)를 생산(구현)한 것이라 생각하면 편하다. 생산(구현)된 자동차는 매우 다양하지만, 그것이 자동차(역할)라는 것은 변함이 없다.
역할과 구현을 분리하면 세상이 단순해지고, 유연해지며 변경이 용이해진다.
- 따라서 우리(클라이언트)는 역할(인터페이스)만 알고있으면 구현의 구체적인 내용은 몰라도 상관없다. 역할만 알고있다면 우리는 구현내용이 변경되더라도 클라이언트에게 영향을 미치지 않는다. 마치 자동차의 엔진, 변속기, 제어 등등의 구체적인 자동차 내부구조 내용을 모르더라도 클라이언트는 인터페이스만 알고있다면 자동차를 운전하는데 큰 문제는 없을 것이다.

역할 - 인터페이스
구현 - 구현클래스

객체를 설계할 때 역할과 구현을 분리하는 것이 매우 중요하다. 수 많은 객체 클라이언트와 객체 서버는 서로 협력관계를 가진다.
클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

728x90
728x90

https://school.programmers.co.kr/learn/courses/30/lessons/120923

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

<나의 답>

def solution(num, total):
    average = total // num
    return [i for i in range(average - (num-1)//2, average + (num + 2)//2)]
  • 연속된 수이기 때문에 평균을 기준으로 좌측, 우측 끝 값만 구하면 된다
  • 좌, 우측 숫자의 개수는 num이 짝수이냐 홀수이냐에 따라 다르기 때문에 왼쪽 끝 값을 구하기 위해서는 num - 1로 하고 우측은 num + 2를 하면 짝수, 홀수를 구분하지 않고 연속적인 리스트를 구할 수 있다

 

<다른 사람 풀이>

def solution(num, total):
    return [(total - (num * (num - 1) // 2)) // num + i for i in range(num)]

이거 진짜 간단하게 풀었음...

728x90
728x90

SOLID 클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리

 

• SRP: 단일 책임 원칙(single responsibility principle)

• OCP: 개방-폐쇄 원칙 (Open/closed principle)

• LSP: 리스코프 치환 원칙 (Liskov substitution principle)

• ISP: 인터페이스 분리 원칙 (Interface segregation principle)

• DIP: 의존관계 역전 원칙 (Dependency inversion principle)

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

1. SRP 단일 책임 원칙

• 한 클래스는 하나의 책임만 가져야 한다.

• 하나의 책임이라는 것은 모호하다.

• 클 수 있고, 작을 수 있다.

• 문맥과 상황에 따라 다르다.

• 중요한 기준은 변경이다. 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것

• 예) UI 변경, 객체의 생성과 사용을 분리

 

=> 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것. SRP원리를 적용하면 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있습니다.

 

2. OCP 개방-폐쇄 원칙 Open/closed principle

• 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

• 이런 거짓말 같은 말이? 확장을 하려면, 당연히 기존 코드를 변경?

• 다형성을 활용해보자

• 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현

• 지금까지 배운 역할과 구현의 분리를 생각해보자

 

OCP 개방-폐쇄 원칙 문제점

• MemberService 클라이언트가 구현 클래스를 직접 선택

• MemberRepository m = new MemoryMemberRepository(); //기존 코드

• MemberRepository m = new JdbcMemberRepository(); //변경 코드

• 구현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.

• 분명 다형성을 사용했지만 OCP 원칙을 지킬 수 없다.

• 이 문제를 어떻게 해결해야 하나?

• 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다.

 

=> 새로운 변경사항이 발생했을 때 객체를 직접 수정하지 않고도 변경사항을 적용할 수 있도록 설계해야함을 말합니다. DI, IoC가 필요합니다.

 

3. LSP 리스코프 치환 원칙 Liskov substitution principle

• 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다

• 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위 한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다.

• 단순히 컴파일에 성공하는 것을 넘어서는 이야기

• 예) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능, 뒤로 가게 구현하면 LSP 위반, 느리 더라도 앞으로 가야함

 

=> 클라이언트는 인터페이스 구현객체의 내부를 모르기 때문에 믿고 쓰기 위해선 인터페이스를 구현한 객체가 인터페이스의 사용 의도에 맞게 구현해야 된다는 것을 의미합니다.

 

4. ISP 인터페이스 분리 원칙 Interface segregation principle

• 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다

• 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리

• 사용자 클라이언트 -> 운전자 클라이언트, 정비사 클라이언트로 분리

• 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않음

• 인터페이스가 명확해지고, 대체 가능성이 높아진다.

 

=> 특정 클래스에서 다 쓰지 않는 다양한 추상메서드가 들어간 커다란 인터페이스 보 다는 인터페이스를 특정 클라이언트에 맞게 구체적이게 쪼개는 것을 의미합니다.

 

5. DIP 의존관계 역전 원칙 Dependency inversion principle

• 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙 을 따르는 방법 중 하나다.

• 쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻

• 앞에서 이야기한 역할(Role)에 의존하게 해야 한다는 것과 같다. 객체 세상도 클라이언트 가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다! 구현체에 의존하게 되면 변 경이 아주 어려워진다.

 

DIP 의존관계 역전 원칙 Dependency inversion principle

• 그런데 OCP에서 설명한 MemberService는 인터페이스에 의존하지만, 구현 클래스도 동시에 의존한다.

• MemberService 클라이언트가 구현 클래스를 직접 선택

• MemberRepository m = new MemoryMemberRepository();

• DIP 위반

 

=> 클라이언트가 구현객체에 의존하는 것이 아닌 클라이언트와 구현객체 사이에 인터페이스를 두고 클라이언트와 구현객체가 인터페이스에 의존하여 구현객체를 변경해도 클라이언트에 변경이 없음을 의미합니다.

 

정리

• 객체 지향의 핵심은 다형성

• 다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.

• 다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경된다.

• 다형성 만으로는 OCP, DIP를 지킬 수 없다.

• 뭔가 더 필요하다

 

 

 

출처 : 인프런 김영한 

728x90

'Spring' 카테고리의 다른 글

[Spring] Thymeleaf 와 jsp 비교  (0) 2023.02.05
[Servlet & JSP] Redirect vs forward 방식 비교  (0) 2023.02.03
[JAVA] JDBC란?  (0) 2023.01.29
Spring과 SpringBoot 의 정의와 사용 이유  (0) 2023.01.29
스프링이란?  (1) 2023.01.05

+ Recent posts