rubiconmd/injectable

Cannot use `super` in `call` with inheritance

Opened this issue · 3 comments

The following spec fails in master, I'm working on a fix, but it will be quite invasive (prepending modules generated at runtime, and aliasing the user-provided :call method so we can respect the method resolution and only use the topmost call(args)

  context 'when subclassing' do
    let(:service) do
      Class.new do
        include Injectable

        argument :num, required: true

        def call
          num + 2
        end
      end
    end

    let(:service_subclass) do
      Class.new(service) do
        def call
          super + 3
        end
      end
    end

    it 'respects inheritance' do
      expect(service_subclass.call(num: 1)).to eq 6
    end
  end

Hi @rewritten ! Thanks for reporting the issue.

In fact, I've been meaning to opening an issue against allowing inheritance in Injectable objects and proposing the removal of code that supports this and even making it more restrictive, so you can't make a class inherit from a class that uses Injectable. I could say you arrived just in time :)

The motivation for this is that I tried using inheritance and injectable in our codebase and we had to amend the library to play nicely with it. All was good.

Some time later, revisiting that part of the code has become harder since inheritance allows you to have Service Objects without any public method acting as an entrypoint, since it's on the parent class. Which is REALLY weird and feels bad. Not only that, the cognitive load is a lot even for me, author of the code, and it makes the learning curve for people approaching that part of the code very steep.

So, after being burnt with this myself, I'm fully convinced inheritance should not be allowed on Injectable objects, because it allows you to create service objects that are very convoluted, obscure, non-explicit and hard to read and follow.

It seemed like a great idea at the time, but time has proven me wrong 😅

Makes sense. What if we force the existence of a call method in subclasses, even if it's just calling super?

Hi @rewritten. Do you have a real use case for inheritance in SOs? Thanks!