Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Suppose that I have an input stream interface, which defines a method for reading data. I also have a seekable interface which defines a method for seeking. A natural way of defining a input file is then to implement both input stream and seekable.

I want to construct a data decoder from the input stream interface so I can read data from a file or from another stream. The problem is that I also want to implement seek functionality to the data decoder, since I want to be able to step individual records not raw bytes. This is not possible if I only provide an input stream, which does not have the bytewise seek method.

Should I skip the seekable interface and add the seek method to input stream instead and force all streams to at least leave it as a nop.

EDIT: The decoder does not need to seek if the client does not request a seek operation. Also the stream is associated with the decoder and cannot be changed after initialization

share|improve this question
1  
think of client code that is expected to use the API you are designing (or better yet, create unit tests to see yourself how it will work). How would it handle nops for streams that don't support seek? If you find it easy and convenient, go for nop option; otherwise, drop this idea –  gnat Dec 13 '12 at 18:38
    
@gnat letting the method return false if seeking is not supported can work very well. I can just probe for seek support using foo.seek(0,SEEK_CURRENT) ie seek 0 bytes from current position. –  user877329 Dec 13 '12 at 18:46
    
"can work very well" - you better double check assumptions like that. I for one have seen it work pretty well in one kind context and being major headache in another. I found it really safer to learn about how my API will be used with unit tests, this helps to lower uncertainty in cases like this. –  gnat Dec 13 '12 at 18:50
add comment

2 Answers

The way the .NET guys solved this problem was to introduce a property IsSeekable that allow to know if a Stream can be seeked. If not and you call Seek() anyway, it throws an exception. It's not very polymorphic but it's simple and works reasonably well in practice. It allows Stream to be passed around freely and each method can optimise for seeking if it want. The downside is that any method that want to use Seek() need to check the property before.

A more object oriented approach would be to create the interface SeekableInputStream that derives from both Seekable and InputStream. That way a class that needs to seek like your data adapter can require that specific interface and be guaranteed that seek will work. Better yet, the compiler will warn you if you try to send an invalid InputStream to such method. Other method can accept any class that implements InputStream, including those that implement SeekableInputStream. The downside to this method is that if you pass your SeekableInputStream around a lot then once its downcasted to InputStream the information about its seekability is lost and you need to cast it to SeekableInputStream back again if you really to optimise when you can seek.

share|improve this answer
add comment

I think this kind of problem can be easily fixed by decorating the object. In your case, you're going to have your streams, using your stream interface, and a seeker stream decorator, which adds the seeking functionality you require. You can then decorate your streams with the seeking functionality whenever needed.

share|improve this answer
    
It seems somewhat overkill –  user877329 Dec 13 '12 at 18:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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