PHP Trait versus Require or Include - php

I'd like to understand why discussions of Traits never seem to include comparison with Require, but always compare with inheritance.
It's my understanding that Require is essentially the same as a copy/paste at runtime, and Require_Once ensures the code is not repeated. Traits are also often referred to as nearly identical to copy/paste.
That said, Require and Include can be used in conditional logic, so in some circumstances they can be a better alternative to a Trait. And Traits have polymorhic and other desirable features that are not available with strict copying of code. For example, the ability to abstract a function in the trait and then optionally override in a container class.
Both of these "code inclusion/import" features have similar behavior when it comes to scope, like with $this.
But a distinct difference is that Include/Require code drops to HTML processing by default, and <?php is optional depending on the context, where with a Trait we know the code must be PHP and must be prefixed with <?php.
So to me, a Trait is more of a higher-level OOP tool while Require is a language-level directive that is not aware of OOP details. And yet, in many cases it seems it would be just as easy and useful to Require code rather than use a Trait to contain the same code.
I'm hoping someone can provide clear-cut examples where one would be chosen over the other, to make it more obvious which one should be used. There are details beyond those that I've cited. Am I already on the right path to making these choices? Is it simpler than this, or more complex? A comparison table would be ideal.

You are correct in that traits are OOP, and require is not, and while I can see how you got there (i.e. both include code) they really aren’t designed for the same use cases at all.
While require does in fact pull in code, I use it almost exclusively like I use an ‘include’ in C++ (my company uses both extensively) – to pull in lists of common defines, and to pull in the parent class for a child. A trait, would not do either of those things. For example, you have to require/include the trait file in order to use it in the desired class def.
A trait is PHP’s way of getting around not having multiple inheritance (as in C++) or a mixin (Java’s ‘fix’ for no multiple inheritance). A trait is typically paired with an interface which is included in the classses that are consumers of the trait.
I’ve used traits extensively (there are strong arguments for and against their use, but I like them), especially with reflection, to provide common behaviours within, and most especially, across class families. For example, in a simple case, I’ve used a trait to provide ‘to html’ functionality for disparate classes – a DB mirror (RDBMS interface), a flat-file mirror that I didn’t wish to force having a common base class. I see no reasonable OOP way to do that with a require. I think sprinkling requires with conditional logic in the body of a class to provide methods, though I guess you could, would be very bad form. If I were interviewing such a programmer I would probably stop at that point.
TLDR – Traits are the PHP OOP method (no pun intended) to provide common methods across classes to avoid artificial common ancestors. Requires pull in defines and parent classes.

Related

Silverstripe 4 - accessing core methods

In Silverstripe 3, eveything was autoloaded on demand. That meant that one could know the class and method that they wanted to use. Example:
Debug::dump('dump message');
If I'm understanding the concepts of SS4 correctly, one needs to import the class to the file that you would like to use the method (or property). In the above example, one would need to do something as follows at the top of the file
use /name/space/to/Debug
Debug::dump('dump message');
Is that understanding correct? If so, my real question is how does a developer effectively know the precise location of everything in core? Are they expected to know exactly where in system these core files reside on top of their names and the methods you wish to use? Are there tools or methods to assist in this?
First, just a clarification -- what you're talking about is not autoloading, it's more like aliasing -- but the two are related.
Because the Debug class is no longer in the global namespace, its name is much more verbose (SilverStripe\Dev\Debug). This is known as a fully qualified class name, or "FQCN" for short. There's nothing short, however, about that new name. It's tedious to type, and if the class ever changes its name, you have a lot of updates to make.
To that end, you can use the use statement to "import" that class into the local scope of your file under an alias. By default, that alias is just the trailing part of the FQCN (Debug), but you're also allowed to use any custom alias you like. (use SilverStripe\Dev\Debug as MyDebugger).
SS4 now uses PSR-4 autoloading, for which namespacing is a critical piece. In very short terms, it dictates that the directory structure must match up with the FQCN, e.g. /framework/src/Dev/Debug.php. This makes the autoloading deterministic and predictable.
As for tooling, using a fully powered IDE like PHPStorm is invaluable for doing dev work in a framework with namespaced classes (which is far more the rule than the exception these days). A good IDE, like PHPStorm, will not only autocomplete as you inject a classname, but will also add the use statement for you, among many, many other wonderful time-saving features.
For a more manual approach, api.silverstripe.org is a good place to look up class mappings.

When should you use traits vs parent/child relationship?

I have two controllers
login.php
auth.php
that both do security related checks (check to make sure user hasn't logged in too many times). they both call the following functions:
isThrottled()
i want to move these checks functions to a trait so I can share them between these two controllers above.
Is the best way to share the functions to use a trait? or to just put them in the parent controller? they both have the same parent.
I think you can reasonably use either in this situation, though I personally would choose to have a (probably abstract) parent class that the classes in login.php and auth.php extend.
Traits, to me, are for where you want a set of functions that you can use and reuse in multiple classes that are not necessarily related. I would argue that functions such as str_replace() and strstr() are methods in a global trait that is the PHP "object". You want those functions no matter what you're doing because they are useful tools in your tool bag.
Methods inherited from a parent are more focused, they provide reuse within a tightly defined scope. They're functions you wouldn't possibly need with a class that doesn't do the specific group of tasks that it is intended to deal with.
You wouldn't be doing anything wrong by using a Trait, but if you ask yourself the question "would I use isThrottled() outside of the specific model functionality of authorising a user" and the answer is "no" then it's probably a bit of an abstraction too far! In terms of maintainability and context that you can provide to future developers (or future you) I wouldn't sacrifice having that function in the middle of the code that it is related to.
This completely depends on the project, your code style, and of course what infrastructure is already in place.
Personally, I tend to go the way of either using Traits, or an interface, obviously the interface being used when I feel that other elements may be added or changed, and I would need to ensure (force) shared functionality across my app areas, without strict constraints on how the function works, or what it produces.
With the Trait being used for when I want to reduce duplication of code, such as in your instance. However this would be dependant on whether the method will have the exact same behaviour, input and return values across all the classes you will use it.
It honestly is never a 1 solution is the right way, and one the wrong way, however in this particular situation, I would use a Trait.
Hope that helps :)

Are traits not simply composition?

I was reading an article about the new features in PHP 5.4.0.
One of the most anticipated one being Traits.
Reading up on these Traits, to see what they're all about, they simply look as compiler assisted copy-paste to me; and a language provided way to use composition, very much as used in the well-known Strategy Pattern which leverages the 'favor composition over inheritance' design principle.
Am I understanding this correctly?
What other advantages might these traits provide, that makes them worthwhile instead of just using the composition design principle?
No, traits are not simply composition due the fact that the rules by which traits are "pasted" into a class are completely different.
When using Composition, there is no chance for conflicts or methods overwriting because the composite element is a completely isolated unit (an instance of some other class) you interface with via it's public API from within the consuming instance. Also, if you need to provide access from the consuming instance, you'd have to add proxy methods to delegate to the composite element.
Traits on the other hand become part of the API of the very instance they are used in. They are not subsystems in the instance. They are not even instances but just a reusable boilerplate code. One benefit this provides is satisfying interfaces with a trait, as I have shown in Traits in PHP – any real world examples/best practices?
You have to be careful about the meaning you give to composition. In the more general sense, traits are a mechanism for decomposition as well as composition.
Decomposition -- how we decompose a software base into suitable units
of reuse(code re-use, DRY).
Composition -- how we compose these units to obtain a class hierarchy
suitable for our application domain.
Traits are a mechanism for composition in the sense that they can be composed with a class. Many trait implementations would also allow for traits to be composed with one another.
The GoF mantra is "favor composition over inheritance".
All class-based languages by default favor inheritance. Object can only acquire behaviours from their class or from classes higher in their inheritance chain. Sure you can achieve the same outcome in different ways. For instance, you can create a Manager Class (e.g., LayoutMananager) and then add a reference to it in any class that has a layable behavior/layout trait and add function that do nothing but call methods of the Manager
public function doSomething() { return layoutManager.doSomething(); }
Traits favor composition. Simple as that. The key characteristic of traits is that they live outside of the class hierarchy. You can "acquire" re-usable behaviors or traits without them coming from any of your super-class (the horizontal vs vertical distinction introduced in other posts). That's the main advantage.
The biggest issue with traits is the emergence of conflict when traits are implemented in a way that you can directly do myObject.doSomething() instead of myObject.trait1.doSometing() (directly, or indirectly as described above with layoutManager). Once you add more than one trait to a class, conflicts can easily emerge. Your implementation needs to support mechanisms like aliasing and override to help with conflict resolution. You get some overhead back.
It is not clear that the PHP implementation conform to this, but traits are also supposed to not specify any instance variables and the methods provided by traits should never directly access instance variables. (source: Adding Traits to (Statically Typed) Languages, PDF). This blog post discusses this. It claims that in PHP, the structure named trait really is a mixin (that is traits with state). (Though this other blog post describe them as stateless)
All, in all, thinking in terms of traits is likely to help write with better code. Writing your traits classes to avoid instantiation could also contribute to better code. This frees traits from any dependency, making it possible to call them in any order. But it is not clear that adding the concept of trait in the language itself would contribute to better code.
The traits "composition" (it's merely an include on the method level of classes) happens at compile time, whereas the composition you talk about is at runtime.
When you do that composition, the trait has already been there.
As the single inheritance in PHP and as well the often seen static utility classes hinder some design goals, traits offer another facet to shape your implementation and allow to reduce code-duplication.
traits are synonym of behaviour more than inheritance or decoration.
It is not the same thing as strategy pattern because you can define a generic algorithme whereas each concrete strategy object has different algorithm.
Moreover it is more a "horizontal" inheritance of a behaviour than a "vertical" inheritance with a specification of a behaviour.
The question is reallty interesting.

Concept of Modules in php similar to Ruby

Is there something similar to the ruby module construct in php ?
Basically I need to create a modules for a mix-in b/w different classes etc.
I know that php has the concept of mixins b/w different classes, but not sure about modules.
PHP doesn't have mixins in the same way Ruby has them. That is, you can't change anything about a class after it's been defined, and you can't sanely add new methods to an instance after it's been created 1. PHP only has the plain old vanilla single-inheritance mechanism, interfaces, and composing traits in 5.4.
The closest thing that PHP might have to a Ruby module is going to be a class. The closest thing that PHP might have to a Ruby mixin is a trait, but traits are not dynamic. They must be referenced by any implementing class at the time that the class is defined. They can not be added or modified at runtime, and apply to the class as a whole, not to individual instances.
While PHP 5.3 has namespaces, they are restricted to holding functions, classes, constants, traits and interfaces only, meaning you can't define variables as a first-class member of a namespace. Attempting to do so results in them being defined in the root namespace instead, which is certainly not what anybody would want. Further, there is no namespace inheritance mechanism, only a namespace reference mechanism.
1: While you can add instance variables (properties) after an object has been created by simply referencing them, this is considered a bad practice. Properties can also contain anonymous functions, but abusing properties this way to emulate adding methods is also bad practice.

Why should I use classes rather than just a collection of functions? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
What are the benefits of OO programming? Will it help me write better code?
OO PHP Explanation for a braindead n00b
Just started learning/playing with creating classes in PHP and I'm wondering what pain do they solve? It seems like I can get the same job done with just a collection of functions that I include into the file. So my question is: Why should I use classes?
The Three Pillars of Object Oriented Programming. Learn them well:
http://codeidol.com/csharp/learncsharp2/Object-Oriented-Programming/The-Three-Pillars-of-Object-Oriented-Programming/
Encapsulation
The first pillar of object-oriented programming is encapsulation. The idea behind encapsulation is that you want to keep each type or class discreet and self-contained, so that you can change the implementation of one class without affecting any other class.
Specialization
The second pillar of object-oriented programming , specialization , is implemented through inheritance ; specifically by declaring that a new class derives from an existing class. The specialized class inherits the characteristics of the more general class. The specialized class is called a derived class, while the more general class is known as a base class.
Rather than cutting and pasting code from one type to another, the derived type inherits the shared fields and methods. If you change how a shared ability is implemented in the base class, you do not have to update code in every derived type; they inherit the changes.
Polymorphism
Polymorphism allows values of different data types to be handled using a uniform interface. The primary usage of polymorphism is the ability of objects belonging to different types to respond to method, field, or property calls of the same name, each one according to an appropriate type-specific behavior. The programmer (and the program) does not have to know the exact type of the object in advance, and so the exact behavior is determined at run time
See also:
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
http://en.wikipedia.org/wiki/Type_polymorphism
It's a way to view your code in a more intuitive, real-world way. (You package the data and all possible operations on that data together.) It also encourages encapsulation, abstraction, data hiding... What you're really looking for is the advantages of OOP.
Basically, classes allow you to put your data with the code - i.e. organization.
Also, classes allow your "followers" to customize your classes without rewriting your code, but rather creating new inherited classes.
Every class-based code might be rewritten with functions, but it would be much harder to understand.
Generally, its so that you can customize the behavior of that set of functions. Typically you have a bunch of functions that work in concert.
People who use these functions may want to only modify one of them for some special case. Or maybe you provide a class that forces the functions to interact in a certain why, but you can't define what they'll actually do.
A trite example: imagine if you had some library to check that some things didn't overlap.
class Comparator:
def Greater(self, left, right): pass
def Less(self, left, right): pass
def EnforceNoOverlap(self, comparator, left, right)
assert comparator.Greater(left, right) != comparator.Lesser(left, right)
It a way to make your code more granular, with proper data hiding, separation of concerns and some other best practices.
IMO using only functions in your code sooner or later leads to spaghetti-code that is hard to maintain and extend. It's harder to fix bugs, its harder to implement new features, because often there are lots of code replication.
Also you can't use polymorphism in your code design, so you can't work with abstractions.
the classes/object is the way of implementation object-oriented application design. it covered detailed in numerous OOAD/OOP books.

Categories