Link to home
Start Free TrialLog in
Avatar of sapbucket
sapbucket

asked on

using tie in a untested design pattern

problem: Need to have two way communication between a Perl application and a VB .NET application using a relational database as an intermediary.

|PERL|<--->|MySQL|<--->|VB .NET|

solution: From the PERL application, use tie::dbi to connect hash objects to tables in a database. From the VB .NET side, use the .NET framework to connect to tables (managed by the PERL application) to the VB .NET application content (ie relate a label caption on a form to a table element, etc.). The PERL application will READ_ONLY state information (such as button clicks) from tables generated by the VB .NET application. So Perl will act as the event handler in terms of the business logic and content.

Conceptually:

  |PERL|--->|MySQL_content|--->|VB.NET|
  and
  |PERL|<---|MySQL_event_state|<---|VB.NET|



Why?

0.   I am using a 3-tier model.
1.   I have a bunch of business logic written in PERL (middle tier, tier2).
2.   VB .NET is to be used as the GUI and event generator (presentation tier, tier1).
3.   I am using SQL Server and relational database (data tier, tier3).


So, what I would like from the experts here is any advice they have about this design pattern. Do the elements of the solution, and their relationships make "sense"? What are the flaws in this pattern? Is it worthwhile for me to pursue this solution?

You see, if it is not, then I cannot use PERL. I have to port all of the business logic from Perl to some .NET language (probably VB .NET).

I'm addicted to PERL, but have professional requirements with .NET. I'd like to marry the two using this design pattern. Any comments on this would be appreciated.

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of jmcg
jmcg
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of sapbucket
sapbucket

ASKER

You bring up good points, I want to address them one at a time:

1. long-range maintenance - I will be the only one working on it. It is a temporary solution to a long-term problem.

2. Event Chain Timeliness - Yes, I am worried about this! I would estimate that there will be upto 200 dB calls a second, and each call will pass no more than 2kB of information, with a average pass of 200 bytes. This goes for both my PERL application and my .NET application (so up to 400 db calls a second). I'm not sure how "chatty" that is in the relative scheme of things. The .NET application is connected by a ethernet network (100 Mbps) with only a single router between it and the server. The PERL application resides on the server, along with the dB, whereas the .NET application is on a Tablet PC running 1.2 MHZ with XP Pro.

While there is only one instance of the .NET application, and only one instance of the PERL application, there may be many users logged into the dB via a .ASP client/server model that dishes up a simple web page. Many users is 5-30 users at a time, max 35 users, min 0 users.

3. Event Flow - Lets see. Yes, the bottleneck situation could be there. I'll break it down into a event cycle:

1. Start Tablet PC, start windows forms application (.NET).
2. Server with PERL application always running and waiting.
3. button_click_event occurs on Tablet PC.
4. event_state is sent and updated in the SQL dB event_states table.
5. PERL application "listens" for changes in event_states table, since we have a button_click_event, the listener calls the appropriate handler.
6. The handler performs some business logic. This may require more dB calls to gather information from content_tables (still within the 2kb limit per pass).
7. The business logic turns up a answer, and stores it in content_tables. It then updates the event_states table.
8. In the meantime, the .NET application is waiting for the update in the event_states table. When it is received, the .NET application may need to fetch content from content_tables and update form fields.
9. .NET application waits for another button_click_event and we repeat the process starting at 3.

So it would be nice if it was an asynchronous model, but it isn't. The PERL business logic has a big say in what the next_state is, so the .NET application has to sit around and wait for a reply.


============


4. Religious and Idealist Programmers (RIPoff) - yah, that goes without saying :) WO IS HE that shalt call their language "object orientated" when it is really "object-like orientated". Computer languages are organic, just like human languages. They change over time. Sometimes I put my foot down and say "damn it, this is what this going to mean!" So for design patterns, I define them as a reusable solution to a clearly repeated problem. In my case, I always need a nice GUI for my Perl applications, and since I can't stand TK programming, I have been left adrift to find my design pattern. I hope to derive it in the next week or two :)

Not to say that the design pattern stuff isn't moving into cool territories. They are perhaps more academic at some point than practical. I stress the practical side of design patterns, but look forward to the results of the academic patterns that are to developed in the future.

Please keep the comments coming :)
Good, I can see you've thought about this quite a bit.

Since I haven't thought about it as much, all I can say at this point is that it looks like it _could_ work. That 200 calls per second to the database strikes me as a lot, but I haven't done performance analysis with well-tuned modern hardware -- I know what it would have taken to get that a few years ago and I can easily imagine that it's achievable today with just about any system worthy of being called a server.
I'm going to go ahead and try it. I am going to post my progress here, and if you have any useful comments I would greatly appreciate them. That goes for you too ozo :)

I purchased "Perl Database Programming" by Brent Michalski and have been enjoying reading it from cover to cover. Using it as a guide it was easy for me to setup tied hashes and DBI to to access my database.

I haven't yet begun to interface on the VB .NET side of things.

Do you have any suggestions for profiling database transactions? It would be useful to have a module that monitors the timing of different dB calls.
In my experience, the database side provides tools that can be used to monitor performance of various transactions. But I was using Oracle, so that may not have been representative.
I am using MySQL - and I am a total newbie. I'm not sure what support tools come with it, but I will take your suggestion and start digging around :)

I was hoping for a PERL solution though.
Kandura might know of something. I'm a lightweight with respect to databases.
Stylistically it may be better to avoid using tied variables all together. They are difficult to explain to other programmers too. I can definitely see specific reasons for using tie, but not as a tool to provide "orthogonal persistence."

I've been reading more books. Sririam has a good one called Advanced Perl Programming; chapter 11 is called "implementing object persistence." In it, Sririam points out that:

"One important stricture that we easily forget is that an object is not just data. The 3 serialization modules we saw in the last chapter  - FreezeThaw, Data::Dumper, and Storable - all make this assumption. They look past an object reference at the underlying structure and serialize whatever is reachable from there. This assumes that all instance specific data is reachable from the the reference: a false assumption. For example, an object reference of type ObjectTemplate is merely a reference to a scalar. By studying that reference, you have no idea of the objects attributes." -p.173.

When I read this it makes me want to ask if there are any new modules (Sririam's book is copyright 1997) that can perform better than the 3 above. Or are the three above still widely used and nothing new has developed?

How do we store an object that has other objects inside of it? The only things that shows up is the object reference - nothing shows up for the attributes. What are different Perl solutions to get around this problem? How can I rebuild an object if its constituent parts are not rebuilt as well?

I don't know about Freeze/Thaw, but I'm reasonably certain that Data::Dumper and Storable are in common use. Data::Dumper will handle objects-within-objects to a certain extent -- at least I think that's what I've seen when I used it for debugging some LWP stuff not too long ago.

Data::Dumper allows you quite a bit of flexibility in how to serialize data structures but the limitations pointed out apply to any generic method for dumping objects. If there's contextual information about objects not contained or represented in the object, then it's not going to be included. These are the same limitations that apply to generic methods for copying a complicated object.

What this means in practice is that you a) don't expect to acheive persistent storage of arbitrary objects, b) design your objects so that everything you need is properly dumped by a generic method, and c) add helper methods to serialize and reconstitute data structures with special needs not met by, say, Data::Dumper.
Oh, about using ties: they do suffer from some difficulties when dealing with complicated objects. Last time I looked, you run into trouble if your tied object contained references to tied objects of a different type. Explaining the limitations to programmers who expect to be able to build arbitrary data structures using ties can by hard (I certainly would have to do a lot of research and experimentation to even begin the task). The basic idea of a tie, however, ought to be relatively easy to get across to someone who's a sufficiently experienced programmer to have dealt with operator overloading or introspection.
"How do we store an object that has other objects inside of it? The only things that shows up is the object reference - nothing shows up for the attributes. What are different Perl solutions to get around this problem? How can I rebuild an object if its constituent parts are not rebuilt as well?"

Is still an issue I am trying to resolve. Complex Object Persitence (COP) is what I am calling it. It is simple to maintain orthogonal persitence in a purely scalar context, however, when we start getting into more complex scenarios the "book" solutions do not work for me (I need more books maybe).

My problem may stem from me having a fundamental misunderstanding of OOP. For instance, I invariably think of things in a "USESA" context instead of a "ISA" context. For example, I do not understand the following scenario:

(objects are in CAPS)

CLASSROOM @ISA(CHALKBOARD DESK CHAIR)

conceptually, the classroom is a collection of chalkboards, desks, chairs. I would have no problem understanding this if there was only a single chalkboard, a single desk, and a single chair. But what if we want to do something like this:

CLASSROOM->clean_chalkboard();

if there were only a single chalkboard, I know which one has been cleaned. But what if there are multiple chalkboards? Did all of them get cleaned?

Thus, I invariable think of things in a "USESA" context because, from my point of view, the classroom *is not* a collection of objects, but in reality, USES a collection of objects.

Let me solidify this concept with a real example:

# package BJGame;
# So the following is a blackjack game object. It has players, rules, and a dealer, among other things.
# The thing to notice is the new objects that are instantiated in the constructor. This defines
# a "USESA" relationship.
# How would I implement persitence on such an object?
sub new {
      my $type = shift;
      my $class = ref ($type) || $type;
      
      my $bjRules = new BJHouseRules();
      $bjRules->default();
      my $dealer = new BJDealer(); # so all routines in BJDealer need to shift in the rules instead of accessing from $self
      my $legal = new BJLegality(); # so all routines in BJLegality need to shift in the rules instead of accessing from $self
      my @players =();

      my $self = {players => \@players,
                        current_player => 0,
                        upcard => undef,
                        option_list => undef, # used by UI_
                        current_cards => undef, # used by UI_
                        deck => undef,
                        rules => $bjRules,
                        dealer => $dealer,
                        legal => $legal,
                        shoe => 0,
                        enable => 0 # if 1, use shoe, if 0, use deck
                     };
      
      bless($self,$class);
      return $self;
}


I have more to say, but I better stop here and get some feedback...



Any suggestions?

Object-oriented design is a subject I have no qualifications to speak on. About all I can say in response to your post is that your class hierarchy has to be constructed with an eye to how it will be used as well as to any real-world relationships it is meant to model.

The ISA relationship describes inheritance, usually from a more general class to a more specific class. The composite objects you propose creating for CLASSROOM or BJgame serve as containers to organize one or multiple instances of a variety of different objects. If those subsidiary objects are of different types, you may have a few methods that can be simply and automatically distributed across all of the constituents when applied to the composite. More commonly, a method meant to be applied to one of the constituent types will not be applied to the composite -- you'll need to disambiguate somehow which constituent object the method should be applied to.

shoot i just lost my post.

anyway, I summarized my results. I'll repost when I am less annoyed with myself ;)