-
20.03.09 ~ 20.03.14 TWIL개발 일기장/TWIL 2020. 3. 15. 23:52
refrence로 전달되는 리스트를 변형해서 값을 반환할 때는 안전하게 복사해서 사용하자.
코드 리뷰 당시 인자로 전달되는 객체를 사용하는 곳이 없어서 변경하지 않아도 됐지만, 안정적인 코드 개발을 위해 필요한 습관.
인자로 받는 객체를 다른 곳에서도 사용할 수 있는데, 인자로 받은 객체를 변경해버리면 다른 사용하는 곳에서도 변경이 일어나버리기 때문에 side effect를 생각해서 객체를 복사해서 사용하는게 낫다.public Product makeCookieBox(Ingredient ingredient) { return new Product( getCandy(ingredient), getChocolate(ingredient), // 예제 메서드 getSnack(ingredient) ); } // AS-IS public String getChocolate(Ingredient ingredient) { List<ChocoIngredient> chocoIngredients = ingredient.getChocoIngredients(); // 이 때 ingredient에 담긴 chocoIngredients 엘리먼트가 변한다. chocoIngredients.sort(Comparator.comparing(ChocoIngredient::getImportance)); // do something } // TO-BE public String getChocolate(Ingredient ingredient) { // stream().collect()를 통해서 객체를 복사한다. List<ChocoIngredient> chocoIngredients = ingredients.getChocoIngredients() .stream() .sorted(Comparator.comparing(ChocoIngredient::getImportance)) .collect(Collectors.toList()); // do something }
map()을 사용할 때, 기존 의도와 다른 의도가 있는 코드를 추가하는 건 별로 좋아보이지 않는다. (위험해보인다)
// AS-IS public List<Product> makeProducts(List<Ingredient> ingredients) { return ingredients.stream() .map(ingredient -> { // 의도와 다른 로직(사용하는 재료를 다른 서비스로 메시지를 쏴야하는 메서드) publishMessageService.sendUsingIngredient(ingredient); Product product = new Product(); // do something... return product; }); } // TO-BE public List<Product> makeProducts(List<Ingredient> ingredients) { // 로직 분리 ingredients.forEach(ingredient -> { publishMessageService.sendUsingIngredient(ingredient); }); return ingredients.stream() .map(ingredient -> { Product product = new Product(); // do something... return product; }); }
null을 return 해야하는 상황이라면 return 타입을 Optional로 지정해보자.
// AS-IS // 인자가 null이면 바로 null을 리턴 public String getMessage(Foo foo) { if (foo == null) { return null; } StringBuilder messageBuilder = new StringBuilder(); // append message... return messageBuilder.toString(); } // TO-BE // null도 리턴할 필요가 있는 메서드라면 Optional 사용 public Optional<String> getMessage(Foo foo) { return Optional.ofNullable(foo).map(foo -> { StringBuilder messageBuilder = new StringBuilder(); // append message... return messageBuilder.toString(); }); }
java 8을 써보는 건 처음이라 Optional을 언제 어떻게 사용하는지 찾아보았다.
해당 포스팅을 읽어보고 큰 도움이 되었다. Optional 주의사항, 가이드
early return을 하자.
return을 해야할 조건에 해당한다면 로직이 끝까지 탈 필요 없게끔 바로 return을 시켜주자.
해당 내용은 마틴 파울러의 refatoring에도 나왔던 걸로 기억하고 있으나, 읽고 까먹으면 뭐하니
// AS-IS // 인자가 null이 아니어야 로직 수행 public String getLovelyMessage(Letter letter) { LovelyWord lovelyWord = letter.getLovelyWord(); StringBuilder messageBuilder = new StringBuilder(); if (lovelyWord != null) { messageBuilder.append(lovelyWord.getPrefix()); // append message... return messageBuilder.toString(); } return "I have no lovely word"; } // TO-BE // null 값이라 수행될 필요가 없는 로직이라면 일찍감치 return 시켜버리자. public String getLovelyMessage(Letter letter) { LovelyWord lovelyWord = letter.getLovelyWord(); // 'early return' 혹은 'return early'라 부른다. if(lovelyWord == null) { return "I have no lovely word"; } StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append(lovelyWord.getPrefix()); // append message... return messageBuilder.toString(); }
운영에 관하여
jojoldu님의 블로그를 구독해서 보고 있다.
jojoldu님의 글 을 읽고 그래도 내가 생각하는 방향이 맞는 방향으로 가고 있구나? 란 생각을 했다.
지금 회사에서 맡은 업무도 운영분들의 일을 수월하게 하기 위한 자동화 작업을 매주 개발해나가고 있다. '몸빵하는 모습을 보면 눈물이 난다'라는 표현이 재밌었는데, 지금 개발하고 있는 자동화 기능들을 보면 '와 이전에는 이것들을 일일이 다 눈으로 체크하고 수정하려면 엄청 힘들었겠구나'란 생각이 들었다.
운영분들을 위함과 동시에 개발자의 반복업무를 줄이는 방법을 강구해내는 것도 중요한 것 같다.
첫 회사 재직 당시, 서비스 오픈 전마다 우리가 맡은 도메인 관련 테이블 데이터를 다 날려줘야 했는데.. 업무 프로세스가 운영분(거기서는 구축 지원팀이라 불렀다)들이 우리 파트에 데이터 초기화 요청을 하면 관련 테이블들을 일일이 delete from 'table'을 쳐주는 작업이었다.
해당 테이블을 다 외우고 있었기에 5분도 안 걸리는 일이었지만 고객사 서버로 접근이 막혀있을 경우에는 우리의 ip 좀 열어달라고 재요청 해야했다.(요청에 대한 피드백을 받기까지 시간 소요도 무시 못했다.)
그게 아니라도 5분을 소요하는 것도 이런 단순한 일은 개발자들이 안해도 되는거 아닌가란 생각을 했었다. 서비스 안에 히든 페이지를 만들어서 전용 아이디, 패스워드를 입력하고 접속하면 관리 페이지가 나오는데, 버튼을 누르면 테이블 데이터를 지워주는 페이지를 만들었다.
정말정말 만들기 간단한 페이지였음에도, 세 개의 큰 이득을 얻었다.(+ 다른 분들을 편하게 해드렸다는 뿌듯함)
1. 고객사 서버 접근이 막혀있어도 서비스 안에 히든 페이지가 있기에 업무를 진행할 수 있다.
2. 더 이상 해당 업무는 개발자들이 아닌 운영분들이 고객사 요청이 들어오는데로 바로바로 처리가 가능해졌다.
3. 해당 페이지를 활용해서 다른 자동화 기능을 추가할 수 있어졌다.(서비스 오픈 때마다 배포해야하는 프로시저, 추가될 테이블의 데이터 초기화 등)업무 시간을 조금씩 쪼갰더니 큰 이득을 봤던 작업이었던 것이다!
jojoldu님의 글을 읽어보면서 갓 개발자 생활을 시작했을 때, 무조건 핫한 기술, 새로운 기술들이 써보고 싶었고, 그런 욕심은 무조건적이었다. 신규 프로젝트라는 걸 참여해서 멋지게 새로운 서비스를 만들어내면 얼마나 좋을까란 생각을 하며 운영이 주가 되버린 맡은 업무가 싫었던 적이 많았다. 여전히 새로운 기술을 써보고 싶지만, 더 중요한 가치가 뭘까 생각해본다. 무조건 신기술보다는 뭐가 더 중요한걸까라는 생각을 한다. 비즈니스의 흐름, 전체적인 그림을 이해하는게 기술보다 더 중요한게 아닐까싶다. 돈을 받고 프로페셔널을 제공하는 사람이라면 더 높은 생산성과 일처리를 해내는게 중요한게 아닐까...
논점에서 벗어나는 얘기지만, 신기술, 새로운 것에만 목 메는 개발자가 되지 않기 위해 카카오 인턴으로 있을 때, 나의 파트장이었던 cree가 해주신 말씀을 남겨놔야겠다.
변하는 것보다 변하지 않는 걸 길러줬으면 좋겠다.
변하는 건 무엇인지 변하지 않는 것은 무엇인지에 대해 더 고민해보고 싶다.
'개발 일기장 > TWIL' 카테고리의 다른 글
20.03.30 ~ 20.04.03 TWIL (0) 2020.04.04 20.03.23 ~ 20.03.27 TWIL (0) 2020.03.30 20.03.16 ~ 20.03.20 TWIL (0) 2020.03.21 20.03.02 ~ 20.03.07 TWIL (0) 2020.03.07 TWIL이란? (0) 2020.03.07