Inheritance in openERP (odoo) - oop

I am new in openERP and have an interview. Please explain the idea of different types of inheritance in openERP, i think it total 3 types. please explain it in very simple way from the perspective of interview.
P.S: I am familiar with the concept of simple inheritance.

Inheritance :
Inheritance mechanism is used to create idea of re usability.there re usability means that reuse the code of the parent class in any Object Oriented Programming.
Advantages :
Reduce code redundancy.
Provides code reusability.
Reduces source code size and improves code readability.
Code is easy to manage and divided into parent and child classes.
Supports code extensibility by overriding the base class
functionality within child classes.
Disadvantages :
In Inheritance base class and child classes are tightly coupled.
Hence If you change the code of parent class, it will get affects to
the all the child classes.
In class hierarchy many data members remain unused and the memory
allocated to them is not utilized. Hence affect performance of your
program if you have not implemented inheritance correctly.
There are two way to inheritance in OpenERP.
1.Classical Using Pythonic Way :
It allows to add specific "generic" behavior to Model by inheriting classes that derive from orm.Model like geoModel that adds goegraphic support.
class Myclass(GeoModel, AUtilsClass):
Using _inherit :-
The main objective is to add new behaviors/extend existing models. For example you want to add a new field to an invoice and add a new method
class AccountInvoice(orm.Model):
_inherit = "account.invoice"
_column = {'my_field': fields.char('My new field')}
def a_new_func(self, cr, uid, ids, x, y, context=None):
# my stuff
return something
override the existing method :
def existing(self, cr, uid, ids, x, y, z, context=None):
parent_res = super(AccountInvoice, self).existing(cr, uid, ids, x, y, z, context=context)
# my stuff
return parent_res_plus_my_stuff
2.Polymorphic Way :-
Using _inherits :-
When using _inherits you will do a kind of polymorphic model in the database way.
For example product.product inherits product.template or res.users inherits res.partner. This mean we create a model that gets the know how of a Model but adds aditional data/columns in a new database table. So when you create a user, all partner data is stored in res_partner table (and a partner is created) and all user related info is stored in res_users table.
To do this we use a dict: _inherits = {'res.partner': 'partner_id'} The key corresponds to the base model and the value to the foreign key to the base model.
As same through XML you can do the inherit the Odoo views (like Form view,Tree view,Search View etc ..) and you can also change the behaviour from the view
Key point :
The above two method can be apply on the Odoo server side and which you can change the behaviour of existing view or any other things you can change in Odoo views the effect with on your client side.
I hope this should helpful for you ..:)

Related

OOP - Best way to populate Object

I try to follow OOP and S.O.L.I.D for my code and came across a topic where I'm not sure what's the best way to align it with OOP.
When I have an Object with different properties, what's the ideal way to populate those properties?
Should the Object if possible populate them?
Should separate code assign the values to the properties?
I have the following example (Python), which I created based on how I think is the best way.
The Object has methods that will populate the properties so if you instantiate the Object, in this case an Account with and Id, it should automatically populate the properties since they can be retrieved with the ID using DB and API.
class Account:
def __init__(self, account_id):
self.id = account_id
self.name = None
self.page = Page(self.id)
def populate(self):
self.get_name()
def get_name(self):
''' Code to retrieve Account name from DB with account_id '''
self.name = <NAME>
class Page:
def __init__(self, account_id):
self.id = 0
self.name = None
self.user_count = 0
self.populate()
def populate():
self.get_id()
self.get_name()
self.get_user_count()
def get_id(self):
''' Code to retrieve Page Id from DB with account_id '''
self.id = <Page_ID>
def get_name(self):
''' Code to retrieve Account name from DB with account_id '''
self.name = <NAME>
def get_user_count(self):
''' Code to retrieve user_count from API with page_id '''
self.user_count = <user_count>
So instead of doing something like:
account = Account()
account.id = 1
account.name = function.to.get.account.name()
account.page = Page()
account.page.id = 1
I will have it managed by the class itself.
The problem I could see with this is the dependency on the DB and API classes/methods which go against S.O.L.I.D (D - Dependency Inversion Principle) as I understand.
For me it makes sense to have the class handle this, today I have some similar code that would describe the Object and then populate the Object properties in a separate Setup class, but I feel this is unnecessary.
The articles I found for OOP/S.O.L.I.D did not cover this and I didn't really find any explanation on how to handle this with OOP.
Thanks for your help!
Michael
Your design seems fairly ok. Try having a look # Builder Pattern and Composite pattern. And for your question on violation of D principle.
The problem I could see with this is the dependency on the DB and API classes/methods which go against S.O.L.I.D (D - Dependency Inversion Principle) as I understand.
The dependencies are already abstracted into separate components I guess. It is the responsibility of that component to give the data you needed per the contract. Your implementation should be independent of the what that component internally does. A DAO layer for accessing DB and Data APIs can help you achieve this.
The dependency then your system will have is the DAO component. That can be injected with different ways. There are frameworks available to help you here or you can control the creation of objects and injections when needed with some combinations of factory, builder and singleton patterns. If it is single DB instance or LogFile you may also consider using Singleton to get the component.
Hope it helps!
In looking at SOLID and OOP the key is to analyze what it is your doing and separate out the various elements to make sure that they do not end up mixed together. If they do the code tends to become brittle and difficult to change.
Looking at the Account class several questions need to be answered when considering the SOLID principles. The first is what is the responsibility of the Account class? The Single Responsibility Principle would say there should be one and only one reason for it to change. So does the Account class exist to retrieve the relevant information from the DB or does it exist for some other purpose? If for some other purpose then it has multiple responsibilities and the code should be refactored so that the class has a single responsibility.
With OOP typically when retrieving data from a DB a repository class is used to retrieve information from the DB for an object. So in this case the code that is used to retrieve information from the DB would be extracted out form the Account class and put in this repository class: AccountRepository.
Dependency Inversion means that the Account class should not depend explicitly on the AccountRepository class, instead the Account class should depend on the abstraction. The abstraction would be an interface or abstract class with no implementation. In this case we could use an interface called IAccountRepository. Now the Account class could use either an IoC container or a factory class to get the repository instance while only having knowledge of IAccountRepository

Saving Entity does not update class-hierachy labels correctly

I have an abstract superclass Report and two Subclasses SimpleReport and ExtendedReport, which I want to persist in my database.
If a SimpleReport is created, it has the labels "Report" and "SimpleReport" attached to it, as expected.
A user can modify such a SimpleReport, which leads to the SimpleReport becoming an ExtendedReport.
If I now save this ExtendedReport (using the same ID as the SimpleReport, because I just want to update it) it has the labels "Report", "SimpleReport"and "ExtendedReport" attached to it.
IMHO the label "SimpleReport" should be removed on save. I`m currently deleting the wrong label using a cypher query after saving the updated report.
I´m asking if there is a better way to archive this, if may approach is wrong or if this is a bug in ogm?
The rules for labels are as follows:
any plain concrete class in the hierarchy generates a label by default
plain abstract class does not generate a label by default
plain interface does not generate a label by default
any class annotated with #NodeEntity or #NodeEntity(label="something") generates a label
empty or null labels must not be allowed
classes / hierarchies that are not to be persisted must be annotated with #Transient
Therefore if you remove abstract from your base class, or add a #NodeEntity annotation, you will see the results you expect.
Edit:
The OGM does not remove labels when a class is renamed. Any additional labels are left intact.
You can remove these manually using direct database access.
You can declare a field with the #Labels annotation to manage adding/removing additional labels from an entity.

Odoo 8 onchange on inherited models

I have a module that implements an onchange method on res.partner. If I create a new model that inherits res.partner, the onchange is not called. Is there a way to make the onchange general, so it's also called on inherited models?
Example:
class ResPartner(models.Model):
_inherit = 'res.partner'
#api.onchange('zip')
def _valid_zip(self):
print 'Validating zip...'
class ExtendedPartner(models.Model):
_name = 'extendedpartner'
_inherits = {'res.partner': 'partner_id'}
If I change the zip code on an extendedpartner, the onchange is not called.
You use delegation inheritance in the code above. Delegation inheritance does not work on model methods. It just simply delegates lookup of fields not found in current model to the "parent" model.
I think what you want is prototype inheritence:
class ExtendedPartner(models.Model):
_name = 'extendedpartner'
_inherit = 'res.partner'
The graphic below shows three types of inheritance available in Odoo:
You currently use the first one ("classic inheritance") in ResPartner (which inherits from res.partner) and the last one (delegation inheritance) in ExtendedPartner. I think the middle one (Prototype inheritance) would be more appropriate for ExtendedPartner. It basically works in a manner very similar to standard Python inheritance.
You can read more about different types of inheritance in the documentation (which is also the source of the image above).

What is the name of described pattern?

From high level perspective, the pattern makes possible to get polymorphic behavior without creating classes hierarchy.
It consists of 3 parts:
Data container classes, which have a certain field to be distinguished (e.g. User class with country field, or any class with tenant field in a multi-tenant saas project).
Context classes: these classes contain the data and logic which varies for different types of data containers (e.g. different logic for different tenants). There's a top-level Context class with all varying props set to default, and multiple derived classes which override defaults.
Data consumers/processors: these are business logic holders. They accept data container(s) and Context as parameters.
The 3rd-group citizen may have a method like:
Price getPrice(Price price, Context context) {
double VAT = context.getVAT()
return new Price(
transform(price.amount + price.amount * VAT, price.currency, context.currency),
context.currency
)
}
...
//and here's the call:
Context ctx = getContext(principal.getCountry())
Price priceInUserCurrency = priceCalculator(priceInUsd, ctx);
Here's a simplified UML diagram:
Basic usage: when we need to introduce a different specific behavior for small groups of objects of the same class,
we add a new method to Context with reasonable default value and implement the actual logic in concrete contexts. Then whereever we need to inject this piece of logic, we just call correspondent context method.
It looks like you are describing the Strategy Design Pattern.
What gives it away is that you can perform process() for both PersonProcessor and PaymentProcessor. Like this example below.
Each object knows how to handle their own case of the functionality.
To me the description of
makes possible to get polymorphic behavior without creating classes hierarchy
is more close to the concept of the State design pattern.
Because it allow an object to alter its behavior when its internal state changes. The object will appear to change its class. Further more also allows you to keep attributes of a former state even when the state changes afterwards.
About the inheritance part you can read more here.

OOP: class inheritance to add just one property vs constructor argument

I'm new to OOP and I'm in the following situation: I have something like a report "Engine" that is used for several reports, the only thing needed is the path of a config file.
I'll code in Python, but this is an agnostic question.So, I have the following two approaches
A) class ReportEngine is an abstract class that has everything needed BUT the path for the config file. This way you just have to instantiate the ReportX class
class ReportEngine(object):
...
class Report1(ReportEngine):
_config_path = '...'
class Report2(ReportEngine):
_config_path = '...'
report_1 = Report1()
B) class ReportEngine can be instantiated passing the config file path
class ReportEngine(object):
def __init__(self, config_path):
self._config_path = config_path
...
report_1 = ReportEngine(config_path="/files/...")
Which approach is the right one? In case it matters, the report object would be inserted in another class, using composition.
IMHO the A) approach is better if you need to implement report engines that are different from each other. If your reports are populated using different logic, follow this approach.
But if the only difference among your report engines is the _config_path i think that B) approach is the right one for you. Obviosly, this way you'll have a shared logic to build every report, regardless the report type.
Generally spoken, put everything which every Report has, in the superclass. Put specific things in the subclasses.
So in your case, put the _config_path in the superclass ReportEngine like in B) (since every Report has a _config_path), but instanciate specific Reports like in A), whereas every Report can set its own path.
I don't know Python, but did a quick search for the proper syntax for Python 3.0+, I hope it makes sense:
class ReportEngine(object):
def __init__(self, config_path):
self._config_path = config_path
def printPath(self):
print self._config_path
...
class Report1(ReportEngine):
def __init__(self):
super().__init__('/files/report1/...')
Then a
reportObj = Report1()
reportObj.printPath()
should print
'/files/report1/...'
Basically the main difference is that approach A is more flexible than B(not mutual change in one report does not influence other reports), while B is simpler and clearer (shows exactly where the difference is) but a change affecting one report type would require more work. If you are pretty sure the reports won't change in time - go with B, if you feel like the differences will not be common in the future - go with A.