게시글
질문&답변
회고 만들기 기능이 안보이는데 혹시 어떻게 하면될까요??
연동 되어있는데 생성이 안되서 문의 드렸는데 새로운 스크럼을 생성하니 갑자기 생성이 되네요. 혹시 다른분들도 같은 증상 겪으실까봐 질문 삭제 안하고 남겨두겠습니다.
- 1
- 2
- 77
질문&답변
logout을 했지만 세션이 남아있습니다.
찾다보니 답을 이미 적어 놓으셨네요. 다른분들 삽질하실까봐 링크 걸어 둡니다.https://www.inflearn.com/questions/40072/%EB%8F%99%EC%8B%9C-%EC%84%B8%EC%85%98-%EC%A0%9C%EC%96%B4-%EB%8F%99%EC%9D%BC-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-%EB%A1%9C%EA%B7%B8%EC%95%84%EC%9B%83%EC%9D%B4-%EC%A0%95%EC%B1%85-%EB%AF%B8%EC%A0%81%EC%9A%A9
- 0
- 1
- 971
질문&답변
실무에서 사용되는 Setter
조금 원론적인 내용이긴 한데 도움이 되었으면 해서 댓글을 달아 봅니다. 실무에서는 실제로 어떤 객체의 값이 있을 경우, 그 값이 DB에서 반환된 값인지 중간에 변경된 값인지 로직이 복잡하면 변경되지 않았다는 사실을 보장하기 쉽지 않습니다. 때문에 setter를 필요할 때만 둔다면 값이 변경되지 않았다는 사실을 보장받을수 있습니다. (디자인 패턴을 통해 보장을 하기도 하지만 결론은 변경을 불가하게 하는 것입니다.)
- 0
- 2
- 348
질문&답변
오류가 뜨네요
practice.py는 travel 디렉토리와 같은 레벨의 위치에 있어야 합니다.
- 0
- 1
- 358
질문&답변
중간값에만 default 값을 설정할수는 없을까요?
아래의 글이 도움이 될것 같네요 https://velog.io/@swhybein/WC6-day2-python-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98-%EA%B4%80%EB%A0%A8
- 1
- 1
- 192
질문&답변
안녕하세요! Quiz8 코드부분중에 궁금한것이 있습니다!!
사용하는 쪽에서 사용하지 않고 생성만 해서 쓰려면 아래와 같이 쓰면 됩니다. class House: houseList = [] # 초기화 def __init__(self , location , house_type , deal_type , price ,completion_year): self.location = location self.house_type = house_type self.deal_type = deal_type self.price = price self.completion_year = completion_year self.houseList.append(self) # 메물 정보 표시 def show_detail(self): print("총 {0}개의 매물이 있습니다.".format(len(House.houseList))) for house in House.houseList: print(house.location , house.house_type , house.deal_type ,\ house.price ,house.completion_year) h = House("강남","아파트","매매","10억","2010년") h = House("마포","오피스텔","전세","5억","2007년") h = House("송파","빌라","월세","500/50","2007년") h.show_detail()
- 0
- 2
- 256
질문&답변
매개변수와 파라미터는 어떻게 다른가요?
바라보는 입장에서의 용어 차이입니다. 변수를 할당 받는 클래스 입장에서 보면 ()안의 변수는 '파라미터' 변수를 보내주는 입장에서 ()의 변수는 '아규먼트' 라고 표현합니다.
- 1
- 3
- 350
질문&답변
질문이 있습니다.
1. 아마 메모리 주소를 사용하는 것이라, 생성보다는 가르킨다는 표현이 맞을껍니다. 하지만 그런 식으로 관리하면 나중에 객체 관리가 힘들어 집니다. 2.네 아래는 간단한 예제입니다. class ParentA: def __init__(self , name): self.name = name def whois(self): print("my name is {0} ".format(self.name)) class ChildA(ParentA): def __init__(self , name): self.name = name def whois(self): print("my parent name is {0} ".format(self.name)) parentA = ParentA("A") parentA.whois() # my name is A childA = ChildA("A") childA.whois() # my parent name is A
- 1
- 1
- 164
질문&답변
if not
if line != null 이 아니고 if line == null 아닌가요?
- 0
- 2
- 663
질문&답변
input은 type이 문자형이기 때문에 str쓰지 않아도 된다고 하셨는데요
temp = int(input("기온은 어때요?") ) 문자열 > 숫자 answer = input("기온은 어때요?") 문자열 print 함수 안에는 문자열 타입만 들어가기 때문에 숫자는 문자로 변환(파싱이라고도 합니다)해서 print 함수안에 넣어야 하는거 같네요 아래 숫자로 넣을시 호출되는 에러를 첨부해 드립니다. Exception has occurred: TypeError can only concatenate str (not "int") to str
- 1
- 1
- 184
블로그
전체 82025. 03. 30.
0
워밍업 클럽 3기 BE 클린코드&테스트 - 1주차 발자국
회고록강의가 시작되었다. 사실 전체적인 내용은 코드 작성이나 분석보다도 기존에 알고 있는 정보를 정리하고 어떻게 적용하지는지에 대하 예시가 많았다. 1. 무엇을 배웠나?이번 주에는 다음과 같은 내용을 학습했다. 섹션 2 추상과 구체추상과 구체자세한 내용은 아래에서 섹션 3 논리, 사고의 흐름뇌 메모리 적게쓰기early return, 사소의 depth 줄이기 (메서드 분리)개발시 의식적으로 쓰고있다.공백 라인, 부정어해피 케이스, 예외처리예외 케이스를 찾아내는게 쉽지 않은데, 방안이 좀 상세 했으면 좋았을텐데...Optional섹션 4 객체 지향 패러다임객체, 협력과 책임, 관심사의 분리, 높은 응집도와 낮은 결합도getter/setter 자제하기, 객체에 메시지 보내기개인적으로는 getter에는 관대해도 된다고 생각하는데 잘 모르겠다. 노출하지 않으려면 field 자체가 없어야 하지 않을까?SOLIDDI/IoC섹션 5 객체 지향 적용하기상속과 조합Value Object, Entity일급 컬렉션Enum추상화와 다형성 활용하여 반복되는 if문 제거, OCP 지키기if문 제거는 생각보다 어렵다. if문 제거를 위해서 라기보다는 전반적인 로직 개선 관점에서 고려해야 될것이다숨겨저 있는 도메인 개념 도출하기 2. 무엇이 인상적이었나?추상과 구체 부분은 보니 처음 개발업을 시작했을때가 생각났다. 붕어빵과 틀 예시를 처음 들었을때를 기억하면서 미술까지 생각하는 것은 나와 비슷한 생각을 하는 사람이 있었구나와 어쩌면 다들 저렇게 생각하고 있었구나 의 사이정도의 감정이 들었다. 3. 이번 주 학습을 통해 얻은 것전반적으로 기존의 인지하고 있는 내용을 반복하는 시간이 되었다.
2025. 03. 30.
0
워밍업 클럽 3기 BE 클린코드&테스트 - 4주차 발자국
회고록4주차로 드디어 스터디가 종료 되었다. 이번 스터디를 진행하면서 진행한 개선방향을 실무에 어떻게 적용할지 생각해보고 반복해서 진행해봐야 할것이다. 1. 무엇을 배웠나?이번 주에는 다음과 같은 내용을 학습했다. 섹션 5~7 BDD(Behavior-Driven Development) 요약BDD는 소프트웨어의 행동(Behavior) 에 초점을 맞춘 개발 방법론이다. Given-When-Then 형식을 사용해 테스트 시나리오를 작성한다. 비즈니스 이해관계자와 개발자 간의 원활한 의사소통을 돕는다. 테스트를 문서화하는 효과가 있어 가독성과 유지보수성이 향상된다테스트 더블(Test Double) 요약Dummy: 사용되지 않지만 인자로 전달되는 객체 (예: null 반환).Fake: 실제 동작하지만 간단한 구현을 제공하는 객체 (예: 인메모리 DB).Stub: 미리 정의된 값을 반환하는 객체 (예: 특정 입력에 대한 고정 응답).Spy: 메서드 호출 내역을 기록하는 객체 (예: 호출된 인자 저장).Mock: 호출 여부 및 횟수를 검증하는 객체 (예: 특정 메서드 호출 확인). 섹션 8~10테스트 진행시 고려해볼 상황과 기타 툴 사용법 2. 무엇이 인상적이었나?서포팅 받을 수 있는 툴 사용 방법이 인상적이었다. 3. 이번 주 학습을 통해 얻은 것사실 개발이라는 작업은 잘 정리된 글쓰기에 가깝다. 정리된 글은 문학이 되지만 정리되지 않은 글은 노트 메모만도 못한 취급을 받는다. 문학적으로는 아니더라도 노트정도는 될수 있도록 코드를 작성하도록 하자.
2025. 03. 27.
0
Day 18 Mission [Layered Architecture 에 대하여 정리]
1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다. 1. @Mock vs @Spy (Mockito)이 두 개는 Mockito에서 제공하는 어노테이션이고, 단위 테스트에서 가짜 객체(Mock 또는 Spy)를 생성할 때 사용된다.@Mock완전히 가짜(Mock) 객체를 생성해서 메서드 호출 시 기본적으로 null, 0, false 같은 값을 반환한다.호출 기록을 확인할 수 있고, 특정 동작을 when(...).thenReturn(...)으로 지정 가능하다.실제 객체의 메서드는 호출되지 않는다.예제:@Mock private UserRepository userRepository; @Test void testMock() { when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "John"))); Optional user = userRepository.findById(1L); System.out.println(user.get().getName()); // John } @Spy실제 객체를 감싸는(Mock하지 않는) 가짜 객체(Spy) 생성한다.기본적으로 실제 객체의 메서드를 실행하지만, 특정 메서드는 when(...).thenReturn(...)을 사용하여 동작을 변경할 수 있다.일부 동작만 모킹하고 싶을 때 유용하다.예제:@Spy private List spyList = new ArrayList(); @Test void testSpy() { spyList.add("one"); spyList.add("two"); when(spyList.size()).thenReturn(100); // 특정 메서드만 모킹 System.out.println(spyList.get(0)); // one (실제 메서드 호출) System.out.println(spyList.size()); // 100 (모킹된 값 반환) } 2. @MockBean vs @SpyBean (Spring Boot)이 두 개는 Spring Boot에서 제공하는 어노테이션이다.Spring 컨테이너에 있는 빈(Bean)을 Mock 또는 Spy로 대체하는 역할을 한다.@MockBeanSpring 컨텍스트에서 기존에 등록된 빈(Bean)을 Mock 객체로 교체.모든 메서드는 기본적으로 null, 0, false를 반환한다.@Mock과 비슷하지만, Spring 컨테이너에 등록된 Bean을 대상으로 한다는 차이점이 있다.예제:@SpringBootTest class MyServiceTest { @MockBean private UserRepository userRepository; @Autowired private MyService myService; @Test void testMockBean() { when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "John"))); User user = myService.getUserById(1L); System.out.println(user.getName()); // John } } ✅MockBean을 사용하면 UserRepository의 실제 빈이 Mock으로 대체됨.@SpyBeanSpring 컨텍스트에서 기존에 등록된 빈(Bean)을 Spy 객체로 교체된다.기본적으로 실제 객체의 메서드를 실행하지만, 특정 메서드는 when(...).thenReturn(...)을 사용해 동작을 변경할 수 있다.@Spy와 비슷하지만, Spring 컨테이너의 실제 Bean을 대상으로 한다는 점이 다르다.예제:@SpringBootTest class MyServiceTest { @SpyBean private UserService userService; // 기존 Bean을 Spy로 감싸서 일부 메서드만 Mock 가능 @Test void testSpyBean() { when(userService.getUserName(1L)).thenReturn("Mocked Name"); System.out.println(userService.getUserName(1L)); // Mocked Name (모킹된 메서드) System.out.println(userService.getUserCount()); // 실제 메서드 실행 } } ✅SpyBean을 사용하면 UserService의 실제 빈이 Spy로 감싸짐.3. @InjectMocks@Mock이나 @Spy로 생성된 객체들을 자동으로 주입해 줌.테스트 대상 클래스에 의존하는 객체들을 자동으로 설정해 주기 때문에, new 키워드 없이 의존성을 주입할 수 있음.@Mock 또는 @Spy로 선언된 객체를 @InjectMocks가 붙은 객체의 생성자, 필드, setter 등을 이용해 주입함.예제:class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public String getUserName(Long id) { return userRepository.findById(id).map(User::getName).orElse("Unknown"); } } class UserServiceTest { @Mock private UserRepository userRepository; @InjectMocks private UserService userService; // userRepository가 자동 주입됨 @Test void testInjectMocks() { when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "Alice"))); System.out.println(userService.getUserName(1L)); // Alice } } ✅userService를 직접 new로 생성하지 않아도 @InjectMocks가 @Mock된 userRepository를 자동으로 주입해 준다. 2. 아래 3개의 테스트가 있습니다. 내용을 살펴보고, 각 항목을 @BeforeEach, given절, when절에 배치한다면 어떻게 배치하고 싶으신가요?(@BeforeEach에 올라간 내용은 공통 항목으로 합칠 수 있습니다. ex. 1-1과 2-1을 하나로 합쳐서 @BeforeEach에 배치)댓글이 목적이니 댓글 이외의 통합할수 있는 부분은 통합처리@BeforeEach void setUp() { 1-1. 2-1. 3-1. 사용자 생성에 필요한 내용 준비 1-3. 2-3. 3-5. 게시물 생성에 필요한 내용 준비 1-2. 2-2. 3-2. 사용자 생성 1-4. 2-4. 3-6. 게시물 생성 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }
2025. 03. 25.
0
Day 16 Mission [Layered Architecture 에 대하여 정리]
1. 레이어 별로 어떤 특징이 있는가?보통 3계층 혹은 4계층으로 구조를 분리하는데 강의에서는 3계층으로 표현하고 있다.프레젠테이션 계층 (Presentation Layer)사용자와 직접 상호작용하는 부분이다. (외부 세계의 요청을 가장 먼저 받는 계층이다.)파라미터에 대한 최소한의 검증을 진행한다.비즈니스 로직 계층 (Business Logic Layer)애플리케이션의 핵심 기능과 규칙을 처리합니다.사용자 요청에 따라 데이터 처리, 검증, 트랜잭션 관리 등을 수행한다.영속성 계층 (Persistence Layer)데이터베이스나 외부 저장소와의 통신을 담당합니다.가공 로직이 포함되어서는 안된다.SQL 쿼리 실행, ORM 매핑 등이 이 계층에서 이뤄집니다.2. 어떻게 테스트 하면 좋을까?각 계층이 다른 계층에 침투하지 않도록 해야한다. 또한 각 레이어의 목표에 맞게 진행해야한다.프레젠테이션 계층 (Presentation Layer)사실 테스트하기 가장 난감하다. 단순 restfull api 서버라면 가능하지만 화면을 제공한다면 테스트가 복잡해진다.화면의 구조나 UI/UX 측인 부분도 검증이 필요하다.restfull 서버라는 가정하에는 MockMvc와 @MockBean을 사용하여 Mocking 처리가 가능하다.비즈니스 로직 계층 (Business Logic Layer)사실상 중간단계의 통합테스트가 많다. @MockBean을 사용하여 Repository를 Mocking하고 비즈니스 로직 검증이 가능하지만 fake객체를 만들어 단독으로 검증할 수 있도록 하는것이 더 좋다.(속도가 월등하다)데이터 접근 계층 (Data Access Layer)@Transactional를 이용한 CRUD 테스트가 가능하다.인메모리 디비를 사용해 테스트가 가능하지만 역시다 fake객체를 이용하여 빠른 속도로 검증이 가능하다.영속성 객체의 속성을 잘못 인지하면 테스트는 통과하지만 실제로는 오류가 발생한다거나 부하테스트 등을 정상적으로 처리다 안되고 영속성 1차 캐시에서만 처리되 무의미한 테스트가 발생할수 있으니 주의가 필요하다.
2025. 03. 23.
0
워밍업 클럽 3기 BE 클린코드&테스트 - 3주차 발자국
회고록3주차로 넘어가면서 벌써 한 강의가 끝났다. 언제나 로직을 구현하고 테스트 코드를 구현하는 것은 어렵고도 귀찮은 일이다 이주 과제인 테스트 코드 과제는 나에게 어떤 의미가 있었나 생각해보는 시간이 필요하다. 1. 무엇을 배웠나?이번 주에는 다음과 같은 내용을 학습했다. 섹션 3 단위 테스트테스트 도구JUnit 5: 단위 테스트를 위한 프레임워크 (XUnit 계열)AssertJ: 풍부한 API 및 메서드 체이닝 지원, 테스트 코드 작성 보조 테스트 케이스 세분화해피 케이스: 정상적인 상황에서 예상된 동작 확인예외 케이스: 에러나 예외 상황 검증경계값 테스트: 특정 범위(이상, 이하, 초과, 미만)나 날짜 등 경계값 테스트 테스트하기 어려운 영역 구분 및 분리테스트하기 어려운 코드 예시현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등표준 출력, 메시지 발송, DB 기록 등 외부 세계에 영향을 주는 코드해결 방법: 테스트하기 어려운 요소를 외부로 분리하여 테스트 가능한 코드로 변환 순수 함수(Pure Function)같은 입력에는 항상 같은 결과를 반환하며, 외부 세계와 단절된 형태 → 테스트하기 쉬운 코드섹션 4 TDDTDD의 핵심 사이클TDD는 RED → GREEN → REFACTOR 3단계로 반복 수행됨.RED (실패하는 테스트 작성)새로운 기능을 추가하기 전에 먼저 실패하는 테스트를 작성GREEN (테스트 통과, 최소한의 코드 작성)테스트를 통과할 수 있도록 최소한의 코드 작성REFACTOR (구현 코드 개선, 테스트 유지)중복 제거, 성능 개선 등의 최적화 수행테스트는 계속 통과해야 함 2. 무엇이 인상적이었나?이번 주 학습 중 가장 인상 깊었던 내용 보다는 궁금한 점이 있었다. 기존 레거시 리펙토링에 대한 테스트 보장을 어떻게 할 것인가? 해당 내용에 대한 해결책은 차주 내용에 포함시켜 보겠다.3. 이번 주 학습을 통해 얻은 것전반적으로 기존의 인지하고 있는 내용을 반복하는 시간이 되었다. 차주에도 꾸준히 이어가길... 4. 다음 주 목표금주 발생한 궁금증을 해소시켜 보기
2025. 03. 16.
0
워밍업 클럽 3기 BE 클린코드&테스트 - 2주차 발자국
회고록2주차로 넘어가면서 벌써 한 강의가 끝났다. 개발을 업으로 하면서 항상 깔끔한 코드에 대한 갈증 있는데 이번에 완료한 강의로 그 갈증을 모두 채우기에는 역시나 아쉬움이 있었다. 이것은 아마도 강의의 문제가 아닌 클린코드 라는 작업 자체에 대한 어려움일 것이다. 그리고 나 자신의 작문 실력의 부족함 때문일것이다. 1. 무엇을 배웠나?이번 주에는 다음과 같은 내용을 학습했다. 섹션 5 객체 지향 적용하기상속과 조합 : 상속보다는 조합을 사용하여 유연한 구조를 설계하는 것이 좋다.내 경험에선 상속을 사용한 클래스를 보기 힘들었다. (사실 본적이 없다.) 아마도 숨겨진 변수에 찾기에 대한 어려움 때문일것이라 생각한다.Value Object (VO) :도메인 개념을 값으로 표현하는 객체로, 불변성과 동등성을 보장해야 한다.개인적으로는 VO객체를 많이 사용하려고 노력한다. 값이 스스로 검증 할 수 있다는 것이 매력적이기 때문일까?DTO 내부에 들어가게 될 경우 어떻게 써야할지 좀 막막하기는 하다. 해당 내용도 있었으면 좋았을텐데일급 컬렉션 :컬렉션을 객체로 감싸서 의미를 부여하고, 가공 로직을 포함할 수 있도록 한다.잘 사용하지 않는 패턴이긴하다. 이건 새로 도입할지 여부를 결정해봐도 좋을것 같다.Enum의 특성과 활용 :상수의 집합이며, 관련된 로직을 포함할 수 있는 추상화된 객체로 활용된다.개인적으로 Enum을 사랑하는 사람이다. 한글로 명확히 표현 할 수 있는건 매력적이다.interface를 적용하는 방법은 적절히 사용하면 좋은 패턴인것 같다.다형성 활용하기 :반복적인 if 문을 제거하고, 변화하는 부분을 분리하여 OCP(Open-Closed Principle)를 지킨다.사실 코드 depth를 줄이기 위해 자주 애용하는 패턴이다.숨겨져 있는 도메인 개념 도출하기 :도메인 개념을 발견하여 설계에 반영하고, 완벽한 설계가 아닌 최선의 설계를 지향해야 한다.자세한 내용은 아래에서 섹션 6 코드 다듬기주석의 양면성 :주석은 코드의 가독성을 높일 수도 있지만, 코드 품질이 낮다는 신호가 될 수도 있으며, 꼭 필요한 경우에만 작성해야 한다.자세한 내용은 아래에서변수와 메서드의 나열 순서 :변수와 메서드는 사용 순서대로 배치하며, 공개 메서드를 상단에 배치해 객체의 협력을 더 쉽게 이해할 수 있도록 해야 한다.사실 배열 순서가 꽤나 개발자 취향을 타는 문제라 내 배열 순서랑 한번 비교해 보는 시간이라 좋았다. (나는 목록,상세,생성,수정,삭제, 기능으로 자주 호출되는 순서로 정리한다.)패키지 나누기 :패키지는 문맥을 제공하므로 적절한 크기로 분리하되, 과도한 세분화나 무분별한 변경은 피해야 한다.패키지 나누기는 어려운 문제다. 대부분은 사내 컨벤션이 있기때문에 마음대로 조정하기 어렵다. 기능 유지보수하기 (1) - 버그 잡기 :기존 기능의 오류를 찾아 수정할 때는 코드의 변경이 최소화되도록 해야 한다.기능 유지보수하기 (2) - 알고리즘 교체하기 :알고리즘을 변경할 때는 성능과 메모리 사용을 고려하여 적절한 방법을 선택해야 한다.사실 리펙토링의 핵심은 이런 부분 때문이 아닐까 싶다. 리팩토링 잘된 코드는 추가 요구사항을 적용할때 때로는 코드 한줄 만으로 처리 가능하게 한다. 개발자라면 그럴때 느끼는 감정은 따로 말하지 않아도 잘 알지 않을까 싶다.(물론 항상 그렇지는 않다.)IDE의 도움 받기 :코드 정렬, linting, 스타일 가이드를 활용하여 가독성과 유지보수성을 높인다.개인적으로 코드 스타일 같은 경우는 툴에 의존되야 되는것이 맞다고 생각한다. (코드 컨벤션은 사람이 지키기에는 정말 어렵다.) 섹션 7 리팩토링 연습리팩토링 (1) - 추상화 레벨 :중복 코드를 제거하고, 메서드를 추출하여 적절한 추상화 레벨을 맞춘다.리팩토링 (2) - 객체의 책임과 응집도 :IO 처리와 화면 출력(display) 기능을 분리하고, 일급 컬렉션과 Order 객체를 도입하여 책임을 명확히 한다. 리팩토링 (3) - 관점의 차이로 달라지는 추상화 :같은 기능이라도 구현 중심과 도메인 개념 중심으로 접근하는 방식에 따라 추상화가 달라질 수 있다.강의를 따라하면서 의문이 들었던 부분은 MVC, MVVC 와 같은 아키텍처 부분이 나올줄 알았는데 안나왔다는 것이다. 강의 분량 때문에 안 나온건지 아니면 일부러 포함을 안 시킨 건지 잘 모르겠지만 중간에 "Controller"라는 표현을 한것 을 보면 후자에 가까운 것으로 보인다.섹션 8 기억하면 좋은 조언들능동적 읽기 : 핵심 목표는 도메인 지식을 늘리는 것이게 정답이다. 중요한 건 도메인이지 기술이 아니다.오버 엔지니어링 : 적정 수준보다 더 높은 수준의 엔지니어링자세한 내용은 아래에서은탄환은 없다 : 클린 코드도 은탄환이 아니다.자세한 내용은 아래에서2. 무엇이 인상적이었나?이번 주 학습 중 가장 인상 깊었던 내용은 숨겨져 있는 도메인 개념 도출하기, 주석의 양면성, 오버엔지니어링, 은탄환은 없다. 이었다.숨겨져 있는 도메인 개념 도출하기업무를 하면서 도메인의 관점에서 생각을 해보지 않아서 새로웠다.주석의 양면성주석이 참 업무를 하다보면 매력적으로 다가올때가 많다. 하지만 레거시에서는 그렇게 보기 싫더라... 히스토리 용으로만 쓰면 좋다는 내용은 동의하지만 고객에게 전달할때 어떻게 코드만으로 전달 수있을지는 여전히 잘 모르겠다.오버엔지니어링사실 개발하면서 신규 요구사항을 한방에 해결하기 위해 오버엔지니어링을 많이 하게되는것 같다. "필요하기전에 만들지 마라"라는 말이 있듯이 참 지키기 어려운 부분인것 같다.은탄환은 없다."머리는 애자일, 몸은 워터풀" 인 상황이 많았다. 사실 강의에서는 "지속 가능한 소프트웨어의 품질 VS. 기술 부채를 안고 가는 빠른 결과물" 이지만 클라이언트의 요구사항은 거의 대부분 "지속 가능한 소프트웨어의 품질을 가진 빠른 결과물" 인 경우가 많다. 그래서 아마 대부분의 개발자가 품질을 높이기 위해 작업 공수를 실 공수보다 높게 부르는 것이라 생각한다. 이게 보통 성과에 직결되는 부분이라 참 어렵다.3. 이번 주 학습을 통해 얻은 것이번 주 학습을 통해 나는 Enum 활용법에 대해 배웠고 도메인에 대한 생각을 더 깊게 해야겠다고 생각했다.특히, 도메인에 대한 생각을 깊게 하는 연습을 게을리 하면 안될것이라 생각한다. 4. 다음 주 목표다음 주에는 테스트 코드 방법론 적용을 달성하고 싶다.항상 로직을 먼저 작업하고 테스트 코드를 작성하는 버릇이 있는데 차주에는 그런 버릇을 의식적으로 수정해 보리라..
백엔드