Why do people rely on comments as business logic ? (example CakePHP, Doctrine)
Doctrine example (from their docs, doctrine is relying on the comments as much as the code itself):
/**
* #Entity #Table(name="products")
**/
class Product
{
/** #Id #Column(type="integer") #GeneratedValue **/
protected $id;
/** #Column(type="string") **/
protected $name;
...
A few weeks ago I had to do a change in a CakePHP app and I had a problem where a callback was not called, only digging deep in their guts I found out that I need to put a docblock comment before the function definition for it to be recognized an called, I was in sock. Unfortunately I don't have the code now to give you an example.
I used many programing languages, but I find this trend that I only saw in PHP to be very annoying, and I think breaks the rules of programming.
Maybe somebody can shed some light on it, in my opinion this is a very bad practice, but I look forward to hear you opinion.
Thank you
Its a relatively easy way (nice or not) to bring third party respectively new functions to a programming language without cause compiler errors. But you are right search for errors is sometimes annoying.
Related
I'm using the paginate method of the query builder and I would like to allow the user to choose the number of items per page.
$paginate= Model::paginate($request->input('per_page'));
Doing this could I be opening a loophole for SQL Injection or is this value sanitized first?
You can use a validator to make sure $request->input('per_page') is an integer or whatever validation you want.
documentation here : https://laravel.com/docs/9.x/validation
Such methods must be protected. This is what models are for.
But you are right, it's better to be safe than sorry and verify your premises. This is especially true with popular frameworks, because sometimes the creators crave for simplicity above everything else, often forgetting even security.
But it seems that in this case, Laravel QueryBuilder casts the perPage value to integer, making it immune to SQL injection:
protected function compileOffset(Builder $query, $offset)
{
return 'offset '.(int) $offset;
}
Then I dug a bit into the history, and found that the protection has been added almost a decade ago, so you can be sure that with any supported version of Laravel this part is safe.
That said, validating user input is still a good idea. Even being protected from SQL injections, you don't want any unexpected behavior. I don't think 500000 or -100 are good values whatsoever. If you can see that the data is not valid, it's a good strategy to bail off already, without waiting for some bizarre things to happen. So you may consider validating this input value just like any other input, like good programmers always do.
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.
In the smell Data Class as Martin Fowler described in Refactoring, he suggests if I have a collection field in my class I should encapsulate it.
The pattern Encapsulate Collection(208) says we should add following methods:
get_unmodified_collection
add_item
remove_item
and remove these:
get_collection
set_collection
To make sure any changes on this collection need go through the class.
Should I refactor every class which has a collection field with this pattern? Or it depends on some other reasons like frequency of usage?
I use C++ in my project now.
Any suggestion would be helpful. Thanks.
These are well formulated questions and my answer is:
Should I refactor every class which has a collection field with this
pattern?
No, you should not refactor every class which has a collection field. Every fundamentalism is a way to hell. Use common sense and do not make your design too good, just good enough.
Or it depends on some other reasons like frequency of usage?
The second question comes from a common mistake. The reason why we refactor or use design pattern is not primarily the frequency of use. We do it to make the code more clear, more maintainable, more expandable, more understandable, sometimes (but not always!) more effective. Everything which adds to these goals is good. Everything which does not, is bad.
You might have expected a yes/no answer, but such one is not possible here. As said, use your common sense and measure your solution from the above mentioned viewpoints.
I generally like the idea of encapsulating collections. Also encapsulating plain Strings into named business classes. I do it almost always when the classes are meaningful in the business domain.
I would always prefer
public class People {
private final Collection<Man> people;
... // useful methods
}
over the plain Collection<Man> when Man is a business class (a domain object). Or I would sometimes do it in this way:
public class People implements Collection<Man> {
private final Collection<Man> people;
... // delegate methods, such as
#Override
public int size() {
return people.size();
}
#Override
public Man get(int index) {
// Here might also be some manipulation with the returned data etc.
return people.get(index);
}
#Override
public boolean add(Man man) {
// Decoration - added some validation
if (/* man does not match some criteria */) {
return false;
}
return people.add(man);
}
... // useful methods
}
Or similarly I prefer
public class StreetAddress {
private final String value;
public String getTextValue() { return value; }
...
// later I may add more business logic, such as parsing the street address
// to street name and house number etc.
}
over just using plain String streetAddress - thus I keep the door opened to any future change of the underlying logic and to adding any useful methods.
However, I try not to overkill my design when it is not needed so I am as well as happy with plain collections and plain Strings when it is more suited.
I think it depends on the language you are developing with. Since there are already interfaces that do just that C# and Java for example. In C# we have ICollection, IEnumerable, IList. In Java Collection, List, etc.
If your language doesn't have an interface to refer to a collection regarless of their inner implementation and you require to have your own abstraction of that class, then it's probably a good idea to do so. And yes, you should not let the collection to be modified directly since that completely defeats the purpose.
It would really help if you tell us which language are you developing with. Granted, it is kind of a language-agnostic question, but people knowledgeable in that language might recommend you the best practices in it and if there's already a way to achieve what you need.
The motivation behind Encapsulate Collection is to reduce the coupling of the collection's owning class to its clients.
Every refactoring tries to improve maintainability of the code, so future changes are easier. In this case changing the collection class from vector to list for example, changes all the clients' uses of the class. If you encapsulate this with this refactoring you can change the collection without changes to clients. This follows on of SOLID principles, the dependency inversion principle: Depend upon Abstractions. Do not depend upon concretions.
You have to decide for your own code base, whether this is relevant for you, meaning that your code base is still being changed and has to be maintained (then yes, do it for every class) or not (then no, leave the code be).
I'm developing a component for Joomla 3, but I don't understand how to use the datamodel in joomla 3. Am I supposed to use the Legacy-classes? Will these not be deprecated after a while?
I see most of the joomla components are using the class JModelList, which extends JModelLegacy. To load such a class I can use
JModelLegacy::getInstance('classname');
but is there a way to do this without using legacy-classes? I would think that the word legacy implies that the code hase been replace for something newer/better/hotter? Please enlighten me if anyone knows better ...
PS: I also asked this question on the Joomla - forum, but got no replies (http://forum.joomla.org/viewtopic.php?f=706&t=837707)
regards Jonas
I tend to use JModelList and JModelForm because this way PHP error logging will notify during code execution if your class has failed to meet some of its "contractual" class obligations from any of the parent/super classes.
The answer depends on yourself, and there is really no "wrong" answer here. Pick the method which makes the most sense to you and go with it.
** EDIT **
You can always load and instantiate a model class like so, using User's registration model as example.
JLoader::register('UsersModelRegistration', JPATH_ROOT . '/components/com_users/models/registration.php');
$model = new UsersModelRegistration();
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