Tagging interfaces

Discussion in 'Java' started by VisionSet, Nov 29, 2005.

  1. VisionSet

    VisionSet Guest

    Why exactly are they bad?

    I have a entity, a collection of which is to be associated with an object
    that has no need to call any methods on or know anymore than the entity is
    of a certain type. These entities are then passed back to the object that
    instantiated them which can cast to the concrete type to do something useful
    with them. So a tagging interface seems to fit the bill for my entity.

    --
    Mike W
     
    VisionSet, Nov 29, 2005
    #1
    1. Advertising

  2. VisionSet

    Guest

    Who said they're bad?
     
    , Nov 29, 2005
    #2
    1. Advertising

  3. VisionSet wrote:
    > Why exactly are they bad?
    >
    > I have a entity, a collection of which is to be associated with an object
    > that has no need to call any methods on or know anymore than the entity is
    > of a certain type. These entities are then passed back to the object that
    > instantiated them which can cast to the concrete type to do something useful
    > with them. So a tagging interface seems to fit the bill for my entity.


    Please correct me if I have misunderstood anything:

    Each "Entity" requires type-specific processing, but you want the code
    for all the processing, for all the different types, to be defined in
    one "Master" object.

    The Master, which actually created all of these Entities, forgets the
    Entities' exact types at some point. It therefore wants them to be
    "tagged," possibly by having them implement empty but nominally
    different interfaces.

    This sounds like a perfect case for polymorphism. Forget all the
    tagging interfaces. Have all the Entities implement just one interface,
    and each concrete Entity type can implement the interface differently.
    If you really want to keep the processing code in the Master object, let
    each concrete Entity type just immediately invoke a type-specific
    callback method in the Master.

    If this isn't clear, or doesn't sound like a good idea, let me know &
    I'll whip up some example code.
     
    Jeffrey Schwab, Nov 29, 2005
    #3
  4. VisionSet

    VisionSet Guest

    "Jeffrey Schwab" <> wrote in message
    news:Hw%if.8543$...
    > VisionSet wrote:
    > > Why exactly are they bad?
    > >
    > > I have a entity, a collection of which is to be associated with an

    object
    > > that has no need to call any methods on or know anymore than the entity

    is
    > > of a certain type. These entities are then passed back to the object

    that
    > > instantiated them which can cast to the concrete type to do something

    useful
    > > with them. So a tagging interface seems to fit the bill for my entity.

    >
    > Please correct me if I have misunderstood anything:
    >
    > Each "Entity" requires type-specific processing, but you want the code
    > for all the processing, for all the different types, to be defined in
    > one "Master" object.


    The number of types (tagged types) and number of master objects is a 1:1
    relationship
    In fact there is only ever likely to be one entity type and one master
    object, but that is not important.
    We shall assume other types may exist at some point.

    >
    > The Master, which actually created all of these Entities, forgets the
    > Entities' exact types at some point. It therefore wants them to be
    > "tagged," possibly by having them implement empty but nominally
    > different interfaces.


    The tagging is merely type safety mechanism so the surrogate collector can
    only collect a certain type, and the master only gets back what it expects.

    --
    Mike W
     
    VisionSet, Nov 29, 2005
    #4
  5. VisionSet wrote:
    > "Jeffrey Schwab" <> wrote in message
    > news:Hw%if.8543$...
    >
    >>VisionSet wrote:
    >>
    >>>Why exactly are they bad?
    >>>
    >>>I have a entity, a collection of which is to be associated with an

    >
    > object
    >
    >>>that has no need to call any methods on or know anymore than the entity

    >
    > is
    >
    >>>of a certain type. These entities are then passed back to the object

    >
    > that
    >
    >>>instantiated them which can cast to the concrete type to do something

    >
    > useful
    >
    >>>with them. So a tagging interface seems to fit the bill for my entity.

    >>
    >>Please correct me if I have misunderstood anything:
    >>
    >>Each "Entity" requires type-specific processing, but you want the code
    >>for all the processing, for all the different types, to be defined in
    >>one "Master" object.

    >
    >
    > The number of types (tagged types) and number of master objects is a 1:1
    > relationship
    > In fact there is only ever likely to be one entity type and one master
    > object, but that is not important.
    > We shall assume other types may exist at some point.
    >
    >
    >>The Master, which actually created all of these Entities, forgets the
    >>Entities' exact types at some point. It therefore wants them to be
    >>"tagged," possibly by having them implement empty but nominally
    >>different interfaces.

    >
    >
    > The tagging is merely type safety mechanism so the surrogate collector can
    > only collect a certain type, and the master only gets back what it expects.


    Wouldn't it be easier, and make your intent clearer, to use generics?
     
    Jeffrey Schwab, Nov 29, 2005
    #5
  6. VisionSet

    VisionSet Guest

    "Jeffrey Schwab" <> wrote in message
    news:eek:11jf.7997$...

    > >
    > > The tagging is merely type safety mechanism so the surrogate collector

    can
    > > only collect a certain type, and the master only gets back what it

    expects.
    >
    > Wouldn't it be easier, and make your intent clearer, to use generics?


    I'll still need a type, no?

    Collection<? extends TagIntf>

    --
    Mike W
     
    VisionSet, Nov 29, 2005
    #6
  7. VisionSet wrote:
    > "Jeffrey Schwab" <> wrote in message
    > news:eek:11jf.7997$...
    >
    >
    >>>The tagging is merely type safety mechanism so the surrogate collector

    >
    > can
    >
    >>>only collect a certain type, and the master only gets back what it

    >
    > expects.
    >
    >>Wouldn't it be easier, and make your intent clearer, to use generics?

    >
    >
    > I'll still need a type, no?
    >
    > Collection<? extends TagIntf>


    You said you wanted the surrogate collector to "only collect a certain
    type." You should be able to use this type as the parameter for the
    generic container, e.g. Collection<Entity>. No?
     
    Jeffrey Schwab, Nov 29, 2005
    #7
  8. VisionSet

    VisionSet Guest

    "Jeffrey Schwab" <> wrote in message
    news:aY1jf.5420$...

    > >>Wouldn't it be easier, and make your intent clearer, to use generics?

    > >
    > >
    > > I'll still need a type, no?
    > >
    > > Collection<? extends TagIntf>

    >
    > You said you wanted the surrogate collector to "only collect a certain
    > type." You should be able to use this type as the parameter for the
    > generic container, e.g. Collection<Entity>. No?


    I said I wanted to assume that the 1 type may grow to include others,
    although only 1 type would be used in any 1 instance of the program, but
    that is irrelevent I want the code to be able to support that eventuallity.
    Hence the tagging interface.

    But I'd heard there really was no defence for tagging interface approach,
    and that is is merely a hack to allow introspection. But when you are faced
    with the situation where an objects references are collected at various
    places because that is where they naturally belong, and that is the best way
    to manage there existence, but no methods are called on them, and you want
    to decouple their logic, then this seems like an okay use to me.

    --
    Mike W
     
    VisionSet, Nov 29, 2005
    #8
  9. VisionSet wrote:
    > Why exactly are they bad?
    >
    > I have a entity, a collection of which is to be associated with an object
    > that has no need to call any methods on or know anymore than the entity is
    > of a certain type. These entities are then passed back to the object that
    > instantiated them which can cast to the concrete type to do something useful
    > with them. So a tagging interface seems to fit the bill for my entity.
    >
    > --
    > Mike W
    >
    >


    Before 1.5, Tagging (or more commonly know as 'Marker') Interfaces were
    a good way of achieving the same effect as 1.5 Annotations.

    They were never bad - mis-understood and therefore mis-used.

    Now we have annotations there is certainly less need for them.

    Andrew
     
    Andrew McDonagh, Nov 29, 2005
    #9
  10. VisionSet

    Chris Smith Guest

    VisionSet <> wrote:
    > Why exactly are they bad?
    >


    My thoughts on the matter.

    If you think of what you're doing as a tag interface, then it's probably
    a bad idea, at least as of Java 1.5. The reason is that interfaces are
    part of the type system, and as such they imply a certain relationship
    between the types of objects that implement them.

    There are two ways you can solve this apparent mismatch.

    (a) Give up on making the "tag" a type. With Java 1.5, you'd then
    decide to use an annotation, instead. Annotations don't define type
    system relationships, but they do allow you to note information about a
    type that can be used (among other places) dynamically at runtime. For
    example, if Java were newly designed today, Cloneable and Serializable
    would probably be annotations, because no one ever keeps a variable of
    type Serializable or Cloneable.

    (b) The other direction: stop thinking of it as a tagging interface, and
    start thinking of it as a full-fledged type. Even if that type doesn't
    necessarily need to declare any methods at all (as in your example), it
    is a type... and it COULD declare methods. Once you're comfortable with
    that, stop calling it a tagging interface, and stop worrying about bad
    design. (Of course, if you then think of operations that make sense and
    are useful to your application on all referents of that type, by all
    means add them to the interface... especially if this allows you to take
    advantage of polymorphism.)

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Nov 30, 2005
    #10
  11. Chris Smith wrote:
    > if Java were newly designed today, Cloneable and Serializable
    > would probably be annotations, because no one ever keeps a variable of
    > type Serializable or Cloneable.


    I do. I at times keep variables and declare method parameters and
    return types as Serializable in classes that implement Serializable, so
    as to improve the likelihood that instances can in fact successfully be
    serialized. Naturally, this tends to involve general-purpose classes
    where the declared types would otherwise be Object. I haven't done this
    with Java 1.5 yet, but in a generic class or method I might use
    Serializable as an upper type bound or (intentionally) in an
    intersection type. It does not seem that this paradigm ever caught on
    in the wider world, but it does lead me to accept Serializable as a very
    reasonable type.

    In the context of the larger discussion of tag interfaces, however, the
    reason that Serializable as an interface makes any sense is that it has
    special meaning to the VM. A type should convey useful information
    about objects, and for interfaces without special meaning to the VM, it
    is my opinion that at least one method is necessary to make the
    information conveyed useful.

    --
    John Bollinger
     
    John C. Bollinger, Dec 1, 2005
    #11
  12. VisionSet

    Chris Smith Guest

    John C. Bollinger <> wrote:
    > In the context of the larger discussion of tag interfaces, however, the
    > reason that Serializable as an interface makes any sense is that it has
    > special meaning to the VM. A type should convey useful information
    > about objects, and for interfaces without special meaning to the VM, it
    > is my opinion that at least one method is necessary to make the
    > information conveyed useful.


    I'm not clear on the details of Mike's case... but if he's being
    generally accurate in his description, Mike may have a counter-example
    to your statement.

    In his case, Mike is apparently keeping objects in some kind of
    specialized data structure whose behavior (presumably) only makes sense
    for objects of that specific type. The type may not have any general
    new operations to introduce, but in may still imply certain constraints
    in the way that its objects should be managed. It may even further
    constrain the implementations of inherited method declarations, such as
    Object's equals and hashCode. Much like in the Collections API, then,
    the client code is arranged to know the type when it retrieves the
    object.

    Of course, this new data structure type *could* be written with a type
    of Object, but that would imply that it works properly and makes sense
    for all Object references... something that may not actually be the
    case. I would think this is exactly the right use for a type, new
    operations or not.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 1, 2005
    #12
  13. VisionSet

    Chris Smith Guest

    John C. Bollinger <> wrote:
    > Chris Smith wrote:
    > > if Java were newly designed today, Cloneable and Serializable
    > > would probably be annotations, because no one ever keeps a variable of
    > > type Serializable or Cloneable.

    >
    > I do. I at times keep variables and declare method parameters and
    > return types as Serializable in classes that implement Serializable, so
    > as to improve the likelihood that instances can in fact successfully be
    > serialized.


    Perhaps. I tend to see this as too leaky to be worthwhile. You're
    impacting a lot of code in order to build something that doesn't provide
    any additional guarantees. After all, ArrayList implements Serializable
    yet can't guarantee that it can be serialized.

    Worse, though, you impact client code here as well. There are plenty of
    good reasons to hold references to objects that you know are
    serializable, and yet not use a serializable type. For example, I often
    keep references of type List for obvious reasons, yet List does not
    extend Serializable. I may need to add casts to my code in order to use
    an API that uses Serializable as a type, and yet there's no good way
    that I could modify my code to hold variables of type Serializable in
    the first place.

    In the end, I dismiss use of Serializable as a type as being without
    significant merit. If it could make serialization safe, of course, that
    would be phenomenal... but it can't. Instead, it only adds more static
    hurdles to using what is ultimately a runtime-checked feature anyway.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 1, 2005
    #13
  14. VisionSet

    VisionSet Guest

    "Chris Smith" <> wrote in message
    news:...

    > I'm not clear on the details of Mike's case... but if he's being
    > generally accurate in his description, Mike may have a counter-example
    > to your statement.


    Okay, since I've generated some interest, I'll expand.

    I'm attempting to decouple the method of networking from the work that the
    server does.
    I have a 2 way socket based network layer that can initiate communication,
    handle requests and reply with responses in either direction.
    This Class is passed handler objects which deal with the requests and return
    something appropriate.
    In order for the server to pass the correct stuff to specific interested
    clients the business part of the server must keep references to its clients.
    These references must know how to locate the client but the business part of
    the server does not need to know this. So ClientRef has some business stuff
    and also a Location reference. It is this location reference that can be an
    empty interface type. The business layer never needs to know anything other
    than it is some form of locator. The network layer created the Location and
    when it gets it back will know how to interrogate it for the address.
    I suppose this is by the by, but I guess port and ip address is only ever
    going to be the information you need to locate. But I don't know that for
    sure, so the principle stands.

    --
    Mike W
     
    VisionSet, Dec 1, 2005
    #14
  15. Chris Smith wrote:
    > John C. Bollinger <> wrote:
    >
    >>Chris Smith wrote:
    >>
    >>> if Java were newly designed today, Cloneable and Serializable
    >>>would probably be annotations, because no one ever keeps a variable of
    >>>type Serializable or Cloneable.

    >>
    >>I do. I at times keep variables and declare method parameters and
    >>return types as Serializable in classes that implement Serializable, so
    >>as to improve the likelihood that instances can in fact successfully be
    >>serialized.

    >
    >
    > Perhaps. I tend to see this as too leaky to be worthwhile. You're
    > impacting a lot of code in order to build something that doesn't provide
    > any additional guarantees. After all, ArrayList implements Serializable
    > yet can't guarantee that it can be serialized.


    I did say I wanted to "improve the likelihood" of being able to
    serialize instances, not that I wanted to ensure successful
    serialization. If the approach I describe were ubiquitous then it would
    be much more effective.

    > Worse, though, you impact client code here as well. There are plenty of
    > good reasons to hold references to objects that you know are
    > serializable, and yet not use a serializable type. For example, I often
    > keep references of type List for obvious reasons, yet List does not
    > extend Serializable. I may need to add casts to my code in order to use
    > an API that uses Serializable as a type, and yet there's no good way
    > that I could modify my code to hold variables of type Serializable in
    > the first place.


    I disagree. For a class whose instances are expected to routinely be
    serialized, declaring method parameters to be Serializable both
    reinforces the point with the class' users and provides some degree of
    compile-time checking. It is incorrect to keep references of a
    non-Serializable type and nevertheless expect the referenced objects to
    be Serializable, even if you "know" that they really are, just as it is
    incorrect to keep references of type Collection and yet assume that the
    referenced objects are Lists. Indeed, the error is precisely in relying
    on knowledge about the objects' classes that is not reflected in their
    references' declared types. Typecasts (of reference types) are usually
    a sign of this kind of error, with the only exception I can think of
    being casting to disambiguate an overloaded method invocation.

    By the way, the type safe solution in the List example is not to cast,
    but rather "new ArrayList<SomeSerializableType>(myAnyList)".

    (Aside: avoiding most need to engage in the kind of incorrect coding
    discussed above is by far my favorite aspect of both generics and
    covariant return types.)

    > In the end, I dismiss use of Serializable as a type as being without
    > significant merit. If it could make serialization safe, of course, that
    > would be phenomenal... but it can't. Instead, it only adds more static
    > hurdles to using what is ultimately a runtime-checked feature anyway.


    No, it can't make serialization safe, because serialization is
    fundamentally unsafe. I remain convinced, however, that it makes
    serialization saf*er* -- by making some of the class' expectations
    explicit in its structure -- and, moreover, that it presents no
    additional hurdle whatsoever to otherwise typesafe code.

    --
    John Bollinger
     
    John C. Bollinger, Dec 3, 2005
    #15
  16. Chris Smith wrote:
    > John C. Bollinger <> wrote:
    >
    >>In the context of the larger discussion of tag interfaces, however, the
    >>reason that Serializable as an interface makes any sense is that it has
    >>special meaning to the VM. A type should convey useful information
    >>about objects, and for interfaces without special meaning to the VM, it
    >>is my opinion that at least one method is necessary to make the
    >>information conveyed useful.

    >
    >
    > I'm not clear on the details of Mike's case... but if he's being
    > generally accurate in his description, Mike may have a counter-example
    > to your statement.
    >
    > In his case, Mike is apparently keeping objects in some kind of
    > specialized data structure whose behavior (presumably) only makes sense
    > for objects of that specific type. The type may not have any general
    > new operations to introduce, but in may still imply certain constraints
    > in the way that its objects should be managed. It may even further
    > constrain the implementations of inherited method declarations, such as
    > Object's equals and hashCode. Much like in the Collections API, then,
    > the client code is arranged to know the type when it retrieves the
    > object.
    >
    > Of course, this new data structure type *could* be written with a type
    > of Object, but that would imply that it works properly and makes sense
    > for all Object references... something that may not actually be the
    > case. I would think this is exactly the right use for a type, new
    > operations or not.


    I'm still not entirely clear on the details of Mike's case even after he
    expanded on it, but I am so far not swayed from my position. My
    argument on this point is much the same as on the Serializable point: it
    is incorrect to *do* anything with a reference of a type that has no
    members, other than simply to hold it and pass it around, because you
    must then make some assumption about the object that is not ensured by
    its type. On the other hand, using a tag interface as the type is just
    as bad as using Object: it implies that any object of the tag interface
    type is appropriate for use with the application, which is unlikely to
    be true. (Try passing it a "new YourTagInterface() { void darnMySocks()
    {}}".) Somewhere, some time, some body is going to have to cast that
    reference to make use of the object, and therein is the indicator of a
    problem.

    (Of course, if the tag interface extends Serializable, then you can at
    least expect to be able to serialize instances.... ;-))

    --
    John Bollinger
     
    John C. Bollinger, Dec 3, 2005
    #16
  17. VisionSet

    Chris Smith Guest

    John C. Bollinger <> wrote:
    > I disagree. For a class whose instances are expected to routinely be
    > serialized, declaring method parameters to be Serializable both
    > reinforces the point with the class' users and provides some degree of
    > compile-time checking. It is incorrect to keep references of a
    > non-Serializable type and nevertheless expect the referenced objects to
    > be Serializable, even if you "know" that they really are, just as it is
    > incorrect to keep references of type Collection and yet assume that the
    > referenced objects are Lists.


    Even accepting this idea, you are forced to make a choice eventually
    between several good design ideas. Perhaps it would be good to extend
    Java to allow type (List & Serializable), in the manner of generic type
    bounds... but that feature isn't currently available. I'd certainly far
    rather use List and imply Serializable than use ArrayList just to get
    the Serializable statically declared.

    I just don't see that there's much benefit to half-solving problems of
    verifiability. It's still not verifiable, and that's the end of the
    story.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 3, 2005
    #17
  18. VisionSet

    Chris Smith Guest

    John C. Bollinger <> wrote:
    > I'm still not entirely clear on the details of Mike's case even after he
    > expanded on it, but I am so far not swayed from my position.


    I'm also not swayed, now that I've read Mike's description... but I
    think I'm unswayed in the opposite direction as you (if I understand you
    correctly). In this case, I actually think that Mike should be using
    Object as the type; no interface, no annotation. The reason is that a
    "location" may be of pretty much any type, not just one that was
    designed to work with this data structure. The only requirement is that
    it is later interpretable by the same piece of code that created it.

    I don't share the same hostility you express toward casts. When they
    are checked at runtime as Java's casts are, casting is just a perfectly
    normal way of telling the compiler some additional information about a
    type. It need not be seen as terribly nefarious. In Mike's case as
    described, using an interface type doesn't just mean modifying classes;
    it means potentially creating a new class when InetSocketAddress may be
    perfectly good enough!

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 3, 2005
    #18
  19. Chris Smith wrote:
    > Perhaps it would be good to extend
    > Java to allow type (List & Serializable), in the manner of generic type
    > bounds... but that feature isn't currently available. I'd certainly far
    > rather use List and imply Serializable than use ArrayList just to get
    > the Serializable statically declared.


    Believe it or not, I almost wrote something to that effect myself. I
    would be downright *delighted* to be able to use intersection types in
    declarations.

    --
    John Bollinger
     
    John C. Bollinger, Dec 6, 2005
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    367
  2. Replies:
    0
    Views:
    329
  3. darrel
    Replies:
    1
    Views:
    1,393
    Karl Seguin
    Dec 20, 2005
  4. Replies:
    0
    Views:
    2,786
  5. Replies:
    1
    Views:
    436
Loading...

Share This Page