[ruby-on-rails] OO Design in Rails : 물건을 넣을 곳

나는 Rails를 정말로 즐기고 있으며 (일반적으로 RESTless 임에도 불구하고) Ruby가 OO 인 것을 좋아합니다. 그럼에도 불구하고 거대한 ActiveRecord 서브 클래스와 거대한 컨트롤러를 만드는 경향은 아주 당연합니다 (리소스별로 컨트롤러를 사용하더라도). 더 깊은 객체 세계를 만들려면 클래스 (및 모듈)를 어디에 두겠습니까? 뷰 (헬퍼 자체?), 컨트롤러 및 모델에 대해 묻고 있습니다.

Lib은 괜찮 습니다. 개발 환경에서 다시로드 할 수있는 솔루션을 찾았 지만이 작업을 수행하는 더 좋은 방법이 있는지 알고 싶습니다. 나는 수업이 너무 커지는 것에 대해 정말로 걱정하고 있습니다. 또한 엔진은 어떻습니까?



답변

Rails는 MVC 측면에서 구조를 제공하기 때문에 사용자에게 제공 되는 모델, 뷰 및 컨트롤러 컨테이너 사용하는 것이 당연 합니다. 초보자 (및 일부 중간 프로그래머)의 일반적인 관용구는 앱의 모든 논리를 모델 (데이터베이스 클래스), 컨트롤러 또는 뷰에 넣는 것입니다.

어느 시점에서 누군가 “지방 모델, 스키니 컨트롤러”패러다임을 지적하고, 중간 개발자는 서둘러 컨트롤러에서 모든 것을 소비하고이를 모델로 던져 애플리케이션 로직의 새로운 쓰레기통이되기 시작합니다.

실제로 스키니 컨트롤러는 좋은 생각이지만 모델에 모든 것을 넣는 추론은 실제로 최고의 계획은 아닙니다.

Ruby에는 모듈화를위한 몇 가지 좋은 옵션이 있습니다. 상당히 인기있는 대답은 lib메소드 그룹을 보유한 모듈 (보통 스태킹 )을 사용한 다음 해당 클래스에 모듈을 포함시키는 것입니다. 여러 클래스에서 재사용하려는 기능 범주가 있지만 기능이 클래스에 개념적으로 첨부되어있는 경우에 유용합니다.

모듈을 클래스에 포함 시키면 메소드는 클래스의 인스턴스 메소드가되므로 톤을 포함하는 클래스로 끝납니다. 방법을, 그들은 단지 여러 파일에 잘 정리하고 있습니다.

이 솔루션은 어떤 경우에는 잘 작동 할 수 있습니다. 다른 경우 에는 모델, 뷰 또는 컨트롤러 가 아닌 코드에서 클래스를 사용하는 것이 좋습니다.

그것에 대해 생각하는 좋은 방법은 “단일 책임 원칙”인데, 이는 클래스가 단일 (또는 소수) 사물을 책임 져야한다고 말합니다. 모델은 애플리케이션에서 데이터베이스로 데이터를 유지해야합니다. 컨트롤러는 요청을 받고 실행 가능한 응답을 반환 할 책임이 있습니다.

해당 상자에 잘 맞지 않는 개념 (지속성, 요청 / 응답 관리)이있는 경우 해당 아이디어를 어떻게 모델링 할 것인지 생각할 수 있습니다 . 비 모델링 클래스를 앱 / 클래스 또는 다른 곳에 저장하고 다음을 수행하여 해당 디렉토리를로드 경로에 추가 할 수 있습니다.

config.load_paths << File.join(Rails.root, "app", "classes")

승객 또는 JRuby를 사용하는 경우 열망하는로드 경로에 경로를 추가 할 수도 있습니다.

config.eager_load_paths << File.join(Rails.root, "app", "classes")

결론은 일단 Rails에서이 질문을하는 지점에 도달하면 Ruby chops을 강화하고 Rails가 기본적으로 제공하는 MVC 클래스가 아닌 모델링 클래스를 시작할 차례입니다.

업데이트 : 이 답변은 Rails 2.x 이상에 적용됩니다.


답변

업데이트 : Rails 4에서 관심사 사용이 새로운 기본값 으로 확인 되었습니다 .

실제로 모듈 자체의 특성에 따라 다릅니다. 나는 보통 컨트롤러 / 모델 확장자를 앱 내의 / concerns 폴더에 넣습니다.

# concerns/authentication.rb
module Authentication
  ...
end

# controllers/application_controller.rb
class ApplicationController
  include Authentication
end



# concerns/configurable.rb
module Configurable
  ...
end

class Model
  include Indexable
end

# controllers/foo_controller.rb
class FooController < ApplicationController
  include Indexable
end

# controllers/bar_controller.rb
class BarController < ApplicationController
  include Indexable
end

/ lib는 범용 라이브러리에서 선호하는 선택입니다. 나는 항상 모든 응용 프로그램 특정 라이브러리를 넣는 lib에 프로젝트 네임 스페이스가 있습니다.

/lib/myapp.rb
module MyApp
  VERSION = ...
end

/lib/myapp/CacheKey.rb
/lib/myapp/somecustomlib.rb

Ruby / Rails 코어 확장은 일반적으로 구성 초기화 프로그램에서 발생하므로 라이브러리는 Rails 부 스트랩에 한 번만로드됩니다.

/config/initializer/config.rb
/config/initializer/core_ext/string.rb
/config/initializer/core_ext/array.rb

재사용 가능한 코드 조각의 경우 다른 프로젝트에서 재사용 할 수 있도록 종종 (마이크로) 플러그인을 만듭니다.

헬퍼 파일은 일반적으로 헬퍼 메소드 (예 : 폼 빌더)와 같이 헬퍼가 오브젝트를 사용할 때 클래스를 보유합니다.

이것은 실제로 일반적인 개요입니다. 보다 맞춤화 된 제안을 받으려면 특정 예에 대한 자세한 정보를 제공하십시오. 🙂


답변

… 거대한 ActiveRecord 서브 클래스와 거대한 컨트롤러를 만드는 경향은 매우 자연 스럽습니다 …

“거대한”은 걱정스러운 단어입니다 … 😉

컨트롤러가 어떻게 커지고 있습니까? 이상적으로 컨트롤러는 얇아 야합니다. 얇은 공기에서 규칙을 선택하면 컨트롤러 방법 (작업) 당 5 ~ 6 줄 이상의 코드를 정기적으로 가지고 있다면 컨트롤러가 너무 뚱뚱 할 것입니다. 헬퍼 기능 또는 필터로 이동할 수있는 중복이 있습니까? 모델에 적용 할 수있는 비즈니스 로직이 있습니까?

모델이 어떻게 커지나요? 각 반의 책임 수를 줄이는 방법을 찾고 있습니까? 믹스 인으로 추출 할 수있는 일반적인 동작이 있습니까? 아니면 도우미 클래스에 위임 할 수있는 기능 영역이 있습니까?

편집 : 비트를 확장하려고하면 너무 심하게 왜곡되지 않는 것이 좋습니다 …

조력자 : 생활하며 app/helpers주로보기를 더 단순하게 만드는 데 사용됩니다. 컨트롤러별로 다르거 나 (해당 컨트롤러의 모든보기에도 사용 가능) 일반적으로 사용 가능합니다 (module ApplicationHelper application_helper.rb에서).

필터 : 여러 작업에서 동일한 코드 줄이 있다고 가정합니다 (물론 사용 params[:id]하거나 이와 유사한 객체 검색 ). 이러한 중복은 먼저 별도의 메소드로 추상화 한 다음 클래스 정의에서 필터를 선언하여 조치에서 완전히 제거 할 수 있습니다 (예 🙂 before_filter :get_object. ActionController 레일 가이드의 6 절을 참조하십시오 . 선언적 프로그래밍을 친구로 십시오.

리팩토링 모델은 좀 더 종교적인 것입니다. 예를 들어 Bob 아저씨의 제자들은 SOLID 의 다섯 계명을 따를 것을 제안 합니다. Joel & Jeff 나중에 좀 더 화해 된 것처럼 보이지만 보다 실용적인 접근 방식을 추천 할 수 있습니다 . 클래스에서 속성의 명확하게 정의 된 하위 집합에서 작동하는 하나 이상의 메서드를 찾는 것이 ActiveRecord 파생 모델에서 리팩토링 될 수있는 클래스를 식별하는 방법 중 하나입니다.

그런데 Rails 모델은 ActiveRecord :: Base의 서브 클래스 일 필요는 없습니다. 또는 다른 방식으로 표현하기 위해 모델은 테이블과 유사하거나 전혀 저장된 것과 관련이 없어도됩니다. app/modelsRails의 규칙 에 따라 파일 이름을 지정 하는 한 (레일 이름을 찾기 위해 클래스 이름에서 #underscore를 호출하면) Rails는 require필요 없이 파일을 찾습니다 .


답변

다음은 “얇은 컨트롤러”철학에서 비롯된 지방 모델을 리팩토링하는 것에 대한 훌륭한 블로그 게시물입니다.

http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

기본 메시지는 “뚱뚱한 모델에서 믹스 인을 추출하지 마십시오”입니다. 대신 서비스 클래스를 사용하십시오.


답변