-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix PaymentTokenFactory interface to have the "Interface" at the end of the name. #9306
Fix PaymentTokenFactory interface to have the "Interface" at the end of the name. #9306
Conversation
… the name with "Interface". In order to let CI check this file everytime changed the following: - Removed the @codingstandardsIgnoreFile from the head of the file. - Renamed the file and the name of the interface to PaymentTokenFactoryInterface so that it ends with the name "Interface" - Refactored references to this class in other Magento modules so that this name change is reflected there as well.
@magento-team For this code violation fix I changed the name of a interface. Please look into this, since I think this might introduce a breaking change and tell me how you want to deal with this. A possible solution I can think of is to keep the old class name and let it extend to the refactored new class name. We can add a "deprecated" message in the old class name, so that it can eventually be removed. Please let me know your thoughts so I can change this in order to get this accepted. |
Hi @dverkade
This is pretty much the way we tend to deal with these issues at the moment. Would be nice if you could update your PR in the proposed way and we will look into it. |
…s the new interface name.
- Reverted refactored changed class names for the Abstract class, which should not have been changed in the first place.
- Reverted refactored changed class names for the Abstract class, which should not have been changed in the first place.
Hi @ishakhsuvarov, I checked this again and made some changes (refactored to much code in the first place) and added the deprecated file which I suggested. So this PR is complete from my side. Hope you can have a look at it. |
@dverkade Thanks for the update. We are in the process of discussion of the proposed changes, since there are some concerns regarding the interface in question. I will provide an update for you when we come up with some ideas. |
Hey @dverkade , Making naming consistency along the code base is very important for us, but we can't introduce changes for API very often. That’s why I want you to ask to accompany your changes with refactoring of the PaymentTokenFactoryInterface, because this contract is far from ideal, and does not represent ideal state dictated by our Technical Vision. Which I'll describe below. The current problems I see are next:
$paymentToken = $this->objectManager->create(PaymentTokenInterface::class);
$paymentToken->setType($this->getType()); also has a "smell" , because in our case instance of Model\PaymentToken doesn't have sense without setting type. But we could potentially create Model\PaymentToken object not specifying one. If we will inject dependency on Model\PaymentToken in Constructor DI of some other object. So, what I propose to do:
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Vault\Api\Data;
/**
* Interface PaymentTokenFactoryInterface
*/
interface PaymentTokenFactoryInterface
{
/**
* Create payment token entity
* @param $type account|card
* @return PaymentTokenInterface
*/
public function create($type);
} which will have correct factory contract. Without getType() method, and create method which accepts type as parameter.
/**
* Class CreditCardTokenFactory
* @api
* @deprecated
* @see PaymentTokenFactoryInterface
*/
class CreditCardTokenFactory extends AbstractPaymentTokenFactory
{
/**
* @var string
*/
const TOKEN_TYPE_CREDIT_CARD = 'card';
public function __construct(
ObjectManagerInterface $objectManager
PaymentTokenFactoryInterface $newTokenFactory = null
) {
$this->objectManager = $objectManager;
$this->tokenFactory = $newTokenFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(PaymentTokenFactoryInterface::class);
}
/**
* Create payment token entity
* @return PaymentTokenInterface
*/
public function create()
{
return $this->tokenFactory->create($this->getType());
}
/**
* @inheritdoc
*/
public function getType()
{
return self::TOKEN_TYPE_CREDIT_CARD;
}
} Doing all of the above, we wouldn't introduce Backward Incompatible changes, and will introduce useful refactoring which moves our Vault Token Factory interface to the desired vision. So, all the 3rd party devs will need to make an upgrade just once. Hope that makes sense for you. |
Hi @maghamed, Thanks for your information and have checked the solution you are suggesting. However I do see a problem with this. In your example you have added a "create" function to the CreditCardTokenFactory class. This class extends the AbstractPaymentTokenFactory class which in its turn implements the PaymentTokenFactoryInterface. The interface has changed and it's now manditory to submit the $type parameter to it, so the proxy create function you are suggestion in the CreditCardTokenFactory will not be compatible with the interface it needs to implement. This will not work and throws an error since the create function is incompatible. How about we change the behaviour of the AbstractPaymentTokenFactory class to something like this, where we have a fallback on the type argument. It can be null, when it is, it will call the $this->getType() function, otherwise it will pass the argument given to it.
|
No, I didn't add "create" function to CreditCardTokenFactory. Function create already there, it was inherited from AbstractPaymentTokenFactory with next implementation. /**
* Create payment token entity
* @return PaymentTokenInterface
*/
public function create()
{
/** @var PaymentTokenInterface $paymentToken */
$paymentToken = $this->objectManager->create(PaymentTokenInterface::class);
$paymentToken->setType($this->getType());
return $paymentToken;
} So, CreditCardTokenFactory already has a contract of So, we not changing existing interface interface PaymentTokenInterfaceFactory
{
/**
* Create payment token entity
* @return PaymentTokenInterface
*/
public function create();
/**
* Return type of payment token
* @return string
*/
public function getType();
} which we consider as deprecated. /**
* Interface PaymentTokenFactoryInterface
*/
interface PaymentTokenFactoryInterface
{
/**
* Create payment token entity
* @param $type account|card
* @return PaymentTokenInterface
*/
public function create($type);
} Regarding changes proposed by you abstract class AbstractPaymentTokenFactory implements PaymentTokenFactoryInterface
{
/**
* Create payment token entity
* @return PaymentTokenInterface
*/
public function create($type = null) we can't change contract of the AbstractPaymentTokenFactory , because that will introduce backward incompatible changes. Which is forbidden. Does it make sense for you? |
Hi @dverkade , will you help us to improve existing APIs of Vault module based on the output above? That would be very valuable for M2 and improve code quality of Magento Service Contracts. |
Hi @maghamed Yes, I would like to update this PR and get is accepted. But i'm a little confused. You are mentioning that the CreditCardTokenFactory already has a create function. But this is not in de develop branch i'm look in. Is this something that is in another branch already? Hope you can point me in the right direction so we can solve this issue. |
In the Develop branch, CreditCardTokenFactory is extended from AbstractPaymentTokenFactory
AbstractPaymentTokenFactory has
This method also part of the PaymentTokenInterfaceFactory interface Thus, CreditCardTokenFactory class already has a method create() which it inherits from the AbstractPaymentTokenFactory. Does it make sense? |
Hi @maghamed, Thank you for your anwer. I will look into this over the weekend. |
- Deprecated AbstractPaymentTokenFactory, CreditCardTokenFactory andd AccountPaymentTokenFactory - Created proxy call for creating the PaymentToken truth the new PaymentTokenFactoryInterface and classes.
…enInterfaceFactory - Fixed coding standards in AbstractPaymentTokenFactory
@@ -11,7 +11,8 @@ | |||
|
|||
/** | |||
* Class AbstractPaymentTokenFactory | |||
* @api | |||
* @deprecated | |||
* @see PaymentTokenFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ see PaymentTokenFactoryInterface
* AccountPaymentTokenFactory constructor. | ||
* @param ObjectManagerInterface $objectManager | ||
*/ | ||
public function __construct(ObjectManagerInterface $objectManager) | ||
public function __construct(ObjectManagerInterface $objectManager, PaymentTokenFactoryInterface $paymentTokenFactory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PaymentTokenFactoryInterface $paymentTokenFactory should be optional parameter
PaymentTokenFactoryInterface $paymentTokenFactory = null
to preserve backward compatibility
@@ -7,7 +7,8 @@ | |||
|
|||
/** | |||
* Class AccountPaymentTokenFactory | |||
* @api | |||
* @deprecated | |||
* @see PaymentTokenFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ see PaymentTokenFactoryInterface
@@ -7,7 +7,8 @@ | |||
|
|||
/** | |||
* Class CreditCardTokenFactory | |||
* @api | |||
* @deprecated | |||
* @see PaymentTokenFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ see PaymentTokenFactoryInterface
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface; | ||
|
||
/** | ||
* Interface PaymentTokenFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please provide a precise description.
as it's not an interface
…e given type is not found.
- Refactored PaymentToken to use data array instead of own variable.
Hi @dverkade |
I did not get a reply on this issue where I'm mentioning the failing tests: When I get an answer I can work on this PR again |
I have finished this PR and tests are now passing with the latest changes made. |
@dverkade |
ObjectManagerInterface $objectManager, | ||
PaymentTokenFactoryInterface $paymentTokenFactory = null | ||
) { | ||
if (!$paymentTokenFactory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use === null instead
/** | ||
* @return string | ||
*/ | ||
abstract public function getType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to specify abstract public getType method here
we get it from PaymentTokenInterfaceFactory
interface PaymentTokenInterfaceFactory
{
/**
* Create payment token entity
* @return PaymentTokenInterface
*/
public function create();
/**
* Return type of payment token
* @return string
*/
public function getType();
}
|
||
/** | ||
* Create payment token entity | ||
* @param $type string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please specify Null as a possible input value
* @param ObjectManagerInterface $objectManager | ||
* @param array $tokenTypes | ||
*/ | ||
public function __construct(ObjectManagerInterface $objectManager, $tokenTypes = []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please specify
array for $tokenTypes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what you mean here. array has been definied in the doc comments and is specified in the param as default value was well. What and how do you want it to be described?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean explicitly specify type hint for $tokenTypes
like
array $tokenTypes = []
- Changed check to === null - Added null to doc comments for $type parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, well done!
Thanks for contribution
Btw @dverkade you made a PR which we accepted and will deliver to mainline soon. Maybe you have some time to write a blog post regarding this Pull Request and share with Magento community the experience you gained. How it's complicated to write APIs in a backward compatible way, and that it's possible to do so, not breaking anybody. Not a lot of contributors introduce changes for Magento APIs and you are one of those. I believe your experience would be helpful for many Mangeto contributors. |
…ce" at the end of the name. #9306
Fixed coding standard violation for an interface which was not ending the name with "Interface". In order to let CI check this file everytime changed the following: