Well I was wondering, is there a way to pass func_get_args() to another method in the same class or to use it in the constructor of an object without explicitly calling func_get_args()? The idea is that I want to have a root class protected method to handle variable arguments passing using a class/object called Argument, which has some interesting methods to manipulate arguments/parameters. In this way, I do not have to call func_get_args() in every method that accepts variable number of arguments, while a special helper method will do the trick. Also func_get_args() always returns a PHP native array, I want such a function/method to return a collection object.

The problem is, func_get_args() is only available in the scope of the initial function call, if you call func_get_args() from second method in the first method, the argument list passed to the first method will not be available in the second method unless you explicitly pass func_get_args() in the method call. I was wondering if this following syntax is valid:

In theory, the func_get_args() default value in method b() is the argument list from client method call $obj->a($arg, $arg2, $arg3...). The idea is that func_get_args() will not be explicitly called in $this->b() method call, but I doubt PHP allows that. If not, is there another way to get around if I just dont want to explicitly write func_get_args() in every method that accept variable arguments?

TomB
—
2013-09-11T12:38:50Z —
#2

Hall_of_Famer said:

Well I was wondering, is there a way to pass func_get_args() to another method in the same class or to use it in the constructor of an object without explicitly calling func_get_args()? The idea is that I want to have a root class protected method to handle variable arguments passing using a class/object called Argument, which has some interesting methods to manipulate arguments/parameters. In this way, I do not have to call func_get_args() in every method that accepts variable number of arguments, while a special helper method will do the trick. Also func_get_args() always returns a PHP native array, I want such a function/method to return a collection object.

The problem is, func_get_args() is only available in the scope of the initial function call, if you call func_get_args() from second method in the first method, the argument list passed to the first method will not be available in the second method unless you explicitly pass func_get_args() in the method call. I was wondering if this following syntax is valid:

In theory, the func_get_args() default value in method b() is the argument list from client method call $obj->a($arg, $arg2, $arg3...). The idea is that func_get_args() will not be explicitly called in $this->b() method call, but I doubt PHP allows that. If not, is there another way to get around if I just dont want to explicitly write func_get_args() in every method that accept variable arguments?

func_get_args isn't a function. It's a language construct. It returns the arguments passed to the current function as an array.

Also, you cannot set the default value of an argument to anything other than a constant value.

Hall_of_Famer
—
2013-09-11T14:06:08Z —
#4

I see, what a pity. Guess I will be working on an Argument class then, the idea is to encapsulate func_get_args() though so that you don't need to call them explicitly in the methods that accept variable number of arguments.

QMonkey
—
2013-09-11T16:44:53Z —
#5

It isn't going to happen and you aren't going to save much anyway if you could. I'll convert your original sketch to something that would do what you want. You'll see it's almost the same. Yes, you have to put func_get_args() in there for each instance you want to use it, but that's not so bad, is it?

It isn't going to happen and you aren't going to save much anyway if you could. I'll convert your original sketch to something that would do what you want. You'll see it's almost the same. Yes, you have to put func_get_args() in there for each instance you want to use it, but that's not so bad, is it?

However, internal method chaining like that (using a direct $this->method() without going via a dependency) often hints at a poor separation of concerns. Is a() really just passing the arguments on to b()? For what purpose?

Really you have two different responsibilities here. Converting a set of args into an $argObject and utilising the $argObject which has been created. This is almost certainly a better solution:

Your code, as it stands, likely suffers from Flaw: Class Does Too Much because it has two entirely different responsibilities, formatting the arguments and processing them, by moving it into two different objects, the responsibility has moved. This frees up the extra responsibility that A had and it means that A never needs to worry about how/where its argObject was created. In terms of flexibility this opens you up to polymorphism and runtime configuration which would previously have been impossible.

Hall_of_Famer
—
2013-09-11T19:59:42Z —
#7

Oh I am sorry I did not explain the situation clear and instead used a poor example. I believe it has nothing to do with violating single responsibility rule, the fact is that in my application every class extends from a root class called Object, while the object class provides functionality needed by all classes(such as object comparison, hash code computation, serialization etc). Since it's possible for all classes to have methods that accept variable number of arguments, I am considering designing a method in the root object class that handles this situation so that each child class do not have to call func_get_args() and play with the array it returns. This method is called Object::getArgs(), which returns an Argument object that contains detailed information for all parameters passed into the method. If func_get_args() can be sent from one method to another without explicit declaration, the following code will work nicely:

In this way, func_get_args() is only directly accessed and used by the root object class, Id say its a really nice approach to encapsulate this function and subsequent operations based on it. Unfortunately, the code above wont work since PHP's func_get_args() has a serious scope issue, for this reason child classes will always have to pass func_get_args() explicitly into the parent method Object::getArgs(), it then becomes Object::getArgs(func_get_args()). It takes more typing for sure, but a bigger concern is elegance, at least for me. Thats why I've been seeking ways to perfectly encapsulate func_get_args(), looks like the most ideal approach won't work out for me. I will have to think of another way then, such as having clients creating argument object explicitly like this:

And the argument object's constructor will handle func_get_args() and its subsequent operations instead. Id say its better than having each variable argument methods calling func_get_args() at least, but still not as good as the first approach I proposed. sigh

TomB
—
2013-09-11T20:38:20Z —
#8

I would definitely suggest that making everything inherit from a base class clearly violates SRP because you are, by definition, adding extra responsibilities to each class which extends it. Inheritance, in most cases, is a bad idea. Let's take serialisation as an example since you mentioned it:

This:

$object->serialize();

Is less useful than:

$serializer->serialize($object);

Why? Because the serialize behaviour is a different behaviour than the responsibility of whatever the object is. The serializer could do a standard php serialize or serialize to JSON, serialize to a url encoded form string or anything. To achieve this using $object->serialize() you either need a switch statement in the serialize method, which will only ever be able to serialize into formats that the serialize method supports, or you need to add a specific serialization method for each type. $object->serializeToJson(); for example.

This is a perfect example of polymorphism in action, you can pass a fully constructed $serialize object around, and it will serialize it into a format decided at the point when $serialize was created. Using $obj->serialize() the serialisation method is hard coded because it's based on the return value of the object's serialization method.

Your problem is definitely that you have a poor separation of concerns. Extending all objects from a base class is a bad idea because it severely reduces portability of individual components.

Jeff_Mott
—
2013-09-11T21:09:57Z —
#9

TomB said:

I would definitely suggest that making everything inherit from a base class clearly violates SRP because you are, by definition, adding extra responsibilities to each class which extends it. Inheritance, in most cases, is a bad idea. Let's take serialisation as an example since you mentioned it:

This:

`php

$object->serialize();

`

Is less useful than:

`php

$serializer->serialize($object);

`

Why? Because the serialize behaviour is a different behaviour than the responsibility of whatever the object is. The serializer could do a standard php serialize or serialize to JSON, serialize to a url encoded form string or anything. To achieve this using $object->serialize() you either need a switch statement in the serialize method, which will only ever be able to serialize into formats that the serialize method supports, or you need to add a specific serialization method for each type. $object->serializeToJson(); for example.

This is a perfect example of polymorphism in action, you can pass a fully constructed $serialize object around, and it will serialize it into a format decided at the point when $serialize was created. Using $obj->serialize() the serialisation method is hard coded because it's based on the return value of the object's serialization method.

Your problem is definitely that you have a poor separation of concerns. Extending all objects from a base class is a bad idea because it severely reduces portability of individual components.

Like, +1, Upvote, etc.

Hall_of_Famer
—
2013-09-11T23:06:49Z —
#10

TomB said:

I would definitely suggest that making everything inherit from a base class clearly violates SRP because you are, by definition, adding extra responsibilities to each class which extends it. Inheritance, in most cases, is a bad idea. Let's take serialisation as an example since you mentioned it:

This:

`php

$object->serialize();

`

Is less useful than:

`php

$serializer->serialize($object);

`

Why? Because the serialize behaviour is a different behaviour than the responsibility of whatever the object is. The serializer could do a standard php serialize or serialize to JSON, serialize to a url encoded form string or anything. To achieve this using $object->serialize() you either need a switch statement in the serialize method, which will only ever be able to serialize into formats that the serialize method supports, or you need to add a specific serialization method for each type. $object->serializeToJson(); for example.

This is a perfect example of polymorphism in action, you can pass a fully constructed $serialize object around, and it will serialize it into a format decided at the point when $serialize was created. Using $obj->serialize() the serialisation method is hard coded because it's based on the return value of the object's serialization method.

Your problem is definitely that you have a poor separation of concerns. Extending all objects from a base class is a bad idea because it severely reduces portability of individual components.

Well you have a good point, I definitely try not to give the root class too much responsibility, definitely not what almost all subclasses actually use. The Object::hashCode() method for instance, is used by every subclass for equality comparison, so yeah its there for a reason. In my system the standard object serialization is far more common than Json-Serialization, which is why each object has a built-in serialize() method. Sure in minor cases when Json-serialization is needed, I will past the very object to a special Json-Serializer object, such cases are rare though. Maybe constructing argument object is not an appropriate responsibility for the root object, if so I will make some changes.

Anyway, there is a reason why almost all OO languages like Smalltalk, Java, C#, Objective-C, Python and Ruby there is a root object class that is parent to all classes. I dont think theres anything wrong with that, after all all objects/classes share certain behaviors, the bottom-line is to make sure the root class does not do more than what its supposed to, dont you agree?

TomB
—
2013-09-12T08:44:01Z —
#11

Hall_of_Famer said:

Well you have a good point, I definitely try not to give the root class too much responsibility, definitely not what almost all subclasses actually use. The Object::hashCode() method for instance, is used by every subclass for equality comparison, so yeah its there for a reason. In my system the standard object serialization is far more common than Json-Serialization, which is why each object has a built-in serialize() method. Sure in minor cases when Json-serialization is needed, I will past the very object to a special Json-Serializer object, such cases are rare though. Maybe constructing argument object is not an appropriate responsibility for the root object, if so I will make some changes.

Anyway, there is a reason why almost all OO languages like Smalltalk, Java, C#, Objective-C, Python and Ruby there is a root object class that is parent to all classes. I dont think theres anything wrong with that, after all all objects/classes share certain behaviors, the bottom-line is to make sure the root class does not do more than what its supposed to, dont you agree?

The same thing with hashCode() is it used by every object in the system, really? Does every object that even exists have its hashCode() used in some way or is hashCode() there in case you might, maybe, occasionally need it? Keep in mind that PHP already supports object comparison without you needing to write your own method to do it.

The problem is, the root class, by providing behaviour, is already doing more than it needs to. Classes, not just the root class, should expose as few behaviours as they possibly need to fulfil their sole responsibility. An object shouldn't understand the concept of serialization, it shouldn't understand that it needs to be hashed, these things are external behaviours that will act on the object, not behaviours which help the object fulfil its responsibility.

Think of it this way: The object will only provide those methods because the developer has made some decisions about what the object needs to do based on the environment in which the object will be sitting. This breaks encapsulation because the object is essentially aware of the system it's going to be used in and provides specific methods to allow for that. If you can remove a method from a class and the object still fulfils its (single!) responsibility then the method does not belong in the class.

Hall_of_Famer
—
2013-09-12T13:54:57Z —
#12

Well so you are saying that its actually a poor OO design for all these OO languages to extend from root object class? Never thought of this, maybe I will remove some methods from the root object class and make it as light-weight as possible, even as a marker. I'd say its still useful in type hinting though, in my collections framework for instance, these collections only accept object that belong to classes extending from the root object class.

TomB
—
2013-09-12T17:15:02Z —
#13

In strictly typed languages it makes sense for everything to inherit a base type for the purposes of hinting, and it would be useful to be able to type hint objects in PHP. Whether being able to type hint objects is worth the downsides when it comes to portability and flexibility is debatable and I'd err on the side of maximum flexibility. Since PHP has an object comparison operator, putting this in a base class is entirely redundant and will only add potential for inconsistency and confusion.

The issue here is type hinting. If you're type hinting a specific type then you're saying "This method must take an object of this type because it needs to call a specific method provided by this type". This ensures a contract between the object and the method. The method needs to call $object->something() so type hint the most primitive thing that has the something() method, be it an interface or a specific class. Only type hint what you need. Don't ask for a class which is 3 levels down an inheritance tree when the class at the top level provides the required methods, hint that instead as it will give you greater flexibility.

Usually, but even the article you cite gives a situation where they are acceptable.

ahundiak
—
2013-09-12T22:33:07Z —
#15

Hall_of_Famer said:

Well so you are saying that its actually a poor OO design for all these OO languages to extend from root object class? Never thought of this, maybe I will remove some methods from the root object class and make it as light-weight as possible, even as a marker. I'd say its still useful in type hinting though, in my collections framework for instance, these collections only accept object that belong to classes extending from the root object class.

So from an abstract point of view, you can say that php does indeed have a base class. Just no need to explicitly extend from it.

As far as collections go, define a collections interface and use it where applicable. No need for a fixed inheritance structure.

Michael_Morris1
—
2013-09-16T20:21:49Z —
#16

K(n) is your worst enemy as a programmer, and most design patterns are designed to fight it.

@Hall of Famer - What you are encountering is the conflicting goals of code reuse and code scope creep. While we definitely don't want to duplicate code, we also don't want a block of code that is a universal can opener because the more areas of code it must interact with, the harder it is to test. This is especially true of classes because, usually, they have some amount of internal state.

Functions don't - well, they shouldn't, even if it is possible to give a function internal state using static variables, but it's VERY BAD DESIGN(TM) to have a function with an internal state. Consider this tiny function

As a function array_sum could be called from anywhere. However, since it has no internal state it should be testable all the same. Also, it doesn't act on any data in the global scope, another common pitfall of PHP programming (If I ever teach a PHP class I will fail any assignment that uses the global statement, even if it works).

I'm digressing. The less code needs to know about the rest of the application, the better, even if any part of the application could call it. Scoping (private, protected, public) sets up barriers to contact between disparate blocks of code to make the application easier to work with in the long term, even if in the short term there are headaches. .