#1
  1. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128

    Poltergeist Anti-Pattern


    I was just browsing around, looking up patterns to see which ones my system qualifies as, when I happened upon the Poltergeist anti-pattern.

    In my homemade CMS software my classes typically have a lone method for performing database lookups. I wanted to limit how many methods actually touch the DB, so that seemed like a good idea.

    But as such, there are a lot of variables you can pass into this method. Pagination, sorting up to the fourth degree, and searching are just a few of the instructions that can be provided to these methods. The query is then dynamically built based on those instructions.

    So rather than have a huge number of optional variables in the function declaration, and rather than have an uncontrolled associative array passed, I opted to create classes tailored to each of these methods.

    There are a couple methods within these request classes to set a few things in bulk, but fundamentally these classes just serve to pass data into another class.

    But I guess that's a bad thing?
    I thought I was doing good by facilitating the request data in a uniform, contractual structure...

    Thoughts?
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Location
    Burb of Detroit, Michigan
    Posts
    89
    Rep Power
    77
    Well, doing a Google search I came across Wikipedia and this is one little snippet - "An anti-pattern (or antipattern) is a pattern used in social or business operations or software engineering that may be commonly used but is ineffective and/or counterproductive in practice." Kind of answers it in one sentence. I find using MVC structure, which technically isn't a design pattern the best I can come up with, pulling the data from the database only when needed.
  4. #3
  5. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128
    Originally Posted by Strider64
    Well, doing a Google search I came across Wikipedia and this is one little snippet - "An anti-pattern (or antipattern) is a pattern used in social or business operations or software engineering that may be commonly used but is ineffective and/or counterproductive in practice." Kind of answers it in one sentence. I find using MVC structure, which technically isn't a design pattern the best I can come up with, pulling the data from the database only when needed.
    That's what I read that lead me to asking here. I'm not sure what would be considered a more "effective" and/or "productive" practice. I'd think it would be the natural evolution of method parameters if you have a lot of them, don't care about order, and want to be able to bulk-set them.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    The anti-pattern here is OOP, actually. Your not simulating anything, nor do you have interface objects with longevity -- there is no need for objects. The habit of using them* has made the demigod pattern (the diminutive version of a God object) seem like a good idea, but what your mind is probably intuitively searching for is an input-output mapping -- which is by definition a function. Websites driven by a database are nearly always best modelled this way, but Java-as-a-first-language has accidentally infected several tribes with complicated OOP habits that seem hard to shake.

    [*"object" here being defined as a struct that subordinates functions as methods -- there are actually a lot of meanings for "object" that seem mostly forgotten today outside of Python runtime hacking, older C and Fortran coders and the Lisp community.]

    This will probably signify the beginning of a flame war, but I am sincerely not trolling here.
  8. #5
  9. Sarcky
    Devshed Supreme Being (6500+ posts)

    Join Date
    Oct 2006
    Location
    Pennsylvania, USA
    Posts
    10,908
    Rep Power
    6351
    Many people use [static] objects as a logical grouping for their functions, similar to how perl libraries or namespaces work. Now that PHP HAS namespaces, it may be better to drop the class structure entirely and namespace these functions as helpers or whatever.

    Using a class for this isn't necessarily wrong, it's just unnecessary with better options available.
    HEY! YOU! Read the New User Guide and Forum Rules

    "They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -Benjamin Franklin

    "The greatest tragedy of this changing society is that people who never knew what it was like before will simply assume that this is the way things are supposed to be." -2600 Magazine, Fall 2002

    Think we're being rude? Maybe you asked a bad question or you're a Help Vampire. Trying to argue intelligently? Please read this.
  10. #6
  11. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128
    Originally Posted by zxq9
    The anti-pattern here is OOP, actually. Your not simulating anything, nor do you have interface objects with longevity -- there is no need for objects. The habit of using them* has made the demigod pattern (the diminutive version of a God object) seem like a good idea, but what your mind is probably intuitively searching for is an input-output mapping -- which is by definition a function. Websites driven by a database are nearly always best modelled this way, but Java-as-a-first-language has accidentally infected several tribes with complicated OOP habits that seem hard to shake.
    Hmm. Well, I'd be lying if I said I'm sure I understood that. It's true that the specific method I'm passing this "request object" to is static and it doesn't need to be in a class.

    That said...

    Originally Posted by ManiacDan
    Many people use [static] objects as a logical grouping for their functions, similar to how perl libraries or namespaces work. Now that PHP HAS namespaces, it may be better to drop the class structure entirely and namespace these functions as helpers or whatever.
    I personally find static methods preferable to simple namespaced functions. In my case I already have non-static classes that contain the usual get/set/etc. methods for a given subject matter (User, Group, etc.) so it makes sense to put related static methods in those same classes for consistency and clarity.

    But even if I didn't have those or had static objects just housing related functions, well... I really don't like the way namespaces look in code.

    I'd rather have:
    PHP Code:
    Class::doSomething(); 
    than:
    PHP Code:
    \Class\doSomething(); 
    (yeah, I know you could "use \Class;" but then the function call lacks all context and is even harder to understand)

    I'd also find static classes preferable if you're also using normal classes, since then you have a consistent grouping concept.

    But I digress...

    Back to the original question, which is applicable whether you're passing it into an object method, a static method, or a standalone function: is there something inherently bad about sending variables in via a method-less object?

    I'm guessing not, based on the direction the conversation took.

    In fact, I remember when I first got in the habit of doing this for complex function calls: SoapServer. PHP itself will pass the request structure into handling functions as a methodless object. Similarly, json_decode creates a methodless object by default.

    I know PHP doesn't always do things "right", but if some of its own functionality is going the route of this "antipattern", well... I feel validated.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    Originally Posted by dmittner
    Back to the original question, which is applicable whether you're passing it into an object method, a static method, or a standalone function: is there something inherently bad about sending variables in via a method-less object?
    The only problem is perhaps that you haven't defined a limit to what functionality your "touch the db method" and hence class model can provide, and so you wound up with arbitrarily long argument lists that worried you (if I'm understanding the situation).

    If you were able to plot exactly what functionality is to be provided and then write your library/class models of functions/methods that provide each piece, and then a way to compose them... then you wouldn't be in uncertain territory.

    If its queries that you are trying to wrap up in a uniform way, then relational algebra could be a simple, finite, rather small set of functionality you could implement without getting all crazy. Chasing SQL can drive you nuts, as its neither relational algebra nor relational calculus -- its just something weird which sports both redundancy and gaps in functionality. I'm not sure how much support PHP has for composition, but even if its very little, this is where class models could provide a solution (messy, but definitely workable).
    I remember when I first got in the habit of doing this for complex function calls: SoapServer. PHP itself will pass the request structure into handling functions as a methodless object. Similarly, json_decode creates a methodless object by default.

    I know PHP doesn't always do things "right", but if some of its own functionality is going the route of this "antipattern", well... I feel validated.
    Its a quirk of PHP that it lacks data structures. It is easier to use methodless classes as a substitute (since "classes" are really just C structs with subordinate functions anyway) -- so that's what you are seeing. In, say, Python you would see a dictionary or list of dictionaries passed -- in PHP you will see a classless method or array pointing to a set of classless methods instead.

    As for the context of the call... of course either the environment, the arguments, or the sub-structure of the arguments has to contain enough information to make the call useful, and sometimes this gets really complex when you're doing things like building queries.

    The complexity of a query wrapper is of two types: the number of permissible query forms, and the number of elements you've inserted into the structure. Relational algebra limits the first type of complexity to a ternary tree at worst, and that's easy to deal with no matter how many elements might exist in that structure. So even though you might pass around a rather large structure (which in this case would probably be a methodless class) its always a structure of the same form, so its not so scary.

    As a side note I've been working on a new data langauge in a fork of Postgres that uses SP-expressions to represent queries. Most query wrappers are an attempt to do something similar (simplify the semantics of queries). In my case the goal is to render a query tree to pass directly to the executor within the db, but your goal is to render SQL that can be passed to a db instead (which will then be reduced back to a query tree and...). The query sub-language (link) might give you some idea how few bases you need to cover to write a fairly complete query wrapper.
  14. #8
  15. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128
    Originally Posted by zxq9
    The only problem is perhaps that you haven't defined a limit to what functionality your "touch the db method" and hence class model can provide, and so you wound up with arbitrarily long argument lists that worried you (if I'm understanding the situation).
    After a fashion. More so, I approached it with the attitude that I don't know every way a user of the method might want data. So rather than try to predict every use case, I designed a request model that maximizes flexibility.

    So my little "poltergeist objects" have common offerings:
    • Field name abstraction: a user sees variable names that differ from the database column names
    • Scaled results: a user can decide exactly what variables they want looked up and returned
    • Simple search: populate a "search" field and it translates automatically into a LIKE check against defined fields
    • Complex search: populate this with an "AdvancedSearch" object and you can define more complex comparison conditions, with unlimited nesting.
    • Sorting up to the fourth degree
    • Start/Limit (duh)
    • A boolean dictates if you return full results, or just a result count


    Then in the method some common logic declares what fields are relevant, their types (for validation), and runs 3-4 functions to build the different parts of the query dynamically.

    I'd be the first to admit that it's not perfect under the hood, but it definitely works. And my little anti-pattern object can translate directly to a WSDL complex type, allowing me to handle a SOAP endpoint with very little in the middle.

    The complexity of a query wrapper is of two types: the number of permissible query forms, and the number of elements you've inserted into the structure. Relational algebra limits the first type of complexity to a ternary tree at worst, and that's easy to deal with no matter how many elements might exist in that structure. So even though you might pass around a rather large structure (which in this case would probably be a methodless class) its always a structure of the same form, so its not so scary.
    Exactly. To fresh eyes it might be a bit daunting, but every one of my active record classes follow the same structure, so there's consistency.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    Originally Posted by dmittner
    So my little "poltergeist objects" have common offerings:
    ...

    To fresh eyes it might be a bit daunting, but every one of my active record classes follow the same structure, so there's consistency.
    It sounds like you've gotten to the point that you can explain the way it works without using too many "kinda does"es or "should do"s. So set your limits, document the API (at least to the point you won't screw yourself when the idea fairy visits a year from now) and then you've created a handler with a discrete API, not engaged in poltergeisting IMO.

    Later on when you decide to redesign things and notice yourself adding lots of possible arguments, just remember these epigrams:

    (Quoting Alan Perlis' "Epigrams in Programming"):
    5. If a program manipulates a large amount of data, it does so in a small number of ways.
    9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
    11. If you have a procedure with ten parameters, you probably missed some.

    Reflecting on those (and a few others) haved saved me from myself on numerous occasions.
    Last edited by zxq9; July 3rd, 2013 at 10:19 AM.
  18. #10
  19. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128
    Originally Posted by zxq9
    It sounds like you've gotten to the point that you can explain the way it works without using too many "kinda does"es or "should do"s. So set your limits, document the API (at least to the point you won't screw yourself when the idea fairy visits a year from now) and then you've created a handler with a discrete API, not engaged in poltergeisting IMO.
    Yep, I'm planning a big documentation phase soon, to make up for some laziness when crunching big chunks of code. That's how I found this anti-pattern; going through trying to identify which patterns my system qualifies as. A bit backwards to figure out the pattern after-the-fact, but meh...

    (Quoting Alan Perlis' "Epigrams in Programming"):
    5. If a program manipulates a large amount of data, it does so in a small number of ways.
    9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
    11. If you have a procedure with ten parameters, you probably missed some.
    Haha, I like #11. I might have to pick that book up.
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    Originally Posted by dmittner
    A bit backwards to figure out the pattern after-the-fact, but meh...
    Absolutely not backwards. This is just part of learning how to design things. There isn't a school, book or internship in the world that can teach you everything and trying is futile. You'll only ever really learn whatever you decide to teach yourself, and this is exactly what you're doing -- which is cool. Revel in your revelations!
    I might have to pick that book up.
    You're in luck. Its not a book, its an ancient snippet from an ACM SIGPLAN notice Alan Perlis wrote in 1982 -- which subsequently became a frequent repost on usenet. Here's a link to one of many copies floating around the net (I think this link to Yale won't die soon):

    Maybe its only famous nowdays in unix hacker circles or something... seems a lot of the Old Lore has never been encountered by much of the web community, actually. Probably explains a lot of the ugly backhacks that occur in web dev.
  22. #12
  23. No Profile Picture
    Dazed&Confused
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2002
    Location
    Tempe, AZ
    Posts
    506
    Rep Power
    128
    Originally Posted by zxq9
    Absolutely not backwards. This is just part of learning how to design things. There isn't a school, book or internship in the world that can teach you everything and trying is futile. You'll only ever really learn whatever you decide to teach yourself, and this is exactly what you're doing -- which is cool. Revel in your revelations!
    Yeah, I'm definitely a learn-by-doing kind of guy. It's just disappointing to go through all the design patterns now and come to the conclusion that it's "kind of like that pattern", "sort of that one", "a hybrid of those two...", etc. Just makes for a lot of fine print in the documentation.

    However, it is funny to find that I've naturally evolved to some of the same practices seen in Zend and other frameworks. Some. Not all. Those things are still way too bloated for my liking.

IMN logo majestic logo threadwatch logo seochat tools logo