spir wrote:
After reading your mail, I cannot help wondering that something
crucial seems to be missing in your class structure. (I get the impression that you are trying to squeeze object information and object meta information together in one class definition.)

Yes. This is a consequence of type & instance beeing defined in the same class() code section. If I unserstand well, what you call meta_information is for me simply type attributes. They will be available to any object of this type. Is this a misuse of types/classes?

Not necessarily, it kind of depends on how you look at the problem. In programming there are usually many good solutions.

However, by moving the 'type' information to a seperate object, your classes become less cluttered, and the problem (and thus the solution) becomes easier to understand/program.


[I have moved this piece of discussion up, since I think it is the core of the structuring gap I experince.]
>> Have you considered using the factory pattern? (ie make an object
> that represents the type, and another one for the data) In that way you
> can nicely seperate both kinds of information.
>>
> Definitely! That is the pattern I'm using -- or trying. I didn't know it
> has a name.  Now, isn't this factory<->object pattern precisely what the
> type<->instance relationship is supposed to be?

No.

The factory pattern is best explained by considering a real factory where you make products. You have a Factory class + factory object (usually 1) that represents the real factory, and you have a Product class + many prduct objects for the products it makes.

Each product object has properties and functions (ie its color and how you can use it). Meta information, like what kind of products exist and how to make/transform them however is *not* part of the product object but belongs in the factory object. (Look at real life, you can use a car to get from A to B and back, but a car cannot tell you what kinds of other cars exist, or how to install eg a radio.)

In your application, that would mean that the things you call 'instance' above are part of eg the 'format' object, and things you name 'type' above, are part of the 'formatfactory' (or 'formattype') object.

The difference between your approach and the factory pattern imho is that the 'type' information of an object is not stored in its class, but in another object (of class Factory).


Unfortunately, I can't paste right now a full & real snippet of the, as it is beeing refactored: it would rather be confusing. Here is a kind of outline of a typical symbol type:

oke.
I used this example mainly to understand better what you are trying to do.
I wrote some comments about things I noticed and observations I made.


class Format(Symbol):
  ''' block formats symbol '''
  # import relevant config data for this symbol type
  from_codes = config.formats.from_codes
  to_codes = config.formats.to_codes
  names = config.formats.names
  # open_format to be checked with closing tag (xhtml only)
  open_format = None
def __init__(self, source, mark, section_level, posV, posH, close = False,
                  list_type = None, list_level=0):
      # posV & posH ~ line & element numbers for error output
      # 'mark' can be a wiki code or an xhfml tag
      self.section_level = section_level        # = current title level
      self.indent = section_level * TAB         # for nicer xhtml output

As a side-note:
self.indent can be computed from self.section_level. In general, it is better in such cases not to store the computable attribute, but instead to compute whenever you need it. This strategy prevents that you get inconsistencies in your data (ie suppose that self.section_level == 1 and self.indent == TAB + TAB at some point in the program, which of both is then the true value?)

self.close = close # for automatic closing (wiki only)
      self.list_level = list_level              # nesting level
      self.list_type = list_type                # bullet or number
      self.error = False                        # flag used for no output

As a side-note:
you may want to consider using doc strings for documenting your class and instance variables, see eg pydoc or epydoc.


A variable like "section_level" leads me to believe that Format class is a part of a page.



      # read & record symbol data
      if source == WIKI:
          self.from_wiki(mark, posV, posH)
          return
      if source == XHTML:
          self.from_xhtml(mark, posV, posH)

This looks like a (factory!) class hierarchy you currently don't have. In OOP I would expect something like

self.load(...) # 'self.from()' is not possible, since 'from' is a reserved word in Python

and the underlying object type of 'self' would decide the conversion you actually perform.

So, as you can see, symbols of the Format type will use data held by their type. This seems rather an obvious and consistent practice to me. Namely, the from_codes, to_codes and names type attributes are available to future Format instances. these attributes were imported from an config module/object built at startup (from a config file).

In the factory pattern, you'd have a formattype object (of class FormatType) that holds the global (config?) information, and each Format object may hold a reference to formattype (if you want).


Now, imagine it was a wiki text instead, and the user wishes to output it into a wiki language different of the one it was originally coded in. At some time between the reading & writing will the config been rebuilt and, as a consequence, data held by Symbol types. As this is an action of the type, I wish it to be performed by the type. So:

That's one option. Another option may be to make the page object language-agnostic (ie you have a 'list', a 'picture' and many more page elements, but not attached to a specific language.)

Also, you have a number of language objects that know how to convert the page to their language.
A few class definitions to make it a bit clearer (hopefully):


class Language(object):
    """
Base class containing symbols/tags of any language used in your application. It also states what operations you can do, and has common code.
    """
    def __init__(self):
        # Setup common attributes (valid for all languages)

    def load_page(self, ....):
        """ Load a page """
        raise NotImplementedError("Implement me in a derived class")

Language class is not really needed, but very nice to make clear what operations you can do with it.



class WikiLanguage(Language):
    """
    Properties and symbols/tags that exist in the wiki language
    """
    def __init__(self):
        Language.__init__()
        self.list_tag = '*'

    def load_page(self, ....):
        # load page in wiki format, and return a Page object

class XHtmlLanguage(Language):
    """
    Properties and symbols/tags that exist in the xhtml language
    """
    def __init__(self):
        Language.__init__()
        self.list_tag = 'li'

    def load_page(self, ....):
        # load page in xhtml format, and return a Page object

For each language class that you have, you make a object (probably 1 for each language that you have). It describes what the language contains and how it performs its functions. A Language object also knows how to load/save a page in its language, how to render it, etc.


Actual pages are stored in a Page object, I am not sure how this relates to your Format object.
(I don't understand the meaning of the name)


class Page(object):
    """
    A page of text
    """
    def __init__(self, lang):
        self.symbols = [] # Contents of the page, list or tree of Element's




class Element(object):
    """
    A concept that exists at a page (list, text, paragraph, picture, etc)
    """

class ListElement(Element):
    ....

class TextElement(Element):
    .....

A page is simply a tree or a list of Elements. Since a page here is language-agnostic, it doesn't even need to know its language.
(don't know whether this would work for you).


Hope it makes some sense,
Albert

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to