4

Preface

I have an ORM library for a relational real estate database. The used framework is peewee. The library contains ~60 models, each representing a distinct table. The models represent a (pre-defined, proprietary) real estate data structure based on XML. There is one top level table called immobilie (real estate), which represents the root of the XML document.

Each model has defined the classmethods from_dom(cls, dom) and from_dict(cls, dictionary) and methods to_dom(self) and to_dict(self) which contain a considerable amount of code.

Problem

The library works fine as it is, but the module currently has 10255 lines of code, which makes it quite hard to read and maintain.

First idea

My idea thus was to split the module into several smaller modules, each for one model. This, however, creates the following problems:

1) peewee requires setting the respective foreign key's model in the respective model definition. For simplicity of presentation let's assume:

class Parent(Model):

    @property
    def semi_orphans(self):
         return Child.select().where(
             (Child.mom == self & Child.dad >> None)
             | (Child.mom >> None & Child.dad == self))


class Child(model):
    mom = ForeignKeyField(Parent)
    dad = ForeignKeyField(Parent)

Thus the referenced model has to be imported in the respective model definition.

2) As the example with the semi_orphans property should clarify, nearly all referenced models also need to know their referencing models for certain selection methods.

This would create unresolvable cyclic imports as I already tested with parts of the code.

Second idea

Thus I thought, I could outsource the backreferencing methods into own subclasses in separate moules. This however would render them unavailable when doing something like:

some_child = Child.get()
semi_orphans = some_child.mom.semi_orphans

This would trigger an AttributeError since some_child.mom would return the base model without the semi_orphans method.

Question

Am I overlooking something? Is it really impossible to split the library into smaller components to increase its code quality and maintainability because there is no way of getting rid of the cyclic dependencies?

  • Welcome to SO software engineering. Thanks for taking the time to do a detailed description of your problem. But I think, it would be easier for anyone to understand what problem you are having and why, when you describe on a more concrete level, what you are doing. From what you wrote it isn't clear for me, why you model things as described above. – Thomas Junk Apr 9 '18 at 14:10
  • Wouldn't any change in the organizational structure of your model still amount to 10,255 lines of code? Can this code be generated instead of maintained by hand? – Robert Harvey Apr 9 '18 at 14:51
  • @ThomasJunk What kind of further information do you require. I'd be happy to add it. – Richard Neumann Apr 12 '18 at 8:47
  • @RobertHarvey Yes. The total amount of code would even slightly increase because of duplicate imports in the several modules. But this is not an issue. What I want to have is multiple smaller modules that each handle one ORM model. I see no way of generating the respective code automatically. – Richard Neumann Apr 12 '18 at 8:47
0

After some more consideration I started to split up the models into the actual ORM models and outsourced the JSON and XML DOM (de-)serialization into an own package, each, using mixin classes. I also solved the anticipated problem of the foreign keys not returning the composit, but base models. peewee has a DeferredForeignKey class I was unaware of. Using it for setting the composit models (with mixins) later, should solve this issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.