Actually, I don't think that is the argument. Everyone here agrees that composition is superior. I think the argument is whether (in PHP) that inheritance should ever be used. My conjecture was that there are common use cases where (in PHP) inheritance can do the same thing as composition but with simpler syntax and less work.Jenk wrote:The argument is: Composition vs Inheritance.
Namespaces and abstract class names
Moderator: General Moderators
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: Namespaces and abstract class names
(#10850)
Re: Namespaces and abstract class names
+120%
There are 10 types of people in this world, those who understand binary and those who don't
Re: Namespaces and abstract class names
Heh, it's certainly digressed from the original topic anyway 
But on that note, I try to avoid inheritance where possible.
But on that note, I try to avoid inheritance where possible.
Re: Namespaces and abstract class names
@Jonah

And not any IDE can show you when methods are in conflict. Only netbeans that I know of, and my netbeans project cache always seems to go bad and code completion and the like stop working. I also work with a guy who uses vim, he refuses to use IDEs, you could have team mates like that some day...
@Vlad
@Jenk
Wanted? Sure. Needed? No. I have a need for objects because I can't structure code w/o them, there is no physical way to do it. I only "want" inheritance though, I don't need it.
In javascript there is one way to define a class IMO, which is to create a function with closures. The essence of prototypical inheritance is adding methods to a class after it's defined, I don't really count that as a second method but even if I did that's still not 4 methodsLooks like I've gotten sucked into the conversation![]()
Right. That's a situation where normal inheritance can't cut it, and composition saves the day.josh wrote:robot cannot inherit animal because robots aren't organisms! They shouldn't breathe() and sleep()!!! You're going to print_r() your object and get loads of unrelated information. That's a big code smell.
I think he means like this:josh wrote:4 ways to define a class in javascript? I know of only one, 'function'.Code: Select all
var MyClass = function () { this.something = function () { // ... } } // or var MyClass = {}; MyClass.prototype.something = function () { // ... }
It seems likely I'll know it? The example I gave was to point out that you may not.For one, if you want to name a method the same as a parent class's method, it seems likely that you know it, and want to override it. And two, any IDE can tell you if the method names are in conflict pretty much instantly. Netbeans for example puts a green circle with an "I" in it beside any overriding method.
And not any IDE can show you when methods are in conflict. Only netbeans that I know of, and my netbeans project cache always seems to go bad and code completion and the like stop working. I also work with a guy who uses vim, he refuses to use IDEs, you could have team mates like that some day...
I wouldn't say that you should use 100% composition just because you might need it.. I wouldn't go as far as making a hard & fast "rule", however inheritance is a code smell. The further from 100% you get, the less I like your codeSo you're saying that we should use 100% composition because we might need what it provides sometime in the future?
Well again, objects model concepts in our brain, which don't exist in a hierarchy. While you may be able to implement as a hierarchy at first, there is a high likelyhood of a user request that contradicts that. I don't know about you but I'd rather not tell my customer he has to pay extra for his feature because it doesn't fit into the way I envisioned the objects working a year ago.Seems like it would be pretty clear cut when a class hierarchy is going to need the functionality that only composition can provide right off the bat.
They don't, but refactoring from an abstract class to composition is easier than just refactoring composition.And how do abstract classes make refactoring difficult?
@Vlad
I didn't. A virtual method is the same thing as an abstract method, we already have it. It doesn't address any of the problems with abstract classes, it just encourages programmers to use more abstract classes (making their inherent problems more rampant!). If one of the things you listed means the same as prototypical inheritance then that one I'd be in favor of. In prototypical inheritance there are NO abstract classes though, I am AGAINST abstract classes.You can not argue against abstract classes, saying some features are missing, and then say that implementing these features sucks because their purpose is to serve abstract classes.
I don't think anyone said it should not be used, I did however say that implementing your code in this way limits your ability to add certain features in the future. Its the same as global variables, static code, or singletons. They have a use and they also have drawbacks. There are also alternative ways to structure your code that have the same uses with less drawbacks. Hence why more experienced programmers recommend staying away from those particular features.Christopher wrote:I think the argument is whether (in PHP) that inheritance should ever be used. My conjecture was that there are common use cases where (in PHP) inheritance can do the same thing as composition but with simpler syntax and less work.
@Jenk
In the same way your code needs to digress from a strict hierarchy sometimes your thread has to digress. lol. I'd be against splitting the thread though, unless the OP requests it.Heh, it's certainly digressed from the original topic anyway
I'd agree except for the "where possible", that implies inheritance is needed, which it is notBut on that note, I try to avoid inheritance where possible.
Re: Namespaces and abstract class names
I meant in cases where it is not in my control
I work fulltime with .NET now, and Inheritance is rife in the various frameworks.
Re: Namespaces and abstract class names
How about the following example for database abstraction (which I'm sure you're familiar with) - you want to support multiple databases but have the same interface. The usual approach is to create an abstract class that defines interface methods (such as query(), connect() and quote() etc) and extend it for the specific database vendors. How would you implement it better using composition instead of inheritance?
Re: Namespaces and abstract class names
As long as no implementation inheritance is needed simple interface would suffice.Eran wrote:How about the following example for database abstraction (which I'm sure you're familiar with) - you want to support multiple databases but have the same interface.
Re: Namespaces and abstract class names
You'd break out interfaces. For example maybe before a query we have to describe some fields, and the way we do that varies depending on the driver. I actually thought of this earlier and figured someone would ask.
For the parts that must vary (describing fields) you move it to another component & polymorphism takes over. Now people can use the "describer" even if their class isn't part of the DB package. All our method's are public and it obeys the single responsibility principle. Each responsibility is in a stand alone component that is not coupled to a bunch of other bloated code. To the person who just wants to describe fields, being able to call query() is just a distraction & would be regarded as bloat. These benefits sound cheesy for something like a database, but I'm sure you see the benefit.
Basically instead of separating at the method level, I'm saying the future will be in separating at the class level
(at least for those of us still living in the past). Its very likely describing those fields may take 20 other methods. Maybe one that sends the query, another method for parsing the string mysql sends back. Another method for breaking it out into an array, etc. Those could be public methods on the "describer" object. Heck, some of those methods could eventually become their own class if your database framework was really complicated.
One thing you may say is theres too many interfaces & classes, but each is in it's own file. You usually don't look at all of them at once. With an abstract class though, you have all of the methods for all of those classes in one big list. What could be worse as far as following single responsibility principle?
See, the above is the style that abstract classes can promote. A bunch of unrelated concerns in one big "god" interface, its a mess to read IMO, especially when your IDE decides to show it in alphabetical order. With composition, if my IDE put the methods in alphabetical order I'd thank the IDE, with an abstract class you may just end up cursing your IDE.
Code: Select all
// the only abstraction we do is to define our interface 'abstracly'
interface Db
{
function __construct(Db_Field_Describer $fieldDescriber );
function query();
function describeFields();
}
interface Db_Field_Describer
{
function describeThoseFields();
}
// the mysql "aspects" of the program:
class Db_Mysql impelements Db
{
}
class Db_Mysql_Field_Describer implements Db_Field_Describer
{
}
// the SQL lite "aspects" of the program
class Db_SQLLite implements Db
{
}
class Db_SQLLite_Field_Describer implements Db_Field_Describer
{
}
Basically instead of separating at the method level, I'm saying the future will be in separating at the class level
One thing you may say is theres too many interfaces & classes, but each is in it's own file. You usually don't look at all of them at once. With an abstract class though, you have all of the methods for all of those classes in one big list. What could be worse as far as following single responsibility principle?
Code: Select all
interface Db_Mysql
{
function describeFields();
protected function describeFieldsParseResults();
protected function describeFieldsExplodeResults();
function query();
protected function doQuery();
}
Re: Namespaces and abstract class names
If you only use interfaces, then you'll be repeating a lot of code - queries on SQL databases are very similar with only minor variations and so are connections and configuration (at least from the PHP side). I'd put some implementation for the general use-cases in the abstract Db class and override only when necessary (which isn't that often).
- Jonah Bron
- DevNet Master
- Posts: 2764
- Joined: Thu Mar 15, 2007 6:28 pm
- Location: Redding, California
Re: Namespaces and abstract class names
Good point Eran. But I think I can answer it for JoshEran wrote:If you only use interfaces, then you'll be repeating a lot of code - queries on SQL databases are very similar with only minor variations and so are connections and configuration (at least from the PHP side). I'd put some implementation for the general use-cases in the abstract Db class and override only when necessary (which isn't that often).
Code: Select all
class DbConnection {
private $dbStrategy;
_construct(Db $strategy) {
$this->dbStrategy = $strategy;
}
// logic common to all databases here
}
// usage
$db = new DbConnection(new Db_Mysql());Doesn't that seem a little extreme though? You could take it farther and continue to break it down to the very lowest level.josh wrote:One thing you may say is theres too many interfaces & classes, but each is in it's own file. You usually don't look at all of them at once. With an abstract class though, you have all of the methods for all of those classes in one big list. What could be worse as far as following single responsibility principle?
Re: Namespaces and abstract class names
It's not just connections, it's also queries and configuration. How do you account for the small differences between database vendors without ending up with a ton of tiny classes that each has one method or two? to me that sounds harder to maintain then just using a base abstract class that implements that common functionality. Not saying you can't do it, but for this purpose it seems like composition is being forced on principle when it doesn't make things simpler or better.Good point Eran. But I think I can answer it for JoshYou'd create another class like this:
And use that instead of directly using Db implementations.
Re: Namespaces and abstract class names
Have a look at the Hibernate project in Java for an example of how exactly that is done. There are IConnection, IQuery, IConfiguration interfaces, and implementations there of for the multitude of supported DB engines.
Already in the post asking What to do with different DBs you've listed a number of roles that, in your example, should be maintained by a single object - this is wrong. Each of those roles should be maintained by separate objects, and kept in a composite.
Already in the post asking What to do with different DBs you've listed a number of roles that, in your example, should be maintained by a single object - this is wrong. Each of those roles should be maintained by separate objects, and kept in a composite.
Re: Namespaces and abstract class names
That's like, your opinion, manthis is wrong
Seriously though, you can't say that is "wrong" - it is just different from the way you do it. You'll need to be more elaborate on why you think each simple operation needs its own class as opposed to being a method on a class that binds those operations together.
Re: Namespaces and abstract class names
Code: Select all
interface ICount
{
public function one($param);
public function all($param);
}
interface IOrder
{
public function one($param);
public function two($param);
}
class AClass implements \ICount, \IOrder
{
public function one($param1)
{
echo 'one: ' . $param;
}
public function two($param)
{
echo 'two: ' . $param;
}
}There are 10 types of people in this world, those who understand binary and those who don't
- Jonah Bron
- DevNet Master
- Posts: 2764
- Joined: Thu Mar 15, 2007 6:28 pm
- Location: Redding, California
Re: Namespaces and abstract class names
Hey, I didn't say that was the best way to do itEran wrote:It's not just connections, it's also queries and configuration. How do you account for the small differences between database vendors without ending up with a ton of tiny classes that each has one method or two? to me that sounds harder to maintain then just using a base abstract class that implements that common functionality. Not saying you can't do it, but for this purpose it seems like composition is being forced on principle when it doesn't make things simpler or better.