In oxid esales everybody likes to extend everything.
Its a bunch of happy ox-classes that just love each other, hug eachother and extend, make out the whooooooole day.
A simple example
oxI18n extends oxBase extends oxSuperCfg
Ok, I understand that you want every happy oxid-super-object to be able to read, write, delete the config, right?
But what the heck are you doing? Did you guys ever hear about design patterns?.
Maybe you should take a look at our friends from pureMVC. They have their patterns well organized in an extra folder:

It gets even better: The Super-Extender
When you want to create an oxoutput object with the following??modules?? loaded:
sub/suboutput1&sub/suboutput2&sub/suboutput3
it magically creates / extends / parties with your classes!
It uses a kind of extension g*ngb*ng function to hook up everyone with everything:
public function getClassName( $sClassName )
{
$aModules = $this->getConfig()->getConfigParam( 'aModules' );
if ( is_array( $aModules ) &&
array_key_exists( $sClassName, $aModules ) ) {
//multiple inheritance implementation
//in case we have multiple modules:
//like oxoutput
//=> sub/suboutput1&sub/suboutput2&sub/suboutput3
$aClassChain = explode( "&", $aModules[$sClassName] );
$sParent = $sClassName;
//security: just preventing string termination
$sParent = str_replace(chr(0), '', $sParent);
//building middle classes if needed
$sClassName =
$this->_makeSafeModuleClassParents( $aClassChain, $sParent );
}
// check if there is a path, if yes, remove it
$sClassName = basename( $sClassName );
return $sClassName;
}
....
/**
* Creates middle classes if needed.
*
* @param array $aClassChain Module names
* @param string $sBaseModule Oxid base class
*
* @throws oxSystemComponentException missing system
* component exception
*
* @return string
*/
private function _makeSafeModuleClassParents( $aClassChain, $sBaseModule )
{
$myConfig = $this->getConfig();
$sParent = $sBaseModule;
//building middle classes if needed
foreach ($aClassChain as $sModule) {
//creating middle classes
//e.g. class suboutput1_parent extends oxoutput {}
// class suboutput2_parent extends suboutput1 {}
//$sModuleClass = $this->getClassName($sModule);
//security: just preventing string termination
$sModule = str_replace(chr(0), '', $sModule);
//get parent and module class names from sub/suboutput2
$sParentClass = basename($sParent);
$sModuleClass = basename($sModule);
//P
//$sInitClass = "class ".$sModuleClass."_parent extends $sParentClass
//{ function ".$sModuleClass."_parent(){
// return ".$sParentClass."::".$sParentClass."();} }";
$sInitClass = "class ".$sModuleClass."_parent extends $sParentClass {}";
//initializing middle class
if (!class_exists($sModuleClass."_parent", false)) {
eval($sInitClass);
}
$sParentPath = $myConfig->getConfigParam( 'sShopDir' ).
"/modules/".$sModule.".php";
//including original file
if ( file_exists( $sParentPath ) ) {
require_once $sParentPath;
} elseif ( !class_exists( $sModuleClass ) ) {
//to avoid problems with unitest and only throw a
// exception if class does not exists MAFI
$oEx = new oxSystemComponentException();
$oEx->setMessage('EXCEPTION_SYSTEMCOMPONENT_CLASSNOTFOUND');
$oEx->setComponent($sModule);
}
$sParent = $sModule;
}
//returning the last module from the chain
$sClassName = $aClassChain[count($aClassChain) - 1];
return $sClassName;
}
So … with all the magic party stuff you end up having created / included these classes, all done by their wonderful __autload function:
- class oxoutput extends oxSuperCfg { … }
- class suboutput1_parent extends oxoutput {}
- class suboutput2_parent extends suboutput1 {}
- class suboutput3_parent extends suboutput2 {}
But what the hell is this stuff for?
A module like MyOrder extends MyOrder_parent. For what? Somebody enlighten me!
You extend non-existing classes just for the sake of creating them from the magic __autoload function, is that it?
Related post:
August 26, 2009 at 7:28 am |
[...] PHPterror took a closer look at some of the OXID code, really jaw-dropping stuff. [...]
August 26, 2009 at 8:05 am |
[...] PHPterror took a closer look at some of the OXID code, really jaw-dropping stuff. Original Link: http://phpkitchen.com/2009/08/phpterror-on-oxid-eshop/ [...]
August 26, 2009 at 8:06 am |
its always good if you extend something that is OOP, extend as much as possible
August 26, 2009 at 8:09 am |
Extend with sense in it. There are better solutions for realizing a config solution than having every single class extend you Super-Duper-Config-Object (watch out for the name of the class oxSuperCfg
August 26, 2009 at 8:56 am |
Im confused, was comment fom “OOP PHP Programming” a sarcasm? or for real?
Agree that alll funky shit like lets have multiple inheritance, or ‘lets do reflection and add methods’ or whatever is crazy. I mean its just asking for trouble especially if people dont expect this kind of crazy behavior.
As to extending … extend only if it really makes sense. Use interfaces instead and composition as primary OOP tool. Extending is not always so good.
If you are looking for a new project to slag … have a look at TYPO3 … its such a lump of crap ;- )
ps. please add more details in your articles, sometimes i cant follow your way of thinking.
August 26, 2009 at 9:03 am |
Hi Artur,
thanks for being aware of the quality problems we have in the “php world”. Good to know that there are more out there like me
I am sure that the comment from “OOP PHP Programming” was not ment to be sarcastic. I dont want to blame anyone for his way of coding, but raise awareness of the lack of quality in many
php projects. Just because a project is popular, does not mean that it is well designed and coded.
For “more details on the posts”: I try to keep it as short and sexy as possible. Its good if you do not always get it from the beginning. I think its necessary to have a look for yourself at the stuff I am pointing at and to question it yourself.
TYPO3 is definitely on the list… but the list is soooooo looooooooong
Thanks for reading!
August 26, 2009 at 9:44 am |
[...] oxid esales – The extend parade! « baaaaaad php usage exposed [...]
August 26, 2009 at 10:01 am |
From your blog post its clear you know your php
. And it’s obvious you don’t run a oxid shop yourself (yet). Pls let me enlighten you
These functions are actually part of the oxid module system. The oxid module system makes it possible to extend almost any class used in the shop and the shop will then automatically create objects of the module where ever the shop would use objects from that original oxid class. Now your module is everywhere were objects of those original class would be. Without you editing the original shop source code. Now updating your shop source code is a breeze. Your module will be working after a shop update. Ok, well, if your base oxid class got changed you may check that change before going live again. But most often the case is that the update will function with your module. Compare this with the situation where you must edit the original source code of a shop system to implement new features. No more re-applying your source code changes after every shop update.
And what’s the business with those “_parent” middle classes? You may want to use several modules, which derive from the same oxid class. To make sure you can do that, the shop ensure that there will be a linear heritage of all modules. You get an object with all modules functionality in it. As long as the modules follow the oxid module design guide (basically making sure you always call parent:: in overridden functions) this will work. No need to edit those 3 party modules source code to get it working. Do remember some commercial modules are encoded by Zend Guard. You cant even edit those.
This system is loved by oxid partners as it really gives them power to change significant parts from the shop without ever screwing up its source code. Most oxid shops have dozen of modules installed from as many module vendors. Several big shop owners have moved to oxid shop software for exactly this feature.
It’s true that the code by itself looks very confusing etc. Now you know what the code is for. Feel free to contact me anytime if you have questions.
August 26, 2009 at 10:14 am |
Hello Erik,
thanks for the quick reply
You guys are really monitoring some channels there for #oxid, right?
Will not go into the “you know your php” thing..
But damn your code is hackish and freaking dirty! The conventions used are very brave as well ….
OK, let me try to come up with a scenario, as you did not really clearly identify and explain a clear usage scenario:
1) A Vendor module oxFoo wants to make use of another module oxBar that extends some oxWhateverYouWannaNameMe module. Considering them modules of the same “category”
2) Therefore you extend them all in a kind of chain, so the oxFoo module can use functionality of oxBar and oxWhateverYouWannaNameMe, right till here?
3) If oxBar also wants to make use of oxFoo, you need to rebuild the extension chain (revert it) ?
Questions, Problems:
1) First of all oxFoo needs to be aware that oxBar even exists, otherwise it cannot rely on its functionality, right?
2) Where are those dependencies managed? Any unit tests for that you can show me?
3) If oxFoo needs to know about dependencies and wants to use other modules functionality, why don’t you go with a Registry that makes modules of the same “category” be able to
get other module instances if needed? something like:
$oxBarModule=$this->getModule(‘oxBar’);
Cheers,
waiting for a reply.
For the oxid crawlers: #oxid
August 26, 2009 at 11:11 am |
I predict this blog lasts about 2 weeks before someone rips the shit out of Arno’s code.
August 26, 2009 at 2:51 pm |
Hello “Steve”,
sorry your comment was in the spam queue.
Please feel free to analyse my open source contributions and comment on it.
My intention with this blog is not to “rip the shit out” of other peoples code, but to raise awareness of quality issues we are having in php … anyone denying this fact has not read a lot of code
And I am more then happy to improve my coding skills, as should any other developer.
Of course that does also include my code
The problem here is that being “nice” with bad habits does not help changing anything. So you have to make some noise and point out stuff in unorthodox ways.
I would be happy if you could join the conversation with something more helpful next time, anyways any comment is welcome if its on the topic.
Cheers
August 26, 2009 at 1:35 pm |
August 26, 2009 at 3:24 pm |
Hi Arno,
mm, yes, it seems I did not express myself clearly. The shop uses a factory which also takes the modules into account. It’s all about modules _not_ knowning each other. And still all modules can (co)operate, without changing any source code, even if intended to inherit from the same oxid class.
I will try to give a minimal example scenario.
Module Foo wants to override getPrice() of oxArticle. For whatever reason
So that would mean:
class Foo extends oxArticle {
public function getPrice() {
$price = parent::getPrice();
$price = $this->doA($price) // do something ..
return $price;
}
}
Now through the use of the factory, every time an original oxArticle object is called on getPrice(), the shop will call Foo::getPrice(). Ok .. so far so good. And as the Foo also calls it’s parent function first, you get Foo::getPrice() which will oxArticle::getPrice(), then Foo::doA()
Now you want to use another module, named ‘Bar’. And this class unfortunally also wants a hook into oxArticle::getPrice().
class Bar extends oxArticle {
public function getPrice() {
$price = parent::getPrice();
$price = $this->doB($price) // do something else..
return $price;
}
}
So if you want this to work combined, so doA() and doB() should be executed, you need to edit the code of one class to inherit from the other.
For instance: class Bar extends class Foo {
But you just edited code in a 3 party software. Maybe you don’t find this a problem to hunt down these places in a larger module. And off course you need to check all modules you use as well. Not to mention the work cut out for you if the shop or any of the modules gets an update.. Every update off course..
So how can you get this to work _without_ editing any source code at all? The shop however will make this work for you. First configure it like : oxArticle => Foo & Bar. The shop will now effectively do
class Foo extends Foo_parent -> extends Bar -> extends Bar_parent -> extends oxArticle.
The shop will then create everywhere a object of Type Foo, who now also inherits from Bar. Again everywhere where the shop used to have oxArticle objects will now have Foo objects. So now a call to getPrice on that object will result in this call stack
- Foo::getPrice()
- Bar::getPrice()
- oxArticle::getPrice()
- Bar::doB() (in Bar::getPrice() – then returns to Foo::getPrice())
- Foo::doB() (in Foo::getPrice() – then returns )
I hope this clarifies the factory part a bit. Especially the “_parent” stuff. The answer got a bit lengthy. Sorry for that. I tried to be clear in all aspects.
Cheers Erik
August 26, 2009 at 3:48 pm |
Thanks Erik.
The fact that it takes such a long time to communicate the purpose and the way this works should make you think that its probably not a very clean and good solution
- Who defines the order of modules?
- What if your intention is to run Bar::getPrice() last, but Foo::getPrice() is the last to modify?
- What if module EUPriceWithoutTax depends on the user being from a certain country or needs another module to work properly?
- But you said they all don’t know about each other, so I guess there are no dependencies at all?
- What if you have 10 modules who extend oxArticle?
Are you sure you would not be cleaner and better of using some kind of events / filter chains?
For discussion a quick sketch:
class oxArticle extends oxSomething {
public function getPrice() {
$price = parent::getPrice();
$price = $this->callFilters(‘FILTER_GET_PRICE’,$price);
return $price;
}
}
The other question is if getPrice() is the right method to calculatePrice() ?
August 26, 2009 at 4:25 pm |
Hehe it’s quite surprising to see own code in blog like this
To clear it out a bit.. These functions are part of our class factory. Any object in OXID framework is instantiated over this factory. Let’s take your example when oxBar class is a standard class (used in the framework) with oxFoo as is its module (written by some 3rd party). When we want to get an instance of oxBar we always use oxNew(“oxBar”) instead of usual way (new oxBar();). Exactly the same way we get EVERY instance of any class in the framework. Normally in framework without any additional modules oxNew(“oxBar”) just returns the instance of oxBar. However the factory takes care about registered modules as well. After registering the module (adding “oxBar => oxFoo” to config) our oxNew(“oxBar”) now would return the instance of oxFoo, which is supposed to be extended from oxFoo_parent() which in turn is build dynamically by the functions you see above and extended from oxBar().
Theoretically one class could be extended by unlimited number of custom modules (oxBar => oxFoo & oxFoo2 & oxFoo3 etc.). The one instantiated is always the deepest child. The best part of it – with OXID modules you can not only implement additional shop functionality, but also easily change standard functionality.
In short: a developer of module oxFoo is not aware which class to extend. It could be either oxBar itself in one shop or oxFoo2 in another or even totally unknown module in third. So he simply defines it like this: “class oxFoo extends oxFoo_parent” and ships the code, the framework does the rest by building all necessary middle classes dynamically according to module chain configuration. This is probably the single case from my experience where the usage of php’s eval() comes very handy and could be justified. I hope it sheds some light on OXID module functionality. As you see it was never meant to be trivial
More information on OXID modules you can find here:
http://www.oxid-esales.com/en/news/blog/how-extend-oxid-eshop-part2
As for oxSuperCfg.. Well, we keep our utility object getters there. Singletons could be used for this purpose as well. Particularly for us the issue with them is problematic unit testing, as you can not mock singleton that easily.
August 26, 2009 at 4:35 pm |
Hi Tomas
I understand what you are doing. But because its cool that it works, does not mean that its a good or the best solution.
As pointed out in my previous comment. Please have a look at it and maybe reply to it.
August 27, 2009 at 6:06 am |
Arno,
I think the OXID guys said enough to explain what they are doing. I think the main problem is that you do not understand why there is a need for such a “super cool” functionality especially in eCommerce (but should be everywhere else also)
Let me try to explain. If you run an online shop you need to make sure that you always use the latest version ( all the patches etc.) due to security reasons. On the other hand – other than e.g. using a CMS – eCommerce is always a very indiviual adopted process which needs a lot of hand tuning to fit your offline processes. You simply can’t take any online shop, install it and start to sell. There are many things you need to take adopt (payment, stock, exports, prices building, Stock….)
Therefore nearly every Shop owner need to make heavy changes in his shop. Now guess what – if you make these changes directly in the source code it leads to massive problems when updating. Shop Owners are usually not very happy if they need to make (ot let make) many changes upon each update.
And this is where the – really good – module system kicks in. They simply can install third-party modules to adopt their shop and also develop themselve without loosing the “release capability” means they can update easily.
Like WordPress or many other OSS there are a lot of free “Modules” which you can install to modify your shop. But – unlike WordPress – these modules will still work even if they inherit the same class due to the “super” Module system in oxid.
I hope I made myself clear – there are many good reasons to have this system and simply – not a real good one for not having it.
To come to an end
– let me add a note to your idea to bundle the design patterns in different directories. This is the most crude, stupid and freaky idea I’ve ever heard of. Why not organizing your files in alphabetical order? For each char a different directory ? Or why not organize it in directories for each class name ?
Man, come on. You should know it better.
August 27, 2009 at 7:39 am |
Hi Lars,
Thanks for commenting.
First of all for the people who read and have not heard about you:
From http://it-republik.de/php/phpconference09/speaker/:
Lars Jankowsky (38) is working as CTO at Swoodoo GmbH and responsible for the PHP-based Flight Searchengine and also Technology Evangelist for OXID eSales AG. He is developing web applications for more than 15 years now and is using PHP since the early days. Besides software development the supervising of teams by eXtreme Programming is one of his passions.
—
You do not seem to understand the purpose of this blog and my posts. I fully understand why you do this and that there is a need for such a modularity. No discussion there.
But guess what? I am trying to get some discussion going, some awareness of how “we php devs” work and how we can become better, cleaner, faster and more of a healthy community, discussing things instead of being pissed if someone criticizes something.
I am not talking about OXID eShop as a product you are selling to your customers here, forget the money part, don’t sell the product to me, I wont buy it.
I am talking about the Opensource Project which gets praised from many sides and I took the freedom, as the source is open (except the unit tests) to have a closer look at it.
You dont want people to have a look at what you are doing? You dont want a community discussing solutions? Then why do you go opensource?
With you thats 3 OXID guys not answering my last questions / suggestions. Is it because you do not discuss design issues in your team? Is it because you are afraid that you would have to admit that there are other ways of reaching the desired modularity?
In my old university there was a guy who had a saying:
German: “Wenn du sie nicht beindrucken kannst, verwirre sie!”
English: “If you cannot impress them, confuse them”
From some of the comments, which do not really come to the main point I am talking about, I have that impression.
Please, lets stop the back patting and try to become a community where we try to improve, open for suggestions, open for criticism instead of having an elitist top 5% of php people not really knowing or trying to neglect whats going on in the rest of the php world.
re: Design Patterns:
Please read the posts about pureMVC and you will understand hopefully the sarcastic undertone
August 27, 2009 at 8:20 am |
Arno,
my intention was not to confuse you instead to explain why it need to be so. As your post was being picked up on planetphp by Damien I think I need to post a public rely also. Please note also that I am not an OXID employee I’ve answered you as the guy who created this “shit”
Arno – please drop me a Mail to discuss this personally a bit more before I release my post to planet-php
And I 100% agree your approach and goals. Just – I believe that the functionality you criticised is the most coolest in OXID. And I would like to see this in more projects.
August 27, 2009 at 8:20 am |
Hi,
before some detective work is necessary I’ll confess: I’m employed at OXID as well (50%). But I’m also freelancer installing and modifying the eShop as anyone else… and today is one of my “non-oxid-days”
First of all I’m sorry that only OXID people seem to be interested in answering this post.
As you fully understood the OXID module system I’ll not bore you with explaining it once more but try to give answers to your questions:
“What if you have 10 modules who extend oxArticle? ”
- Everything is fine, the same as if your’re using 20 modules of oxArticle. Ok I have to admit the text box in admin where you register the modules is quite small so editing the entries is a bit hard
“The other question is if getPrice() is the right method to calculatePrice() ?”
Who says that getPrice() calculates the price? It simply returns an oxPrice object that contains the price and to corresponding VAT. The only calculation done is adding or removing VAT (net or gross price)
“$price = $this->callFilters(’FILTER_GET_PRICE’,$price);”
You want OXID to put such a filter for EACH method in the code, in order to make extensions possible? Seems to me very dirty L
“But you said they all don’t know about each other, so I guess there are no dependencies at all?”
That’s right, the only dependencies you tend to have are the same like in all class hierarchies in OOP.
“What if module EUPriceWithoutTax depends on the user being from a certain country or needs another module to work properly?”
Usually modules are extensions to the shop and not extrensions to other modules. But if you want to develop a module of a module, that’s fine. It will work without a problem.
“What if your intention is to run Bar::getPrice() last, but Foo::getPrice() is the last to modify?“
If the modules are independent from each other the order in which they occur in the inheritance should not matter. Anyway you can simply modify the order in admin area.
“Who defines the order of modules?” You do
Hope I could help …
August 27, 2009 at 11:38 am |
Hi Mathias,
thanks for commenting and sorry for the delay, was busy doing some work and talking with Lars
I think events and hooks + a sound mix of observers are the more sane solution.
I understand that you have a huge app with legacy modules and customers, so of course you need to run it the way your clients need it and cannot just change from one day to the other your core.
But as mentioned before, I am not bashing the goal and the solution per se. I am trying to discuss better, different solutions for a problem which definitely is a hard one to solve.
Well some will, but unluckily (or luckily for you) the source is not very self-explanatory and people will have a hard time questioning/ understanding what you are doing …
Your solution works, which is good. But can you imagine people learning any good practices from your source code like this? As it is open source, people will read it
Again, the absence of your unit tests in the trunk do not help at all here.
As mentioned to Lars, if the source would be cleaner, conventions more understandable, method naming would have sense and there would be unit tests showing exactly what you do and how you do it, things would be different. Like this it looks like dirty black magic with an unclear outcome
So again, show me your unit tests and clean up the code so people can understand what you are doing and we can continue discussing
Saying that using events / filters requires too much LoC and therefore is more likely to be buggy is something which I cannot agree on. I would rather say that your current setup makes it practically untestable, since you have thousands of combinations of possible modules and ways how they are chained together.
How do you unit test the outcome of each of those combinations?
August 27, 2009 at 11:49 am |
[...] I first saw the posting about ‘bad’ code in OXID over at phpterror I wondered if I could ignore this – but now I’ve realized that this article was published on [...]
August 27, 2009 at 12:07 pm |
Is this a candidate for the Decorator pattern?
I wrote some sample code demonstrating how it might work: http://pastie.org/596499
@Arno – Shitting on other peoples’ code is the easier thing in the world to do. You might add value to this blog if instead of laughing at “bad code” you explained why you think the code is bad, and offered suggestions on how it might better be done.
August 27, 2009 at 12:23 pm |
Hy Richard,
first of all I am not considering myself “shitting on other peoples” code.
That image would be stuck in my memory for ever and give me nightmares.
Second, its not easy, believe me, to review code. Everyone who ever did a code review knows that its not an easy thing to do to identify questionable code, pick an interesting small, discussable part out and actually get a discussion going.
Third, the fact that you wrote this comment, pointing to some example code, shows that what I am doing has some value. Otherwise why would you care taking the time to write that sample code?
I am not here to refactor other peoples code. I am writing here to point out stuff and get people thinking. I dont want to tell you what I think and proclaim that I have the right solution, I want you to think, reflect what you and we as php devs are doing every day and discuss it.
Now if criticism in a sarcastic manner pisses you off
I welcome you to be pissed of by my posts!
If you like a bit of sarcasm and also think that we do have a quality issue in php, I also welcome you to help me on that mission, improving things for us all.
The noise that this simple blog post generated shows me that I have hit a hornet’s nest
So all you bees out there … bite!
August 27, 2009 at 1:47 pm |
My beef is that you’re not being constructive Arno. You say you want to improve things but all you’re doing is pointing at bad code and mocking its authors. How is the community to learn from that?
I posted a suggestion because I recognised Erik’s use-case as something the Decorator pattern deals with. Hopefully someone will find that helpful – that’s me trying to be constructive and contribute. That’s where the value is.
Taking the piss is easy (no, i don’t mean literally taking someone’s piss from them Arno). It’s a cheap shot. I’m quite sure people will be discussing this blog, but I don’t quite think they’ll be referring to you quite as favorably as you’d like.
August 27, 2009 at 2:01 pm |
[...] Arno Schneider’s “oxid esales – the extend parade [...]
August 27, 2009 at 2:13 pm |
Richard,
you are looking at everything so serious
I thought only germans take themselves too serious
The post is very aggressive and thats on purpose, so someone listens.
But if you re-read the comments I have made you will find some constructive thoughts in them. Just repeating that I am not constructive does not make it any more true.
And again the fact that you jumped right onto it, even though a bit pissed in general, and proposed the Decorator pattern as one part of a different solution approach shows again, that this article is constructive.
But if you really read all the comments and what the real problem is they are trying to solve you will also see that the Decorator pattern does not solve all their problems.
Again, I encourage you to re-read.
I do not feel the need to be favoured and loved by everyone reading my blog.
The people that have a certain sense of humour and don’t take themselves so serious will most likely understand what I am doing here.
Cheers and thanks for contributing!
August 27, 2009 at 2:33 pm |
Seems like OXID could do with the dependency injection pattern.
That deals with all this.
August 27, 2009 at 7:49 pm |
Hi Arno,
I am working as a PHP deveolper since about 2000 and my company is OXID Premium Solution Partner since 2003. My decision to take OXID for our customers was exactly the module interface and how it works. Now you say:
“But can you imagine people learning any good practices from your source code like this? As it is open source, people will read it
Well some will, but unluckily (or luckily for you) the source is not very self-explanatory and people will have a hard time questioning/ understanding what you are doing …”
This is your personal point of view and I am very sure that a lot of people – working with OXID eShop – would not agree.
For quite a few years I am working as a trainer and consultant for OXID eShop projects. And I mostly get the feedback, that understanding the module concept of the shop ist very easy. Actually you do not have to understand the whole framework but in a 2-hours lesson I could teach you how write your own modules for OXID eShop.
Today I even write some tools for our internal use – which have nothing to do with ecommerce at all – based on the OXID CE, because I just LOVE that framework! In a saturday afternoon session I wrote myself a tool for some project tracking, storing time, analysing efficiency of staff members and so on. At the first run I tried to use Zend Framework for that – and after two hours I got so angry that I kicked it in the corner and than starting to do it again using the OXID CE for it. Maybe that I just need some more experience with ZF but the OXID framework in my opinion is much easyier to understand then the ZF.
I cannot see the real point in your critics – and especialy I do not see any realistic suggestion of you how to do it in a better way. Instead of that I still have the impression that after all the explanations you still did not really understand how things work in OXID framework.
Actually it might be interesting to have a face-to-face discussion some time … – will you be on the next IPC? This could be a good occasion to talk about your suggestions.
Cheers!
Andreas
August 27, 2009 at 10:05 pm |
Hi Andreas,
thanks for commenting. I understand how this solution works and why it is needed
I am re-typing the same message here quite often now
Yes, I understand. And yes, I see the need for modularity.
But if you read thoroughly through all the comments here and for example here: http://www.frontalaufprall.com/2009/08/27/extension-terror
You will see that there is people (not only me) that believe that there are better, cleaner solutions. And thats what this is all about, discussing solutions to real problems. And not about dizzing, bashing or pissing on other peoples code, as some people who do not read the whole thing, comment here and there
The provoking post is just the trigger that needs to be pulled it seems …
Cheers
August 27, 2009 at 9:45 pm |
Thanks for doing this Arno. I applaud this kind of environment. I have worked in an environment where this was the norm and we developed high quality code as a result. Not everyone has the skin for it though.
August 27, 2009 at 10:01 pm |
[...] Arno Schneider’s “oxid esales – the extend parade [...]
August 29, 2009 at 8:00 am |
Hi Arno,
I was not saying that your purpose is to bash on other peoples code. I quite a appreciate your goal to have a serious dicussion about better code. And I do agree that the fact that somethings does a good job mustn’t mean that it couldn’t be improved.
Now you say: “I understand how this solution works and why it is needed.” – If ths is true, I do not understand the following questions you asked during this discussion:
You ask:
“You extend non-existing classes just for the sake of creating them from the magic __autoload function, is that it?”
Answer: No, this has nothing to do with the autoloader. The autoloader came in with version 4 but the module concept was already there in former versions.
You ask:
“First of all oxFoo needs to be aware that oxBar even exists, otherwise it cannot rely on its functionality, right?”
Answer: No. No module needs to be aware of any other module of the same class. That’s even the clou of the whole thing. You don’t have to care about other modules as long as each module considers the oxid guidelines. And in this case you will NOT rely on other modules functionality.
You ask:
“Where are those dependencies managed? Any unit tests for that you can show me?”
In most cases there are NO dependencies between modules of the same class at all. Each module carries its own functionality and should use parent-calls if functions of the original class are modified or extended. Off course if any module overloads the whole function of the original class and does not call the parent-function this breaks the chain an might lead into problems. So if this happens it has to be documented by the module developer.
Some oxid partners do already use unit testing but still not many. For partners oxid offers a unit test enviroment with all the oxid tests in it where we can test our modules together with all the other oxid stuff.
By the way: I totally agree with you that the oxid tests should be delivered together with the OS version. And I think this will happen soon.
You ask:
“If oxFoo needs to know about dependencies and wants to use other modules functionality, why don’t you go with a Registry that makes modules of the same category be able to get other module instances if needed?”
This is a different purpose. The oxid module concept mainly is not meant to manage dependencies between 3rd party modules. It’s more the opposite: Don’t care about dependencies with other modules – just do your job with your own module and take care not to break the chain. As long as you do that you are totaly free to extend and modify oxid functionality.
Now you suggested to use hooks and/or filters. To do that one would have to equip nearly each function of each class with such hooks or filters. And of course you would have to document that very well. Do you really think this would make things easier? or cleaner? If yes – please let me know why and how.
The oxid concept means that I can modify EVERY function of nearly any class. And this is great, I think. And I still cannot see why this should be a bad way or how this could be done in a better way. And I still did not hear any realistic suggestion how this could be done. If you have any: let us know and please explain it a bit.
You say:
“I think events and hooks + a sound mix of observers are the more sane solution.”
I’d like to see that on an explicit example of the oxid eShop. Because this could be solid base for getting a few steps forward in this discussion.
Cheers!
Andreas
August 29, 2009 at 9:13 am |
Hi Andreas,
yes, I understand the module system …. now.
After someone “enlightened” me about oxid, thanks Erik!
So there is little sense in refering back again to my original questions asked in the post, but rather read the comment thread and you will see the evolution of the discussion.
I would like to see an example as well… How about you start it by showing me an OXID module, the OXID core it extends and explaining me why this needs to be built on exactly the module system you are using?
Then I am glad to reply to that, discussing on a real world example.
As you guys are using the software day by day, it should be a lot easier for you to bring forward a real real-world example.
Thanks and hit me with the example and we will discuss it.
Cheers
August 31, 2009 at 6:15 pm |
The clean (without eval) Solution for all this “problems” is “DI” aka “Dependency Injection (Framework)”.
This Oxid thing is a typical quick&dirty solution the PHP-way.
Thank Arno for pointing this out. Keep up ur good work!