Object Oriented Method Bridge

Several resources on my system use the Java collections concept of object collections.

This Collection (abstract) class provides basic functions for another specific class, called lists, that let you find objects through collection indices.

I will use my HTTP header class as an example for explanation.

I have in my constructor an instance of this list class. Each HTTP header field is added to the collection through the Headers :: addHeader () method.

Obviously, I have a getter getHeaders () method that returns a Storage collection, not a Collection Object .

So, if I need to list the headers outside this class, I just need to call $ obj -> getHeaders () , and I have an ArrayObject with all the objects added.

Good!

But recently, it became necessary to use one of the List methods, Lists :: find () , which finds an object that does not even know the name of the object or its specific position in the Storage collection.

Since the List object is in a private property, Headers :: getHeaders () returns the collection store, and I do not want to violate encapsulation by making this property public, I cannot access this method.

Everything that I code, in addition to functionality, should be visually elegant and create another getter method, for example, getHeadersLists () will call, for example:

$obj -> getHeadersLists() -> find( 'foo' ); 

It's not beautiful!

So, I quickly added __call () to the header class and worked fine:

 $obj -> find( 'foo' ); 

But someone I know (and he is very versed in the topic "Object Orientation") told me that this is wrong.

My argument was focused on readability, and he counter-argued: "In Object Orientation, Magical methods and readability cannot coexist."

So what? What should I do to create this “bridge” between the two classes without using _call () and preserving the principles of object orientation?

I know, I could return the Collection object to Headers :: getHeaders () and use something like:

 $obj -> getHeaders() -> find(); 

But something that I learned about object orientation is a responsibility. The responsibility of this method, as stated in the statement, should return all the headers, not the external object.

+4
source share
2 answers

I intend to impress you with Uncle Bob aka's sole responsibility principle (SOLID Big S). Which you can read more about OOD Principles . Also, for a direct answer to your question, Tom Dalling is a very good article and example .

Single Responsibility Principle. Acknowledgment I have no rights or claims on this image.

The problem is, when you hide the call to the getHeaders () function, which returns an object of type Lists , it looks like you are calling the object and it has a function called find that it should not have "since it is not his responsibility to find the correct headers .

I understand your approach to responsibility.

You say: when I call getHeaders (), I should not force further manipulation of the result to get what I want.

This is your suggestion completely correct. But to achieve this result, hiding the call to getHeaders () with syntactic sugar is completely wrong. Because he will mislead me.

Consider me a third party reading your code, I would immediately suggest that there is a find () function of this class that is very misleading. Also, I would reject this find () function, since searching from a list of headers does not imply responsibility from an object, which is just an extra complement or error. So your colleague is also right: D.

I believe that faults arise here that make you call find () in order to be able to use an object of type Headings .

My suggestion for your dilemma is something like this.

  • This object must have a specific function called getHeaders (). Do not change this. It should return all headers.
  • Make a second funciton called getRelatedHeaders ("foo") or getFooHeaders (), which calls getHeaders () internally in an encapsulated form, which uses find ("foo") on them and returns your "foo" headers.

Now I have only one small sugestion left. I think your discussion raises a much more interesting question that you and your teammate should ask.

Almost always, if you need to get some kind of object and act on them. Then you can also encapsulate this functionality with this object / class. It almost always smells like code when you get a property of objects and use it to do something, and then bring it back.

Why does this object not fulfill its responsibility, but are you manipulating its properties for it?

Thanks for your time, I hope I helped you in some way: D.

+1
source

This is why there is a “protected” area in PHP, like other OO programming languages.

In case you know, a "protected" member can access descendant classes, but cannot be accessed as public.

As a rule, I usually do not use "private", but instead I defend myself, for the same reasons as your post.

0
source

Source: https://habr.com/ru/post/1389442/


All Articles