Would you agree this is the definition of a PHP framework?

And you should do the same. Stop bringing up your framework and your code as a reference. If you do that, we can continue discussing.


I think this is a necessary point. We keep going round in circles:

Tony: This is how I do $whatever, isn’t it great?
Everyone else: That approach can be improved/is outdated/causes issues

Incorrect. I simple said that DI is evil when used in inappropriate circumstances. I showed that in my framework I actually DO use DI when the appropriate circumstances exist, but where those circumstances do not exist I do not use DI. I never said that where I do not use DI the code that I use is better than DI.

Please respond to this:

Are you going to defend your claim that a statement on wikipedia (With [citation needed], I might add) is more authoritative than peer reviewed academic papers or will you concede that academic papers are more likely to be correct?

For reference you said:

Your view is that I must be breaking SRP simply because I have a class with 120 methods. Coming to that opinion based on nothing more than a count is not an acceptable method. That class represents nothing more than the Model in MVC. It does not contain any control code as that is held is separate Controllers. It does not contain any view code as that is held in separate Views. It does not contain any Data Access code as that is held in separate Data Access Objects. It does not contain any code which does not belong in the Model, so it does not violate SRP. Others may have a different opinion, but that is their concern, not mine.

You are again talking about SoC and not SRP. They are different. One is about the architectural split of main tasks or services within a software and the other is about single reason for change within a class.



You said,

The model in MVC holds a good bit of different functionalities for the application. Actually, it holds all of it really, or it is extended to hold the rest of the functionality. This goes seriously against SRP stated in Wikipedia.

every class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.

So I don’t have to do much more proving. You prove you break SRP on your own, through your own statement.


No, it breaks SRP because it has more than one reason to change

  • You’re generating a PDF. If this PDF generation logic needs to change, you need to change the class. For example
var $pdf_destination;               // I=Inline (browser), D=Download (browser), F=Filename (on server), S=String

If you need to add another option to this, the class needs to change

  • You’re generating a CSV:
 var $no_csv_header = false; 

If you want to change the way the CSV is generated you need to change this class

var $no_display_count = false;   

Whatever this does, if you want to change the way the display count is used you need to change this class

var $pageno;  

If your pagination logic changes, you need to change this class

  var $picker_subdir;                 // subdirectory for the File Picker
    var $picker_filetypes = array();    // array of file types

If you want to use a different file picker or change the way the file picker works you need to amend this class. For instance adding a file-size limit as well as a file type limit here.

var $report_structure;              // report structure

If you add a new report structure, this class needs to change

    var $wf_case_id;                    // workflow case id
    var $wf_context;                    // workitem context
    var $wf_workitem_id;                // workflow workitem id
    var $wf_user_id;                    // update workitem with this value, not $_SESSION['logon_user_id']

If the “workflow” structure changes, you need to change this class

    // the following are used to construct SQL queries
    var $default_orderby = null;        // default for table, may be overridden by $sql_orderby
    var $default_orderby_task = null;   // default for task, may be overridden by $sql_orderby
    var $sql_from;
    var $sql_groupby;
    var $sql_having;
    var $sql_no_foreign_db = false;     // if TRUE _sqlProcessJoin() method will skip tables in other databases
    var $sql_orderby;                   // sort field
    var $prev_sql_orderby;              // previous sort field
    var $sql_orderby_seq;               // 'asc' or 'desc'
    var $sql_orderby_table;             // tablename qualifier for optional sort criteria
    var $sql_search;                    // optional search criteria from a search screen (modifiable)
    var $sql_search_orig;               // original search criteria (unmodified)
    var $sql_search_table;              // tablename qualifier for optional search criteria
    var $sql_select;                    // fields to be selected
    var $sql_selection;                 // selection passed down from previous task
    var $sql_union;                     // optional UNION clause
    var $sql_where;                     // additional selection criteria

If you want to support a different query grammar you need to change this class

var $dirname_dict;                  // directory name where '*.dict.inc' script is located (optional)

If you want to support a different dictionary format, this class has to change

    var $inner_table;                   // used in an outer-link-inner relationship

To add different relationship types, this class has to change

There are dozens more and that’s just looking at the variables.

You mean you have to write your own code to get your application going? How quaint! How so-o-o-o last century! All 2,500 user transactions in my application are started from a script such as this:

$table_id = "person";                      // identify the Model
$screen   = 'person.detail.screen.inc';    // identify the View
require 'std.enquire1.inc';                // activate the Controller

And guess what? Each of these scripts is generated by the framework from a GUI screen. The Controller scripts are part of the framework, and each Model class is generated by the framework from another GUI screen. The $screen script specifies which XSL stylesheet will be used by the standard View component. This is how I can generate the code for a user transaction, and run it immediately from an online menu, without having to write a single line of code - no PHP, no HTML, no SQL. This transaction will automatically include all default behaviour, and the developer only has to write code when he wants to alter this behaviour.

Neither does anyone else - the difference is they create small REUSABLE objects that end up in many different applications whereas you have written objects that can’t be reused and so are stuck with the version you have got.

Why not just accept that your idea of good programming is different to everyone else in the world and stop trying to convert everyone else to your view when you absolutely refuse to even consider that some of what everyone else is saying might be right.

1 Like

All of that is well and good, but none of it has anything to do with the definition of a framework. I’m happy you think you’ve done some great work on your application, but again, one of the definitions of a framework is as follows:

Inversion of Control: In a framework, unlike in libraries or normal user applications, the overall program’s flow of control is not dictated by the caller, but by the framework.

I highlight “the caller” here because that phrase is important. It means we, the application developer call the framework, and then the framework runs the application. It does not mean we don’t have to write any code.

I’m not sure what the relevance of your application’s structure is to this conversation about what a framework is. Whether you think writing code to run a framework is quaint or not doesn’t change the fact that, for a framework to be a framework, you have to write code to call it.

If in RADicore, you don’t have to write code to make it do anything, it would be more appropriately termed an application in and of itself. Similarly, WordPress is an application, as it doesn’t require anyone to write any code for it to run.

1 Like

I agree and good point.


It’s probably worth also looking at what the big players call frameworks. Microsoft’s .NET Framework? Does it work without providing any code? Nope, you need to provide code to use it (At minimum you need to write an entry point). Google’s WebApp2 framework: https://cloud.google.com/appengine/docs/python/gettingstartedpython27/usingwebapp Oh, look at that, the first example shows that you have to call a method on the framework to register your classes with it:

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

Apple Homekit framework: https://developer.apple.com/homekit/ oh look, the docs show that you have to register your applicaiton with the framework


    [self.homeManager addHomeWithName:@"My Home" completionHandler:^(HMHome *home, NSError *error) {
        if (error != nil) {
            // Failed to add a home
        } else {
            // Successfully added a home

So that’s an academic journal from CERN relating to work on the large hadron collider, an academic paper from Manchester University, Google, Microsoft and Apple who all disagree with Tony’s statement

You have obviously forgotten that the title of this thread is “Would you agree that this is the definition of a PHP framework?” In post #4 you referred to a definition of a framework in https://en.wikipedia.org/wiki/Software_framework and also http://ifacethoughts.net/2007/06/04/difference-between-a-library-and-a-framework/. In post #15 I agreed with the definitions in those articles but not with some of your other comments. In post #16 I described how Radicore met the four characteristics of that wikipedia definition but without discussing the code that I used to do it. If you read the subsequent posts you will clearly see that it is YOU and your partner-in-crime @TomB who wandered off the topic in this discussion and started to attack my coding style and my failure to adhere to your version of “best practices”.

If you want this discussion to stay on-topic then I suggest that YOU stop making posts which are off-topic. As long as you keep attacking me I reserve the right to defend myself.

You should also learn to stop contradicting yourself in your attacks as it clearly shows that you haven’t a clue what you are talking about and are simply throwing mud for the sake of it. For example, in http://www.sitepoint.com/community/t/dependency-injection-breaks-encapsulation/113596/167 you accuse my abstract Model class of being a “monster class” which does too much, but then in http://www.sitepoint.com/community/t/would-you-agree-this-is-the-definition-of-a-php-framework/191138/30 you accused it of being an “anemic domain model” which doesn’t do enough. Which is it? Too Much or Not Enough? It cannot possibly be guilty of both.

You also claim that my abstract Model class breaks SRP/SoC simply because it has 120 methods. Everybody knows that SRP/SoC has nothing to do with counting methods or lines of code, it is about the separation of responsibilities or concerns. Robert C. Martin had this to say on that subject in his article http://blog.8thlight.com/uncle-bob/2014/05/01/Design-Damage.html

He is saying quite clearly that in a “good design” the logic for GUI. business rules and database should be separated. This description matches the 3-Tier Architecture EXACTLY and which is EXACTLY what I have implemented. Not only that I have also incorporated the MVC design pattern for good measure. My implementation matches Robert C. Martin’s description to a tee, so when you say that my implementation is wrong you are also saying that Robert C. Martin is wrong.

What is YOUR definition of SRP/SoC and why is it so much better than Robert C. Martin’s?

This is an excerpt from the book Clean Code by Robert C. Martin:

Classes Should Be Small!
The first rule of classes is that they should be small. The second rule of classes is that they
should be smaller than that. No, we’re not going to repeat the exact same text from the
Functions chapter. But as with functions, smaller is the primary rule when it comes to
designing classes. As with functions, our immediate question is always “How small?”
With functions we measured size by counting physical lines. With classes we use a
different measure. We count responsibilities.1
Listing 10-1 outlines a class, SuperDashboard, that exposes about 70 public methods.
Most developers would agree that it’s a bit too super in size. Some developers might refer
to SuperDashboard as a “God class.”

He specifically says that 70 methods is too much. He goes on to say:

Five methods isn’t too much, is it? In this case it is because despite its small number
of methods, SuperDashboard has too many responsibilities.
The name of a class should describe what responsibilities it fulfills. In fact, naming
is probably the first way of helping determine class size. If we cannot derive a concise
name for a class, then it’s likely too large. The more ambiguous the class name, the more
likely it has too many responsibilities. For example, class names including weasel words
like Processor or Manager or Super often hint at unfortunate aggregation of
We should also be able to write a brief description of the class in about 25 words,
without using the words “if,” “and,” “or,” or “but.” How would we describe the
SuperDashboard? “The SuperDashboard provides access to the component that last held the
focus, and it also allows us to track the version and build numbers.” The first “and” is a
hint that SuperDashboard has too many responsibilities.


To restate the former points for emphasis: We want our systems to be composed of
many small classes, not a few large ones. Each small class encapsulates a single responsibility,
has a single reason to change, and collaborates with a few others to achieve the
desired system behaviors.

You have repeatedly stated that your system is “a few large ones”. And let’s be clear, he called a 70 method class too large, your 120 method class is nearly double that.

He also says:

Classes should have a small number of instance variables. Each of the methods of a class
should manipulate one or more of those variables. In general the more variables a method
manipulates the more cohesive that method is to its class. A class in which each variable is
used by each method is maximally cohesive.

Your class has about 50 variables, some of which aren’t used in the class and it’s impossible to sum up. So let’s turn it around: What is YOUR definition of SRP/SoC and why is it so much better than Robert C. Martin’s?

1 Like

No, they are NOT different. They both talk about “separation” and breaking down code into smaller modules. If you ask the average programmer to specify the difference between a “concern” and a “responsibility” you will find that there are none. You cannot apply these two principles to the same piece of code and get different results so they are the same.

I prove no such thing. I have clearly implemented the MVC design pattern as I have different components for the Models, Views and Controllers and this conforms to the definition of SRP. I do NOT have a monster Model class for the entire application, I actually have a separate Model class for each table in my database (and my application has over 300 tables). So each Model class is responsible for the validation and business rules for a SINGLE database table, so again it matches the “Single Responsibility Principle”.

SRP is violated when there is more than one “reason to change”

  • Changing the validation is a reason to change
  • Changing the business rules is a reason to change

The class does too much and breaks SRP.

Not according to Robert C. Martin’s definition of “reason to change”.

Wrong. That is a variable in the Model which is passed to the View object which is responsible for the production of PDF documents.

Wrong. That is a variable in the Model which is passed to the View object which is responsible for the production of CSV files.

All your accusations are wrong. Those are simply variables which are defined in the Model but which are passed to other objects for the actual processing. It is these other objects which contain the logic which deals with the contents of those variables so to say that my Model class contains too much logic is completely bogus.

Excellent then you also have broken encapsulation. You’ve quoted this exact definition before:

Encapsulation is the packing of data and functions into a single component. The features of encapsulation are supported using classes in most object-oriented programming languages, although other alternatives also exist.

A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

You have just said you have the data in the model and the functions in the view. The data and functions are in different components. So that’s two for two.

Wrong again. I quoted Robert C. Martin in #118

Completely wrong, as usual. In the first place it is my framework which contains the most reusable components as I have used it to build several different applications. It is the framework that supplies the Controllers, Views and Data Access Objects, while each application provides nothing but the Models.

In the second place my main enterprise application is comprised of 9 modules each of which has its own database as well as being able to share components from other modules.

You can use my framework to create you own applications, but you cannot take one of my application components and reuse it in your application.

Nowhere in the Wikipedia definition of a framework does it say that the developer has to write code to call the framework before the framework takes control. While a little code may be necessary in order to tell the framework which application component to run, it should be so little and so simple that the framework should be able to generate it for you. That is exactly what Radicore does.

You aren’t reading what I wrote. I said that you don’t have to write any code in order to generate components which have basic and default behaviour, but you DO have to write code in order to change or enhance that default behaviour.