http-message
http-message copied to clipboard
Create LateStreamInterface.php
Adds an interface to describe a late stream, which doesn't requires an already opened resource.
If accepted, I adds the factory too. ;)
What about the StreamInterface requires an already opened stream?
This is how I did it: https://github.com/PuristPHP/http-message/blob/c196b4c4859a19208d577291d7b89a26aaff6c03/src/Stream/LazyStream.php#L8
@nicholasruunu Because https://github.com/php-fig/http-factory/blob/master/src/StreamFactoryInterface.php#L42
;)
Still seem strange to me, there's nothing to stop you from doing this right now.
Yes, you can't manually just open() but I don't really see the point with that.
To create a stream, based only on StreamInterface, with a file resource, there is dirty 3 solutions:
- use a constructor ignoring the
$filename, $modepair if we have a third param$resource - use a constructor ignoring the file load if no given
$filename, then pass theresourceto the stream, by a method (permits to change theresource) >_< - duplicate the
resourcehandler, using itsmetadata['uri']
My solution seems cleaner, no ?
Sorry, I don't understand why you need to do this. Changing the resource for a stream basically just means constructing a new Stream.
Why would you need a Stream with a resource/file you won't use? In this case just create a new Steam with the correct resource.
Also, you don't need to skip constructor arguments, just create more classes. https://github.com/PuristPHP/http-message/blob/c196b4c4859a19208d577291d7b89a26aaff6c03/src/Stream/Stream.php https://github.com/PuristPHP/http-message/blob/c196b4c4859a19208d577291d7b89a26aaff6c03/src/Stream/LazyReadOnlyTextStream.php https://github.com/PuristPHP/http-message/blob/c196b4c4859a19208d577291d7b89a26aaff6c03/src/Stream/LazyStream.php
About the why, I like to create some generic libraries/frameworks and I want to provide a streams collection, but I don't want to take the responsability to open each of them, even if the user really use all of them or not. ;)
Yeah, so do what I did in LazyStream?
Yeah but your Stream classes are only related by the StreamInterface, the LazyStream doesn't extends Stream... we can also extend it, of course, but can't call the parent::__construct() in this case and I don't like to see some notice in my IDE. :D
Why do you need to extend Stream? It's using Stream everywhere.
I dislike the final classes, they pushed me to create my own tools, fully extensibles, ever.
Then don't use final, I still don't see why a new interface is needed. My classes are fully extensible via composition, but you can do it any way you want.
Extensibility by composition is fine but I prefer permit to my users to use it as they want, inheritance or not.
But maybe it can be a part of a new PSR, merged with the current interface.
(My proposal is only in a new interface to avoid any possible breaking changes)
Honestly I feel like this would pollute the StreamInterface and still haven't gotten any reason for it to exist either as a new interface or merged with the old.
Are you reading the related topic on the mailing list ?
@Lcfvs, sorry but I agree with others, here and on email thread. Doing stuff lazy is definitely an implementation concerns.
Interfaces needs to be as generic as possible and there is rarely a need for more specific interfaces. Otherwise, clients of your library will have to use an if instanceof condition in their code.
And I'll say it again, please create all your classes final without even thinking as long as you have an interface to implement. It simply reduces bugs and increase maintainability by not using the "extend" keyword.
@drealecs Why use an if instanceof condition?
If the methods call the open, it's invisible, nothing to test, nothing to change externally.
About the final, I don't want to take the decision himself, and let my framework users make the best choice for us...
Let the choice isn't promote, everyone must assume their responsibilities.
Why use an if instanceof condition?
Let's say you have BsonDataExtractor class that is used in an application that scans a BSON Stream. You would have a method in that class parseBsonStream that receive a stream of bytes. As this class is a generic class, you should accept a stream, be it lazy or not.
public function parseBsonStream (StreamInterface $stream)
{
if ($stream instanceof LazyStreamInterface) {
$stream->open();
}
// stream processing further...
}
About the final, I don't want to take the decision himself, and let my framework users make the best choice for us...
If you let users of your framework use it by inheritance, they will couple their code with yours and this will make it hard for you to refactor internal code and improve your framework. If you or the users of your framework end up with big inheritance chain, it makes it harder to reason about it as and more bugs start to appear. Good articles for you to read: https://ocramius.github.io/blog/when-to-declare-classes-final/ https://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html Maybe we can continue this thread about final separately if you still it's necessary to continue discussing it.
@drealecs Thanks for the docs ;)
About the open, I think you miss a point in my proposal: it CAN be called by the user, but any LateStreamInterface implementations MUST open the stream ITSELF if not already opened.
Then there is no need to call open from outer, it's only optional. ;)
I'm closing this. As @Jean85 pointed out, this is a non-trivial change to the spec that would not be eligible for errata. If you would like to see the interface standardized, you would need to propose a new PSR.