On Wed, Jul 13, 2016 at 8:03 AM, Niall <[email protected]> wrote:
> Thanks for taking the time to respond. If I'm understanding what you're both
> saying then the best approach may be to abandon using my customized db
> wrapper and go back to using standard sqlalchemy. Since i have not really
> started the reporting app yet, that's certainly doable. One of the reasons I
> was opting for the custom solution was that it would give me a separate
> place to put all the packaging of the data to be returned to the web app.
> I'm dealing with complex data where I will normally need to touch 5 to 8
> tables to put all the pieces needed together in a query. My db structure is
> granular. Instead of using things like Oracle stored procs and/or complex
> views, which would anchor me in future to Oracle, I want to keep that logic
> in the application, outside the database. I originally wrote the db load
> application using sqlite on a Windows machine and then ported it to Oracle
> on Linux, simply by re-writing the db wrapper. I'd like to continue in that
> vein so that, should the company decide to move to another DB in the future,
> it won't be an issue for my application.

If the ability to switch database types is more important to you than
your Oracle code, then rewriting it in SQLAlchemy would be a good
choice. If you're ever going to do it, you might as well do it now
when you're overhauling your application anyway.

But as a speaker at a PostgreSQL conference said, it's also worth
taking advantage of your database's unique features, because if you
use it in the least-common-denominator fashion you're not getting the
most out of it. Which option you choose -- a database-neutral approach
or a database-specific approach -- depends on the application. In one
application I use PostgreSQL and have started using its unique types
and full-text search and may use PostGIS. Another application has to
work both as a website and a desktop application (the wxPython wrapper
spwans a Pylons application and an embedded browser that uses it), so
we initially designed it for both SQLite (desktop) and PostgreSQL
(webserver). But at one point I got foreign key errors from PostgreSQL
because it's stricter than SQLite, and rather than unravel them we
just went with SQLite exclusively because it's performing fine on the
webserver.

> One other thing occurs to me:- Since Pyramid has all this routing
> infrastructure built in, would another solution possibly be to build a
> separate app which would service database requests and create a layer > So 
> now, assuming I go with pure
> sqlAlchemy, is there a way I can deploy a python class between my web app's
> view callables and the database to house the functionality I was going to
> put in my custom wrapper?
> As I said before, at this point I'm simply trying to decide the route to
> take, not the actual detailed specifics of the solution.
> (where
> I could put my custom data packaging)? My reporting app could then route db
> requests using urls to this separate database servicing app?

My current structure is to have small view callables that handle the
input validation and template variables and Pyramid-specific stuff,
and a separate library tree for high-level queries and other logic
that's not closely tied to Pyramid our the output format. That way my
business logic is separate from both the views, the models, the
templates, and Pyramid, so if I wanted to use it outside the Pyramid
application or port it to another framework it would be clear which
code would be relatively easy and which difficult.

Sometimes I allow a little Pyramid into the library modules, such as
the request when I need a lot of things out of it or I need to
generate URLs, or the HTTP exceptions because it's silly to make a
custom exception just to catch it and raise an HTTPException (and unit
tests can deal with HTTP exceptions just as easily as any other
exception), and 'pyramid.compat' for Python 2/3 compatible stuff.

That would give you an applcation with view modules calling library
modules. You can go a step further with 'pyramid_services', where you
register service classes and then ask for them, but when I tried it it
was overkill. It has a niche if you might sometimes want to use an
alternate interpretation, then you can ask Pyramid, "Give me an object
that does X (an interface)". But if you have only one implementation
and no likelyhood of a second one, why not just import it directly?

I have actually taken a step in the opposite direction and gone to
function-based views and library functions, based on a talk at PyCon
that said that functions and modules are better organization for code
than classes, and more readable for future maintainers. So Iried it in
a Pyramid app and it is pretty readable: you don't have to look
closely for subtle 'self' references and inherited dependencies. The
talk argued that classes are for data, not code, and if you have a
complex set of state data then put it in an object and pass it between
your functions. I don't go as far as that, and passing a state object
as the first argument reminds me of the horrors of C. And it doesn't
work for some things; for instance, I have a class to do model field
updating. You initialize it with a model and call a method to update a
field by name. It checks whether the value has changed and if so,
updates the model attribute and adds it to a set of field names. Then
at the end I have a set of which fields have changed, which I can put
in an audit record. You can't reduce that class to functions without
having to carry the set of changed fields around, which is excessively
verbose. So that kind of thing I keep a class.

Another approach would be a separate data-server application, so one
application would be calling another, perhaps as an HTTP service.
That may be useful in specialized cases where you really want to keep
the data code in a separate process, either for some structural reason
or to serve multilingual clients. But as a general pattern for a
Pyramid application it sounds like more trouble than it's worth. When
you get to the integration test section in the Pyramid manual it says
that it's often better to create a unit test that sets up a minimal
Configurator rather than loading the entire application if you don't
need it. It's that kind of thing. If what you immediately need is a
logic function, it's better to call that directly than to wrap it in a
view which then has to parse the post params and make some kind of
response or renderable dict. But that scales out too: it's better to
call a view callable than to shoehorn your request into HTTP, which is
what you'd do if you have one website call another. Sometimes that's
worthwhile, as in the aforementioned common server for multilingual
clients. But it's a lot of overhead if you don't have to.

And if you have an extensive Javascript front end, then maybe your web
application reduces down to zero, and the Javascript code can just
call the data server directly. That's how GMail works.

--
Mike Orr <[email protected]>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pylons-discuss/CAH9f%3DuqyzAfmcnhqT_8B3%3Dun8OjC7qhBwLqegfzR5p07FPPNcg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to