DataReaderInterface::read() does not define whether to caching or not.
kamarton opened this issue · comments
What steps will reproduce the problem?
It also causes problems with usage and implementation.
data/src/Reader/DataReaderInterface.php
Line 16 in 1dae24f
For example, the PaginatorInterface
cache is the result itself or not, because the data reader is already doing it.
Repeated reading may require:
- caching: repeated read for get count, items and more.
- not caching: reuse object, and watch change at any time.
What is the expected result?
specfy exactly
What do you get instead?
not specified
Q | A |
---|---|
Version | 3.0.x-dev |
PHP version | - |
Operating system | - |
I suggests:
- By default, be non-cache.
- Extend interface with
snapshot(): self
method. This method would return a reader that, based on the data provided, saves and provide the current data now and in the future.
I can suggest:
- Add a
CachedDataReader
decorator for theDataReaderInterface
. A kind of universal caching layerclass CachedReader implements DataReader { private $cache; private DataReader $dataReader ; __construct(DataReader $dataReader) { $this->dataReader = $dataReader; } function read() { // read from $this->dataReader, write to cache; on next call read from cache } }
- We can also add the
CachedDataReader
interface, which will tell us that theDataReader
itself implements the cache - I also liked the idea of adding the
IteratorAggregate
interface to theDataReader
.
Wherein, thegetIterator
method does not write to the cache: realization, documentation
@roxblnfk idea is basically like it.
I also liked the idea of adding the IteratorAggregate interface to the DataReader.
Wherein, the getIterator method does not write to the cache: realization, documentation
Ok, if the iterator clearly defines that it represents the current state. I'm thinking here that the iterator can work directly from the data source (eg. fetch partially).
The only problem with this is that count
and read
are not handled together, eg.If the delay is significant (depend on data source change) between the two, the two together are inconsistent.
class CachedReader implements DataReader {
private $cache;
private DataReader $dataReader ;
__construct(DataReader $dataReader) {
$this->dataReader = $dataReader;
}
function read() {
// read count write to cache; on next call read from cache
// read from $this->dataReader, write to cache; on next call read from cache
}
function count() {
// read count write to cache; on next call read from cache
// read from $this->dataReader, write to cache; on next call read from cache
}
}
It is also advisable to assume that the class is already inherited from CachedReader
.
class CachedReader implements DataReader {
private DataReader $dataReader ;
__construct(DataReader $dataReader) {
$this->dataReader = $dataReader;
}
function read() {
if($this->dataReader instanceof CachedReader) {
return $this->dataReader->read();
}
// ...
}
function count() {
if($this->dataReader instanceof CachedReader) {
return $this->dataReader->count();
}
// ...
}
}
I don't think it should be specified in the interface. In the discussion above about the caching decorator it is clearly visible: one implementation may require caching while another one may not.
About the cached decorator, I don't see an immediate use-case for it so closing the issue till it's requested for a real use-case.