The Drupal 7 version included some performance analysis of the view and recommendations provided to the user.
I've created an event system for handling this so that it's easy to hook in with various types of analysis/feedback, and I created a subscriber named ViewsPerformanceAnalyzerSubscriber that I plan to do the analysis in, though there's currently just a TODO in the code where the analysis should be done.
I'll try and get to this ASAP as I believe it's the main thing lacking to be feature-congruent with the D7 version. I haven't assigned to me because I haven't actually started on this. If someone else gets to it before me, that's cool too, but I'll self-assign when I get started to make sure everyone knows it's underway.
Comments
Comment #2
replicaobscuraJmOkay:
I'm curious for your thoughts on an alpha release of the D8 branch.
On the one hand, it'd be good to create the Views performance analysis functionality so that the features are fully congruent between D7 and D8 first.
But on the other hand, since everything else works in the D8 branch and all that's missing is performance analysis, it might be good if I made an alpha1 release ASAP so that we can increase adoption of the D8 version and get more people looking at it and submitting any issues before a beta would hit.
Do you have a preference whether alpha1 would get released now or wait until this issue is closed first? Thanks for your feedback!
Comment #3
JmOkay commentedHi bmcclure
The Views performance analysis code you have written is implementing the Mediator Design pattern, decoupling the analysis from the class it is analysing. By doing it this way you are potentially introducing a logic hole, where you are relying on always injecting correctly information for the analysis to run. The alternative way to do it is with inheritence, the way I did it, which has the advantage that it is looking at the source to do its analysis. Whilst there are always lots of ways of doing things, using inheritance in this case guarantees you are analysing the actual issues as oppose to a recreation of it via Dependency Injection. As the analysis only works on the main class it is of little use decoupled. If you are going to decouple analysis it might be an idea to just do it when you have found a problem. If you do it that way you should be able to use the existing D7 analysis class using inheritance with a few quick changes. You can then dispatch off findings using your Analysis class.
In answer to your question, I don’t see why the module can’t be moved to Alpha status. Alpha implies nearly finished, but still adding the odd features.
Hope you find this useful.
All the best
JmOkay
Comment #4
replicaobscuraThanks for your feedback, it was very useful. tl;dr I'll go ahead and release an alpha version ASAP!
To continue the discussion about the best way to code the analysis:
My main concern with not keeping the monolithic class inheritance structure was in separating the logic. I wanted to make sure we had clear interfaces designed to do one thing, for representing each discrete part of the system. In the case of an entity pager, to me it seems like this boils down to there being the concept of an EntityPager, an EntityPagerLink, and an EntityPagerAnalyzer.
The analyzer isn't designed just to analyze a specific class, but the whole system while it's active (The pager, the links, the view, the current entity, whatever makes sense). Also, the analyzer isn't really supposed to be a mediator; the Analyzer is directly what's responsible for the entirety of the analysis. My implementation of the analyzer fires off events to further decouple the analysis, but since it's a separate, discrete class it'd be easy to do something else instead as the system does not rely on the analysis being event-based.
The contract of the EntityPagerAnalyzerInterface and implementation of the EntityPagerAnalyzer class ensures everything happens consistently and at exactly the right time. The fact that the two default events are included in the core module means they can be relied upon to run every time as well.
I'm definitely open to discussing other ways to accomplish this decoupling that wouldn't require the event system. Perhaps using a Plugin system instead of firing off an Event would be preferable, though that feels more heavy to me when the analysis doesn't have to involve much code as it is. What I'd like to avoid if possible is making the EntityPager class responsible for doing too much. It's already managing the view, handling its links, and storing its options, so it seems like the analysis portion is a good candidate for being able to live decoupled form that core class somehow.
One thing that could possibly make what's happening clearer, and do more to prevent misuse, could maybe be to extend the EntityPagerAnalyzerInterface a bit so that instead of just an analyze() function, it includes specific methods for defining how it happens, such as a method for retrieving the analyzed logs (so that the analyze() class isn't responsible for doing the logging).
Anyway, just wanted to lay out my thinking with this functionality and open it up to further discussion so we can hopefully find a good middle path forward before I start coding out the analysis. Thanks again!
Comment #5
replicaobscuraFirst Alpha released, and I linked to this issue in the release notes as a remaining item before beta. Thanks again for your feedback on this!
Comment #6
JmOkay commentedHi bmcclure
I'm happy for you to code it how you see fit. It is always nice to hear / think about and analyse other peoples opinions. I would not agree that the Links require a Class with methods. They are just an l(), it slightly bugged me in D7 that the main method calculateNextAllPrevValuesFromView() grew beyond about 12 lines and I think I should have been a bit more brutal in keeping it to an easy read top down logic few lines. I intended but never got around to splitting the complicated l() lines into a method. I think a l() Class is over engineering it.
I think you are misunderstanding the code with your monolithic class thoughts, I would disagree. Certainly if you read a text book as a sound bite, mass inheritance should be avoided, but that is not what the layers of classes are about. They could easily be all in one class. I just moved methods of a similar genre into inheritance classes, but they are in the main very small classes with very few methods. I should have marked the sub class as Abstract. Most people would not have added genres and stuffed them into more confusing mass classes. They are not class overloading etc... they are just about putting similar methods together with similar class names implying their codependency.
There are a few things I'd have changed in D7 if I'd had time. Wanting to refactor after gaining enhanced knowledge beyond conception after creating code from a blank slate is inevitable. That said the module evolved to how it was and how it is. For me the process of creating the D8 module would have involved updating the D7 module to define the D7 / D8 points of exchange of information (interfaces) in preparation for D8. In doing this amongst other things I would have introduced the EntithyPagerView (based entirely off the view object) as a dependency injection with its methods D7 / D8 the same names but their contents updated. At this point I would have introduced interfaces that would be the defined D7 / D8 exchange points.
On a final note I still feel analyzing the main Object is best done via inheritance. But as I said earlier I'm happy for you to code it how you see fit - you are obviously a good developer.
All the best
JmOkay
Comment #7
replicaobscuraThanks again for your thoughts!
Regarding my reference to it being a monolithic class, I was referring mainly to the inheritance structure--even though each class only adds several methods, by the time you get to the outermost class that actually gets interacted with and inherits from all the others, it's got a lot of methods and is responsible for doing a lot of things. I don't think that's necessarily a bad thing or the wrong way to do it, but it became harder for me to think about extending the class structure in that way, which prompted me to split out the classes so they each are responsible for one primary thing and each have their own contract.
I see your point about the links; a separate class isn't strictly required there, and maybe it should be simplified. I wanted to encapsulate the functionality of determining how to generate it based on the view result row provided. If there's no associated result row, it works differently, but no other classes need concern themselves with that logic, they just ask for link markup. I do like thinking about that logic separately, but I wonder if there's a better (and more lightweight) way to handle it than a class instantiated for each link. I've got a couple ideas there, I may do some performance testing to see if I can find a lighter weight solution that still encapsulates the link generation as much as possible (perhaps a single static class responsible for generating pager links?).
I'm still putting some thought into the best way to handle the analysis in the current D8 structure given my original intent and your responses. I'll take a crack at getting that together soon, and whichever route I go we can evaluate and always decide to revisit again.
Btw, I know you've had a strong focus on performance in the Entity Pager module, so I plan to continue that a focus in my work on the D8 version. My initial goal is just to get all the functionality together in a logical way, and then I think when we hit Beta I'd like to start some performance tuning and refactoring in preparation for the first RC. By the time 1.0 hits, I'd like to try and make sure it's on par with the performance numbers you listed on the main module page (Are those accurate and recent? Was there a certain procedure used to test them that I could follow for D8?).
Comment #8
JmOkay commentedHi bmcclure
There are loads of ways to see load times for a webpage a decent Drupal way is by using the Devel module and turning on: Display page timer - Display page execution time in the query log box.
You can see it in action happily navigating through 50,000 nodes virtually instantly in the instructional youtube video I created for the module to help people use the Module. You can see the video at: https://www.youtube.com/watch?v=oJUcjKLz8ls
Cheers JmOkay
Comment #9
JmOkay commentedComment #11
wongjn commented