What are the best practices when creating a Magento extension to avoid conflicts with other extensions that get loaded to a store. I know how to code with the override method, observer methods and the details behind how to do that the preferred way. That still doesn't stop you from having conflicts with other modules out there and upgrades.
Alan Storm, if you read this, I also have read your recent post about overrides and upgradability. Is that the best way to think for this type of situation as well? I also see extensions and articles people have created to allow multiple classes extend the same class.
The best possible way to avoid this problem is to use the Observer pattern built into Magento whenever possible. It's not in nearly enough places, but when you have the option, using it will let you play nicely even with other poorly behaved extensions.
Nextly, try to override the minimum number of classes. It sounds obvious, but there have been times when I've thought it was necessary to override every one of the shipping calculator classes (the code was easy, but needed to be repeated). With some more work, I was instead able to override a single class and save myself some maintenance headache to boot.
When you do this, you may still run into conflicfts with other extensions overriding the same classes you are. This is unfortunately not a solved problem in Magento, and there isn't a great way to resolve it other than contacting the person in question and hashing out a solution.
Finally, to the problem of upgradeability, a common problem I see in people's code is that they, without thinking, override an entire function when it isn't necessary. So you get this:
function doSomethingUseful() {
// ...100 lines of parent code...
unset($result['badKey']);
// ...100 lines of parent code...
return $result;
}
When you go to upgrade a site, that's 200 more lines of code likely to cause a bug. Bad times! Instead, something like this often works (and is an easy improvement):
function doSomethingUseful() {
$result = parent::doSomethingUseful();
unset($result['badKey']);
return $result;
}
It's faster, it's more readable, it's less error prone, everyone wins!
Hope that helps!
Thanks,
Joe
Related
Using RubyMine, in an rspec test, is there a way to let RubyMine know the type of the created object (for auto-completion and 'cannot find ' warning suppression?
eg:
# #yieldreturn [Tibbees::Tibbee]
let!(:tibbee) {
create(:tibbee,
canonical_vendible: article_vendible,
owner: tibbee_user)
}
RubyMine doesn't seem to recognise #yieldreturn (and I'm not sure if that's correct anyhow) and I've had no luck with #type and #return.
The
let!(:tibbee) { create(...) || Tibbees::Tibbee.new }
cludge works, but yuk. Any advice greatly appreciated. Perhaps there's even a way to let the factories take care of it, but that seems 'too deep' an abstraction to be likely to be picked up by RubyMine?
Not an immediate solution, but:
While google on this, I came across https://github.com/JetBrains/ruby-type-inference which holds great promise for the future, that is probably relevant to anyone with an interest in this question.
From the README:
ruby-type-inference project is a completely new approach to tackle the problems Ruby dynamic nature by providing more reliable symbol resolution and type inference.
In answer to some questions I asked them:
We are going to make the plugin working and publicly available with 2017.3 release though it will definitely be in "beta" since several problems are yet to be solved even on the theoretical side. For everything to work real properly we have to rework our type system on IDE side which is most likely not going to be completed in 2017.
It might be run at the moment, however ... the results are more of experimental value ... [and] it will be difficult to use it on a daily basis.
This is an old request, but updating for future reference with discussion at https://youtrack.jetbrains.com/issue/RUBY-19907:
As of today (RubyMine 2021.2.3, Build #RM-212.5457.52) Rubymine can now introspect the correct type for FactoryBot create within a let, so that:
let(:name) { create(:some_model)} now has the type inferred correct from the factory.
However it would still be useful to be able to annotate a let that can't be introspected (maybe it's not calling FactoryBot).
But the suggestion of #yieldreturn seems wrong - that's for methods that take a block. But it would be nice if you could annotate let(:whatever){} with #return tag. Compare https://rubydoc.info/gems/yard/file/docs/Tags.md#yieldreturn with https://rubydoc.info/gems/yard/file/docs/Tags.md#return
I'm reading some tuts about SOLID programming, and I'm trying to refactor my test project to implement some of those rules.
Often I have doubts with SingleResponsibilityPrinciple, so I hope someone could help me with that.
As I understood, SRP means that (in case of a function), function should be responsible for only one thing. And that's seems pretty easy and simple, but I do get in a trap of doing more than thing.
This is simplified example:
class TicketService {
private ticket;
getTicket() {
httpClient.get().then(function(response) {
ticket = response.ticket;
emit(ticket); <----------------------
});
}
}
The confusing part is emit(ticket). So, my function is named getTicket, that's exactly what I'm doing there (fetching it from server e.g.), but on the other hand, I need to emit that change to all other parts of my application, and let them know that ticket is changed.
I could create separate set() function, where I could do setting of private variable, and emit it there, but that seems like a same thing.
Is this wrong? Does it break the rule? How would you fix it?
You could also return the ticket from the getTicket() function, and then have a separate function called setUpdatedTicket() that takes a ticket and sets the private parameter, and at the end calls the emit function.
This can lead to unexpected behavior. If I want to re-use your class in the future and I see with auto-completion in my IDE the method getTicket() I expect to get a Ticket.
However renaming this method to mailChangedTicket, ideally you want this method to call the getTicket method (which actually returns the ticket) and this way you have re-usable code which will make more sense.
You can take SRP really far, for example your TicketService has a httpClient, but it probably doesn't matter where the ticket comes from. In order to 'fix' this, you will have to create a seperate interface and class for this.
A few advantages:
Code is becoming more re-usable
It is easier to test parts separately
I can recommend the book 'Clean Code' from Robert C. Martin which gives some good guidelines to achieve this.
I am having trouble in using documentation. Lets say I want to see the source of function
DB::transaction();
I go to http://laravel.com/api/index.html
and enter in the search form 'transaction'
Nothing is found.
I then try to go on the left to Namespaces/Database which makes sense.
And later I have no idea where to go. There is some namespaces, some classes, some interfaces. Later found out that this is in the connection class, which at first I did not even look at. Connection associates to connecting to the database, not making transaction.
And there often happens when I don't know how to quickly find things.
How do you deal with that?
I assume the documentation should be one of best developers friends, but I guess I found this function by using sublime massive search in all files.
Btw also - I lowed the Codeigniter documentation, so thats why also I am disapointed. In codeigniter everythign looked so simple and search worked very well. Typing same word 'transaction' finds like charm.
Ok, tried same way as CI does to serch:
transaction site:http://laravel.com/api/
then it finds. If there is no other way, maybe I should bookmark the search link and just change the keyword or something like that.
CodeIgniter was definitely simpler, to the point that any larger project suffered greatly under the weight of (forcibly) badly misplaced code. Laravel raises the bar there a little bit, but it's to your benefit as a developer (I promise :D ).
Firstly, kudos for searching through the code. Many people do not. You learn a LOT by looking in there.
Laravel Code
For Laravel, you'll do best by knowing about Namespaces, and how they relate to autoloading files (Namespaces will relate to directories, essentially). You likely know this, but it relates to how you can find classes and their methods.
Now, this doesn't go towards knowing where anything is - that comes with some digging into the code yourself. I almost always have Github open to the laravel/framework repository to look at code.
Note: That API search looks for files, rather than methods within them (unfortunately).
Github
As mentioned, I use Github mercilessly for searching code, instead of the API documentation. The search in Github is quite good - it will search within the current repository.
For example, I searched "function transaction" in github and got good results.
It led me to see here that it accepts a closure, and surrounds the code run within the closure around a transaction. You can see that throwing any exception within that closure will get caught and cancel the transaction (and gives you a way to control it).
Facades
As #matit pointed out, Facades do in fact hide where code is. That's a tricky part. In general, you can call the getFacadeRoot() method on any facade to figure out what class it is:
// Figure out what underlying class the Auth facade actually is
echo get_class( Auth::getFacadeRoot() );
Eventually you'll discover patterns in the code. Most facades point towards certain types of classes within each package (For instance, a Manager class who's job it is to decide which underlying implementation is used).
I really suggest reading Taylor's book which goes into the general architecture of Laravel. It's a quick read which is highly worth it.
Where CodeIgniter excelled in simplicity, Laravel excels in teaching you better coding concepts. Give it some time :D (Or use CodeIgniter still, that's cool too - whatever gets your work done!)
This is why I strongly suggest using CTAGS! I use sublime text 2 with the CTAGS plugin. I just press CTRL+SHIFT+Click on the class method and it will bring up a list of classes that have that method, or if only one exists, take me directly to the file and method. It beats searching the API/docs in terms of speed. There is even a Sublime text 2 plugin for Laravel Facades !
https://github.com/stidges/Laravel-Facades-for-ST
If one needs JSON, XML, etc. als output format, one can use the AcceptableViewModelSelector Controller Plugin or / and (?) alternate rendering / response strategies.
When should the one and when the other (and when a combination) be applied?
Can/should they be combined?
Well, the Strategies are basically listeners. Listeners that give action depending on what kind of Model will be returned from your Controllers actions. If you return a ViewModel the PhpRendererStrategy will take place. If you return a JsonModel, the JsonStrategy will do it's stuff and if you return a FeedModel it's the FeedStrategy doing it's thing.
However the Strategies only apply if they are registered. So if you return a JsonModel without having the JsonStrategy registered, then nothing will happen.
The AcceptableViewModelSelector exists to provide an easier access and handling of different ModelFormats depending on the accept header. It helps to make things easier, no more, no less.
Strategies, you can also register your own one. There's modules out there that have a PdfStrategy which will render out a PDF-Document if you tell it to.
To tune this down a little to your question:
Strategies have been there from the start of ZF 2.0
The controller plugin AVMS only got in sometime within ZF 2.1 to just make things easier - that's why it's nothing more than a "plugin" ;)
If that doesn't really cover your question, i'm quite insecure on how to answer you ^^
I have two classes, Class A and Class B.
I've recently noticed that they share a lot of the same code. For example:
def viewable_by?(user)
super || clinic.has_staff_member?(user) || user.system_admin? || self.person == user.person
end
I want to minimize the code duplicated between the classes. But in refactoring, I've found that much of it doesn't fit neatly into one class that falls cleanly in the Single Responsibility Principle. I want to put it all into a single module, but the methods will have to do with time formatting, viewing permissions, and a few other things.
As I see it, I have a few choices. (And I bet you can suggest others.) From an object oriented point of view, which approach should I go with and why?
Use one single module shared between both of the classes. It may
not have a specific single responsibility, but it does clean up the
code significantly, and keeps it all in one place.
Make tiny classes and mix in to both classes as modules. They
will all have a single responsibility, but there will be many of
them, some of which may only have one method. Seems like a waste.
Perhaps use a presenter for things like time formatting, and a
permissions module shared between both classes. Perhaps "cleaner,"
but methods are going to be everywhere.
Another possibility I haven't yet considered?
EDIT
This question had previously mentioned Clinic::Appointment and Clinic::Visit classes, rather than A and B. Answers may refer to appointments and visits.
This is a neat question because it deals in a great way with the overall strucuture of your project. I understand that Appointment and Visit are separated things, and an Visit don't need to be linked to an Appointment.
For authorization methods, like viewable_by?, I recommend move all authorizations to other place - you might want to check the cancan structure, that have worked well for many Rails projects, and most likely will work well for any application, even coding an authorization system yourself. So in part, my answer for you is to use (3).
However, since not all code that is shared by the two classes are for authorization purposes, I would try to classify a set of methods, and give an answer for each class of methods you could think of. For method classes that have a similar behavior I would try to encapsulate in a module and include it (so just like (1), but in smaller parts). For example one module HasVisitors with methods like got_on_time? and was_conclusive? (well, maybe not the best examples, but you get it). When your model has a broader scope, like Authorization, that is present in most of your classes, then it is time to go to (3).
I suggest you stop and think again if you should have a Visit class apart from Appointment and it relationship, but not now. After got at home, have fun, take it off from your head, then think again next day.
Would the design be clearer if you shifted the responsibilities? e.g. user.can_view?(resource)