"Roland Winkler" <wink...@gnu.org> writes:

> On Thu Dec 24 2015 Eric Abrahamsen wrote:
>> A while ago there was a very brief exchange about the possibility of a
>> version of BBDB refactored on top of the EIEIO object orientation
>> library. I've been thinking about that for a while, and recently wrote
>> a sort of prototype. I'd like to share it with everyone, either as an
>> attachment to the list, or I guess preferably by pushing a branch to
>> the git repo.
>> 
>> There isn't anything particularly wrong with BBDB that needs fixing,
>> but an OO version of the database does lots of good things, mostly in
>> the direction of extension and customization. It also gets us free
>> file serialization courtesy of eieio-persistent, and I've added in
>> support for multiple databases.
>
> I don't know much about EIEIO, but I am not sure it would benefit
> BBDB so much to add an extra layer of abstraction.  Correct me if I
> am wrong, but what kind of problem can really be solved cleaner and
> how?

It's not really about abstraction, but the way that classes and methods
are modular, and "pluggable". Some examples below.

> Extensions and customizations of BBDB should use a high-level API,
> which does not expose the details of how things are implemented.
> Currently, a good example for this is the function
> bbdb-record-set-field.  Anyone wanting to extend or customize BBDB
> should not call the low-level functions that do the real work inside
> bbdb-record-set-field, because the low-level implementation might
> change at some point for whatever reason.  How could EIEIO possibly
> provide a better solution (better in what sense)?

Extension/customization would be a result not of exposing BBDB's inner
workings, but of making database/record/field classes responsible for
their own behavior, and allowing external code to replace or alter that
behavior.

For example, adding a new field to a record. What the code does is pick
up the current record, then prompt the user for the field class to
insert. Then it passes the field class to the record's
`bbdb-record-insert-field' method. The record itself decides if it can
accept this field. If it can, the record calls the field class's
`bbdb-read' method, which prompts the user for values, and returns an
actual field object. The record then puts this object in the appropriate
slot, and calls a method on its database to let it know it's done.

All this happens in methods belonging to the various classes. Users have
customization options saying what default classes they want to use --
they can change the behavior by changing the default classes. Or they
can load libraries that override the basic methods, changing behavior
without having to change any of BBDB's internal code, or their own init
options.

I've tried to set it up this way for most aspects of BBDB's internal
behavior: The classes themselves are responsible for creation/set-up,
deletion/tear-down, "noticing"... In other words, the API we're
"exposing" to developers isn't BBDB's internals at all, but the method
signatures of the various classes.

Other possibilities:

1. Funky database subclasses. A database backend that reads from/writes
   to a VCARD file, or a remote CardDav server. These backends would be
   a lot of work to write, obviously, but they could be written and
   plugged in without having to modify the existing codebase at all.

2. A "more international" BBDB. Users load an additional library, say
   "bbdb-i18n.el", containing new `bbdb-read' and `bbdb-display' methods
   for the name, phone and address field classes that are more
   internationally aware. For instance, when a phone field is created,
   it would first prompt for a country name. The country code would then
   be automatically added, and the phone number displayed in the proper
   format for that country. A Hong Kong address would not ask you for a
   postcode. Etc. From the user's point of view, all they had to do was
   (require 'bbdb-i18n).

3. Newer versions of EIEIO support dispatch on multiple arguments, and
   dispatch using `eql'. That means field display could be completely
   modular. For instance, the way a phone field displays in the one-line
   format is a method with this signature:

   (cl-defmethod bbdb-display ((field bbdb-field-phone) (format (eql 
one-line))))

   Overriding these methods would provide very fine-grained control
   over how the BBDB buffer looks. You could even register a new
   display symbol and write your own display routine.

I definitely understand the wariness over letting people run amok in the
guts of BBDB. But the great thing about generic functions is that you
can just load them on top of existing code, either replacing or
augmenting it.

A last example of customizability: I live and work in China, and have a
lot of Chinese contacts. If someone is surnamed 周 and named 丽华, I
usually add the romanization of this name as an aka: "Zhou Lihua", so
that I don't have to switch input methods to search/complete with this
contact. That's extra work, and data duplication.

With this class system, I could put something like the following in my
init files:

#+BEGIN_SRC elisp
  (with-eval-after-load 'bbdb
    (cl-defmethod bbdb-init :after ((name bbdb-field-name) &optional record)
      (let ((namestring (bbdb-string name))
            (roman
             (when (string-match-p "\\`\cc+" namestring)
               (make-pinyin-roman namestring))))
        (when (and roman record)
          (bbdb-puthash roman record)))))
#+END_SRC

The `bbdb-init' method runs when the name object is loaded, created, or
edited. If the name is in Chinese, the function `make-pinyin-roman'
takes the characters and turns them into roman letters (I already have
this function), and then hashes the record against the romanization. Now
I can search/complete against the contact's romanized name, without
having to do any extra work.

If later I develop that package further, with more Chinese-based stuff
in it, I could stick it on Elpa and let other people install it.

> Apart from that, I also believe that currently there are more
> important issues.  First of all, I hope that with the OK from RMS,
> we can now integrate the core of BBDB into GNU Emacs (which still
> requires some work to make it happen).

Fair enough! Out of curiosity, what sort of things have to happen?

Sorry for the enormous message. I also recognize that no one asked me to
do this, and it might be a little presumptuous! But I do think it could
really open things up both for third-party developers, and regular
users.

Eric


------------------------------------------------------------------------------
_______________________________________________
bbdb-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bbdb-info
BBDB Home Page: http://bbdb.sourceforge.net/

Reply via email to