Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby에서 정크 드로어 클래스 피하기

Ruby는 객체 지향 언어이기 때문에 세계를 객체 집합으로 모델링하는 경향이 있습니다. 두 개의 정수(x와 y)는 Point이고 Line에는 두 개의 정수가 있습니다.

이 접근 방식은 종종 유용하지만 한 가지 큰 문제가 있습니다. 그것은 다른 모든 것보다 데이터에 대한 한 가지 해석에 특권을 부여합니다. x와 y는 항상 점이고 셀이나 벡터로 작동하는 데 필요하지 않다고 가정합니다.

세포가 필요하면 어떻게 됩니까? 음, 포인트는 데이터를 소유합니다. 따라서 셀 메서드를 Point에 추가합니다. 시간이 지남에 따라 느슨하게 관련된 메서드의 쓰레기 서랍인 Point 클래스가 생깁니다.

정크 서랍 클래스는 너무 일반적이어서 우리는 종종 이를 불가피한 것으로 받아들이고 개발을 위한 "리팩토링" 단계를 밟습니다. 하지만 애초에 문제를 피할 수 있다면 어떨까요?

웹 개발의 첫 번째 규칙은 사용자 클래스

전투로 단련된 프로덕션 Rails 앱의 핵심에는 User라는 클래스의 거대한 괴물이 있습니다. .

그것은 항상 충분히 순진하게 시작됩니다. 사람들이 로그인하도록 하고 싶습니다. 사용자 이름과 비밀번호를 저장해야 하므로 클래스를 생성합니다.

class User
  attr_accessor :username, :password, :email, :address

  def authenticate!(password)
    ...
  end
end

그것은 사람들이 결국 당신에게 돈을 주고 싶어할 정도로 잘 작동합니다. "알겠습니다. 사용자는 기본적으로 구독자와 동일하므로 몇 가지 속성과 몇 가지 메서드만 추가하겠습니다."

class User
    ...

    attr_accessor :payment_processor_token, :subscription_plan_id, ...etc

    def charge_cc
      ...
    end
end

엄청난! 이제 우리는 실제 돈을 벌고 있습니다! CEO는 영업 팀이 SalesForce로 쉽게 가져올 수 있도록 사용자 연락처 정보가 포함된 VCard를 내보낼 수 있기를 원했습니다. vim을 실행할 시간:

class User
    ...

    def export_vcard
      ...
    end
end

우리는 무엇을 했는가?

인증을 처리하는 것이 유일한 목적인 User 클래스로 시작했습니다. 방법과 속성을 추가하여 사용자/구독자/연락처 Frankenstein 하이브리드로 전환했습니다.

우리는 왜 이것을 할까요? 우리는 개발자로서 스스로를 존중하지 않습니까? 우리 부모님이 우리를 충분히 사랑하지 않으셨나요? 아니면 이 데이터가 실제로 다음과 같다고 믿고 실패를 대비했습니까? 물건, 물건?

사용자 이름, 비밀번호 및 이메일 주소의 조합을 사용자라고 하는 이유는 무엇입니까? 구독자가 아닌 이유는 무엇입니까? 아니면 연락처? 아니면 SessionHolder입니까?

데이터에 대한 진실은 데이터라는 것입니다

데이터는 데이터일 뿐입니다. 오늘은 남자친구처럼 대해야 할 수도 있습니다. 내일은 전 남자친구일지도 모릅니다.

이것이 Elixir와 같은 함수형 언어가 취하는 접근 방식입니다. 데이터는 Ruby의 해시, 배열, 문자열 등과 같은 간단한 구조로 저장됩니다. 데이터로 무언가를 하고 싶을 때 함수에 전달합니다. 모든 결과는 해당 함수에서 반환됩니다.

간단해 보이지만 이 접근 방식을 사용하면 관심사를 여러 모듈로 쉽게 분리할 수 있습니다.

다음은 Elixir에서 사용자 시스템을 구성하는 방법에 대한 만화입니다.

my_user = %{username: "foo", password: ..., phone: ..., payment_token: ...}
my_user = Authentication.authenticate(my_user)
my_user = Subscription.charge(my_user)
my_user = Contact.export_vcard(my_user)

데이터는 코드와 분리되어 있기 때문에 해당 데이터에 대한 권한 있는 해석이 있는 모듈은 없습니다.

Ruby로 다시 가져오기

이 접근 방식은 Elixir에서 매우 잘 작동하므로 Ruby에서 채택하지 않겠습니까? User를 만드는 것을 막을 수 있는 것은 없습니다. 데이터를 위한 간단한 래퍼로 만들고 모든 비즈니스 로직을 모듈로 가져옵니다.

class User
  attr_accessor :username, :password, :email, :address
end

module Authentication
  def self.authenticate!(user)
    ..
  end
end

module Subscription
  def self.charge(user)
    ..
  end
end

module Contact
  def self.export_vcard(user)
    ..
  end
end

User 클래스를 구조체에 넣거나 코드를 추가하여 (일종의) 변경할 수 없도록 합니다.

그래서?

이것이 사소한 변화처럼 보입니까? 요점이 무엇입니까?

우리가 보았듯이, 전형적인 OO 접근 방식은 나이가 들면서 문제가 있습니다. 특정 클래스가 소유한다고 말함으로써 데이터를 다른 방식으로 사용해야 할 때 문제가 발생합니다.

그러나 모듈식 접근 방식에서는 동작을 추가해도 문제가 없습니다. 필요한 방식으로 데이터를 해석하는 새 모듈을 생성하기만 하면 됩니다. 데이터와 기능이 완전히 분리되어 있기 때문에 쉽게 할 수 있습니다.

기타 접근 방식

정크 드로어 문제를 방지하는 다른 접근 방식이 있습니다. 전통적으로 객체 지향 프로그래밍에서는 상속과 신중한 리팩토링을 통해 그렇게 하려고 했습니다. 2012년 Sandi Metz는 Ruby의 Practical Object Oriented Design을 발표했습니다. 이는 많은 사람들이 의존성 주입을 사용하여 객체를 작성하기 시작하도록 설득했습니다. 더욱 최근에는 함수형 프로그래밍의 인기로 인해 Rubyists가 변경할 수 없는 "데이터 개체"를 실험하게 되었습니다.

이 모든 접근 방식을 사용하여 깨끗하고 아름다운 코드를 만들 수 있습니다. 그러나 클래스가 일반적으로 데이터를 소유한다는 사실은 클래스가 무엇인지 클래스가 데이터로 수행하는 작업

이러한 접근 방식이 정크 드로어 문제를 피하는 데 어떤 성공을 거두든 간에 코드에서 데이터를 분리한 결과라고 생각합니다.