Methods that receive buffer objects AND return another Object – is that bad design?

The Argument

Some say that if you write a method that receives a buffer, iT MUST RETURN VOID -> the buffer is your exit point.
Do not abuse the methods by receiving buffers AND returning a another object.

Example (BAD):
Object myMethod(String param1, String param2, Map<K,V> bufferMap)

Example (Better):
void myMethod(String param1, String param2, Map<K,V> bufferMap, Object obj)

The Counter Argument

Some say that this is fine and should not be a problem.

The Question

  • Is that a design problem ?
  • (If yes) What issuesimpacts could this kind of design have ?

EDIT

On the original question, I tried to keep it neutral to avoid any bias.
As pointed out by answers below, more context is needed since for some languages both implementations serve different purposes.

In my specific case, it is a on going discussion on a Java codebase.

Like all “must”, “always” or other imperial rules they’re more guideline than hard rules.

First what is Object to buffer? Is it the difference between before and after the call to MyMethod? Is it an Error status? Why do you need it?

I think the rule to returning “void” and without adding a parameter so plainly is true if the buffer itself is the result:

void myMethod(String param1, String param2, Map<K,V> bufferMap)

Now if you really need more information I tend to prefer return value since they allow writing:

Object res = myMethod(String param1, String param2, Map<K,V> bufferMap);

Instead of:

Object res;
myMethod(String param1, String param2, Map<K,V> bufferMap, res);

A use case I see is for error handling:

enum potentialResults { Error, nothingToDo, OK }
potentialResults res = myMethod(String param1, String param2, Map<K,V> bufferMap);
switch (res) {
  ...
}

3

First, these two forms are not equivalent:

  • returning some Object allows the callee to create or choose the object to return
  • passing in an object requires the caller to create the Object in advance!

Second, these are fairly low level details whose merits go to the specifics of the language in use.  We need to understand if the language has:

  • out parameters
  • references
  • multiple return values
  • struct or record or tuples
  • exceptions

Without these, it is low-level discussion but general across all languages, which is probably pointless!

1

Object myMethod(
    String param1, 
    String param2, 
    Map<K,V> bufferMap
)

Is not a problem if bufferMap is simply being “received”. It’s when it’s being changed by myMethod that things are getting confusing.

There is some wisdom behind this rule but it’s being masked with loose terms. Would a String count as a buffer? Why not?

I see the real issue as mixing return and out parameters. There isn’t a profound architectural reason. It’s about readability. Humans like to use one convention at a time. I don’t see anything special about a parameter being a buffer if you never change it. But if you do, while returning, then you’re expressing results in two different ways. That’s a bit confusing.

void myMethod(
    String param1, 
    String param2, 
    Map<K,V> bufferMap, 
    Object obj
)

When you’re mutating bufferMap that’s a bit less confusing. Since it returns void no ones going to confuse this with a side-effect-free pure function.

2

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *