반응형

 

리팩토링 전 상태: https://github.com/Wanted-preonboarding-team4/8percent-assignment-2

리팩토링 repo : https://github.com/Heon4856/8percent-assignment-2

 

리팩토링 전 상태 점검

1. serializer가 없어서, view 단의 코드가 지저분함 

2. 테스트 코드가 미비함.

3. 거래내역 1억건에 대한 고려나, 잔액 무결성에 대한 고려가 빈약함.

 

이에 따른 리팩토링 계획

0. 과제의 의도 파악하기.

더보기

1.  문제의 해석

1) 왜 이러한 문제를 줬을까?

8 퍼센트는 핀테크 기업이다. 핀테크 기업에게 제일 중요한 것은 신뢰다. 사고는 곧바로 고객의 손실로 이어지거나 적어도 고객의 신뢰 저하로 이어진다. 때문에 견고하고 사고없는 프로그래밍이 매우 중요하다. 이에 따라서 계좌의 잔액과 거래내역의 잔액 무결성이라던지, 1억건이 넘어가더라도 손실이 없고, 빠르게 찾을 수 있는 부분에 대한 고려가 필요하다.

 

극단적으로 보수적으로 잡도록 할것이다.

1. drf 도입을 통해 view 단 코드 정리 --> 했음.

2. 테스트 코드 작성 -->12.11 하는 중

3. 거래내역 1억건에 대한 풍부한 고려 및 잔액 무결성에 대한 고려를 할 것.  -->했음.

반응형
반응형

1. 파이썬 버전은 3.8, 3.9, 3.10 만 지원함

2. tmizeon은 zoneinfo가 default임

3. UniqueConstraint가 생김.

 

흠....그 외에는 아직 장고 초심자여서.. 바뀐것이 어떤의미인지 잘모르겠음.

 

 

 

 

https://www.youtube.com/watch?v=bE23wioMGao 

 

https://docs.djangoproject.com/en/4.0/releases/4.0

반응형
반응형
from collections import deque

n, m = map(int,input().split())
temp = []
for _ in range(n):
    aaa = input()
    aa = []
    for a in aaa:
        aa.append( int(a))

    temp.append(aa)

# print(temp)
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]


visited=[(0,0)]
round = 0
stack = deque ()
stack.append((0,0, 0) )
pointX = 0
pointY = 0
while pointX != n-1 or pointY != m-1:
    pointX, pointY, round =stack.popleft()
    for i in range(4):
        temp_pointX  =pointX+ dx[i]
        if temp_pointX <0 or temp_pointX> n-1:
            continue
        temp_pointY  =pointY+ dy[i]
        if temp_pointY <0 or temp_pointY >m-1:
            continue
        if temp[temp_pointX][temp_pointY] ==0:
            continue
        else:
            temp[temp_pointX][temp_pointY] = 0
            stack.append((temp_pointX, temp_pointY, round+1) )


print(round+1)
반응형
반응형

0. 서

 과제를 하면서 이러한 생각을 차분하게 했다면 좋았겠지만, 시간에 쫓기고 팀원들과 함께하느라 못했으므로,, 리팩토링하면서도 해야겠다는 생각에 정리한다.

 

1.  문제의 해석

1) 왜 이러한 문제를 줬을까?

8 퍼센트는 핀테크 기업이다. 핀테크 기업에게 제일 중요한 것은 신뢰다. 사고는 곧바로 고객의 손실로 이어지거나 적어도 고객의 신뢰 저하로 이어진다. 때문에 견고하고 사고없는 프로그래밍이 매우 중요하다. 이에 따라서 계좌의 잔액과 거래내역의 잔액 무결성이라던지, 1억건이 넘어가더라도 손실이 없고, 빠르게 찾을 수 있는 부분에 대한 고려가 필요하다.

 

극단적으로 보수적으로 잡도록 할것이다.

 

2. 문제의 해결

1) 잔액 무결성

트랜잭션의 무결성을 유지하도록 설계가 되어야한다.

이러기 위해서는 원자성, 일관성, 고립성, 지속성이 유지가 되어야한다.

(1) 원자성이 보장되기 위해, atomic을 수행한다.

기본적으로 장고는 auto_commit이다.

이에 따라 해당 계좌에 가서,  잔액을 바꾸고 거래내역을 등록하는 이 2가지 행위가 한번에 이루어져야하지만, 각각 이루어질 우려가 있으므로, **with transaction.atomic()**을 넣어줘야 한다.

(2) 일관성 같은 경우는 테이블이 생성될 때 명시되므로, 크게 신경 쓸 필요없다.

(3) 고립성을 보장하기 위해, 동시성 제어를 한다.(concurrency control)

  • 은행이니 만큼, 최고수준의 격리를 하여서 안정성을 확보해야한다.
  • 쓰기와 관련된 충돌은 select_for_update()를 통해서 방지한다.
  • 읽기/읽기와 관련된 충돌은 고립수준을 serializable 모드로 하여서 방지한다.
  • *TMI:

main -replica db로 나뉘어져 있는 상황에도 isolation을 신경써야할까?

  • 그렇다. 왜냐하면 main db가 다운되면 replica가 maindb가되기 때문이다.

(4) 지속성 역시 aws에서 로그기록을 남기도록 설정하였다.

추가적으로 aws-rds에서 multi-az를 활성화하였다.

이를 통해 혹시나 생길 db instance 중단에 standby replica로 대체하도록 하였다.

2) 1억건의 데이터고려

  1. 인덱싱
    • main db 와 replication db로 나누어서, write, update는 main에서만 하고, read는 replication db 에서만 가능하게 한다.
  2. 거래방식(입금인지,출금인지)과 계좌번호로 인덱싱하였음.
  3. 월별 partinioning:
    1. partition의 기준을 월로 한 이유비즈니스 로직에 따라, 연이나 주단위로 하는 것보다 월단위로 하는 것이 효율적이라 판단하였음.
    2. 카카오뱅크나 기타 다른 은행앱들을 보면, 1개월, 3개월 단위로 거래내역 목록을 볼 수 있게 해놓음.

 

 

 

 

리팩토링 중입니다..

https://semper-fide1is.tistory.com/115

반응형

'회고 > 매일회고' 카테고리의 다른 글

0210 GWJ  (0) 2022.02.10
11/06 회고  (0) 2021.11.06
11/03 TIL  (0) 2021.11.02
0918 til  (0) 2021.09.18
0916 til  (0) 2021.09.17
반응형

1. 말하는 사람은 들리게 말해야하고, 듣는 사람은 말하게 해야한다.

 

2. 커뮤니케이션의 실패는 무조건 쌍방과실이다.

 

3. 나에게 0.1%의 책임이 있더라도 나의 책임이다.

 

4. 좀 더 명확하고, 좀 더 잘 전달하기 위해 부단히 노력해야 한다.

 

 

 

 

위 원칙들을 생각하게 된 계기.

위와 같은 원칙들을  군대에서 일들과 제대후 미용실을 예약하는 과정에서 만들었다.

군대에서 관찰해보니까 나는 전파받은 기억이 없는데, 선임은 전파했다고 그러면 내가 혼나고

반대로 나는 분명히 전파했는데, 선임은 전파받은 기억이 없다고 내가 혼나고 하는 경험들을 하면서..

커뮤니케이션의 실패에 대한 책임이 권력관계에 의해 좌지우지 되는 것이 참 이상하다고 생각했다.

그래서 2, 3번 원칙을 생각하게 되었고, 적어도 내가 선임이 되었을때는 커뮤니케이션 실패시 내가 먼저 사과하였다.

내가 좀더 잘 전파했어야 하는데 미안하다. 내가 좀 더 신경써서 내용을 숙지했어야하는데 미안한다.

물론 단전에서 끓어오르는 분노가 생길때도 있었지만,,, 그럼에도 불구하고 2,3원칙에 따르면 나의 책임이 분명하고 내가 신경썻으면 분명 안일어났을것이기 때문에 먼저 사과하였다.

 

 

1번 원칙은 특히 미용실의 커뮤니케이션 방식에서 감명을 받았다. 그때 미용실을 예약하면, 예약했을때 한번, 예약일 하루전날 한번, 예약 당일에 한번 이렇게 3번 문자가 왔었다. 업장입장에서는 노쇼족을 방지하기 위해서 이렇게까지 전파하기위해서 애를 쓴 것을 보면서, 참 듣는 사람에게 들리게끔 커뮤니케이션한다.라는 생각이 들었었다.

 

아래는 내가 생각한 것을 도식화한 것이다.

이와 같이 말하는 사람의 영역과 듣는 사람의 영역이 겹치기만 하면 커뮤니케이션은 성공한다.
그런데 이렇게 두 영역이 겹치지 않으면, 실패한다.

 

아래 커뮤니케이션 실패를 해결하는 방법은 두가지이다.

파란색의 영역을 넓히거나, 빨간색의 영역을 넓히면 된다.

즉, 발화자, 청취자 둘중 한명이 부단히 노력하면 되는 것이다.

 

 

 

 

 

반응형

'회고 > 단상' 카테고리의 다른 글

협업에 관한 소고  (0) 2021.11.17
소프트웨어 장인정신 메니페스토  (0) 2021.10.07
반응형

정의

the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. 

-- 영어 위키백과

Factory method는 부모(상위) 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며. 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다.

-- 한국어 위키백과

 

이런식으로 정의만 보면 절대 이해가 안간다.

바로 예시로 들어가보자.

 

일단 피자가게 사장님이 되었다고 해보자.

1.햄머슈룸 피자

2. 디럭스피자

3. 해산물 피자를 메뉴로 준비하였다.

 

class HamAndMushroomPizza():
    def __init__(self):
        self.__price = 8.50
        
    def put_toping(self):
    	self.topping = "HAM"

class DeluxePizza():
    def __init__(self):
        self.__price = 10.50
        
    def add_toping(self):
    	self.topping = "meat"

class SeafoodPizza():
    def __init__(self):
        self.__price = 11.50
    
    def add_toping(self):
    	self.topping = "meat"
        
    def add_cheese_crust(self):
    	self.cheese_crust = True

 

만약 이렇게 될시에, 소비자가 주문하려고 할때, 각각의 객체생성 방법에 대해 알고 있어야한다.

ham_mushroom_pizza = HamAndMushroomPizza()
delux_pizza = DeluxePizza()
seafood_pizza = SeafoodPizza()

 

이때, pizzaFactory를 하나 만들어준다면 어떻게 될까?

class PizzaFactory: 
    "The Factory Class"

    @staticmethod
    def create_pizza(pizza_type: str):
        if pizza_type == 'HAM_MUSHROOM_PIZZA_TYPE':
            return HamAndMushroomPizza()
        if pizza_type == 'DELUXE_PIZZA_TYPE':
            return DeluxePizza()
        if pizza_type == 'SEAFOOD_PIZZA_TYPE':
            return SeafoodPizza()
        return None


pizza = PizzaFactory().create_pizza("HAM_MUSHROOM_PIZZA_TYPE")

pizza.put_toping()

소비자는 피자 팩토리만 알면, 복잡한 객체생성방법에 대해 알 필요가 없게된다.

지금 예시는 간단해서 필요성을 못느낄수도 있지만,

각 피자에 따라 직접 토핑을 집어넣어줘야 피자가 생성됐다면?

팩토리라는 클라스의 필요성을 느낄수 있을 것이다.

 

 

이렇게만 바뀌면 객체지향적이라고 할 수 있을까?

SOLID원칙중 open/close원칙에 비추어 확인해보도록 하자.

 

 

class PizzaFactory: 
    "The Factory Class"

    @staticmethod
    def create_pizza(pizza_type: str):
        if pizza_type == 'HAM_MUSHROOM_PIZZA_TYPE':
            return HamAndMushroomPizza()
        if pizza_type == 'DELUXE_PIZZA_TYPE':
            return DeluxePizza()
        if pizza_type == 'SEAFOOD_PIZZA_TYPE':
            return SeafoodPizza()
        return None


pizza = PizzaFactory().create_pizza("SEAFOOD_PIZZA")

pizza.put_toping()

앞선 코드에서 피자종류만, 해산물피자로 바꾸었다.

그런데 에러가 날 것이다.

왜냐하면, SEAFOOD피자에서는 put_toping이 아니라 add_toping이기 때문이다.

 

이는 즉, 만약 HAM_MUSHROOM_PIZZA를 먼저만들고, SEAFOOD 피자로 확장했다고 했을떄,

확장을 했을때 코드를 수정해야한느 일이 발생한 것이다.

즉, 확장에 열려있고, 수정에 닫혀있어야한다는 open/closed principle에 어긋난다.

 

그러면 어떻게 해줘야할까?

class Pizza(ABCMeta):
    def __init__(self):
        self.__price = None
	
    @abstractmethod
    def add_toping(self):
    	pass


class HamAndMushroomPizza(Pizza):
    def __init__(self):
        self.__price = 8.50

    def add_toping(self):
	self.topping = "HAM"


class DeluxePizza(Pizza):
    def __init__(self):
        self.__price = 10.50

    def add_toping(self):
	self.topping = "MEAT"
        
        
class SeafoodPizza(Pizza):
    def __init__(self):
        self.__price = 11.50
        
       
    def add_toping(self):
	self.topping = "SEAFOOD"        
        
        
    def add_cheese_crust(self):
    	self.cheese_crust = True

 이런식으로 추상화된 클라스를 만들어줘서 통일감있게 강제해줘야한다.

이렇게 추상화된 클라스를 상속받기만 하면, 기존코드 수정 없이, 새로운 피자를 만들어낼 수 있다.(확장)

 

이는 또한 생성이라는 역할을 factory가 다 맡고 있다는 점에서 단일책임 원칙을 지키고 있다고 볼 수 있다.

반응형
반응형

1. 발단

어떻게 하면 객체지향 프로그래밍 지식을 한 시간안에 잘 전달할 수 있을까? 이러한 고민에서 이 시리즈가 시작되었다.

필자는 매주 일요일 cs지식공유스터디를 하는데, 각자 공부한 것을 30~1시간정도 나누는 시간이다.

그래서 필자가 최근 열심히 공부한 객체지향을 나누고 싶은데, 이게 객체지향 특성상 말로 떠든다고 절대 와닿지 않는다.

특히 solid원칙은 직접해보고 생각해보고, 리팩토링을 해봐야 느낄수 있는 영역이라고 생각된다.

 

2. 전개

그러던중 필자는 디자인패턴을 공부하고 있었는데 너무 노잼이었다. 이 역시 객체지향을 처음 공부할떄랑 비슷한 느낌이 드는건데, 그거 좋은거 알겠는데, 머 어쩌라고? 이런느낌이 드는건 어쩔 수 없다.

이때 머릿속을 스쳐지나간 생각이 아. 디자인패턴을 역으로 solid 원칙 및  4기둥에 비추어 분석하고, 이를 같이 나눠보면 나도 공부되고 스터디원도 공부되지 않을까? 생각이 들었다.

 

 

반응형

'computer 지식 > 디자인패턴으로 알아보는 객체지향' 카테고리의 다른 글

디자인 패턴 용어들  (0) 2022.01.08
#1 팩토리패턴  (0) 2021.11.28
반응형

 비전공자로서 자료구조를 공부하다가 궁금했던 것이 있다. 내가 파이썬부터 배우기 시작해서 그런지는 몰라도.

스택/큐 다되는 deque가 있는데, 왜 굳이 스택/큐를 나누어서 쓰는 것일까? 그냥 그 모든 기능을 다 되게하면 안되는 걸까?

 

이 질문에 대한 답을 오늘 드디어 깨달아서, 이렇게 글을 쓴다.

 

일단 자료구조의 정의부터 알아보자.

In computer science, a data structure is a particular way of storing and organizing data in a computer so that it can be used efficiently

즉, 효율적으로 사용되기 위해, 데이터를 저장하고 표현하기 위한 특정한 방식이 자료구조라고 할 수 있다.

그러니까 스택이나 큐가 먼저 있었고, 그에 따른 기능들이 나온 것이 아니라.

FIFO, LIFO등의 데이터를 저장하고 표현하기  위한 방식이 있었고, 이에 대한 이름을 스택, 큐라고 붙인 것이다.

 

 

여기서부터는 내 상상이자, 뇌피셜이 살짝 섞여있다. (실제로는 아닐 수 있음 주의)

 

컴퓨터과학자들이 먼저 자료구조를 만들고, 프로그래머들이 이를 사용했을까?

아니면 프로그래머가 먼저 코드를 짜다보니 특정한 데이터의 저장/표현방식이 반복되었고, 이를 컴퓨터과학자들이 스택/큐라고 이름을 붙였을까?

 

나는 후자라고 생각한다. 사실 프로그래밍 세계의 발전이 그러한 것 같다. 계속 해결해야한느 문제점들이 발생하고, 이를 해결하려고 노력하고, 그 해결점들이 컴퓨터과학으로 학문화되는 것 같다. (그래서 나는 운영체제 과목을 물리적 한계에서 최적화된 컴퓨터를 개발하기 위한 컴퓨터과학자들의 분투들이 담겨있다고 느꼈다.)

 

 

그리고 C언어로 된 책을 보면 ADT를 설정하고 이를 자료구조로 구현한다.

이는 ADT는 설계도 같은 것으로, FIFO를 구현하는데 LIFO까지 가능하게 하면 이는 사족이 달려있는 것과 같다.

또한 다른 프로그래머들이 어떠한 맥락을 파악하는데 어려움을 겪을 것이다.

예를 들어, a라는 프로그래머가 FIFO기능이 필요한데 그냥 deque로 짜놓았다면, b란느 프로그래머는 deque가 fifo기능을 위해 들어갔다는 사실을 전후 코드를 살펴야하는 노력이 필요하다. 이러한 비효율을 줄이기 위해서라도, queue/ stack은 나누어서 쓰여져야 한다.

 

여튼 내가 가졌던 의문은 전제가 잘못되었다.

일단 나누어서 개발한게 아니라, 개발된것에 이름을 붙인것 뿐이다.

그리고 나뉘어져있어야 타 개발자와의 협업, 소통 등에서 유리하다.

 

반응형

+ Recent posts