If we use type hinting, we can place an object mandatory:
public function myMethodThatDoFineStuff(MyObject $myobject) {
}
What if, we would like to place, not the all object but only some of it's attributes, to be mandatory ? Let's assume that our domain model will be better, if it better represents a certain domain.If this could make more sense on our business model (on our domain)? How should we do it ?
Our should we always place the ALL Object no matter what ?
EXAMPLE for clarification proposes:
Let's imagine that, in order to list books of a certain author we have this method:
public function listBookOfAuthor(Author $author) {
}
Now, let's imagine that the author object has 200 properties or so, BUT, in order to process the list of books, we only need their first and last name.
Should we receive the ALL $author object anyway ?
I would test for required properties in the following way:
public function listBookOfAuthor(Author $author) {
if (empty($author->firstName)) {
throw new listBookOfAuthorException('firstName must be defined');
}
}
If you find you're doing this lots you could write some kind of parent class that includes a method for checking properties are present.
What if, we would like to place, not the all object but only some of it's attributes, to be mandatory ?
Technically you can create an interface with only those some attributes the function expects. Isolated this might look a bit like overhead but Interfaces are worth to play around a bit with, more in the manual how they work in PHP.
Just because it could make more sense on our business model ?
I know nothing about your business model, so I can't say if it makes sense or not. But I thought you were asking a programming question not a business one.
Our should we always place the ALL Object no matter what ?
Then you'll loose type hinting but you will be able to pass any object. Depends a bit how strict you want to write your code. If you use interfaces you're pretty flexible when refactoring the code (changing concrete object implementations), as well as with the stclass object. However with the stdclass object the function needs to verify what it get's first before processing on the functions input.
Depending upon your schema, the method listBooksOfAuthor() (which looks like a method on a service object like BookService) could probably suffice with only an $authorId, not a full Author object.
But I think I understand the point of question. Perhaps the Author object is expensive to fully populate - say, from a method like AuthorService::getAuthorById().
For those circumstances when all you need is a modest subset of Author functionality, then perhaps you could create a distinct interface - maybe something like AuthorSummaryInterface - that reflects only those methods you need for those circumstances. Allow the Author object to implement that interface so that when you already have an Author object in hand, you can perform operations that only require that limited Author functionality. Alternatively, you could create a method Author:getSummary() that returns a concrete implementation of AuthorSummaryInterface. In this method, you could enforce your member requirements - must have a name, for exmaple - and throw an exception when those requirements are not fulfilled.
You might also create a set of methods - perhaps on an AuthorService object or an AuthorSummaryService object - that produce AuthorSummary objects. Then in those circumstances where only AuthorSummaryInterface functionality is required, you can create these limited functionality, less-expensive-to-create objects.
Just some ideas.
Related
I know this is kind of a question of faith and has been asked many times before, but the answers I've found were either too general, didn't apply to my use case, or didn't satisfy otherwise.
I'm currently building an application that uses classes as representation for database tables. These classes don't offer any methods of their own, I've written a parser class for each one that works with their objects and returns the data in the format I need, which makes the parent classes nothing more than data storages and makes a nice distinction between data and logic.
Now, the consensus in OOP seems to be that you always have to use getters and setters instead of accessing class attributes directly.
An argument I've often heard is that using getters and setters gives the possibility of extending those functions later on, but in my opinion this goes against YAGNI and some other concepts I can't remember the name of right now - that a method should do exactly what you would expect from its name. If I wanted to do something more than simply set a value, I would write a new method, not put that into my setter method, since that one is, per definition, only supposed to set attributes. So I might as well skip the setter and just access the attribute directly.
Another one is that you can put validation in your setters, which I already do in my API that accesses these classes. In my opinion you shouldn't just pass values and have the object tell you if your value is okay or not, but instead validate those values first before you pass them to the object.
I do understand the purpose of private/protected attributes in "usual" classes, but when the class is literally just a data container without any methods, is this really needed? In other words: is there a glaring disadvantage to using public values, when the setter methods for those (were they private) would all just look like public function getAttr($attr) { $this->atrr = $attr; } anyway?
You only need a data structure, but the only suitable PHP construct is the class.
Typically, in object-oriented analysis, design and programming, a class is a model of a thing or concept and it encapsulates any knowledge and/or behaviour of the thing or concept.
However, in the context of this question, encapsulation is not needed since you only require a data structure.
First of all let me tell you that programming is my hobby (love programming) and even though I have taken some programming classes in college (C++) and have created some small programs in C++(QT), Objective-C, PHP and now Swift, I have never had the need to heavily use custom objects other than create instances, call some functions/methods from those objects or inherit from one to the other, all pretty simple stuff. The one thing that has been bothering me and that I think is the heart of the OOP world is understanding the concept of creating and using custom objects. I know this question is something I should have asked long time ago, shame on me.
Can someone be so kind and create a quick and simple example of how and what functionality is usually involved when creating custom objects?
Here I'm using Swift but this could be in any other language:
// custom object
class ClassA{
// what functionality could fit here
}
class ClassB{
init(customObject:ClassA){
// when would you pass a custom object to this class?
{
func returnCustomObjec()->ClassA{
// when would you return a custom object?
}
func passCustomObject(customObjec:ClassA){
// when would you pass a custom object?
}
}
FYI - I know when to return or pass, Stings, Ints, Doubles, etc. but I want to see when would make sense to create functions that return or accept custom objects in a real program.
IMHO the most basic use of custom objects is return types of functions. Lets say I want to write a function that returns an int a double and a string then I could do this by passing references:
void foo(int& a,double& b,string& c);
However, in this way it is not so clear that these parameters are only for return values. And also now the caller has to take care to declare (and maybe initialize) these 3 variables and has to give them reasonable names. If the return type is lightweight and copying is not a problem, this can be done like this:
struct foo_returnType {
int a;
double b;
string c;
}
foo_returnType foo();
Now there is no confusion whether its return values or parameters and more importantly if the function returns those 3 parameters, it is very likely that they logically belong together and this should be reflected in the code. I can give them a reasonable name (maybe something better than foo_returnType) and for convenience I can provide some more nice features for this new type (e.g. overloading ostreams << operator to print the type on the screen with some additional meaningful information on the meaning of the 3 parameters).
Oh my, there is a lot, lot of cases that does this. I just made some object that deal with uniform shaders in opengl. See my simplified code. There is a lot of object involved here:
Shader ShaderManager::load(Camera* camera, Entity* entity) {
Shader shader;
shader.addUniform("transform", make_unique<TransformUniform>(camera));
shader.addUniform("color", make_unique<Vec4Uniform>(entity->getColor()));
return shader;
}
And even color is an object, a very simple struct, but still an object. I rarely deal with primitives, but again some of my object act as primitive (I'm in C++, dynamic allocation is a choice)
I have a php backgound. I messed around a bit with c++ and java, but this answer is in a php perspective.
In php, custom objects are the objects which actually do things (in java there are a lot of libraries if I understand correctly, one might be able to do a lot without any custom object). That is, objects representing your business entities, such as an invoice or a sale item, or representing your application, such as a http response object, or a template parser object.
Passing and returning custom objects ensures that your methods will have a predictable behavior, that is, not calling non-existing methods on your objects, being sure that if you type-hint an interface in a method, any object that implements the sumable interface will be able to be sumed (for example).
The purpose of passing and returning cutom objects is to ensure of an application's behavior
I'm just getting into PHP OOP and I'm unclear on what properties I need to declare at the start of a class.
Do I declare properties:
A: that are arguments for methods?
B: are not arguments for methods but are still within a method?
C: that are returned from a method?
Edit For Example
Here's an example userclass I'm trying to create
class user
{
public function selectMember($username,$password)
$query = "SELECT * FROM users WHERE username='$username' && password='$password'";
return $query;
}
So I would have to declare $query only at the top of the class?
The way I think of these things is that an object is a code representation of a real life object (duh). The car example above is a good one. For most real life objects there are attributes and actions. If our object is person, it will have attributes like name, height, weight, hair color. Then, our person will have actions, like run, sleep, eat.
The actions will be methods and the attributes will be properties. Properties will either be used in the actions or by other parts of the program which need to check the state of your object, IE, another part of your program asks the person how tall it is right now.
In most cases, return values and arguments will not be properties. A notable exception would be arguments you use to instantiate an object, as those will typically be needed by your other methods. As far as variables used within a method, these should be properties if they define the overall state of the object, but if you are creating a variable, like a counter, inside your method, that is just needed to accomplish the goal of the method, it doesn't make sense for it to be a property of your object.
I would start out by erring on the side of fewer properties. If you get to a point where you need a property to accomplish something, then create it. I wouldn't create them until I have a direct need. This way, you'll begin to get a feel for what properties an object will need in order to function logically.
I hope that makes a little sense.
Properties are pieces of data about the object. For example, to take the classic car example:
The car's color, make/model, year, etc. are all properties of the car.
There may be a method StartCar that requires a Key object to start. The car does not have a key, therefore the key is not a property -- it is a method argument. But the car does have a lock that is capable of validating a given key. The argument and the property work together to perform the action (or, in this case, validate the action).
Each instance of the car class may have different values for these properties.
If you need specific help deciding what to make into properties, we will need more information about your specific requirements.
Php.net have a real good documentation about PHP OOP
It's pretty much your choice, according to the best answer in "When should I declare variables in a PHP class?".
I'm trying to understand the factory design pattern.
I don't understand why it's good to have a middleman between the client and the product (object that the client wants).
example with no factory:
$mac = new Mac();
example with a factory:
$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');
How does the factory pattern decouple the client from the product?
Could someone give an example of a future code change that will impact on example 1 negative, but positive in example 2 so I understand the importance of decoupling?
Thanks.
I think it has to do with the resources needed to construct some types of objects.
Informally, if you told someone to build a Mac, it would be a painstaking process that would take years of design, development, manufacturing, and testing, and it might not be done right. This process would have to be repeated for every single Mac. However, if you introduce a factory, all the hard work can be done just once, then Macs can be produced more cheaply.
Now consider Joomla's factory.php. From what I can tell, the main purpose of JFactory is to pool objects and make sure objects that should be the same aren't copied. For instance, JFactory::getUser() will return a reference to one and only one object. If something gets changed in that user object, it will appear everywhere. Also, note that JFactory::getUser() returns a reference, not a new object. That is something you simply cannot do with a constructor.
Often, you need local context when constructing an object, and that context may persist and possibly take on many forms. For instance, there might be a MySQL database holding users. If User objects are created with a constructor, you'll need to pass a Database object to the constructor (or have it rely on a global variable). If you decide to switch your application to PostgreSQL, the semantics of the Database object may change, causing all uses of the constructor to need review. Global variables let us hide those details, and so do factories. Thus, a User factory would decouple the details of constructing User objects from places where User objects are needed.
When are factories helpful? When constructing an object involves background details. When are constructors better? When global variables suffice.
Don't know if I can put it any better than IBM did https://www.ibm.com/developerworks/library/os-php-designptrns/#N10076
This example returns an object of type Mac and it can never be anything different:
$mac = new Mac();
It can't be a subclass of Mac, not can it be a class that matches the interface of Mac.
Whereas the following example may return an object of type Mac or whatever other type the factory decides is appropriate.
$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');
You might want a set of subclasses of Mac, each representing a different model of Mac. Then you write code in the factory to decide which of these subclasses to use. You can't do that with the new operator.
So a factory gives you more flexibility in object creation. Flexibility often goes hand in hand with decoupling.
Re your comment: I wouldn't say never use new. In fact, I do use new for the majority of simple object creation. But it has nothing to do with who is writing the client code. The factory pattern is for when you want an architecture that can choose the class to instantiate dynamically.
In your Apple Store example, you would probably want some simple code to instantiate a product and add it to a shopping cart. If you use new and you have different object types for each different product type, you'd have to write a huge case statement so you could make a new object of the appropriate type. Every time you add a product type, you'd have to update that case statement. And you might have several of these case statements in other parts of your application.
By using a factory, you would only have one place to update, that knows how to take a parameter and instantiate the right type of object. All places in your app would implicitly gain support for the new type, with no code changes needed. This is a win whether you're the sole developer or if you're on a team.
But again, you don't need a factory if you don't need to support a variety of subtypes. Just continue to use new in simple cases.
My question is more like a theoretical.
Say you have an object, that represents the list of something (articles, pages, accounts etc.)
class ObjCollection
You have a class, that represents a specific item in collection:
class objItem
I have a problem thinking of a basic responsibilities of each object.
Which class is responsible for creating a new objItem?
Which class is responsible for deleting a objItem? Should it delete itself as a method?
Update 1:
Techpriester: Is it ok to use object's constructor as a function to create new item?
I think of that like:
class objItem {
public function __construct($id = 0) {
if ($id > 0) {
// load item data...
} else {
// make new item...
}
}
}
But what if something goes wrong in the code, and instead of passing an $id > 0, it passes 0? In this case a more expected behavior would be an empty object, and not the new one, or am I wrong?
A way of thinking about this:
objItem usually have a class constructor so this class might be responsible for creating objects of type objItem.
When an objItem is inserted in a list/collection let's say objCollection it can be objCollection responsability to delete it from the collection.
objItem usually have a class
constructor so this class is
responsible for creating objects of
type objItem.
Constructor has nothing to do with responsibility (usually). Thinking this way, every object would be only responsible for itself.
Responsiblity is a concept not directly binded with class hierarchy.
If:
ObjCollection = Nest objItem = Egg. And there is third object Bird, Then Bird takes responsibility for creating egs (even if nest contains egg). It is not about programming it is about common sense... :)
There is not such thing like "empty object". Objects have "state". You can create an object and then you have it, or you may not to create it and there is no object then.
All you have to worry about is if your constructor will work fine in both cases, with new object created and without it.
Usually it is better to inject object as a constructor parameter (instead of $id) not to create it inside another object.
I know this doesn't answer your question, but since you tagged this as PHP I'm going to assume that it will almost certainly be applied with some sort of database model.
In that case, it's probably a better idea to do away with 'collections' altogether since if you made each class represent only one object, if you wanted to view 10 blog posts, for example, you would be calling 10 separate SELECT queries each retrieving only an individual database record, because you decided to have the 'BlogPost' class encapsulate its retrieval method.
The alternative is to let the class represent either one or more records, that way, you only need to run one SELECT query whether you're retrieving 5000 records or only one. Pretty much every object-relational-mapper does this.
When doing object-oriented programming, it's better to think in terms of behavior or responsibility than whether or not the object is a tangible 'thing'. That's the problem with theoretical discussion of OOP. It's very tempting to use analogies like animals and fruits which have very little relevance to real-world programming.
Since an object cannot delete itself, that has to be the responsibility of the collection.
Wether you let the collection create it's objects like $collection->makeNewItem(); (which then calls the items constructor) or use $item = new Item(); directly and then some $collection->addItem($item);method is entirely up to you and the needs of your application.
I'd recommend using regular instantiation if the items themselves are also used outside of the collection.