2010-08-12 8 views
9

좋아, 여기서 불꽃 전쟁을 시작하려하지 않고 정적 언어와 동적 언어 간의 논쟁이 여기 포함하여 여러 번 해쉬되었습니다. 그러나 나는 여기 누군가가 좀 더 밝힐 수 있기를 바랍니다. 길이는 유감 스럽지만 간단한 질문이 아닙니다. 아마도 간단한 대답이 아닙니다.동적 유형 언어로 리팩토링

Ruby, PHP 및 Javascript는 요즘 꽤 인기있는 언어이며, 많은 사람들이이를 방어하고 동적 유형 지정이 개발자를 다시 붙들 지 않는다고 주장합니다. 저는이 언어에 익숙하지 않고 더 큰 프로젝트를 위해이 언어를 사용하기를 원합니다. 그러나 여기에 직장에서 항상오고있는 기본적인 리팩토링 시나리오가 있습니다 (작업 == C#). 그 접근 방법이 궁금합니다. Ruby - 나는 OO 때문에 Ruby를 선택했다.

좋아, Ruby를 사용하고 있으며 Customer 개체를 작성합니다. 그것은 데이터베이스에서로드/저장/삭제하는 방법을 가지고 있습니다. 그것은 좋으며 사람들은 그것을 사용합니다. 나는 다른 것들에 대한 더 많은 메소드를 추가하고 사람들은 그것을 더 많이 사용합니다. 일부 매개 변수를 기반으로 주문 내역을 계산하는 방법을 추가합니다. 지금이 클래스는 시스템 전체에서 사용되고 있습니다. 그런 다음 언젠가 GetOrderHistory 메서드의 매개 변수를 변경하기로 결정했습니다. 그래서 :

  • 가 내가 생각했던 클라이언트 코드는 새로운 매개 변수를 전달하고 사용하기
  • 변경이 수정
  • 새로운 매개 변수를 사용하는 방법의 코드를 다시 작성
  • 방법에 새 매개 변수를 추가 방법

하지만 이제 어떻게해야합니까? 나는 수십/수백/whoknows 시스템에서 얼마나 많은 다른 장소를 변경해야합니다. Ruby 나 Javascript와 같은 동적 OO 언어에서는 어떻게해야할까요? 아주 잘 내 머리, 루비를 모르고의 상단 오프

, 나는이 개 바보 답변을 생각할 수 있습니다

  1. 100 %의 코드 커버리지. 나는 전체 응용 프로그램을 테스트하고 그것이 깨질 때마다 그 방법인지 확인하고 고칠 수 있습니다.
  2. 찾기 및 바꾸기. 그 방법을 찾기 위해 텍스트 검색을 사용합니다. 그러나 동일한 메소드 이름을 가진 다른 객체를 가질 수 있습니다.

이렇게 좋은 대답이 있습니까? IDE가 어려움을 겪을 것 같습니다. 내가

c = Customer.new 

과 같은 코드를 가지고 있다면 그것을 알아낼 수있을 것입니다,하지만

c= SomeFunctionThatProbablyReturnsACustomerButMightReturnOtherThings() 

을 무엇을한다면 어떤 방법을 사용하면 루비 전문가들은이 경우에 걸릴까요?

+0

리팩토링이 기존 계약을 깨뜨리지 않아야한다고 확신합니다. – CurtainDog

+0

@CurtainDog 라이브러리 내에서 개인 함수의 이름을 바꾸면 어떨까요? – Toskan

+0

또 다른 좋은 예는 루비와 파이썬입니다. 루비 나 파이썬이 새 버전을 발표 할 때 방금 말한 것에 충실 할 수 있다는 점을 상기시켜 주시겠습니까? – Toskan

답변

3

하나는 사전에 테스트를 작성해야한다는 것입니다 방법에 대해 설명합니다. 이론적으로 이것은 뭔가 다른 것이 바뀌면 앱이 어디서 변경되어야 하는지를 정확하게 보여줍니다.

그러나 이것은 빙산의 꼭대기에 불과합니다. 루비는 짧고 표현적인 기능, 모듈에서의 책임 분담, 코드의 비 반복 (DRY), 최소한의 놀라움의 원칙 등과 같은 특정 지침을 염두에두고 설계되었습니다. 첫 번째 테스트, 매개 변수를 해시 옵션으로 전달, 메타 프로그래밍을 현명하게 사용하는 것과 같은 일련의 권장 사례가 추가되었습니다. 다른 동적 언어에서도이를 수행 할 것으로 확신합니다.

c이 고객이 아니면 적어도 과 같습니다. IDE는 특정 클래스의 인스턴스를 확인하는 것보다 유연한 오리 타이핑을 찾을 수 있습니다.

일부 IDE (Rubymine 이상)도 규칙을 고수합니다. 예를 들어 Rails 애플리케이션에서 Rubymine은 스키마 파일로 이동하여 모델 등록 정보를 메소드로 추가합니다. 또한 연관 (has_many, belongs_to 등)을 인식하고 Rails가 생성하는 해당 메소드를 동적으로 추가합니다.

이제는 최소한 리팩토링에 대한 필요성을 줄여줍니다. 하지만 확실히 은 문제를 해결하지 못합니다.. 그리고 나는 그것이 해결 될 수 있다고 생각하지 않는다.

+0

좋은 통찰력, 감사합니다. 오리 타이핑 아이디어는 특히 흥미 롭습니다. 나는 더 자세히 살펴볼 것입니다. 또한, 다른 게시물 여기에, 누군가가 흐름 분석을 언급, 내가 생각보다 지능형 사전 컴파일 일은 런타임 유형이 될 수 있습니다 알아낼 수 있습니다. 비록 복잡하지만 ... – LoveMeSomeCode

+1

도 논란의 여지가 없지만, 테스트의 아이디어는 나를 귀찮게합니다. 테스트 자체가 아닙니다. 왜냐하면 모든 훌륭한 코드는 철저한 단위 테스트를해야한다고 생각하기 때문입니다. 많은 사람들은 타입 설명자를 필요로하지 않기 때문에 동적 언어가 덜 장황하다고 주장 할 것입니다.하지만 타입 안전성에 관해 사람들이 말할 때 그들은 추가 테스트의 필요성을 언급 할 것입니다. 어떤 종류의 코드는 간결한 코드를 취소합니다 . 그냥 일반적인 관찰 ... – LoveMeSomeCode

+0

글쎄요, 유감입니다.하지만 당신은 할 수 없었습니다. 그리고 저는 심각합니다.이 개념들이 모든 프로그래밍 언어에 적용되어야한다고 주장합니까? 정말로 리펙토링 할 수 없다는 것이 큰 문제입니다. – Toskan

1

아마도이 질문에 대한 최상의 대답은 아니지만 향후 변경 사항을 처리하기 위해 해시를 허용하는 방법을 설계하는 경향이 있습니다.

예 :

def my_method(options = {}) 
    if options[:name] 
    ... 
    end 
end 

나는 고급 루비 사람들의 많은 메타 프로그래밍 패턴의 일종을 구현에 보일 것이다 생각합니다.

다른 옵션에는 원하는 기능을 수행하기 위해 하위 클래스에서 메소드를 오버라이드하는 것이 포함될 수 있습니다.

또는 당신이 듣게 될 것입니다 강한 인수

...에 대한
def get_order_history(required_param, options = []) 

    @required_param = required_param 

    if options[:do_something_else] 
    result = other_method(options[:do_something_else]) 
    else 
    result = ... 
    end 

    result  

end 

def other_method(something_else) 
    ... 
end 
+0

서브 클래 싱은 좋은 지적입니다. 그것이 게시 된 후에 고려해야 할 옵션 중 하나입니다.하지만 'db 스키마 변경으로 인해 메소드가 실제로 변경되는 경우, 이전 코드가 전혀 필요하지 않으며 모든 사용자가 새로운 방법을 사용 하시겠습니까? ' – LoveMeSomeCode