Mail archive
acf

[Acf] [Fwd: Re: ACF and OOP]

From: Nathan Angelacos <nangel_at_nothome.org>
Date: Wed, 06 Dec 2006 01:16:03 -0000

for the records...

attached mail follows:



Natanael Copa wrote:
> Hi,
>
> I feel I *have* to write down what I have been thinking 2 weeks ago,
> when I looked at the ACF stuff last time.

Why?
>
> object.lua should probely be renamed to class.lua. Its a basic class
> that does nothing else but enable several instances of a class (objects)
> Strictly we don't need it, but I thought it might be good. (Its directly
> copied from the PiL)
>

Yes.. Calling it object.lua was confusing.

> The CfObject class should be renamed to FrontController, or
> FrontControllerClass. This is the generic front controller.
>
> WebCfObject should be renamed to WebFrontController. It is a class that
> inherits most of the methods directly from FrontController and just
> add/replace the web specific stuff. This way, we can reuse the common,
> shared, code if we create a CLI front controller.
>
> cf = WebFrontController{ .... something ... }
> will initialize cf as an instance of the WebFrontController class, with
> its own private data.
>
> This is the easy part. What we have today more or less.
>

I have been thinking along the same lines. attached is a simple test
case I wrote, just so to make sure I understand the "oo" in lua. Its
not acf - its just testing inheritance/overloading.


I too came to the conclusion that (what you call) FrontController is a
generic object that should simply define the variables for where
everything is (e.g read_conf and init_dirs)

the CLIFrontController has a cli-based parse_controller_action and the
WebFrontController has a path_info based parse_controller_action. (Same
function name, does different things)

I like the way you try to just "run_controller" - based on that idea,
with model/controller/view objects. There needs to be an "error" object
composed of an error model (method to log error data to a file), error
controller and error view. So in architecture, the error condition /is/
a standard component, just like say.. set hostname.

BUT... when you define a new model object (or controller object or view
object), it is an object with the self.__index set to the error
controller.foo_method. So, if you run
cf.controller.action_does_not_exist the cf.controller.__index metatable
will run the error.controller.foo_method. Its like all the
"if/then/else" things you hated, but it has lua do it itself. It uses
the language to catch the exceptions.

You don't like the error method? overload it. It makes errors just like
setting a hostname - its just another part of the system.

Before I start coding this though, I've wanted to sit down and actually
/think/ it through. We've done too many half-baked ideas in code
already... I want to make sure this idea is correct. Unfortunately,
there's been lots of interruptions, so I haven't had time to think.

> I was thinking of removing all the html stuff in the webconf file and
> let the controller execute the view. The controller has then also the
> possibility to pick different view methods from the view module,
> depending on in-data or results from model.
>
> The *.view.lua can be an object that generates the html code from tables
> in the way you described earlier with header, preamble, menu, contents,
> footer etc.
>

Heh.. and I am thinking about your idea of multiple front controllers.
 What if you had a web cgi that had its WebFrontController method that
looked for controller.view.lsp

A txt cgi that had its WebFrontController method look for
controller.view.txt.lsp

a Soap cgi that had its WebFrontController method look for
controller.view.xml.lsp

etc.

So, to switch from html to text based cgi output, you change the front
controller.

That's one idea (not sure I like it - just an idea)

Alternatively, what about making VIEWTYPE=HTML or VIEWTYPE=TXT a
post/get variable that webconf looks for, and passes on to the
WebFrontController. So the "viewhint" is passed as FORM_data, not in
the URI. I think I like this idea better - so far - but havent' had
time to think about it much - I'm more worried about making sure the
error object idea is viable.

> I am also thinking of generating the contents from a table the way you
> did the controller stuff (that plovs liked so much and started to use).
> The difference would be that this code is in the view module and not in
> the controller.

http://www.cs.usfca.edu/~parrt/papers/mvc.templates.pdf

Has some good points. One is that the view should be html, not tables
or code. Not that it can't have code, but that it should /look/ like
html. Your OOP Webconf was that way - it had some lua at the top, but
then code at the bottom. That's what lsp should be - just a template.

Just a thought.
>
> I'm wirintg very quick and long time since I actually looked at the
> code. (I dont even know if you have commited new things to the ncopa
> branch)
>

I did - but nothing recently.

> Re SVN. What if we create a new branch named oop, then we move the
> useful things from ncopa branch and trunk. When we have oop branch
> working at the level trunk is today we replave trunk with oop branch.
>
> What do you think about that?

Is there anything left to save? Its almost like starting over.

I'm going to try to get some simple code working to see if the cf object
inheriting from the error "object" is a good idea. There's lots of dark
corners there... Its still better than kepler and orbits though. :-)



#!/Users/na/bin/lua


--[[ This is a generic class. It is the base class, and contains a label, a "new" constructor,
        and a "print" function ]]--
generic = {
        label = "Generic Class",

        new = function ( self, object )
                object= object or {}
                setmetatable ( object, self )
                self.__index = self
                return object
        end,

        print = function ( self, message )
                io.write(string.format ("%s says %s\n", self.label, message));
        end,

        a = function ( self )
                print ("This is the a function from the Generic Class");
        end,


        set = function ( self, variable, value )
                self[variable] = value
        end
        }


--[[ This is a "specific" class, that inherits stuff from the generic class.
        It does so because its definition is a "generic:new" - because we give
        the generic:new a table, that table is used as the initializer - thus
        these functions overload the base class
  ]]--
specific = generic:new{
        label = "Specific Class",

        -- This is a Print function, which is different from the base .print function
        Print = function ( self, message )
                io.write(string.format ("SPECIFIC %s says %s\n", self.label, message ));
        end,

        -- this a specific "a" function. It overrides the a function from the
        -- generic class
        a = function ( self )
                print ("This is the a function from the Specific Class");
        end
        }


furball = generic:new()

bobo= generic:new();
burp= specific:new();


furball:print("Hello from a generic furball");
furball.label="Brand Name"
furball:print("Furball thinks its Brand Name");
bobo:print("Bobo thinks it should be called from Generic Class");

generic.label="Not Quite Generic";
furball:print("This is furball, but generic is now Not Quite Generic");


burp:print("This is burp:print");
burp:Print("This is burp:Print");

burp:a()
bobo:a()



burp:set("foo", "Mikey");
bobo:set("foo", "Mouse");
print ("Generic.foo (burp) should be Mikey. It is: " .. burp.foo)
print ("Specific.foo (bobo) should be Mouse. It is: " .. bobo.foo)

print();
Received on Wed Dec 06 2006 - 01:16:03 GMT