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

Rails의 우려 사항:우려 여부

Ruby on Rails를 사용해 본 적이 있다면 아마도 우려의 개념을 접했을 것입니다. 새 Rails 프로젝트를 시작할 때마다 app/controllers/concerns 디렉토리가 생성됩니다. 및 app/models/concerns . 그러나 무슨 우려가 있습니까? 그리고 Rails 커뮤니티의 사람들이 때때로 그들에 대해 나쁘게 말하는 이유는 무엇입니까?

빠른 개요

Rails Concern은 ActiveSupport::Concern을 확장하는 모든 모듈입니다. 기준 치수. 우려 사항이 모듈과 어떻게 다른가요? 가장 큰 차이점은 Rails에 대한 관심을 통해 다음과 같이 약간의 마법을 수행할 수 있다는 것입니다.

# app/models/concerns/trashable.rb
 
module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end

그 단어가 포함된 것을 볼 수 있습니다. Ruby 모듈에 약간의 Rails 탄수화물을 뿌린 것입니다. ActiveSupport::Concern 당신을 위해 당신이 포함된 블록 내에서 평가하려는 코드를 넣을 수 있습니다. 예를 들어 모델에서 쓰레기 논리를 추출하려고 합니다. included 우리가 한 일을 수행하고 나중에 다음과 같이 모델의 관심사를 포함할 수 있습니다.

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  # ...
end

이 시점에서 꽤 편리하고 순진하지 않습니까? 모델의 무게가 약간 줄었고 이제 Song 모델뿐만 아니라 다른 모델에서 휴지통을 재사용할 수 있습니다. 문제가 복잡해질 수 있습니다. 자세히 알아보도록 하겠습니다.

Mixin의 고전적인 예

우려 사항에 대해 더 깊이 들어가기 전에 이에 대한 설명을 더 추가하겠습니다. include SomeModule이 표시되면 또는 extend AnotherModule , 이것을 믹스인이라고 합니다. 믹스인은 다른 클래스에 추가할 수 있는 코드 세트입니다. 그리고 Ruby 문서에서 알 수 있듯이 모듈은 메서드와 상수의 모음입니다. 그래서 여기서 우리가 하는 일은 메소드와 상수가 있는 모듈을 다른 클래스에 포함시켜 그들이 사용할 수 있도록 하는 것입니다.

이것이 바로 Trashable로 우리가 한 일입니다. 우려. 우리는 모델 개체를 모듈로 폐기하는 일반적인 논리를 추출했습니다. 이 모듈은 나중에 다른 위치에 포함될 수 있습니다. 따라서 믹싱 Ruby와 Rails에서만 사용되는 디자인 패턴이 아닙니다. 그러나 사용되는 곳마다 사람들은 그것을 좋아하고 좋다고 생각하거나 싫어하지만 쉽게 통제할 수 없다고 생각합니다.

이것을 더 잘 이해하기 위해 우리는 그것들을 사용할 때의 몇 가지 장단점을 살펴볼 것입니다. 바라건대, 이를 통해 우려 사항을 언제 또는 사용해야 하는지에 대한 이해를 얻을 수 있습니다.

나는 모든 것을 가지고 있다

Trashable과 같이 우려되는 항목을 추출하기로 결정한 경우 이제 Trashable의 모든 기능에 액세스할 수 있습니다. 포함되어 있습니다. 이것은 큰 힘을 가져오지만 Richard Schneeman이 주제에 대한 자신의 블로그 게시물에서 말했듯이 "큰 힘은 복잡한 코드를 만드는 큰 능력을 낳습니다." 그는 의존할 수도 있는 복잡한 코드를 의미했습니다.당연한 귀하의 관심사에 있습니다.

Trashable 한 번 더:

module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end

문제의 논리는 trashed 필드는 우려 사항이 포함된 모든 곳에 존재합니다. 오른쪽? 큰 문제가 아닙니다. 이것이 결국 우리가 원하는 것입니다. 그러나 내가 본 것은 사람들이 모델의 다른 것들을 관심으로 끌어들이고자 하는 유혹을 받는다는 것입니다. 이것이 어떻게 일어날 수 있는지 그림을 그리려면 Song 모델에 다른 메소드 featured_authors가 있습니다. :

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end

더 잘 설명하기 위해 Album을 추가했습니다. Trashable도 포함하는 모델 .그런 다음 해당 노래와 앨범의 추천 작성자에게 휴지통이 생겼을 때 알리고 싶다고 가정해 보겠습니다. 사람들은 다음과 같이 우려 사항에 이 논리를 집어넣고 싶어할 것입니다.

module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
 
    notify(featured_authors)
  end
 
  def notify(authors)
    # ...
  end
end

바로 여기에서 상황이 약간 복잡해지기 시작합니다. Song 모델 외부에 로직을 트래싱하므로 Trashable에 알림을 넣고 싶을 수 있습니다. 우려. 거기에서 "잘못된" 일이 발생합니다. featured_authors Song에서 가져옴 모델. 알겠습니다. 요청 검토 및 CI 확인을 통과했다고 가정해 보겠습니다.

그런 다음 몇 달 후 개발자가 featured_authors를 표시하는 방식을 변경해야 하는 새로운 요구 사항이 설정됩니다. 노래를 위해. 예를 들어, 새로운 요구 사항은 유럽의 추천 작성자만 표시하려는 것입니다. 당연히 개발자는 추천 작성자가 정의된 위치를 찾아 편집합니다.

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true).where(region: 'Europe')
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  # ...
end

이것은 우리가 작가를 보여줄 때마다 잘 작동하지만 프로덕션에 배포한 후에는 세계의 다른 지역에서 온 사람들에게 더 이상 노래에 대한 알림이 표시되지 않습니다. 이러한 실수는 우려 사항을 사용할 때 저지르기 쉽습니다. 위의 예는 단순하고 인위적인 것이지만 "야생"에 있는 것은 매우 까다로울 수 있습니다.

여기서 위험한 것은 문제(mixin)가 포함되는 모델에 대해 많이 알고 있다는 것입니다. 이것이 순환 종속성이라고 불리는 것입니다. . SongAlbum Trashable에 의존 휴지통용, Trashable featured_authors에 대해 둘 다에 의존 정의. trashed 필드가 Trashable을 가지려면 두 모델에 모두 존재해야 합니다. 작업에 대한 우려

이것이 무관심 클럽이 반대하고 친관심 클럽이 찬성하는 이유입니다. 먼저 Trashable 버전 내 코드베이스에서 함께 갈 것입니다. 더 나은 알림 없이 두 번째 버전을 만드는 방법을 살펴보겠습니다.

너희들은 어디에서 왔니

Trashable을 되돌아보면 알림과 함께 우리는 그것에 대해 뭔가를 해야 합니다. 우려 사항을 사용할 때 발생하는 또 다른 일은 우리가 일을 과도하게 건조시키는 경향이 있다는 것입니다. 데모 목적으로 또 다른 우려 사항을 생성하여 기존 모델에 그렇게 하도록 합시다. 이것은):

module Authorable
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
end

그런 다음 SongAlbum 다음과 같이 표시됩니다.

class Song < ApplicationRecord
  include Trashable
  include Authorable
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
  include Authorable
 
  # ...
end

우리는 모든 것을 말렸지만 이제 유럽의 추천 작가에 대한 요구 사항이 충족되지 않습니다. 설상가상으로 이제 Trashable 관심 및 모델은 Authorable에 따라 다릅니다. . 도대체? 얼마 전 우려 사항을 다룰 때 정확히 내 질문입니다. 방법의 출처를 추적하기가 어렵습니다.

이 모든 것에 대한 나의 해결책은 featured_authors를 유지하는 것입니다. 최대한 모델에 가깝게 notify 방법은 해서는 안 됩니다. Trashable의 일부가 됩니다. 전혀 걱정. 각 모델은 특히 다른 하위 그룹에 알리는 경향이 있는 경우 자체적으로 이를 처리해야 합니다. 덜 고통스럽게 하는 방법을 살펴보겠습니다.

 
# Concerns
module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end
 
module Authorable
  has_many :authors
 
  # Other useful methods that relate to authors across models.
  # If there are none, ditch the concern.
end
 
# Models
class Song < ApplicationRecord
  include Trashable
  include Authorable
 
  def featured_authors
    authors.where(featured: true).where(region: 'Europe')
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
  include Authorable
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end

이러한 문제는 관리할 수 있으며 너무 복잡하지 않습니다. notify을 건너뛰었습니다. 다른 날의 주제가 될 수 있으므로 앞서 설명한 기능입니다.

최종 보스

Rails 제작자인 Basecamp의 경우 다른 문제를 언급하는 문제는 얼마 전 트윗에서 설명한 DHH처럼 완벽하게 괜찮아 보입니다.

코드 스크린샷을 보면 놀라거나 소름이 끼칠 정도로 입을 벌리고 있습니다. 나는 여기에 중간이 없다고 느낀다. 이 코드를 편집할 기회가 있다면 "최종 우려 보스 싸움"으로 구상하고 싶습니다. 그러나 농담과 별개로 여기서 흥미로운 점은 어떤 관심사가 어느 것에 의존하는지를 말하는 댓글이 있다는 것입니다. 살펴보세요:

  # ...
 
  include Subscribable # Depends on Readable
  include Eventable    # Depends on Recordables
 
  # ...

이와 같은 주석을 다는 것은 도움이 될 수 있지만, 특히 코드베이스를 처음 접하는 경우에는 여전히 대략적인 작업을 수행하도록 설정되어 있습니다. 새로운 사람이 되고 코드에 있는 모든 "문제"를 인식하지 못하는 것은 확실히 당신을 우려의 하향 나선형으로 떨어뜨릴 수 있습니다.

이와 같은 것이 DHH가 토론 내부의 주석에서 공유한 것입니다. 내부 응답 트윗은 이 코드베이스로 작업하는 사람들이 이러한 문제와 어떻게 상호 작용해야 하는지 묻습니다. DHH는 작성된 문서가 많지 않고 거의 고용하지 않기 때문에 팀이 문서에 대해 잘 알고 있다고 답합니다.

그러나 코드베이스와 이를 사용하는 주장을 잘 알고 있는 경험 많은 팀이 있다는 것은 이상하고 강력하지 않습니다. 사용하느냐 마느냐가 더 중요한 것 같아요. 모듈이 제공하는 다중 상속이 더 편합니까, 아니면 구성을 선호합니까? 당신의 전화입니다.

결론

우리가 보았듯이 우려는 코드를 추출하고 건조하는 데 유용한 구문을 제공하는 모듈에 불과합니다. 당신의 벨트 아래에 더 유용한 도구가 있다면 문제에 대해 즉시 연락해서는 안 됩니다. 첨부 파일 처리 및 예제에서 보여준 쓰레기 처리 논리와 같은 동작은 모듈로 추출하기에 좋은 후보일 수 있습니다(우려).

일반적으로 우려 사항과 모듈을 다룰 때 가능한 좋은 점과 나쁜 점을 볼 수 있기를 바랍니다. 어떤 코드도 완벽하지 않다는 것을 명심하십시오. 그리고 결국, 시도도 하지 않고 실패하거나 성공할 가능성이 있는 경우에 무엇이 당신에게 좋고 무엇이 나쁜지 어떻게 알 수 있습니까?

완벽한 솔루션은 없으며 블로그 게시물에서 Rails의 우려 사항을 이해하기를 바랍니다. 항상 그렇듯이 판단을 내리고 장단점을 파악하십시오.

다음 편까지, 건배!

추신 Ruby Magic 게시물이 언론에 공개되는 즉시 읽고 싶다면 Ruby Magic 뉴스레터를 구독하고 게시물을 놓치지 마세요!