Forum OpenACS Development: user preferences - a new package?

Posted by Ben Adida on
Hi all,

In thinking about bboard and other packages, it's become obvious that
there are a bunch of ways of displaying certain data, and that the
method of displaying said data should be left to the user in many
cases. Do you want to see the hot threads? The new threads? What do
*you* consider a new message? 1 day, 2 days, since your last visit?
It's really a per-user thing.

The obvious thing to do here is to build a generic user preferences
package that tracks per-user preferences, possibly with defaults for
users who haven't set a preference,etc...

I'm envisioning something very simple, with preferences tagged by
package, and potentially by package_id (so that your preference can be
different between different instances of bboard). A simple PL/SQL (and
PL/pgSQL) API, mirrored by a wrapper Tcl API, would allow these
preferences to be used in Tcl and also directly within queries.

Thoughts? Has anyone started on something like this already?

Posted by Michael Feldstein on
This is a great idea. The one potential UI issue to be aware of
(which I encountered in the old ACES interface for bboard alerts)
is how to handle nested relationships. For example, a user can
set email alert preferences on a thread, one bboard,or all
bboards. Do you allow a user to, say, set immediate emails on
one thread but also get a digest for the whole bboard on a
weekly basis? If so, how do you represent those choices to the
user? And how do you handle cascades when a user changes
preferences at a higher level?
Posted by Ben Adida on
These days, I am a big proponent of end-to-end: making sure your core pieces are not trying to too smart, because being too smart will actually prevent new packages from innovating freely on top of your core.

In this case, the piece of code that is best going to be able to tell if there is a potential overlap of notifications is the bboard package itself. The underlying notifications package shouldn't try to figure this out for every package that uses it....

But I see your point, and eventually bboard should be smart about this.

Posted by Michael Feldstein on
What's the best way to spread best practices in a case where the
code is best implemented in the specific package but where
there is likely to be overlap in coding and/or UI needs from
package to package?
Posted by Don Baccus on
Well ... again my favorite "glue tool" is the service contract.  Yeah, I know we need to improve it.  I've been giving thought to writing a higher-level declarative layer, just as I'm now doing for forms.  That would remove some of the boring and tedious aspects of working with service contracts (repetitive SQL in Oracle and SQL versions).  Janine Sisk and I have also talked about providing default values and named parameters on the calling side.  There are other things that could be done to make using service contracts pain free.

If the need is there to provide PL/SQL functions that can be used in queries, you could define a standard parameter signature and just have the contract return the name for that package.  Something like that.

Service contracts are nice because they provide us with on mechanism for "gluing" pieces together.  I fear ad hoc approaches because everyone has the tendency to do theirs slightly differently  ...

Posted by Don Baccus on
I guess my answer to the real question - "yes, this would be good" - was implied by my answer but in case there's any doubt, this should make my answer explicit.
Posted by Ben Adida on
I think there is a difference in philosophy on the service contract tool here. Would you make the Content Repository accessible via the service contract? Seems like that doesn't fit. To me, the key difference is this:

- is your package going to serve a function that another package will also serve on the same system? Or is it conceivable that you will switch a live running system to running a different package offering the same functionality? If so, then use service contracts. For example, portlets inside the portals package (more than one portlet). Or the credit card processing package (you might switch from Verisign to... I don't know whoever buys Verisign?).

- is your package going to serve a core function that no other package provides? Or, if some other package provides it, it's not like you could switch yours out and the other one in easily? Think Content Repository. Workflow. acs-datetime. Seems like a straight dependency is the right thing to do there. The reason for the straight dependency is so you can start depending on the underlying SQL API and tables, too, not just the Tcl API. If we move too much to Tcl API dependence, we'll start to get bloated and lose the true power of SQL (eerily reminiscent of EJB architectures...).

- there is, however, a use for service contracts in these core packages. Think of 5 packages that depend on user-preferences. The user-preferences UI needs to link back out to those 5 packages, to provide relevant information in a summary screen. Thus, a reverse-dependency contract, called user-preferences-extension, is very useful to implement callbacks into these extensions.

Posted by David Geilhufe on
Is this a places that a stricter definition of/ distinction between "service" vs. "package" would help over the long run? It seems like we often get caught up in providing APIs to developers and UI's for users all in the same piece of code. I really like Ben's idea that the core should not be too smart... it should allow programmers and even site designers (installers of packages) to do stuff that is "dumb". <br><br>
I guess the issue here is which parts are the toolkit-- building blocks-- and which parts are applications. The toolkit parts of the bboard would include functions-- allow different looks and feels, email integrations, tie to the content repository to access advanced functionality, etc. Some functions are delivered by the bboard package, some are delivered by other packages through the bboard package (email for instance).<br><br>
The application... an actual place to post messages with a user interface and a place within the navigation structure of the site is an entirely different creature composed of a UI and logic that assembles all the functions in the "correct" way. That application could put together the functions provided by the toolkit in ways that may or may not make sense-- allowing innovation and many different applications that do the same basic thing built off of the same toolkit.<br><br>
I'm not sure that this means that bboard somehow becomes two packages-- the toolkit and the application-- just that the code within the package is segregated in such a way that folks can differentiate between the toolkit parts and the application parts.<br><br>
Not being a developer, please enlighten me if I have missed some fundimental way that this does not make sense.
Posted by Michael Feldstein on
Forgive the naive question, but shouldn't it be possible to share
commonly used bits of code with all the package builders
without building those bits into the core? Can you create some
kind of (dare I say it?) objects that can be implemented
individually and, if absolutely necessary, ideosynchratically in
various packages without having to cram those features into the
core? Or does this not make sense in the OpenACS world?
Posted by Ben Adida on
Michael: sure, you can do that. Build packages that provide certain services (you can call them objects) without a UI, allowing the services to be used by other packages. Credit Card Processing, for example (although you might have a generic management UI there).

"Cramming them into the core" is a tad misleading. There are two issues:
1) what should be distributed as OpenACS core and 2) what pieces become de-facto core since many other packages use them.

Going back to something Don and I were talking about a while ago, the right thing to do is probably to distribute a very minimal core, and each package individually. Then, we need an easy way to create vertical-specific applications that mix and match the right packages. This makes it flexible for developers, and functional for users.

Posted by Yonatan Feldman on
it would be useful to create a generic preferences package that worked on
many types of objects: parties, packages, and possibly others. it might be
interesting to make it an acs_object level service.
Posted by Don Baccus on
<blockquote><i> there is, however, a use for service contracts in these core packages. Think of 5 packages that depend on user-preferences. The user-preferences UI needs to link back out to those 5 packages, to provide relevant information in a summary screen. Thus, a reverse-dependency contract, called user-preferences-extension, is very useful to implement callbacks into these extensions.
Yes, this is exactly what I was thinking about.  A service contract exposes the API to the package developer and also checks to make sure that they're at least claiming to return the right stuff.
<p>I don't mind if there's a predefined and well-documented PL/SQL and Tcl API in the other direction.
Posted by Ben Adida on
I've put together a high-level specification for this user-preferences package over here:

I am trying to keep this simple for the first iteration. Please comment (on this bboard). I plan on doing a very quick first implementation in the very near future, so early comments are welcome!

Posted by Ola Hansson on
Have you considered cookies?

Setting a cookie when the user updates her preferences in the db, and then checking for the existence of it before hitting the db if it doesn't... Or maybe the extra cost of hitting the db just isn't that high with todays hardware(?)

In case you're going to use cookies it might be a good thing to add a user_id or some other token to the cookie name, in order for multiple persons to be able to use the same browser; "acs_prefs_$user_id: ...." (IE works like this anyway)

Just my tuppence worth,

Posted by defunct defunct on
General mechanism for user preferences.. excellent notion. No real comments on your document, however, I'm guessing whatyour proposing essentially puts the owness on the package itself to register potential preference types etc.. therefore has anyone estimated how much work is involved in retro-fitting existing packages?

I know you've mentioned it but I would re-emphasise that making it package 'instance' aware is critical. I assume of course it would also therefore be subsite aware?

This is of course assuming that the intention is to nake older packages use it, and that there is a development step there also, aplogies if I misunderstand.

Posted by Ben Adida on
As always, thanks for the comments!

The cookie idea: it's a good idea, as long as we make sure to
keep the # and size of cookies to a minimum. What is probably
better (and related) is to keep a cache of preferences on the
server side keyed by session ID so that we only have to load up
the preferences once for a particular user. Let's keep this one in
the back of our mind for when we start optimizing.

Simon, we definitely want to allow package-instance-specific
preferences. No question there. I think there is one thing to think
about: system-wide preferences that all packages can tap into.
This is probably the hardest part of it all: we don't want the core
preference type list to grow in an outrageous manner, but we
also don't want individual packages to have redundant
preference types because of a lack of core preference types.

For example, it's probably a good idea to store "Data Newness"
in the core, so that a user can say that she wants all data older
than 2 days to show up as new throughout the system. It would
be too bad if both calendar and bboard had their own way of
thinking about what constitutes new data.

As for whether older packages will be retro-fitted, I'm guessing
that will happen on an as-needed basis. You can bet that the
new forums package I'm working on will use this preference
package. I'm hoping others can help moving other packages to
this framework, whenever it makes sense.

Posted by Deds Castillo on

Is the user-preferences module still in the works?  Last post on this thread was 3 months ago.  I can't read your proposal document as the site hierarchy of the openforce site has changed.

Posted by Arjun Sanyal on
deds: there is a user-preferences package in oacs cvs, but i'm not sure of the state of its development. ben's paper is back up here: