-
Notifications
You must be signed in to change notification settings - Fork 0
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
Separate command and options #6
Conversation
"php": ">=5.5" | ||
"php": ">=5.5", | ||
"equip/assist": "^0.1.2", | ||
"equip/data": "^2.3" |
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.
Should we separate the the immutable traits from this package to avoid version conflicts?
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.
Not sure I follow. Why would the immutable traits not being separate cause version conflicts?
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.
equip/data
would depend on equip/immutable
and this version would depend on equip/immutable
only.
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.
The goal is to prevent packages that depend on equip/data
from having conflicts with this package.
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.
Are we anticipating those sorts of conflicts would happen often enough to warrant the overhead that comes from maintaining an entirely separate repository?
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.
equip/immutable#1 here's what it would look like.
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.
What it could look like isn't difficult to visualize, but that doesn't address the points I expressed above. How many use cases are we likely to encounter where we'd want to use the immutable traits apart from the repository and entity implementations, even assuming this repository did serve as a solitary example? I'm not convinced it's worth the trouble of separation and long-term maintenance versus pulling in a bit more code from api-commands than might be needed for this particular use case.
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.
Anywhere you want an immutable value object without entity/repo stuff.
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.
This could be really useful for notifications too.
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.
Anywhere you want an immutable value object without entity/repo stuff.
Well, yeah. I included that in the question when I asked it. This doesn't answer it. I'm looking for specifics.
This could be really useful for notifications too.
How so? Would we not have entities or repositories for notifications?
95410de
to
7cf4187
Compare
|
||
use PHPUnit_Framework_TestCase as TestCase; | ||
|
||
class AbstractCommandTest extends TestCase |
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.
This is not modified, just moved.
@equip/contributors CR please! |
Not sure I see how these changes accomplish what's described above. Can you give specific use cases that these changes would improve over the existing code? |
7cf4187
to
71e4405
Compare
@elazar for example if we have a command that allows for some options that are not required and do not have defaults (say, "employee code") then having a value object makes it much more clear that this option exists. Currently in many of our commands we are not sure of what all the possible options are, so having a value object makes a source of truth for these scenarios. It also makes the command implementation easier and separates concerns better, so that the command objects can contain less option checking. |
The code in this scenario would look something like: final class CreateUserOptions extends Options
{
protected $first_name;
protected $last_name;
protected $email;
protected $password;
protected $phone_number;
protected $employee_code;
protected $role = UsersRepository::ROLE_EMPLOYEE;
} Edit: updated to match PR changes. |
@equip/contributors anyone else have thoughts about this? |
71e4405
to
22d5e98
Compare
I think representing required options within I think having value objects for options is a good idea, but I also think it may be possible to implement it satisfactorily without deprecating existing code or breaking backward compatibility. For example, we could provide a generic implementation of |
22d5e98
to
a6e3932
Compare
@elazar any further thoughts on this? I've updated my example code and switched to using an abstract class for Options (and no interface) because it's a lot more convenient. |
@shadowhand I don't follow: how is it more convenient to have no interface? This PR seems to be moving further away from design by contract and favoring composition over inheritance. I can see having a stock implementation of said interface, but I don't see why the command and options classes can't be implementations of an interface to allow for alternative implementations. |
@elazar YAGNI. The classes are so simple and high level that I don't see why anyone would need the interfaces. Type hinting against a |
a6e3932
to
b417722
Compare
This looks reasonable @shadowhand. Is this something we still want to move forward with? |
Having separate value objects for options makes it easier to understand what options are available to a command and simplifies the validation process. This change was implemented as separate classes so that usage can be upgraded incrementally and version 2.0 can remove the deprecated things.
b417722
to
37ba6d0
Compare
/** | ||
* Get a copy with new options. | ||
* | ||
* @param Options $options |
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.
Corrected this type hint, as per this Scrutinizer issue.
* | ||
* @since 1.3.0 | ||
*/ | ||
abstract class Options |
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 immutable mutators (i.e. with*()
methods)? If not, that's fine, just curious.
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, because options cannot be modified after construction.
c27171c
to
c348e57
Compare
Released in 1.3.0. |
Having separate value objects for options makes it easier to understand
what options are available to a command and simplifies the validation
process.
This change was implemented as separate classes so that usage can be
upgraded incrementally and version 2.0 can remove the deprecated things.