Coffeehouse Thread

13 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Struggling w/ design pattern

Back to Forum: Coffeehouse
  • User profile image
    Minh

    I think I might be overthinking this... but here goes.

    I have a proxy to a web service that will be doing all of the work, and I want to build an object oriented system on top of that. So, let's say I have an Account object, which contains multiple Bucket objects, and each Bucket object can contain multiple File objecs.

    So, when I do a:

       Account act = new Account(id, password);
       act.Initialize();

       Bucket[] buckets = act.GetBuckets();

       File[] files = buckets[0].GetFiles();

    The Account & Bucket classes must know about the WS proxy, so I will have to pass a reference of the proxy around.

    Or, I can wrap the proxy around a singleton pattern off a static class.

    Another option is to have the Account, Bucket, & File class as data containers only, and have a proxy wrapper class that would do the real work:

       Account act = new Account(id, password);
       S3.Initialize(act);

       Bucket[] buckets = S3.GetBuckets(act);

       File[] files = S3.GetFiles(buckets[0]);

    What do you think? Which is preferrable?

  • User profile image
    Secret​Software

    I don't have enough infomration as to what your proxy will do, but I would go with option 1.

  • User profile image
    Dr Herbie

    Option 1.

    If there's only one proxy then singleton it - doesn't take much code.

    I don't like option 2 -- objects should initialise themselves and not reply of the dev remembering to pass them to a 'manager'.


    Herbie

  • User profile image
    blowdart

    Dr Herbie wrote:
    Option 1.

    If there's only one proxy then singleton it - doesn't take much code.

    I don't like option 2 -- objects should initialise themselves and not reply of the dev remembering to pass them to a 'manager'.



    Whereas I like 2 because objects shouldn't care about where their data comes from, as that introduces tight coupling to their source.

  • User profile image
    Rossj

    Minh wrote:
    
    So, when I do a:

       Account act = new Account(id, password);
       act.Initialize();

       Bucket[] buckets = act.GetBuckets();

       File[] files = buckets[0].GetFiles();

    The Account & Bucket classes must know about the WS proxy, so I will have to pass a reference of the proxy around.


    Hmm. My choice would be a slightly modified option 2, but without the S3 class being passed in the Account, more of a direct wrapper around the Account class.

    Any particular reason why you can't have a class AccountProxy (not the WS proxy) that allows you to call GetBuckets() or GetFiles() (on a bucket) and pass the WS proxy around only within the AccountProxy class and not in end-user code.  The AccountProxy class would obviously contain an instance of Account and know how to pass the WS proxy to the other relevant objects that it contains.

    That way at least the dependency is localised in one location, conforms to nice information hiding practices and keeps the code clean. Yes you are adding another layer of abstraction but in this case I would prefer that than end-user code containing lots of calls to set the relevant WS proxy.

    One last thought - Singletons are evil (unless they are Factory objects)

  • User profile image
    blowdart

    Rossj wrote:
    
    One last thought - Singletons are evil (unless they are Factory objects)


    Are not.

    Consider; right now I'm writing an Information Card security token service, with custom username/password validation. The customers backend exposes a long term token as part of their login procedures, this is then used in subsequent API calls to pull back entity information. So I must use this to get the data I need to populate the response.

    However I can't guarentee that the thread used to perform the authentication is the same thread that handles the processing of the message body, which in turn may not be the same thread that issues the response.

    So I have a singleton tokencache object, which is just a dictionary keyed off the username, and the value being the long term token. Thus I can access this easily cross threads.

  • User profile image
    Dr Herbie

    blowdart wrote:
    
    Dr Herbie wrote:
    Option 1.

    If there's only one proxy then singleton it - doesn't take much code.

    I don't like option 2 -- objects should initialise themselves and not reply of the dev remembering to pass them to a 'manager'.



    Whereas I like 2 because objects shouldn't care about where their data comes from, as that introduces tight coupling to their source.


    Sure, but that should happen inside the object, IMHO, the dev shouldn't have the overhead of setting up.
    I make a distinction here between mechanism and responsibility, the object should be responsible for getting their data, but the mechanism of how this actually happens should be decoupled.
    I don't get to do much architecture/design any more working on mature products Sad

    Herbie

  • User profile image
    Rossj

    blowdart wrote:
    
    Rossj wrote:
    
    One last thought - Singletons are evil (unless they are Factory objects)


    Are not.

    So I have a singleton tokencache object, which is just a dictionary keyed off the username, and the value being the long term token. Thus I can access this easily cross threads.


    Okay, forgot about them, those too.

  • User profile image
    blowdart

    Dr Herbie wrote:
    

    Sure, but that should happen inside the object, IMHO, the dev shouldn't have the overhead of setting up.
    I make a distinction here between mechanism and responsibility, the object should be responsible for getting their data, but the mechanism of how this actually happens should be decoupled.
    I don't get to do much architecture/design any more working on mature products



    Well I view it as an object should be good at what it's principle function is.

    And being loaded or saved generally isn't. That's for something else to do.

  • User profile image
    Dr Herbie

    blowdart wrote:
    
    Dr Herbie wrote:
    

    Sure, but that should happen inside the object, IMHO, the dev shouldn't have the overhead of setting up.
    I make a distinction here between mechanism and responsibility, the object should be responsible for getting their data, but the mechanism of how this actually happens should be decoupled.
    I don't get to do much architecture/design any more working on mature products



    Well I view it as an object should be good at what it's principle function is.

    And being loaded or saved generally isn't. That's for something else to do.


    I'm happy to use loose coupling (through interfaces) to make my classes a little smarter -- I think it's a worthwhile trade off for clearer code further up the stack. My classes simply know the provider interface to use for loading and saving.

    I generally don't feel happy about 'objects' that are purely data containers.  That's not an object, that's a struct (just like a 'stateless' object isn't an object, if a function library) Wink

    Herbie

  • User profile image
    blowdart

    Dr Herbie wrote:
    lly don't feel happy about 'objects' that are purely data containers.  That's not an object, that's a struct (just like a 'stateless' object isn't an object, if a function library)



    Oh now that depends on the methods; if an object can provide any fuctionality beyond set/get then it's an object. And that includes validating accessors.

    Tongue Out

  • User profile image
    Minh

    Thanks for the feedback, guys. I'm as confused as ever.

    But I have decide to take a stab & see how it goes.

    class ProxyMgr
    {
       static ProxyMgr()
       {
          // Let the CLR does the hard work of creating the singleton
          _proxy = new AmazonS3Proxy();
       }

       public void Initialize(Account act)
       {
          // Login, etc...
       }

       public Bucket[] GetBuckets(Account act)
       {
          // Set up security & call parameters based on act
          // ...

          ListAllMyBucketsResult result = _proxy.ListAllMyBuckets( ... );

          return Bucket.Create(result, act); // act is the parent obj reference
       }

       public File[] GetFiles(Account act, Bucket buc)
       {
          // Set up security & call parameters based on act, buc
          // ...

          ListBucketResult result = _proxy.ListBucket( ... );

          return File.Create(result);
       }
    }

    class Account
    {
       public Account(string id, string password)
       {
          // store params
       }

       public void Initialize()
       {
          ProxyMgr.Initialize(this);
       }

       public Bucket[] GetBuckets()
       {
          return ProxyMgr.GetBuckets(this);
       }
    }

    class Bucket
    {
       public static Create(ListAllMyBucketsResult data, Account parent)
       {
          // Convert web service data to native
          // store a ref to the parent account
          //...
       }

       public File[] GetFiles()
       {
          return ProxyMgr.GetFiles(this.Parent, this);
       }
    }

    class File
    {
       public static Create(ListBucketResult data, Bucket parent)
       {
          // Convert web service data to native
          // store a ref to the parent bucket
          // ...
       }
    }

    EDIT:
    Splitting the DAL functions (Create) into various classes bothers me. But I need to enforce read-only for the class data members. And to allow creation of objects & setting their members, I have to move that code into the classes themselves. Too bad C# doesn't have "friends"

    EDIT 2:
    I need read-only objects because multi-threading will be used to keep the UI responsive, and I just don't feel like messing with locking issues. Also, to change the object properties themselves require a long web service call, so I don't want the code to willy-nilly does obj.Name = "something else"

    instead, the object will have a specific method

    obj.Update(p1, p2, p3, ..., pn)

    to mirror the web service

  • User profile image
    lorad

    We had a similar setup the last place I worked. We had the following

    Data access on the server - all methods mapped directly to the WS

    Utility layer that would either create an instance of the WS or of the DLL directly if a switch in the app.config said to go direct. (made it nice to debug a problem or for services)

    Business objects - talked to the Utility classes to fill itself, our business objects had properties for the table (we code gen'ed the basic functionality - members accessors, constructors, child collections etc) and could be filled form datasets, datatables, or datarows. All our data rows where named [TableName].[ColumnName] so all the fill classes could check for columns for any child collections and fill the child collection if the data came back, this was useful for prefetching data that most people wanted all the time.

    All three of those layers where generated code. It did tie our BO to the database layout a little bit, but I have never worked on a project where the BO where entirely different that the data objects, I would be interested to see such a project Smiley

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.