Understanding Class Interfaces

Asked 2 years ago, Updated 2 years ago, 48 views

I'm making a class with Ruby, but I'm wondering which interface is better.

Pattern A

class Hoge
  def piyo=(piyo_data)
    # do_something
    @piyo=piyo_data
  end

  def fuga=(fuga_data)
    # do_something
    @fuga=fuga_data
  end

  def send
    Api.call({
      piyo:@piyo,
      fuga —@fuga
    })
  end
end

# Usage
hoge = Hoge.new
hoge.piyo=piyo
hoge.fuga=fuga
hoge.send

Pattern B

class Hoge
  def send(piyo_data, fuga_data)
    Api.call({
      piyo: piyo(piyo_data),
      fuga —fuga(fuga_data)
    })
  end

  private
  def piyo(piyo_data)
    # do_something
    piyo_data
  end

  def fuga(fuga_data)
    # do_something
    fuga_data
  end
end

# Usage
hoge = Hoge.new
hoge.send(piyo, fuga)

Pattern A seems troublesome to the user to set the data using each method.Pattern B appears confusing when arguments are increasing.

ruby

2022-09-30 16:21

2 Answers

I think it's close to Ruby's culture to have every means available as a library.

class Hoge
  def initialize(piyo_data=nil, fuga_data=nil)
    piyo=piyo_data if piyo_data
    fuga=fuga_data if fuga_data
  end

  def piyo=(piyo_data)
    @piyo=piyo(piyo_data)
  end

  def fuga=(fuga_data)
    @fuga=fuga(fuga_data)
  end

  def send(piyo_data=nil, fuga_data=nil)
    Api.call({
      piyo:(piyo_data?piyo(piyo_data):@piyo),
      fuga: (fuga_data?fuga(fuga_data):@fuga)
    })
  end

  private
  def piyo(piyo_data)
    # do_something
    piyo_data
  end

  def fuga(fuga_data)
    # do_something
    fuga_data
  end
end

# Usage
# Set at initialization
hoge=Hoge.new(piyo,hoge)
hoge.send
# Later Configuration
hoge.piyo=piyo
hoge.fuga=fuga
hoge.send
# Set on call
hoge.send(piyo, fuga)


2022-09-30 16:21

Pattern B doesn't make sense to create an instance in the first place.
Class method is fine (if you only send once).

class Hoge
  def self.send(piyo_data, fuga_data)
    piyopiyo=do_something(piyo_data)
    fuguga=do_something(fuga_data)
    Api.call(piyo:piyopiyo, fuga:fuguga)
  end
end

Hoge.send('foo', 'bar')

If piyo_data, fuga_data is used outside of send, you must generate an instance.
In that case, it would be better to use initialize instead of substituting one by one.

class Hoge
  def initialize(piyo_data, fuga_data)
    @piyo_data, @fuga_data=piyo_data, fuga_data
  end

  def send
    piyopiyo=do_something(piyo_data)
    fuguga=do_something(fuga_data)
    Api.call(piyo:piyopiyo, fuga:fuguga)
  end

  def inspect
    "piyo_data:#{@piyo_data}, fuga_data:#{@fuga_data}"
  end
end

hoge=Hoge.new('foo', 'bar')
hoge.send
hoge.inspect

Well, what's good depends on the situation, so I don't think I can say for sure in this abstract code.

Add)

"I wrote ""depending on the situation"" briefly, but I'll give you just one example of what kind of situation it is."

  • How much does send cost (e.g., processing time)
  • How often do you expect send to run?
    • How many times a day?
    • Thousands of times per second?
  • do_something is heavy or relatively light (doesn't it matter if you run it a few thousand times a second?)
  • Does the
  • piyo_data, fuga_data value change or not after do_something?
    • Do I need to keep the original value if it changes?
  • do_something should be done immediately before send (depending on the time and state of the send destination), or can I do it as soon as piyo_data, fuga_data is given?
  • etc.
  • How many times a day?
  • Thousands of times per second?
  • Do I need to keep the original value if it changes?

I have written a lot of things, but if you are developing it with an individual or small team, you can implement it in a way that you think is good and refactoring (although it's not exactly refactoring because the interface changes).

When you first create something that assumes all the conditions, you often end up having functions that you don't use or having difficulty refactoring.
It is easier to give birth than to worry!
For now, I personally think it would be good to make the minimum and gradually improve it.

However, if you are creating a library to publish to public, or if you can't easily change the interface for a large project, it will be different.


2022-09-30 16:21

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.