Totally agree on this. Again I stick with “Choose your paths wisely”. Know them and score the advantages and disadvantages
By the way who would you define the follow in terms of product / application / framework / language / library / component / “a thing” ?
.NET Framework (this one is interesting because of it’s name… )
For me the framework [origin freym-wurk] is the a “skeletal structure designed to support or enclose something” , the “foundation for someone else’s use”. If there’s an english word for it, why redefine it? That base can be a collection of libraries, the language itself, the tools used or a mix. A framework is the “frame for my work”. So all of the above can be consider the framework of “my applications” and some of them also “applications”. Some of them have “default” behavior and are ready to be used by the customer (SAP, Sharepoint, Drupal, Joomla, for instance), and the same time are ready to be adapted and add extra behavior making it a new “application”.
This is so context sensitive that I ask you what defines an application ? Does a frontend to another app defines an application? Does an REST service qualify as an application? Just like @fretburner said, why does it matter? The boundaries are so thin and so context based that it is just not worth it.
Joomla - Application(with a system for extension)
Drupal - Application(with a system for extension)
SAP - Application(with a system for extension)
.NET Framework (this one is interesting because of it’s name… ) Collection of libraries for .NET
Html Foundation - Framework
Angular - Framework
Sharepoint - Application(with a system for extension)
What he is clearly saying there is that you should separate out all GUI logic, Business logic and Data Access logic which is precisely what I have done by virtue of the fact that my framework is based on a combination of the 3-Tier Architecture and the MVC design pattern. That is all the separation that is needed, and that is all the separation that I have provided. By going any further you are going too far and turning a collection of cohesive modules into a collection of fragments where all unity is lost.
The fact that it does more than is absolutely necessary does not stop it from being a framework. It satisfies all four characteristics described in https://en.wikipedia.org/wiki/Software_framework so it IS a framework. Anything which does not provide all four of those characteristics does not deserve to call itself a framework.
I have never said that I know it all, just that I know enough. I know when to apply a pattern and when not to. I now when to separate a monolithic piece of code into cohesive modules and when to stop separating so that I don’t end up with a bunch of tiny fragments where all cohesion and unity is lost.
Look at my earlier reply in this post.
There are many places on the web which supposedly show “best practices”, but they can’t all be right.
Wrong again. The framework is supposed to supply default behaviour, not the developer. The developer should only need to write code when he wants to override or extend the default behaviour.
Read the Wikipedia definition which I have quoted several times. You do know how to read don’t you?
Yes, but if the developer has to write code to invoke this default behaviour then that does not follow the description of a framework. The developer should only have to write code to override or extend the default behaviour.
Yet when I have the audacity to question some of the things that YOU believe in all you can do is brand me a heretic for not following your interpretation of “best practices”. That sounds like hypocrisy to me.
You really have shot yourself in the foot this time. You claim that my Model classes, which all inherit from my “monster” abstract class, are examples of the “call super” anti-pattern. Not only are you wrong - which I have already addressed in a previous reply - but you completely failed to notice what is said in the third paragraph, which is supposed to be a solution to this anti-pattern:
If you bothered to try to read and understand my code you would plainly see that I have implemented a series of these “hook” methods. For example, take the following processing flow from my ADD1 pattern:
The Controller calls the insertRecord () method in the Model object, which is defined within the abstract class. This then does the following
It calls the -cm-getInitialData () method.
It calls the -cm-pre_insertRecord () method.
It calls the _validateInsert () method which performs default data validation.
It calls the -cm-commonValidation () method.
It calls the -cm-validateInsert () method.
It calls the -dml_insertRecord () method which calls the DAO to update the database.
All of the method names which begin with “-cm-” (note that the hyphens should be underscores, but this blog software converts text surrounded by two underscores into italics - what a bummer) are customisable methods which are called as part of the normal processing flow, but which are defined in the abstract class as empty methods which do nothing. To provide custom logic at any point in the processing cycle all the developer has to do is copy the empty method from the abstract class to his concrete class, then fill this empty method with relevant code.
So not only am I not guilty of using code which fits the description of this anti-pattern, I am actually following his description of a solution to this anti-pattern.
What do you think of THEM apples? I am not as stupid as you think, and you are not as clever as you think. You see things which do not exist in my code, and you do not see things which do exist in my code. Is it any wonder that I think that all your arguments are nothing but total hogwash? You are the one who has accused my Model class of being both examples of a “god” class which tries to do too much, and in another post (in this thread) you also accuse it of being an example of an anemic domain model which does practically nothing. These two accusations contradict each other, and if you knew what you were talking about you would see that neither of those accusations apply. My code fits halfway between “too much” and “not enough” which is “just right”. This is known as the Goldilocks Principle (see https://en.wikipedia.org/wiki/Goldilocks_principle).
I realise this is off-topic, but I think it’s an important question nonetheless:
@tony_marston404 Are there any parts of the Radicore codebase where, as time has passed, you’ve revisited and felt that you would do it differently now, because you’ve since learned there was a better way?
That sounds pretty similar to what Martin says here and what you will find, when the smell is apparent:
The documentation (of the framework) says something like “to do your own thing, just subclass the process method. However it’s important to remember to start your method with a call to the super-class”.
You can come up with all the examples of what is right with your monster class as you’d like Tony. Having a 9000 LoC class is one thing you will never convince me is a good practice.
I use my framework in my major enterprise application which I am actively supporting and supplying to large corporations all over the world. I am constantly being asked, either directly by a customer or from my business partner whose business acumen far exceeds mine, to make additions to the application. Sometimes I can achieve this with code that customises the core product without affecting the core product, but sometimes I need to add new components to the core product. Sometimes I can do what is necessary within application code, but sometimes I need to change the framework code.
There was a situation a few weeks ago where a change to a customer’s requirements did not quite fit the capabilities of the software, and I had the choice of a “quick and dirty” solution and a “proper” solution. As well as being a follower of the “If it ain’t broke don’t fix it” principle I am also a follower of the “If a job is worth doing then it’s worth doing well” principle, so any ideas of a “quick and dirty” solution were consigned to the rubbish bin. I spent about three days refactoring my code so that I could provide this new requirement as an option within the framework.
There have been many similar situations in the past where I have had to modify the framework code, and I always make the effort to do a “proper” job and not a quick bodge. If I look at the code and I cannot see where the old code joins the new then I know that I have done a good job.
If, when looking at my code, I see a better way of doing something (note that “different” does not always equate with “better”) and I can make the change without breaking backwards compatibility, then I will go ahead and make the change. It also depends of how big the change is and what the benefits of the change are. Spending a penny to save £1 would be a good investment, but spending £1 to save a penny would not.
Read it again. What Martin wrote is nowhere near how my framework functions.
You simply aren’t getting it, are you? Nowhere in my framework does it say that the developer, when writing his own method, has to start it by calling the method in the super-class. The super-class contains calls to numerous methods, some of which are “hook” methods. These “hook” methods are defined in the abstract class, and when executed they do nothing. When the developer wants the framework to execute custom code at a particular point in the processing cycle all he has to do is identify the relevant “hook” method, copy that empty method into his concrete class, then fill it with the relevant code. At no point does he have to call a method in the super-class.
So you are claiming that I am not following SRP simply because my abstract class has 120 methods and 9000 lines? I am following Robert C. Martins definition of SRP, not yours. And I am also following the first rule of encapsulation which states that ALL the properties and ALL the methods for an entity should be placed in the same class, so if an entity NEEDS 120 methods and 9000 lines then that is what it needs. Breaking such a class into smaller units would therefore be breaking encapsulation.
You’ve not really answered my question. I’m not talking about making changes or additions to your code because of customer requirements. What I’m asking is, have you learned or grown as a developer over the previous 10 years to the point where you can look at your older code and realise that it could have been done better, irrespective of whether you actually update the code or not?
They mean exactly the same thing. If you take a monolithic piece of code and break into smaller modules, it doesn’t matter whether you say you are following SRP or SoC, the results will be the same. These two principles can only mean different things if the results of applying them are different.
If those other so-called frameworks do not have all the characteristics of a framework, as defined in that Wikipedia article, then they cannot call themselves frameworks.
On what basis? I have said that I apply SRP only as far as described in Robert C. Martin’s article, yet you keep insisting that I should go even further. Why should I follow YOUR advice instead of Robert C. Martin’s?
You mean practically all good PHP developers that you now about. I would also question your claim concerning “practically all” and “good” developers. On that basis you can claim that anyone who does not follow YOUR rules must, by definition, not be a “good” developer, in which case their opinion does not count.
The truth of the matter is that some developers hold one opinion, while numerous other groups of developers have numerous other opinions. Nobody can claim to speak on behalf of the majority of PHP developers, and anybody who tries to is a charlatan.
You forget that I had over 20 years of development experience in other languages before I switched to PHP so I had already learned an enormous amount, especially application design and framework design. The only thing I have learned over the last 10 years is that there are a lot of developers out there with peculiar ideas who try to pass themselves of as experts when, in my eyes, they are nothing but charlatans and snake-oil salesmen. I can spot good advice when I see it, but too much of what I see nowadays is plain rubbish.
The problem is, those people you’re calling “charlatans” are academics and programmers who work for places like Google and Microsoft. What makes you think you know more than those people? Have you ever had a paper published in a peer reviewed journal? (Fwiw, I’m in the process of getting my first paper published as we speak). Have you ever worked for a top level company such as google? What makes you think you know more than people like Misko Hevery who is a programming coach at google?
edit: As an extension, if you did really know better than these people you would actually be able to articulate your position and back it up with evidence in the form of code examples and alternative approaches. You’re unable to do this which makes your claims baseless
What can be asserted without evidence can be dismissed without evidence
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.
Which does not translate to this:
This tells me that the only code you should have to write is when you want to override the default behaviour which the framework provides.
As an example: In Laravel, there’s an Application class that that manages the application flow, running the request through the Router and whatever other components that have to deal with it, taking the result of all that processing, and then using Symphony’s HTTPKernel to respond to the user’s request via HTTP.
It doesn’t mean the developer shouldn’t have to write any code in order for the framework to run. It just means, once s/he does, the framework is what is primarily responsible for the program’s “flow of control” or order of execution. Laravel provides that with the above class, which is why it’s a framework.
Quick tip: if you want to write _underscores_, escape them with backslashes:
if you want to write \_underscores\_, escape them with backslashes.