2

According to following article Named Constructors The Author suggests using static factory pattern to construct objects is way better than instantinate with new keyword. At the begining the idea is appealing(according to some details in article) yes method names are more obvious and it gives a sense that the construction of the class it is not dependent to it's contstructor but class has different behaviours according to different problems on construction level.

<?php
$customer = new Customer($name); 
// We can't "new a customer" or "instantiate a customer" in real life.
// Better:
$customer = Customer::fromRegistration($name);
$customer = Customer::fromImport($name);

But the problem I see here according to this idiom we are using class methods like functions! And according to the above example it creates coupling issues we have to wrap this static factories with an injectible factory to decouple from the rest of the application?

Could you please clarify me to understand this. I started to see this idiom all around in PHP community and even in some Java examples.

  • 4
    "we are using class methods like functions!". You say this like it's a bad thing... – Nick Keighley Oct 3 '17 at 9:05
  • 12
    "We can't "new a customer" or "instantiate a customer" in real life." what a nonsense argument. Code is not real life. – CodesInChaos Oct 3 '17 at 9:09
  • 3
    It looks like the motivation is to work around PHP's restriction on only one constructor. It is orthogonal to coupling issues around newing objects (I.e. new has to appear somewhere) – Caleth Oct 3 '17 at 9:09
  • 2
    @CodesInChaos The author is not only one thinking it. You are correct that code is not real life, but DDD code SHOULD be using ubiquitous language the business understands, too. newing a customer makes no sense to the business. Creating a customer from registration session does. I see the motivation there. – Andy Oct 3 '17 at 10:22
  • 1
    Note : even if you can have multiple constructors, if you have two possibilities : one from name, another from registration, and they're both String, you're stucked. Either you need to create a wrapper class for one of them, or you need static method/factories. Problem is, you can't use inheritance and override static methods. – Walfrat Oct 3 '17 at 11:10
8

Named Constructors in PHP

Don't limit yourself by PHP's single constructor. Use static factory methods.

The article is not about coupling. There is zero difference in coupling between using new Customer(/* some args */) and Customer::fromFoo(/* some args */). Where you put those expressions determines how coupled they are. All the "Factory Pattern" boils down to is "expression returning object".

The difference is instead about working around PHP's restriction on a class having a single constructor. If you want to have multiple ways of constructing a class, there are two choices:

  • distinguish them in the single constructor, from the arguments
  • distinguish them with multiple static factories, which take different arguments from each other.
| improve this answer | |
  • I got your point here so then when you need to pass this to DI your container have to support object instantination through static factory methods. With that you can still pass things through DI. – FZE Oct 3 '17 at 12:38
  • function ($args) { return new Customer($args) } is a value of type args_type -> Customer. Customer::fromArgs is also a value of type args_type -> Customer. That is what a "Customer Factory" is. Dependancy Injection is "taking objects via parameters, not newing them", you don't need a "DI container" to do it. – Caleth Oct 3 '17 at 12:49
  • We don't need to but we do, at least according to our application sizes we have service container. – FZE Oct 3 '17 at 12:53
0

In PHP we don't have multiple constructors per class but that won't help anyway because they would be named the same: __construct, a term that is not from the ubiquitous language.

But why do we use a constructor anyway? We use it to correctly initiate an object to a valid initial state. We can do that by making the properties private, which also helps in protecting the object encapsulation. This means that they can be changed only from the context of the class. The problem is that there could be more than one valid initial state for many of our objects. So, in order to allow only initial valid states and to protect encapsulation we can use class static methods as object constructors, one for each use case.

In C++ there are friend classes that may access private properties and so they can have a friend class as factory for each use case but we don't so we must use static methods.

BTW, using static methods doesn't break encapsulation because the context is class. You can see that by the fact that PHP let you access private properties and methods also from static class methods.

| improve this answer | |
  • I aggree most of your explanations but there something needs to be fixed. First of all you cannot access class properties or methods from static context because static has nothing to do with object it's a shared global state it cannot call local states because it doesn't aware but you can call global state from local state. You can only call static methods properties and constants from static context. Another thing is static is a violation of encapsulation because it doesn't belong to object we cannot even mention encapsulation. – FZE Oct 4 '17 at 6:12
  • @FZE Thanks! But yes you can access them from static context, but not using $this. Regarding encapsulation, I don't agree again, static context participate in defining encapsulation also. Static/class context is still inside encapsulation, as long as the object modified is owned/created by static context, like our case. – Constantin Galbenu Oct 4 '17 at 6:27
  • I really couldn't understand do you mean like the following example ? <?php class A { private static $x = 'X'; private $y = 'Y'; public static function m() { return self::$x . self::$y; } } echo A::m(); If it is the case no you cannot. It is also meaningless because there is no object instantinated so it cannot access to variable $y if it can access that would be an ultimate violation of encapsulation :) – FZE Oct 4 '17 at 11:18
  • Besides that a Class and an Object are different as we deal. encapsulation it's meaningful when there is an object. Static methods are nothing to do with the object it is not the object method it's global belongs to class. I created following example to show what is my point when saying it violates encapsulation. gist.github.com/feyyazesat/d0c0839df11b001d7144616d2aa68abf – FZE Oct 4 '17 at 11:32
  • @FZE "Encapsulation is used to hide the values or state of a structured data object inside a class" - read carefully that and notice the term "class"; your example is not right, I didn't speak about that situation. See my response here: gist.github.com/xprt64/14638467d02f59bbb4127f4415c5017c – Constantin Galbenu Oct 4 '17 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.