-2

I've kind of been experimenting around with some different ways of dependencies, inheritance and scoping. No way of doing it is set in stone yet, I'm just experimenting so I would like to have an answer to the actual problem I'm facing or to know if I'm wanting the impossible. I don't want advice on how to build a standard MVC. The point of this experimenting is to find out if there really aren't better ways of doing very specific things.

Necessary information

I have about 8 'core' classes which I basically want to be available everywhere, even within each other (like siblings). This would likely create circular dependency, which is never what we want.

The thing is that I want all of these classes to come together as the "core", meaning I want all of them to share one object and modify situations for each other (kind of like a singleton pattern, I guess?). Then within the MVC itself, the classes will extend this core and those will be dependency-injected and such as any other MVC would.

The core is quite small. It just has some very basic functions like loading classes, being able to set a few things to $this, compiling the templates and such things.

So, I've been having this tiny little train of thoughts, what if I extended said 8 in a "train" type manner, and call only the very last extension so that I have them all within 1 single instance? This would look like this:

class base{
//The base
}

class model extends base{
 //The 1st child
 public function load($modelName){
   //Code to load a model
 }
}

class controller extends model{
 //2nd child
  public function load($controllerName){
    //code to load controller
  }
}

Great, I have everything in one instance!

Well, not exactly how I'd like it to be, though!

This brings out a big issue: Calling any "duplicate" function like load() will cause the last one to run by default.

$this->load('mymodel');
//Returns: controller "mymodel" not found

How I would like to call it is as follows;

$core->model->load('mymodel');
//Executes the childclass Model's "load" method
$core->controller->load('mycontroller');
//Executes the controller class's load method.

The real question:

Can I achieve this? If so, how?

I was thinking of something like this:

1 ) construct in the base

2 ) get all the child classes

3 ) put child classes within variables through $this->{$className} = $classObj;

4 ) call $this->classname->method style.

But I simply can't think of any way to achieve this. Googling it only results in people asking about extending multiple parents...

yivi
  • 42,438
  • 18
  • 116
  • 138
NoobishPro
  • 2,539
  • 1
  • 12
  • 23
  • Why would controller extend model? – RiggsFolly Mar 02 '18 at 17:14
  • Stop abusing inheritance. The `extends` keyword, when read out aloud, means *"is specialized type of"*. And start going through this lecture list: https://stackoverflow.com/a/16356866/727208 – tereško Mar 02 '18 at 17:17
  • Maybe you should consider injecting all these individual classes into a class called ... maybe .... App – RiggsFolly Mar 02 '18 at 17:17
  • @RiggsFolly that is the setup I have right now. But that negates my ability to be able to call them within eachother. – NoobishPro Mar 02 '18 at 17:19
  • @NoobishPro you obviously do not have even slightest clue what MVC is about. – tereško Mar 02 '18 at 17:20
  • @tereško I do, it's not the point. This is NOT the MVC. This is a combination of classes which I want any controller within the MVC to inherit. It's a core which gets extended by the mvc. I merely want to split this base-class off into more specific classes instead of having one huge core class. I really love how I'm getting downvotes for asking a question about experimenting though. I CLEARLY stated in my question that I do NOT want to go the STANDARD MVC route. Did you even read my question? I'm TRYING DIFFERENT THINGS here. – NoobishPro Mar 02 '18 at 17:21
  • Don't do that. You are using the OOP wrong. Instead of abusing inheritance, you should use composition in the form of dependency injection. And, btw, "MVC" does not mean "My Very Code", so ... **either stop using it to describe what you do, or start following the "Separation of Concerns" principle.** – tereško Mar 02 '18 at 17:23
  • @tereško I'm EXPERIMENTING with non-standards. That's the WHOLE POINT. I'm not trying to recreate something that has been created over 980.000 times on SO here. And I am NOT creating an MVC here, I'm creating a core which I want to be used as a core for a bunch of different types of frameworks, not necessarily MVC's. It has to be modular. – NoobishPro Mar 02 '18 at 17:24
  • 1
    Abuse of inheritance has also been covered in SO many times. You have not discovered a new magical method. Instead you are trying to use a bad programming practice and excusing it by calling it "experiment". Just stop. – tereško Mar 02 '18 at 17:26
  • @tereško nowhere have I said that I'm trying to build an MVC. You're just being very condescending based on assumptions. – NoobishPro Mar 02 '18 at 17:26
  • Stop abusing inheritance. – tereško Mar 02 '18 at 17:27
  • @tereško How about you explain how I'm abusing it? I'm experimenting with the possibilities of PHP and seeing what works and what doesn't. – NoobishPro Mar 02 '18 at 17:27
  • I already did. In my **first** comment about what "extends" keyword means. – tereško Mar 02 '18 at 17:27
  • @tereško and that means absolutely nothing at all? I'm asking whether something is possible or not. I specifically stated in my question that I am NOT asking to be harassed about following standards. – NoobishPro Mar 02 '18 at 17:29
  • @RiggsFolly Anyway, the controller should not extend model. That's just an example markup and besides the point, haha. I just want all classes to be able to call on each-other but still be able to call it as `$this->classname->method`. I don't want these classes to be limited to injected dependencies. – NoobishPro Mar 02 '18 at 17:32
  • imo, don't try and use inheritance for this. ;-/ Instead, look at the 'service' architecture. Define a specific interface for each class (service). That way anything can access any other service, via the interface, without getting confused. Now, let each of the services access a 'directory' of all the available services. They can call each other as required and none of them gets confused. It is used quite successfully in real systems. – Ryan Vincent Mar 02 '18 at 18:12
  • @RyanVincent thank you for the serious answer. That sounds great. Do you have an example for this or maybe a link to something that explains it in more detail? Also, are there reasons as to WHY this is bad? Everybody just yells at me that it's bad but I see no arguments lol. – NoobishPro Mar 02 '18 at 20:57
  • The issue with inheritance is that that it is can be 'coupling of different things'. 'Inheritance' implies a subset of the original object. e.g class FoxHound extends Dog. This is terrible when you have say a list of customers that you want to access. e.g Customer extends Database. Now you want to get the customer from a spreadsheet? Obvious a Customer is not a subset of database. It can be a lot more subtle than this and it is not until a lot later is it realised how expensive it is to change. Always choose composition over inheritance where you can. – Ryan Vincent Mar 02 '18 at 21:20
  • Service pattern: search: 'design pattern service layer pattern' – Ryan Vincent Mar 02 '18 at 21:28
  • @RyanVincent thank you for the sincere responses. I'm honestly getting tired of getting berated and downvoted for questioning standards and experimenting outside of said standards here on SO. It's almost like everything is good and fine as long as you don't question the way someone else works. It's not like standards are the best ways of doing things by default... Before you know it, anyone not using a laravel + mongodb + angular stack is going to get downvoted for not adhering to a trend. *sigh*. People assuming I don't know MVC because I'm trying something else... crazy. – NoobishPro Mar 02 '18 at 23:35
  • I agree with trying different approaches. However, if working on a team then the design patterns are very helpful. People know what to expect and know the issues with them. They are a tool. Each problem can be solved with more than one 'pattern' or combination of 'patterns'. They are useful as they control the 'coupling' between the various 'modules' used by the code. There is never only one 'right way' to write a program to process the required data :) – Ryan Vincent Mar 03 '18 at 00:58
  • @RyanVincent completely agree! Luckily, I'm experimenting with my team. We have been tasked to experiment and see what fairs how well for our very specific needs. We have an MVC.The MVC is perfectly fine on its own, but we'd just like to add some type of global management (core) class to make the MVC more fluid/modular, meaning we can "influence" the MVC's working structure through some classes that manage said MVC. Manually doing this has proven effective. We want to automate it, like rewriting the entire the routing on a whim *without* changing the core files. This to allow global updates. – NoobishPro Mar 03 '18 at 01:16
  • @RyanVincent basically the entire point of this core class is to add specific attributes or workings to the MVC core without changing it. This has proven to be effective in quite a few of our cases when done manually. We want to be able to add things in a 100% modular way that does not require any changing of this core. We must sometimes overwrite things in specific situations but not always. You have to be able to make these changes from almost anywhere or it'll still be useless. Got it working with simple depency injection for now, but I'm just looking into dynamic solutions – NoobishPro Mar 03 '18 at 01:23

2 Answers2

0

Okay, I understand that this is just an experiment - so let me explain why this isn't a road you want to go down.

If you've got three classes that you chain together with inheritance:

  • Class A - has method Load() and members X, Y, and Z
  • Class B - inherits from Class A, has methods Load() and Unload(), and member X
  • Class C - inherits from Class B, has members W and X.

Okay, so you declare an instance of C... what do you get?

You get something that has:

  • Load() - the version declared in class C (because you overrode the ones in A and B)
  • Unload() - the one declared in class B
  • Members W and X declared in class C
  • Members Y and Z declared in class A

... at this point, you've lost two X members and two Load() methods. They were overriden by their children.

"That's fine - I'll just make sure I don't name my methods and members the same from class to class. Problem solved!"

Putting aside that all this will do is basically just build one "super-class" that contains everything (this is terrible design - please don't do this), but it'll be a maintenance nightmare. Suddenly, you can't put in any new methods and members in any of the classes without checking all the rest to see if that method or member is in use - because if it is, one of them will override the other.

Teresko's being a bit abrasive, but it's for a good reason: you are abusing inheritance, and you're doing it to create a structure that's terrible. You should brush up a bit on OOP principles before trying to go down this road.

Kevin
  • 2,133
  • 1
  • 9
  • 21
  • `Suddenly, you can't put in any new methods and members in any of the classes without checking all the rest to see if that method or member is in use` and that is exactly the problem that I was wondering about whether it's solveable or not. So, welll, thank you for your answer and information. You're the first one to actually explain something. – NoobishPro Mar 02 '18 at 20:58
0

Ok, so I've figured it out myself since nobody was willing to help exactly.

class core {

    //This works to get all classes together
    public function __construct($isLoad = false, $calledClass = 'routing') {
        if( !$isLoad ) {
            global $coreClasses,;
            foreach( $coreClasses as $c => $o ) {
                if( $calledClass != $c ) {
                    $this->{$c} = $o;
                }
            }
        }
    }
        public function loadCore() {
            global $coreClasses;
            global $coreDependencies;
            // require_once BASE . 'base.php';
            foreach( $coreClasses as $class => $object ) {
                $classFile = "$class.php";
                $className = "$class";
                if( !class_exists($className) ) {
                    require_once BASE . $classFile;
                    $coreClasses[$class] = new $className();
                }
                $this->{$class} = $coreClasses[$class];
            }

            foreach( $coreDependencies as $className => $aDependency ) {
                foreach( $aDependency as $sDependency ) {
                    $coreClasses[$className]->{$sDependency} = $coreClasses[$sDependency];
                }
            }
        }
}

The above somewhat gets it done. The core-controller class of the MVC now extends the core class, which is going to include all necessary core-classes within the $this scope. The controllers in turn extend the controller class.

The funny thing is, I went for dependency injection in the first place... Then I was quick to notice that dependency injection was performing slower for me than just re-using the same class instances.

I figured it's because not reinitiating the classes and easily adding them is actually faster than doing the 5-10 operations required to actually inject dependencies.

I'm not joking, on all my tests so far, this method seems to be quite a bit faster.

Note Now, I still went for dependency injection, given that it's a bit more strict and less 'free to mess up' that way... As people have been making clear, standards are there for a reason. I felt it should be noted nonetheless.

I'm still slightly upset that experimenting and trying out different ways of doing things is apparently not allowed.

NoobishPro
  • 2,539
  • 1
  • 12
  • 23