내가 보려고 정리하는/Spring

웹 : SOLID원칙에 맞춰 5Layered Model2 방식 만들기 : 0314

보동이용용 2023. 3. 14. 09:01
반응형

4Layered Model2 →

🚩오늘은 5Layered

 SOLID 

SRP : 단일 책임의 원칙

OCP : 개방 폐쇄의 원칙 

LSP : 리스코프 치환 : 다형성 

ISP : 인터페이스 분리 원칙

DIP : 의존관계 역전 원칙 (DRP : 중복 제거 원칙)


《 의존성 , 결합력 》

Controller, DAO 결합력이 높다.

> 의존성 역전 원칙으로 Container를 이용해서 (new제거하여) 직접 생성하지 않고 필요한 내용을 Container에 다 등록해두고 꺼내어 사용한다.

 


DAO가 있어야 Service가 사용가능... > 결합력이 높아 협업이 어렵다.

해결 ↓↓↓

모니터에 기댈때 모니터가 어떻게 작용되는지는 상관없다. 모니터가 있기만 하면됨 → 인터페이스

package kr.or.ddit.props.service;

import java.util.List;

import kr.or.ddit.props.vo.PropertyVO;

public interface PropertyService {
	public List<PropertyVO> retrieveProperties();
	public boolean createProperty(PropertyVO newProp);
	public boolean modifyProperty(PropertyVO modifyProp);
	public boolean removeProperty(PropertyVO removeProp);
}

▶ interface : 사용방법           ▶ interface  구현체 : 실제 사용하는 내용 

갤럭시 쓰다가 아이폰으로 바껴도 ios가 어떻게 작동하는지 몰라도 쓰는데 지장없다.

< 캡슐화 >

캡슐화를 통해 협업이 가능하다.

1. 데이터 보호를 위해 감추기 : private

2. 행동의 정보를 감추기 :  사용자가 행동에 대해 종속성을 갖지 않도록 하기위해 : 실행코드의 캡슐화

2번의 방법중 하나  인터페이스 분리원칙 >> 캡슐화, 협업 : 기술면접 기출


<< 요구사항 변경 >>

1.모든 프로퍼티 조회 할때마다 언제 조회한것인지 확인하게 해달라.

2.value를 변경하되 언제 조회된 것인지 

>> 조건 : 중복코드 최소화 /  책임분리

>> 단일 책임을 위해 서비스 객체 필요해 >>PropertyServiceImpl1

package kr.or.ddit.props.service;

import java.util.List;

import kr.or.ddit.props.vo.PropertyVO;

public interface PropertyService {
	public List<PropertyVO> retrieveProperties();
	public boolean createProperty(PropertyVO newProp);
	public boolean modifyProperty(PropertyVO modifyProp);
	public boolean removeProperty(PropertyVO removeProp);
}

interface로 사용 방법만 명시해 놓음 > 존재하는 것을 알았으니, controller가 사용할 수 있음. > 결합도를 낮췄다.

package kr.or.ddit.props.service;

import java.time.LocalDateTime;
import java.util.List;

import kr.or.ddit.props.dao.PropertyDAOImpl;
import kr.or.ddit.props.vo.PropertyVO;

public class PropertyServiceImpl1 implements PropertyService {
	private PropertyDAOImpl dao = new PropertyDAOImpl();
	
	@Override
	public List<PropertyVO> retrieveProperties() {
		List<PropertyVO> propertyList = dao.selectProperties();
		for( PropertyVO prop : propertyList) {
			prop.setPropertyValue(String.format("%s[%s]", prop.getPropertyValue(), LocalDateTime.now()));
		} 
		return propertyList;
	}

	@Override
	public boolean createProperty(PropertyVO newProp) {
		int rowcnt = dao.insertProperty(newProp);
		return rowcnt > 0;
	}

	@Override
	public boolean modifyProperty(PropertyVO modifyProp) {
		return dao.updateProperty(modifyProp) > 0;
	}

	@Override
	public boolean removeProperty(PropertyVO removeProp) {
		return dao.deleteProperty(removeProp) > 0;
	}

}

>> interface를 implements 하고 > DAO객체 생성해서 > 각 메서드 Override하여 재정의.  

@WebServlet("/props")
public class PropertyContollerServlet extends HttpServlet {
	private PropertyService service = new PropertyServiceImpl1();

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		super.service(req, resp);
	}

>> 의존하는 객체를 DAO 에서 serviceImpl1 로 변경함. >> controller가 service를 사용한다. >> controller가 service에 의존한다. >> 결합도


<< 또변경 >>

윈도우 콘솔에 내용을 출력해달라.

=>기능 추가 service책임이 많아짐. 상속받는 자식을 하나 더 만들자.

>>PropertyServiceImpl2 

package kr.or.ddit.props.service;

import java.util.List;

import kr.or.ddit.props.vo.PropertyVO;

public class PropertyServiceImpl2 extends PropertyServiceImpl1 {
	@Override
	public List<PropertyVO> retrieveProperties() {
		List<PropertyVO> list = super.retrieveProperties();
		list.stream()
			.forEach(System.out::println);
		return list;
	}
}

>> 첫 서블릿인 PropertySErviceImpl1을 extends(상속받고)하고 > 부모의 인스턴스를 Override하고 > stream()으로 결과를 만들어낸다. > List로 리턴! 

@WebServlet("/props")
public class PropertyContollerServlet extends HttpServlet {
	private PropertyService service = new PropertyServiceImpl2();

서비스 임플 2번으로 컨트롤러에서 받는 객체를 바꾸어야한다. 의존관계, 결합력

만약에 new를 없앤다면? 결합도를 낮춘 좋은 코드가 될 것이다.

어떻게 없앨까? ==> Framework를 사용한다.

 


람다식에 

조건1. 파라미터 하나일때

조건2. 실행코드 하나일  때

메소드 래퍼런스로 코드를 짧게 쓸 수 있다.

: Java 8에서 도입된 메소드 레퍼런스(Method Reference)는 Lambda 표현식을 더 간단하게 표현하는 방법.

// 기존 람다식
list.stream().forEach( (text) -> System.out.println(text) );

// 메서드 래퍼런스로 표현한 람다식
list.stream().forEach( System.out::println );

https://codechacha.com/ko/java8-method-reference/

 

Java - 메소드 레퍼런스(Method Reference) 이해하기

메소드 레퍼런스(Method Reference)는 Lambda 표현식을 더 간단하게 표현하는 방법입니다. 메소드 레퍼런스는 사용하는 패턴에 따라 다음과 같이 분류할 수 있습니다. Static 메소드 레퍼런스, Instance 메

codechacha.com


 


어제만든 custom.js는 좋지않다. key하나에 value가 여러개인 경우는 담을 수 없다. 불안한 코드..

라이브러리로 대체해보자.

https://plugins.jquery.com/serializeObject/

여기서 github링크로 들어가 dist에서  다운로드 

https://api.jquery.com/ajaxError/#ajaxError-handler

 

.ajaxError() | jQuery API Documentation

Description: Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event. Whenever an Ajax request completes with an error, jQuery triggers the ajaxError event. Any and all handlers that have been registered with the .a

api.jquery.com

도큐먼트 전체에 이벤트를 걸어서 ajaxError를 핸들링 할 수 있다.


const settings를 통해

자바스크립트에서 객체를 똑같은 구조로 재활용하는 방법을 실습해볼 수 있었다.

그러나 success는 const일수 없다. 계속 변함. ==> 변하는 형태로 success를 받아야한다. 

해결해보자!

>> object clone

( 자바 )

: Obejct 클래스에는 clone() 메서드가 정의되어 있습니다. clone 메서드는 네이티브 메서드로 해당하는 객체의 모든 필드를 복사하여 새로운 객체에 넣어 반환하는 동작을 수행합니다.

https://velog.io/@tomato2532/Object.clone-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC-%EB%B3%B5%EC%82%AC-%EC%83%9D%EC%84%B1%EC%9E%90

 

[JAVA] Object.clone(), 얕은 복사, 깊은 복사, 복사 생성자

Obejct 클래스에는 clone() 메서드가 정의되어 있습니다. clone 메서드는 네이티브 메서드로 해당하는 객체의 모든 필드를 복사하여 새로운 객체에 넣어 반환하는 동작을 수행합니다.위 코드가 Object

velog.io

settings를 여러개를 복사해서 사용한다. object clone을 이용한다.동일한 구조의 객체를 복사해서 사용한다.

console에 연습해보자. 얕은 복제, 깊은 복제

1. 먼저, 얕은 복제

obj 객체를 생성하고 obj1로 복사를 해본다. 주소값을 비교해보니 같다. 그러면?

주소가 같다 = 복제가 아니다

스왈로우 얕은복제 => 실패


2. 다음, Object의 assign이용해보기

Object.assign()메서드는 출처 객체들의 모든열거 가능자체 속성을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환합니다.

또다시 주소값 같음. => 복제 실패


3. 깊은 복제, 딥 카피

이번에는 주소값이 다름 => 딥카피 성공


json은 함수가 아니라서 

success를 복사할수는 없다. 그래서settings 객체를 만들어주는 factory패턴 을 만들어준다.

//DOM(Document Object Model)
let settingsFactory = function(){
	return {
		url : $.CPATH + "/props"
			, dataType:"json"
			, success : function(resp, textStatus, jqXHR){
				if(jqXHR.responseJSON){
					if(resp.error){
						Swal.fire({
							  icon: 'error',
							  title: 'Oops...',
							  text: resp.message,
							  footer: '<a href="">Why do I have this issue?</a>'
							})
					}else if(resp.status && resp.location){
						loadBtn.trigger("click");
					}else{
						let trTags=[];
						list = resp.propertyList
						list.forEach(prop => {
							let tr = $("<tr>").append(
                                        $("<td data-bs-toggle='modal' data-bs-target='#exampleModal'>").html(prop.propertyName)
                                        , $("<td>").html(prop.propertyValue)
                                        , $("<td>").html(
                                            $("<button>")
                                                .addClass("deleteBtn")
                                                .text("삭제")		
                                        )
                                    ).data("source", prop);
							trTags.push(tr);
						});
						listBody.html(trTags);
						insertForm[0].reset();
						exampleModal.modal("hide");
					}
				}
			}
		}
}

>> 문제를 해결하기위한 디자인 패턴 중의 하나인 팩토리 패턴

: 클래스의 인스턴스를 서브 클래스에서 결정하도록 책임을 나누는 것. 결합도 낮추기.

https://jusungpark.tistory.com/14

 

디자인패턴 - 팩토리 패턴 (factory pattern)

팩토리 패턴 (factory pattern) 팩토리 메소드 패턴 : 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 만든다. 즉 팩토리 메소드 패턴

jusungpark.tistory.com

이렇게 되면 settings를 다양한 형태로 받아서 사용 가능, 객체이기에 복사도 가능!!


url을 설정하려고 봤더니, 

자바스크립트 파일에서 <%=request.getContextPath()%>못쓴다.

방법 1.상대경로로 바꾼다. 방법 2. 미리 만들어놓고 불러온다.

상대경로는 비교적 쓰기 불편함. ../ ./ 구분이 쉽지 않음 

그래서 미리 만들어놓고 불러와보았다.

일단 전역변수로 필요해서 봤더니, 책임을 분리하기 위해  include해놓은 preScript 에다가 만들어야겠다.

<script>
	$.CPATH = "<%=request.getContextPath() %>";
</script>

그래서 url은

url : $.CPATH + "/props"

이렇게 설정하였다.


🚩오늘의 할일 2

  • BTS 페이지 동기 형식으로 만들기
  •  

 

프라이머리키를 생성할때 시퀀스를 쓰지만 sql에마 있는것 mriadb에는 없음

쿼리문으로 해결하자

슈거신텍스 람다식을 사용하면 자꾸 코드가 짧아진다.

optional 리턴값 : 있거나 없거나를 반환한다.

 

wa에서 데이터를 공유할 수 있는 4가지의 데이터 저장소

scope :

page, request, session, application

싱글톤으로 생성된 jsp의 기본객체이고 서블릿컨테이너와 대화하는 녀석 : ServletContext

 

//map 리턴값 optional

//flatMap((e)->e[0])  //가지고있는 배열을 1차원으로 바꿔주는 flatMap 리턴값Object

 

.flatMap(array->Optional.of(array[0]))

optional로 받는 방법

 


 

과제 : 비동기로 페이지 이동

반응형