Yeah, I didn't want to drill down the entire design if it was off topic, but
since you mention it... :)
I'd probably also use adjectives to imply the constraints on the smaller
interfaces, rather than remove the constraints from the fuller interfaces.
Seems to scale better. I would also assume it's better to require sync/async
support upfront in the implementation, rather than force sync/async fallback
cases in the consumer.
--simplex--
IReadForwardStream : IDisposable {read, readasync}
IWriteForwardStream : IDisposable {write, writeasync, flush}
ISeekable {position}
--complex--
IStream : IReadStream, IWriteStream, IReadForwardStream,
IWriteForwardStream, ISeekable
IForwardStream : IReadForwardStream, IWriteForwardStream
IReadStream : IReadForwardStream, ISeekable
IWriteStream : IWriteForwardStream, ISeekable
IMHO, this is a perfectly fine use of the interface segregation principle
[1] where a Stream is "split into smaller and more specific interfaces so
that any clients of the interface will only know about the methods that
pertain to them. In a nutshell, no client should be forced to depend on
methods it does not use." [2]
I agree composition of types only gets you so far, and inheritance hierarchy
based on exposing layers of capabilities is a source of great evil, but
factoring interfaces for different client roles is very different animal.
[1] http://davidhayden.com/blog/dave/archive/2005/06/15/1482.aspx
[2] http://en.wikipedia.org/wiki/Interface_segregation_principle
On Fri, Mar 11, 2011 at 1:30 PM, Chris Tavares <[email protected]>wrote:
> Plus you'd need IAsyncReadableStream, IAsyncWritableStream,
> IAsyncSeekableStream, etc. Composition of types in a static type system
> only
> gets you so far.
>
> Design concerns in a framework are a little different than those concerns
> for an application. You not only have to worry about maintenance, you also
> have serious binary compatibility concerns around code that you didn't
> write, never see, and know is out there somewhere but know nothing about.
>
> I again point to the .NET Framework design guidelines, particularly the
> annotations. There's a discussion in there (my copy's currently packed in a
> box or I'd give a page #) when talking about preferring abstract base
> classes over interfaces about the streams library and why it's built the
> way
> it is. You may not agree with the conclusions, but it's definitely worth
> reading and thinking about.
>
> -Chris
>
> -----Original Message-----
> From: [email protected] [mailto:
> [email protected]]
> On Behalf Of Frank Schwieterman
> Sent: Friday, March 11, 2011 12:15 PM
> To: [email protected]
> Subject: Re: Your Favorite Liskov Violations Examples in .NET
>
> You'd also need an ISeekableReadyStream and ISeekableWriteStrream,
> as not all streams support seek.
>
> Its awkward, maybe in the same way the
> System.Net.WebRequest.CreateWebRequest() was built to support multiple
> protocols, making the only protocol I care about (HTTP) require more
> legwork. I don't know if its a Liskov violation.
>
> This whole Liskov threads has made me think there is some "In Soviet
> Russia, ..." joke I could make but I haven't thought of it yet.
>
>
> On Fri, Mar 11, 2011 at 11:35 AM, Louis DeJardin
> <[email protected]> wrote:
> > Ah, yes. Maybe it's a violation of the "I" you're looking for in the case
> of
> > Stream?
> >
> > If there was an IReadableStream, IWritableStream, and IStream :
> > IReadableStream, IWritableStream would you even need the Stream abstract
> > base class? The subtypes don't share implementation code at that low
> level.
> >
> > Even if it did turn out there was some protected code in common between,
> for
> > example, a FileStream, SocketStream, and EncryptionStream you would be
> > better off favoring composition over inheritance. Other classes, for
> > example, whose only concern was an efficient write-bytes-buffer... Or
> winapi
> > io handle wrapper...
> >
> >
> > On Fri, Mar 11, 2011 at 10:42 AM, Justin Bozonier <[email protected]
> >
> > wrote:
> >>
> >> I think it is technically ok by the Liskov Principle (I researched
> >> some more about the original intent) since the actual contract
> >> stipulates that you check that property.
> >>
> >> The fact that you need to care about the implementation is suboptimal
> >> though. I typically think of LSP meaning that if I have a method on an
> >> interface then ideally I should be able to use it.
> >>
> >> The advent of CQRS supports this point (though not definitively).
> >>
> >> I'm also not saying Microsoft did a piss poor job just that for my
> >> use, avoiding the property check would have resulted in an API design
> >> that was cleaner and simpler for my use.
> >>
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Seattle area Alt.Net" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to
> > [email protected].
> > For more options, visit this group at
> > http://groups.google.com/group/altnetseattle?hl=en.
> >
>
> --
> You received this message because you are subscribed to the Google Groups
> "Seattle area Alt.Net" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/altnetseattle?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Seattle area Alt.Net" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/altnetseattle?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"Seattle area Alt.Net" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/altnetseattle?hl=en.