2011-08-19 5 views
1

원격 객체에서 변경 사항을 명령하는 코드 조각을 작업하는 상황이 발생했습니다 (복제 할 수없는 부분이 있습니다). 복제를 통해 작업), 원격 객체에 새로운 상태의 일부 조작을 요청하고 반대 명령의 순서로 작성한 모든 변경 사항을 되돌립니다. 문제는 이러한 모든 변경 사항의 중간에 오류가 발생하면 지금까지 작성한 모든 변경 사항을 롤백 할 수 있기를 바랍니다.극단적 인 식별자없이 파이썬에서 롤백 가능한 코드 흐름 유지하기

내 마음에 와서 가장 좋은 피팅 솔루션은 시도 - 마지막으로 파이썬입니다 워크 플로우하지만, 명령의 순서가 긴 경우 오히려 문제가있다 :

try: 
    # perform action 
    try: 
     # perform action 
     try: 
      # ... 
     finally: 
      # unroll 
    finally: 
     # unroll 
finally: 
    # unroll 

이 방법은, 더 많은 명령은 내가 깊은 필요 내 들여 쓰기 및 중첩이 진행되고 내 코드가 읽기 어려워집니다. 나는 모든 명령에 대해 롤백 작업을 푸시하는 스택 유지와 같은 몇 가지 다른 솔루션을 고려해 왔지만, 다소 복잡해질 수 있으며 바인딩 된 메서드를 스택으로 푸시하는 것을 싫어합니다. 나는 하나의 작업에서 내가 수행 한 모든 작업에 대해 카운터를 증가시키는 것을 고려했다. 카운터에 따라 원하는 롤백 종류를 결정하지만, 다시 말해 그러한 코드의 유지 관리가 어려워진다.

"트랜잭션"과 "롤백"에 대한 검색 결과가 DB와 관련되어 있으며 일반적인 유형의 코드에 잘 맞지 않습니다. 누구나 체계적으로 평면화하는 방법에 대해 좋은 생각이 있습니다. 이 극악?

+0

왜 스택 방법을 좋아합니까? 그것을하는 완벽한 방법처럼 보입니다. – carlpett

답변

5

Context Manager objectswith 성명을 사용하면 상황이 개선되지 않습니까? 특히 with 문이 다중 컨텍스트 표현식을 지원하는 Python 버전을 2.7 또는 3.x로 사용할 수 있다면. 다음은 예입니다 :

class Action(object): 
    def __init__(self, count): 
     self.count = count 
    def perform(self): 
     print "perform " + str(self.count) 
     if self.count == 2: 
      raise Exception("self.count is " + str(self.count)) 
    def commit(self): 
     print "commit " + str(self.count) 
    def rollback(self): 
     print "rollback " + str(self.count) 
    def __enter__(self): 
     perform() 
     return self 
    def __exit__(self, exc_type, exc_value, traceback): 
     if exc_value is None: 
      self.commit() 
     else: 
      self.rollback() 

with Action(1), Action(2), Action(3): 
    pass 

당신은 작업이 종료되면, __enter__() 방법으로 실행하고 수행 할 위 Action, 같은 "트랜잭션"클래스의 집합에 코드를 이동해야 할 것 일반적으로 해당 __exit()__ 메서드가 호출 될 것이라고 보장됩니다.

제 예제는 귀하의 것과 정확히 일치하지 않습니다. __enter__() 메쏘드에서 무엇을 실행할 지, 그리고 with 문장의 몸체에서 무엇을 실행할지를 조정해야합니다. 이 경우 다음 구문을 사용할 수 있습니다 :

with Action(1) as a1, Action(2) as a2: 
    pass 

with 문의 신체 내에서 Action 개체에 액세스 할 수 있으려면.

+0

사용 예를 들려 줄 수 있습니까? – Izkata

+0

@이 카타 : 예제를 사용하여 답변을 업데이트했습니다. –

+0

와우, 그건 꽤 우아한 솔루션입니다 ... 두 작업 사이에서 중간 계산을 수행해야한다면 "함께"중첩해야합니다. BTW, 구문은 Python 2.6에서 동일합니까? 또는 당신이 의미했던 것은 2.7 이전의 "with"에 대한 단일 액션 이었습니까? – immortal

관련 문제