Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Falling for the same trap – since 1942

by Aristotle (Chancellor)
on Jul 13, 2003 at 21:16 UTC ( [id://273828]=perlmeditation: print w/replies, xml ) Need Help??

I found this tiny article a few days ago: Session Object considered Harmful

When I read the conclusion, it immediately reminded me of the assertion about the common Perl object orientation pattern (using an anonymous hash to store instance data) that Abigail strived to correct by inside out objects.

Which reminds me I have seen this antipattern elsewhere: Singletons are likely to lead to the same problem.

I’m talking about global variables – a master shape shifter concept that seems to crop up in every paradigm sooner or later, and is seldomly easy to identify for what it is at first glance – even when in retrospect, it is perfectly obvious.

The lesson I’m taking home from seeing the same concept identified so many times in so many different shapes is to constantly be on the lookout for it. It is everywhere.

(Obviously, session objects are still useful. So are singletons. So can hash based Perl objects be. Since obviously, so can globals be. But you have to be very careful and discriminating when employing them; it is easy to get them wrong.)

Update: fixed some really braindead grammar screw ups.

Makeshifts last the longest.

  • Comment on Falling for the same trap – since 1942

Replies are listed 'Best First'.
Re: Falling for the same trap - since 1942
by dws (Chancellor) on Jul 14, 2003 at 05:06 UTC
    Warning: Java ahead, but the message applies more broadly than that.

    Understanding the article may require a bit more context than was given. The author is talking about Session objects within a Java application server (e.g., Tomcat, Weblogic, JBoss, etc.) Such a session is a funny beast. The application has to explicity ask for one during the processing of a request (which would typically be an HTTP request). This results in the generation of a session key, and the creation of a object (the "session" object) that corresponds to that key in which information that applies to that session can be stashed. The key is communicated back to the client by either session cookie or by URL rewriting (the key gets tacked onto URLs), and is presented to the server on subsequent requests. If an application stuffs stuff into the session object, that information will persist across requests.

    There are two bit problems with using a session object:

    1. Sessions expire. Either by timeout or by application server restart. If you hang state off of a session object, you can lose that state. This is usually very bad.
    2. Unless you're careful with bookkeeping, a state object can accumulate a lot of cruft. This can act like a memory leak, at least as long as the session persists. It can also be a data consistency issue, if you're caching stuff in the session without checking cache consistency.

    In Java app server land, the standard advice is to avoid using the session for anything other than a cache, and to pass a cache key in via session cookie or URL/form parameter. This allows the application to validate the cache, and to rebuild the cache if the session has timed out, or if the server has been restarted while the browser user wandered away for coffee. This advice isn't Java-specific. In any system that keeps sessions that can be timed-out, it's unsafe to do anything other than use the session object as a cache.

      I think the main problem the author wants to point out is another (and if it's not, it should be ;-). Say you have a dynamic page search.cgi (or search.jsp, search.asp, search.shtml, whatever) which allows logged-in users to look for books in an online book-store. When you pass it parameter author=asimov it looks for all available books by Asimov, and since there are more than 10, it stores all of them in an array in the session object. It outputs a html page with the first 10 results and a link to search.cgi?start=11. By clicking on the link, the page retrieves the array of Asimov's books from the session object and builds a page with the next 10 results. All's well.

      Now, imagine you are browsing the bookstore site looking for books by Asimov and by Lem. You log-in, then middle-click and open another tab to perform a parallel search. After selecting Asimov in a page, you look for Lem in the second one. Asimov's result array is substituted by Lem's books. When you go back to the page with Asimov's books and follow the link "next results", you are quite surprised to find out that Solaris is on the page.

      A possible way out of this problem is to assign each query a progressive number within the session and pass it along with parameter start. So, from Asimov's page you go to search.cgi?query=1&start=11 and from Lem's page to search.cgi?query=2&start=11. This requires a bit more work and housekeeping, but can deal with non-linear interaction quite well

      Cheers

      Antonio

      The stupider the astronaut, the easier it is to win the trip to Vega - A. Tucket

      Well, since the guy who wrote that is in my Perlmongers group and I got the link from following a discussion on our mailing list, I feel qualified to say he is talking about any dynamic web programming. And though irrelevant to the point at hand, at least his current job is a Perl based ecommerce site. At any rate, his point is that the session object represents a global namespace. And we know what happens when you try to stuff the variables for every scope of your program into a single namespace.

      It's as simple as that.

      Actually, if you browse the directory above that article, you'll find a number of other short articles on web programming that I found quite insightful, esp in how he questions and rejects a few other common practices in this subject area as well.

      Makeshifts last the longest.

        Well, since the guy who wrote that is in my Perlmongers group and I got the link from following a discussion on our mailing list, I feel qualified to say he is talking about any dynamic web programming.

        I went back and read the rest of the stuff on his site, and you're right. He's either talking about Perl without saying so, or is talking in general. The funny thing is that the page you cited could have come right out of a J2EE discussion forum.

        I disagree though, that the underlying issue is that using a session object equates to using global state, unless there's some peculiarity with the one he's using. Generally, session objects are kept in a hash keyed by session id, and themselves hold hashes (or the equivalent) for stuffing in session-specific data. Adding data to one session doesn't ipso facto make it available to others. The problem, or one of them, is that session object can become a dumping ground for cruft that isn't garbage collected until the session expires. One can look at that as clogging up the session's namespace, I suppose.

        Could you expand on that because I'm just not buying it. To me, session objects are great and I'm happy to use them, but it's important to remember that a session object, like any object, should be limited in scope to what's it's trying to conceptually represent.

        For example, it seems reasonable that the object would have the expiration time (tracked in the database and not the cookie) and a user object for representing the user for whom the session is being maintained (again, the key to that would be in the database). Anything else would be superfluous. Thus, it seems to me that the complaints about session objects are actually about using poorly designed objects. Is there something I am missing?

        Cheers,
        Ovid

        Looking for work. Here's my resume. Will work for food (plus salary).
        New address of my CGI Course.

Re: Falling for the same trap - since 1942
by hsmyers (Canon) on Jul 14, 2003 at 02:44 UTC
    I'm glad to see the remark in italic Obviously, session objects... since the poor thing is merely the messenger, not the message so to speak. The real villain here has been around a good deal longer than since 1942. After all Ada Augusta, Lord Byron's daughter allowed for the possibility of bad coding very nearly a century earlier (well perhaps not directly, but to her the whole point of the Analytical Engine was to avoid the error-prone nature of calculations done by hand)! And that is the thing to obsess about, not it's many symptoms. Not to say that you should ignore them---as any diagnostician will tell you symptoms are damn handy but if they are all you fix then you never really speak to the cause of the disease now do you!

    --hsm

    "Never try to teach a pig to sing...it wastes your time and it annoys the pig."
Re: Falling for the same trap - since 1942
by bobn (Chaplain) on Jul 14, 2003 at 13:13 UTC

    The advice at the end of the quoted article sounds similar to merlyn's advice for use of cookies:

    • Use the cookie to index into db table to get a userid (allowing 1 userid to be remembered for multiple browsers)
    • Then use the userid to index into one or more other tables for state.
    --Bob Niederman, http://bob-n.com
Re: Falling for the same trap - since 1942
by Anonymous Monk on Jul 13, 2003 at 22:25 UTC
    Rumour has it that there will be a module on CPAN soon that handle the problem described in Session Object considered Harmful and some related issues in a clean structured way.
Re: Falling for the same trap - since 1942
by Jenda (Abbot) on Jul 14, 2003 at 17:33 UTC

    Sessions variables are global so they should be used only for global stuff :-)

    We have two faces to a system, one stores only the the user id and settings in Session, the other (actually the newer&external, go figure) stores all kind of stuff there. The result ... if the session times out (or we restart the server while you are making your coffee) and you are using the internal interface all you have to do is to log back in and you may continue where you left off without any data loss whatsoever. In the other you are fscked up. You've lost your data, we have no idea what were you doing, go and do it again! Sweet.

    Jenda
    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
       -- Rick Osborne

    P.S.: The "author" of that second face even stores a list of IDs in several variables names "Sites(1)", "Sites(2)", ... but I know where does he live ...

    Edit by castaway: Closed small tag in signature

Re: Falling for the same trap - since 1942
by dragonchild (Archbishop) on Jul 14, 2003 at 17:14 UTC
    This is why Antipatterns are so useful. I would say they're more useful than patterns. Everyone knows when they do something right. Figuring out when what you're doing "right" is actually wrong is much harder. (Of course, having the managerial will to fix it is nigh-unto-impossible, but we can still dream ...)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Falling for the same trap - since 1942
by sauoq (Abbot) on Jul 15, 2003 at 01:16 UTC
    When I read the conclusion, it immediately reminded of the assertion about the common Perl object orientation pattern (using an anonymous hash to store instance data) that Abigail strived to correct by inside out objects.

    I think the problem Abigail addresses with Inside Out Objects is, although similar, a very different issue. Inside out objects solve the problem of classes vying for slots to put their instance data in and do it in such a way that retrieving instance data is still efficient (e.g. rather than multiple hash lookups) and strict checking becomes useful again. Your acquaintance's article looks like it is just a short note on one strategy for namespace partitioning within a Session object.

    I've looked at some of the other articles on his site. In many cases, he seems to find profundity in a little semantic slight-of-hand... For instance, his assertion that there are no web objects and http requests should be thought of as functions. Well, I think that depends on the web application... Oh! But he goes on to suggest developers should think in terms of "request handlers" rather than "web applications." Ok... whatever. Sometimes you have to group together a few hundred request handlers and call them an application. It's mighty convenient when they act on the same data and even share code.

    In other cases, his statements seem to be more academic than experienced. Like when he says, "GET requests should not have side effects while POSTs may." Well, yes and no. That's really a convention and it is often not followed. It makes sense in the context of getting the most out of caching... You've got to keep in mind though that almost every hit counter in the history of the web breaks this guideline.

    I don't know what to say about his POST requests must always result in redirects idea...

    Or his Put all interactive content into images with headers for immediate expiration idea...

    I couldn't help but notice that he rolled his own templating system. Have you reviewed the code? (And you've accused me of writing in a C-ish style! ;-)

    I don't doubt that this guy is bright and has some good ideas about programming in general and writing web applications specifically but I don't find a lot to be impressed by on that site. Frankly, when someone writes a "Thingamajiggie Considered Harmful" paper, I expect it to have some real meat. This one didn't.

    -sauoq
    "My two cents aren't worth a dime.";
    
      I think the problem Abigail addresses with Inside Out Objects is, although similar, a very different issue.
      There are several issues they address. I'm specifically talking about just one of them.
      That's really a convention and it is often not followed.
      What he's saying is that it should be followed if you want to make your life easier.
      I don't know what to say about his POST requests must always result in redirects idea...

      Well, keeping in mind that it is assumed that your GETs never change server state, then it makes a lot of sense considering the problem he is trying to address.

      Yes, I saw that he rolled his own templating system. I was irked as well. I didn't review the code, no.

      Note that if you think I "accused" you of writing C-ish Perl, then at the same time I "accused" myself of writing LISP-ish Perl. I was simply commenting on our preferences.

      Makeshifts last the longest.

        What he's saying is that it should be followed if you want to make your life easier.

        Do you (or does he) care to elaborate? I think it depends on requirements. It is a convention, and so it often is followed. OTOH, it's just a convention, and it often is not followed. I think the current state of affairs has come about by real world pressures. Without explanation, I think the gentleman is, at best, oversimplifying.

        Well, keeping in mind that it is assumed that your GETs never change server state, then it makes a lot of sense considering the problem he is trying to address.

        I must be missing something. What's the problem he is trying to solve with redirects?

        Note that if you think I "accused" you of writing C-ish Perl, then at the same time I "accused" myself of writing LISP-ish Perl.

        Oh, I know. And I did take it a bit personally, I guess. Really, that's because of the associations to both C and LISP that I have in my own mind. Things like... LISP: pure, clean, fun. C: applied, messy, work. It's also ingrained into me that "writing C in Perl" is something to be avoided. I do know that your comment wasn't pejorative, though. ;-)

        -sauoq
        "My two cents aren't worth a dime.";
        

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://273828]
Approved by sauoq
Front-paged by allolex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (9)
As of 2024-04-23 07:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found