SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 31
  1. #1
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    J’Accuse: InterceptingFilter

    A description of InterceptingFilter might go something like this:

    The InterceptingFilter pattern is used to wrap an application core with various pre and post processing tasks eg authentication, validation, logging, user input filters or output compression. Filters are loosely coupled allowing individual items to be added and removed at will. Filters don’t interact directly with the application core.

    InterceptingFilter provides a central location for common tasks. Configuration files may be used to load different filter chains for different requests.

    Different sets of filters might allow the same core to be re-used in a different context (perhaps this applies more to languages other than php?).


    Intuitively, you might think of a filter as something which silently processes a request, adjusting the values of certain parameters. For example, a magic quotes filter would check if magic quotes are on, and remove them if so.

    However, InterceptingFilter is also used to load filters which don’t do any filtering in the dictionary sense of the word - authentication for example. An authentication filter might affect the logical flow of the program by making a decision on whether to continue processing the request or to stop and show a login page. The big difference compared to the magic quotes example is that authentication can direct request processing. This is what you might call a "request handling" role: ie deciding the nature of the response which should be made to an http request.

    The charge against InterceptingFilter is that allowing request handling functionality in candidate filters is a major design flaw. Ideally you would have a single location where all the request handling is carried out but InterceptingFilter creates another layer where this can occur in addition to a FrontController/PageControllers. That can't be good.

    A Chain of Responsibility is a good fit for request handling classes, however. By allowing items to be dropped in and out easily without disturbing anything else, it's a powerful pattern. Loosely coupled handlers create a robust, flexible design. Configurable chains can be customised per request at the same time as allowing common handlers to be shared.

    We want to keep all that. Perhaps the answer is a separate request handling chain. This would be a strict GoF CoR (only one handler in the chain is ever active) and might look something like this (handler/client page):

    validation handler/400-type page -->
    authentication handler/login page -->
    authorisation handler/access denied page -->
    foo handler/the foo page -->
    unknown resource/404.

    Requests would map one to one with handler chains and individual handlers would map one to one with one of the possible client pages which might be generated as part of the response to a request. A handler chain which maps to a form submission might add a redisplay handler and a form processor handler to the above list.

    If request-handling is refactored into its own chain, InterceptingFilter no longer does any intercepting. We could simply call it a FilterChain - except that filter candidates don't necessarily do any filtering either (logging is often mentioned as a candidate filter, for example). In essence, InterceptingFilter is just a frame on which to hang any kind of tasks which wrap the core. Some don’t intercept. Some don’t filter. Some might not do either. So let's rename it CoreWrapper.

    Perhaps it should be deconstructed further although a certain degree of vagueness could be useful in a layer which can serve as a kind of catch-all for items you didn't think about when you first wrote the app. I'm really not sure: the main thing is to get all the request handling out of there.

  2. #2
    SitePoint Enthusiast
    Join Date
    Oct 2004
    Posts
    88
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As i understand the role of intercepting is that those filters are executed before and after the application logic. Authentication and authorisation filters needs to access some data, which is part of the application logic -> user management -> access controle. So the authentication filter should be at the front of the application logic and the authorisation filters should evaluate the requests to detailed application items.

  3. #3
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think in PHP is makes sense to just build a simple execution queue that you can put as few or as many "actions" on as the page needs. They can be filters, controllers, etc. and the queue can be either a Front or Page Controller. Other languages separate things because of how their base libraries are designed. But PHP does not have this contraint.

  4. #4
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Intuitively, you might think of a filter as something which silently processes a request, adjusting the values of certain parameters.
    When you think of a filter as a thing that lets some things (in this case that would be incoming requests) through and reflects others, it makes sense.

    So let's rename it CoreWrapper.
    IMHO I find that definition even worse, in the sense that it's even more ambiguous. 'Core' can be almost any part of your application. For some the presentation layer is the core of their app, but for others it's the data access layer for example. The same goes for wrapper.

  5. #5
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    I think in PHP is makes sense to just build a simple execution queue that you can put as few or as many "actions" on as the page needs. They can be filters, controllers, etc. and the queue can be either a Front or Page Controller. Other languages separate things because of how their base libraries are designed. But PHP does not have this contraint.
    In order to make the application easy to maintain, I think it is worthwhile to categorise the different items carried out in response to a request and put these in separate layers. With a CoreWrapper you can easily add non-core "filters" without disturbing anything else. With a request handling chain, you can again add or remove individual handlers without requiring changes elsewhere.

    One test: suppose you had to add an input filter for all form processing scripts. Can you do that once for all or would you have to edit them individually?

  6. #6
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Captain Proton
    When you think of a filter as a thing that lets some things (in this case that would be incoming requests) through and reflects others, it makes sense.
    OK, you could see this as filtering the logical flow but we still have several different entities in here: items with request handling roles, items which silently process values and other items which do neither. IMO request handling ought to be refactored out of there (possibly other items as well although I'm not so sure about that). I think that leads to greater clarity in the design.

    Suppose an application uses an InterceptingFilter and a FrontController. Request handling can occur in the filters, the FC and possibly again in the entity which the FrontController hands over to. A single request-handling chain is simpler and easier to maintain, I think.

    Quote Originally Posted by Captain Proton
    IMHO I find that definition even worse, in the sense that it's even more ambiguous. 'Core' can be almost any part of your application. For some the presentation layer is the core of their app, but for others it's the data access layer for example. The same goes for wrapper.
    What is the core? I guess I have this detailed, technical picture in my mind's eye of a big round blob. The blob has inputs and outputs - HTTP request, persistent data storage, output points where "printers" are mounted for client page, emails, file writing etc.

    What I've sketched out is a framework blueprint. A CoreWrapper - or whatever you call it - can take care of non-core tasks; a request-handling chain has sole responsibility for deciding what core tasks should be called. The blob isn't defined - just whatever business stuff you need in here.

  7. #7
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I've sketched out is a framework blueprint. A CoreWrapper - or whatever you call it - can take care of non-core tasks; a request-handling chain has sole responsibility for deciding what core tasks should be called. The blob isn't defined - just whatever business stuff you need in here.
    I'd like to see some sample code showing your thoughts.

    The reason I go for a more generic solution has to do with the difference between web apps and the applications that these design patterns were created for. A traditional application always has the same type of request/reponse going on (e.g. mouse clicks, repaint) continuously. But a web page is just a small part of the code of a larger application. The form to define a report may have no request and a huge response; the report has a huge request and no response. I think you need to formalize them across the web application, but not across a web page.

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is an interesting post - I have had some of the same thoughts.

    I do agree to your attack on the interceptingfilter pattern. if not for anything else, at least for the decptive name of it.

    However i don't find CoreWrapper a good name either. In fact it should be a candidate for a worst-pattern-name-ever award. Just my humble opinion of course.

    As i see it, your concern is that the FilterChain holds A) what we can dub RequestHandler's (They choose the appropriate PageController) and B) other stuff that needs to be running at all requests. The only thing B have in common are that they happen at every request.

    If the FilterChain makes up the main part of the FrontController, you could say that the control flows through the chain and ends up at a PageController. Thus each InterceptingFilter could be considered as a Controller in the MVC-universe. A better naming could then be :
    Controller in lieu of InterceptingFilter
    ControllerChain in lieu of FilterChain


    Don't forget that InterceptingFilter is the name of a pattern. When implementing it, you wouldn't nescesarrily have a 1:1 relationship between pattern and class/object. In fact you most often shouldn't.

    Regarding the seperation between RequestHandlers and other arbitrary Controllers, it could be a solution to divide the chain into two - one to take on global processing (logging, anti-magicquotes etc.), followed by a chain specifically dealing with selecting the appropriate PageController to serve. If we implement FilterChain as a descendand of Controller, the second filter could be appended as the last controller in the first chain. You're not really changing anything, but it might help seperating the two.
    (That came out pretty messy - say if i need to elaborate on that one)

  9. #9
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    I'd like to see some sample code showing your thoughts.
    I'm working on an implementation of this idea but I don't have anything to show as yet.

    The posts above should explain most of it. Items in the CoreWrapper chain are always active as opposed to handlers in the request handling chain where only one handler is ever active.

    Chains possibly are most useful when they are configurable: this can allow you to share items between responses as well as configure individual responses. I'm looking at ini files and some kind of configuration manager which defines groups, assigns items to groups, and then compiles ini files for each request. This should provide the ability to edit once-for-all which I mentioned above. I hope.

  10. #10
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    i don't find CoreWrapper a good name either
    lol - honestly I think it's quite descriptive and also as vague as it needs to be, but nobody's biting. Thanks for your comments.

    The name isn't that important: the aim is to split the chain in two. In my defence, at least I didn't name them after my nieces.

  11. #11
    SitePoint Zealot prefab's Avatar
    Join Date
    Jan 2003
    Location
    Belgium
    Posts
    133
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've deceided to split things from the start. So in my current FrontController based framework I have these elements:

    - Filter: the base object where inputFilter and outputFilter inherit from.

    - inputFilter: handles incoming request object and is able to modify it by reference
    - outputFilter: recieves the output string from the renderer

    - interceptor: can intercept calls to the execute() method of a State or Action object (State is a grouping of Action objects).
    It recieves the State or Action (depending on the configuration), in essence you can override the execute() method using the interceptor.
    The original object (State/Action) is accessable too, so the interceptor can deceide to continue with the original execute() call.

    - interceptorFilter: this class extends from the Interceptor. You can set multiple Pre and PostFilter objects (which are Filter instances), which will be applied accordingly.

    - interceptorConfig: a configuration stating which interceptors to apply to which State or Object

    - the Dispatcher (which instanciates State and Action) takes this interceptorConfig and applies it at runtime.

    I hope I'm making any sense here... it's working really well, and there are some things left I can't tell you about here (like how the configuration is setup...)

    This is applied in this order:
    - setup Application
    - execute application
    - apply inputFilters
    - use Dispatcher
    - dispatch State and Action
    - apply interceptors / execute State/Action
    - use Renderer
    - apply output filters

  12. #12
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    prefab > any chance you could show a stripped down version of that ?

  13. #13
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think what I often use might be called an ActionChain. I consider everything prefab lists as an action. An action can modify the chain if it needs to so it can be a Controller itself. For some pages the chain is as complex or more complex than what prefab lists, but for many it much simpler. The problem I have with Java like frameworks is that they are such crazy overkill for most pages.

  14. #14
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    The posts above should explain most of it. Items in the CoreWrapper chain are always active as opposed to handlers in the request handling chain where only one handler is ever active.
    Sorry, I don't get it. Could you at least give some examples of what would go into each chain?
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  15. #15
    SitePoint Zealot prefab's Avatar
    Join Date
    Jan 2003
    Location
    Belgium
    Posts
    133
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    prefab > any chance you could show a stripped down version of that ?
    I would be quite happy to do so, but unfortunately I'm a bit hesitant atm. Since this is the core of my soon-to-be released 'commercial' CMF, I'm not really comfortable to share this yet. I think I'll eventually release an OS version of the core though. Maybe you could tell me how much stripped down is acceptable for you?

    - prefab

  16. #16
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Since this is the core of my soon-to-be released 'commercial' CMF, I'm not really comfortable to share this yet
    Would you feel better if the code had a copyrightnotice with a text prohibiting any use at all, stripped to it ?
    I sinceriously don't think the core construction is worth stealing for anybody. If you need commercial software, it's not the idea you pay for - it's other things, like the certainty that it's always up-to-date.
    Maybe you could tell me how much stripped down is acceptable for you?
    Well, stripped down to the point where it's just a bunch of hollow classes. It's the interconnection between the classes that's interesting in this aspect.

  17. #17
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dagfinn
    Sorry, I don't get it. Could you at least give some examples of what would go into each chain?
    It's the job of a framework to create a to do list of tasks to carry out in response to a http request. Some (most) of these tasks interact with the application core. Others are independent of the core.

    InterceptingFilter is a common pattern used to load non-core tasks; examples might be a magic quotes filter or (anonymous) user activity logging (I've deliberately avoided calling these filters since an item such as logging doesn't actually filter anything). They are non-core because they are independent, stand-alone items which don't know anything about the specific application they work with.

    Output filters are often mentioned as candidate filters for a core wrapper but I think these are better placed in individual "printers". Think of a printer as a routine which outputs data obtained from the core: email, file, client page. It makes more sense to me to apply output filters here rather than trying to add them to a core wrapper although this is a non client-centric way of looking at things which doesn't suit everyone.

    You might not need a CoreWrapper initially but I think you should at least have an idea of how to stick one in. It might be needed later.

    I've suggested a strict GoF Chain of Responsibility (ie only one item in the chain actually executes) to decide on the core to do list. The request is passed down the chain and each handler decides if it can process the request; if not, it passes the request on to the next handler in the chain. Handlers map one-to-one with client pages.

    In the example I posted above the request is first checked for bad syntax (primary input validation). If it's a bad request, the handler kicks in, displays a 400 page and the chain ends. Otherwise, on to the next handler.

    The next handler checks if the user has been successfully authenticated. If not a login page is displayed and the chain ends. Otherwise, on to the next handler.

    And so on.. At the end of every chain is a 404 handler to catch anything the others couldn't deal with.

    A list of tasks is associated with each handler: client output and non-client actions such as emails, logs or whatever is required. These core tasks are specific to the application and access various business objects to do their thing. Anything which doesn't can be removed to the CoreWrapper - you've just discovered a class which is potentially re-usable with other applications.

    Incidentally, with user activity logging, if you were recording details against named users rather than anonymous page hits, this would become a core task. Logging is now interacting with the business core.

    With a good solution to the configuration problem (ie how to share common items between responses at the same time as allowing individually configurable responses) it should be a flexible and easy to maintain design. That's the aim, anyway.

  18. #18
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think that the pattern InterceptingFilter is one that maps particularly poorly onto PHP. It is a vague pattern anyway, but because many of the problems it solves in other languages are one liners in PHP it's just not that useful a OO pattern in PHP. In essence every PHP page is a big InterceptingFilter with a couple of one-two line InterceptingFilters scattered around inside.

  19. #19
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Although I've been arguing that InterceptingFilter is a somewhat schizophrenic version of Chain of Responsibility, I do see CoR as a core php patten. The ability to pop things in and out of a chain without disturbing anything else is very powerful.

  20. #20
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think there are a couple of problems with the classic CoR being used as general PHP controller.

    "Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it."

    First, I don't think PHP scripts have the luxury or loading a bunch of stuff on the chain and see if one handles the request.

    Second, I think sequence if very important in PHP scripts because the are smaller parts of a larger application. The goal is to very quickly sort out the request and then roll through a short sequence of actions. It's not near the same problem as "I got a keyboard event" where the potential actions are many.

    I do think a modified CoR can apply to things like access control and error handling, but the classic CoR is not that good a fit.

    As for modifying the chain, I find that most of the time I just want to clear the chain and add an error action.

  21. #21
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's the strict GoF CoR. It's also often used more loosely ie where several - or all - of the items on the chain are executed.

    Either way I think it's important to be clear that this is not a heavy pattern to implement. It works very well in php anywhere you might have loosely-coupled objects to stick in a chain (Observer can sometimes be an alternative option).

    PS: it's probably also best if there aren't a huge number of handlers in the chain.
    Last edited by McGruff; Oct 14, 2004 at 17:26.

  22. #22
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree, I chose to solve the same problem with a simple action chain.

  23. #23
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    In the example I posted above the request is first checked for bad syntax (primary input validation). If it's a bad request, the handler kicks in, displays a 400 page and the chain ends. Otherwise, on to the next handler.
    You're right, you basically already gave the example I asked for. I somehow overlooked it. And I agree with you that there's an crucial distinction between what you call the handlers (overall flow control) and what you call the core wrappers (pre- and post-processing).

    The word "core" is problematic, but I don't have a good alternative.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  24. #24
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    as mentioned, core is problematic, because it has so many meanings. wrapper is bad too, because it's the name of another pattern.
    actually it's more like a plugin - except it's plugged around

  25. #25
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So it's a process....envelope....chain? Perhaps the name of those wooden dolls from Russia that you keep finding more little dolls inside would be appropriate.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •