locked
inheritance of services? RRS feed

  • Question

  • hello,
    we are doing a robotics project for our university and just finished up the class diagram for our services. we do have some services that share a lot of code and only have small differences in their implementation, so normally one would create a abstract service with the common shared code and derive the 3 or 4 other services  from it. can you do "normal" inheritance in robotics studio? if so, what would happen to the decorations of the class that is beeing derived, do you have to put them into the child classes again?
    if that doesnt work, can you  create a sort of inheritance by using a generic service, that means put actual code in the generic service, so that you dont have to write (or copy) the code into the child classes?

    thanks in advance
    tom
    Tuesday, November 13, 2007 5:10 PM

Answers

  • Yes, you can use a generic class definition to describe the common behavior (state and operations) between your services. Service Tutorials 8 and 9 show various examples of this as described in [1].If you have a bunch of services that have almost the same behavior then you can abstract the communality out into its own service and have the other services partner with the common service. That allows you to compose with that functionality in a very loosely coupled manner.

     

    Henrik

     

    [1] http://msdn2.microsoft.com/en-us/library/bb648746.aspx

     

    Friday, November 16, 2007 12:36 AM

All replies

  • I have been considering for some time whether or not it was worthwhile to initiate a discussion about architectural issues associated with the current implimentation of Robotics Studio classes, and I am still not sure if getting into a Jihad about "proper" Object Oriented design would be constructive or not at this juncture.  However, you post does touch on what I feel is a troubling issue with how MSRS it is currently implemented.

     

    First of all, I deeply appreciate the skill, effort, and initiative that has gone into Robotics Studio, and do not wish to appear to be ungrateful for this excellent product.  CCR, DSS, and Microsoft Robotics Studio have brought a lot of value and innovation into the field of robotics software. I appreciate how difficult it can be to create something new, and how tough it can be to throw off a lifetime of hard won C++ programming experience and really internalize proper C# programming techniques and Object Oriented design principles.  Also, although I have reflected over some of the code base I do not claim to have any particular insight about some of the deeper issues that may have dictated that the architecture would need to be the way that it is.  In other words, I am willing to be educated about why some of the choices were made the way that they were, and why they had to appear to conform more to (pseudo OO) C++ programming practice than (true OO) C# programming practice.

     

    After all, there may be perfectly legitmate reasons to use Namespaces as if they were Classes, to create classes (for example the Contract class) that contain a single string field rather than make that field a member of the service class, to use a seperate class, rather than a struct, to define the state of the seperate service class defined elsewhere under the same namespace, to create duplicates of all of the "standard" operational classes (Get, Replace, Subscribe, etc., etc.) under each seperate "service class" namespace, rather than use inheritance on a standard Interface class containing appropriate Get, Replace, Subscribe, etc. methods that could simply be overridden if necessary, and so on.  I think that I could rant on for quite a while - but that would not be constructive....

     

    Normally, I would simply write my own classes, organized the way that I like them, and get on with things.  However, in this case it is difficult to know how tightly coupled the infrastructure of MSRS is to the architecture choices represented in the [service]types.cs and [service].cs source files (as found in the Service Tutorials).  I am particularily worried about the "hidden" processing that happens during compilation to create the .proxy.dll and .transform.dll libraries.  How badly would I break that infrastructure by reworking the architecture of the namespace/classes into something more OO? 

    Wednesday, November 14, 2007 6:31 PM
  • Well, I've tried it now and can now report that it does appear that modifying the organization or nesting of classes found in the [service].cs and [service]types.cs code files will break the infrastructure, in that dssProxy.exe will not be able to find the classes that it expects, and will not be able to successfully create the .proxy.dll and .transform.dll files that MSRS needs to run the service successfully.

     

    As a result, it looks like it will be necessary to live - for better or worse - with the organization of classes found in the [service].cs and [service]types.cs files.

     

    This means that services cannot use inheritance in a normal object oriented way, since there is of course no mechanism to inherit from a namespace - the top level "container" for a service in MSRS.  (So you can forget about using polymorphism across related services either, since no services will actually be related to each other in a normal Object Oriented sense...)

     

    Instead, it seems that the best way to create services that duplicate substantial functionality (for example, handling standard operations in a standard way) will be to:

    1. Copy the entire project directory for the "parent" service to a "child" project directory.

    2. Rename the [parentservice]*.* files in the "child" project directory to [childservice]*.*.

    3. Add the child service to the solution using Add Existing Project.

    4. Remove the old files (which will report that they cannot be found) from the project.

    5. Add the renamed files to the project using Add Existing Item.

    6. Replace all [parentservice] instances in the code with [childservice].

     

    The project should now compile, and give you a duplicate of the existing service functionality under the new service name.

     

    Then you can add or change code to modify or extend the functionality of the new service.

     

    I suspect that this is not what you were hoping to hear, but it looks to me like this is just how it is...

    Thursday, November 15, 2007 6:23 PM
  • Yes, you can use a generic class definition to describe the common behavior (state and operations) between your services. Service Tutorials 8 and 9 show various examples of this as described in [1].If you have a bunch of services that have almost the same behavior then you can abstract the communality out into its own service and have the other services partner with the common service. That allows you to compose with that functionality in a very loosely coupled manner.

     

    Henrik

     

    [1] http://msdn2.microsoft.com/en-us/library/bb648746.aspx

     

    Friday, November 16, 2007 12:36 AM
  • A very late kick for this topic, but it is exactly what I'm looking for.

    I want to extend the standard differential drive implementation with a steer operation.
    Now I could just create a new differential drive implementation and copy all the code from the Drive.cs to implement it and adding a steer operation + handler.
    But that's not really neat.

    What I'd like to be able to do is specify a service implementation from which to 'inherit', so that the implementation (the handlers, not just the contract/state) are used from the 'parent service' and the added operations are handled in the 'child service'. It'd also be nice if any of the 'parent handlers' could be overriden.

    Is there any way to accomplish this with DSS?

    I was thinking of inheriting my NewDiffDriveImplementation service from the Drive class. But I have no idea how to implement it like that from here.
    I have feeling that will not work because of the _mainPort / contracts etc.

    Any idea's or suggestions are welcome!


    Kind regards,
    Cageon / Kevin

    • Edited by Cageon Wednesday, March 25, 2009 5:11 PM typo
    Wednesday, March 25, 2009 5:04 PM
  • There is no real concept of "inheritance" in RDS because it uses a REST model that is similar to Web Services.

    You can use a generic contract, and then implement it. However, you cannot add operations to the generic contract. You implicitly override the generic operations because you have to write handlers. Generic contracts are data-only contracts -- there is no code. The confusing part with the Generic Differential Drive is that we actually supply an implementation, that in turn uses the Generic Motor and Generic Encoder contracts. This is used by the Fischer-Technik sample for instance, but most people just skip the motor services and talk directly to the drive from their diff drive service.

    When you implement a generic contract, you can also define a set of "native" operations. However, the native implementation has a different contract identifier. So you can connect to the service using two contract IDs -- generic or "native". In fact, you can connect to both at the same time, but that might be a little confusing because you would have to send generic requests on one port, and native requests on a different port. You might also need to subscribe twice.

    I am not sure if all this will make sense to you, but just understand that RDS does not use an Object Oriented model for services (although all services are based on the DsspServiceBase class).

    Trevor
    Saturday, March 28, 2009 4:06 AM

  • Thanks for the reply and yes it did make sense! Most of it I've already found, I was just having a bit of hope. :)

    >You can use a generic contract, and then implement it.
    > However, you cannot add operations to the generic contract.
    > You implicitly override the generic operations because you have to write handlers.

    That's exactly my point, I'd like to be able to inherit the handlers from the drive service implementation.
    That way another step to another service isn't needed and it's easier to expand existing services or just enhance a single operation for a single service instead of having to implement a complete service.
    But I understand that there are difficulties to get that implemented, but it would've been neat. ;)


    I solved it now by making my service a 'proxy' service for the generic differential drive, by making every handler (for the GDD) call the actuall differential drive service, which my service is consuming.
    Monday, March 30, 2009 9:09 AM
  • I have found some reasonable successes with MRDS and basic OOP and inheritance. Not full service inheritance (main port type of thing) mind you but I have been able to build in a set of generic base classes that provide elements of functionality that are needed across multiple services.

    Specifically, I was able to:

    1)
    Extend the DsspServiceBase class and inside build a bunch of basic functionality methods using C# generics (the saviour of MRDS) to eliminate the seemingly endless cut and paste for standard operations. In this base class I have Subscription methods that take the Notification/Service port, response handlers and behind the scenes build subscription objects that are tied into service teardown to shutodown the subscription.
    Build in basic error handling and a Service handler that is for unsupported requests so everyone responds in a congruent manner.
    Automatic partner dropping at teardown. This is tricky as at present I force myself to do CreateAlways partnerships and override them using the Manifests. I don't know if this is proper but it _seems_ to work.
    A core teardown handler that is designed to be an iterative task and can have subclass operations added.
    This class was designed to encapsulate all the reoccurring code work that I found myself doing in services. If I found myself cut and pasting code, I found a way to make it a generic method and stuffed it into this class. Which wasn't always easy, trust me.

    2)
    Create a few other Extensions of the "ExtendedDsspServiceBase" class that build in specific partnerships. For example, I have an EmergencyStop service that implements a partnership with the EmergencyStop service and related functionality... This pattern has been very useful - making partnerships in base classes. Its allowed me to build up a set of core functionality for a system without needing to constantly add the same partnerships. To get this  to work you need to delcare things protected (rather than private) so that the reflection over the classes can find the partnerships but its a small price to pay for the OOP style. These base classes never implement a service port, only alternate or partnerships. I always reserve the service port for the bottom of the inheritance chain.

    These two patterns have been very useful to me.

    Few things to note. Inheritance of XML style sheets doesn't work and I can't figure it out. - I.e. If I create a base class that implements an alternate contract and I try to incorportate an XML style sheet into its dll using the EmbeddedResourceAttribute it can't find the resource. I have used reflector and the resource is in there but its not being found. Best I can figure it has something to do with the resource being located in a different dll than the inherited service. At present the only way I could solve this is to make a copy of the xslt file in the subclass. I guess I could build in my own resource search but it was a while ago that I looked into it and I don't recall if I tried that approach and it also failed or I just didn't get there yet.

    I have also found it MUCH cleaner and easier to understand if I build up classes that implement multiple contracts by using the Partial class keyword and making a new file for each contract implemented. Naming would extend the base service name... I.e. MyService, MyService.Drive, and MyService.Encoder files would be for the MyService contract, MyService.Drive would implement the Drive contract, and .Encoder the Encoder contract.

    YMMV
    Bryan


    Tuesday, April 7, 2009 12:25 PM