[Bf-python] API overhaul - irc meeting?
Michael Reimpell
M.Reimpell at tu-bs.de
Sun Jan 8 15:43:02 CET 2006
> 6) The start: define API before coding it, create (epy)docs and tests, etc.
This is a very good idea! Blender's BPy development is definitely missing some
tests (aka "use cases"). For example, take the Key module. You have access to
the Key Ipo and to to Key KeyBlocks, but there is no way of getting the
IpoCurve that belongs to a KeyBlock. A simple use case "read the ipo curve
belonging to a relative shape" would have revealed it.
A good examples of the problems with the current BPy implementation is the
NMesh.getMaterials() method. Due to a missing use case "get a material by
index" the getMaterials method returned a material list with "None" materials
removed. Of course that led to wrong material associations and index errors.
This behaviour is still available with the what=1 option, which shows another
problem with BPy: "premature backward compatibility".
Software development is an iterative process. This is especially true for open
source software, where developers just add what they need and don't bother
about other peoples usage of the software. Early backward compatibility
constraints do not allow you to correct errors or improve the interface after
the first few iterations, although the api is still far away from convergence
to optimum. (In the getMaterials() case, backward compatibility just results
in the survival of an error-prone option, see the discussion to
http://projects.blender.org/tracker/?func=detail&atid=127&aid=3701&group_id=9
for another example where this problem arises)
The NMesh.getMaterials() methods also shows another problem with the api: You
can get the list of materials of the underlying Python object, or that of the
Blender object. In other words: Although Blender has a data driven design,
the python data is out of sync. This is obviously a problem, especially if
you want to interact with the user input from the 3D view.
That the NMesh.getMaterials() method needs a "what" argument should ring the
alarm bells of the BPy developers. Such crutches are a warning for problems
with the api design. I'm glad that this was realized and led to the Mesh
module.
To avoid such issues in the future, I propose the following design guidelines:
1) There is a one-to-one correspondence between Blender internal C-structs and
BPy's classes. This includes that all struct elements are available as
attributes and derived values are available via methods (I will address the
"C-struct element names are too cryptic" and "attributes above methods"
arguments later)
2) BPy is a thin wrapper to the C-structs. There is no caching inbetween.
Elements created in BPy are immediately created in Blender. This avoids
snycing issues resp. spreading of BPy code all over the codebase (e.g., into
to dependency graph).
3) BPy classes can (and should) provide all kind of convenient methods to make
life easier. That is, although the BPy class attributes are limited to the
C-struct elements, there can (and should) be getters or setters for derived
values. For example an armature bone could have a setter
setTransformation(matrix) which changes the head, tail and roll values
according to the given matrix.
Benefits of this approach are:
Due to the 1-1 correspondence, there are no assumptions about the use case of
the BPy class. In principle, coding in BPy becomes as powerful as coding
within Blender's C code. This is as flexible and feature save as possible.
Also, due to the thin wrapper, there are no syncronization issues and BPy
code stays located in contrast to spreading all over Blender's codebase.
Another advantage is that script writers can more easily contribute to
Blender's internal code, as they allready know the corresponding C-structs
and connections from BPy.
As promised, here my comment on "most script writers are not interested in the
internal representation". Although I can't know what most script writers are
interested in, it is simply not possible to write any nontrivial script in
BPy without looking into Blender's interal codebase: You want to know what
the camera "lens" value is? You have to look into the corresponding C code.
You want to know what the light attenuation function is? You have to look
into the corresponding C code. In fact, having a different BPy representation
compared to Blender's C-structs is a severe slowdown: After you checked
Blender's C-code you have to additional check the BPy code, just to see how
to access Blender's internals (or if at all it's possible). If you think that
the C-struct elements are cryptic, add a meaningful comment in the api
documentaiton! "Camera.getLens() Get the lens value" has the same information
as no documentation at all. C developers may even start to look into the BPy
documentation to see what the C struct elements mean.
Also, I don't understand the "attributes above methods" philosophy. Don't let
a language dictate your design. In the proposed design attributes have a
clear meaning as Blender's internal data, and this meaning fits very well
with Blender's data driven design.
The proposed BPy design can be summerized into one sentence: "The same design
as Blender's codebase". On the one hand this concept is extremly easy to
grab, on the other hand it is flexible and feature save. Even if you come up
with another BPy design in the end, please check that with the arguments
above.
Cheers,
Michael
More information about the Bf-python
mailing list