Difference between revisions of "Efforts/Package Restructuring/Modelling"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Rules of Thumb)
m (De-Composition)
Line 1: Line 1:
 
==De-Composition==
 
==De-Composition==
Looking at an installed OOo and its files, registry entries etc., we can see, that all these entities belong to one or multiple of the following categories, such that they provide or depend on it
+
Looking at an installed OOo and its files, registry entries etc., we can see, that all these entities belong to one or multiple of the following categories, such that they provide or depend on it.
# brand - this is everything somehow related to a specific product, such as StarOffice or OpenOffice.org,
+
;Brand: This is everything somehow related to a specific product, such as StarOffice or OpenOffice.org.
# Operating System - this is everything somehow related to a specific operating system as Solaris, MS Windows or Linux,
+
;Operating System: This is everything somehow related to a specific operating system as Solaris, MS Windows or Linux.
# Machine Architecture / interpreter - this is everything related to an (machine) interpreter, such as x86 or SPARC,
+
;Machine Architecture: This is everything related to a native (machine) interpreter, such as x86 or SPARC.
# localization - this is everything related to a human language, such as English or German,
+
;Localization: This is everything related to a human language, such as English or German.
# version - this is everything related to a particular version.
+
;Version: This is everything related to a particular version.
  
 
The consequences of this observation are, that entities unrelated to one or multiple categories, but shared by products differing in these categories, are identical and thus may be re-used for creating, changing or updating products respectively installed products.
 
The consequences of this observation are, that entities unrelated to one or multiple categories, but shared by products differing in these categories, are identical and thus may be re-used for creating, changing or updating products respectively installed products.
Line 12: Line 12:
 
* feature
 
* feature
 
as otherwise it would not be needed for any feature, thus it would not be needed at all. Certainly features may be related such that they require one another, even if this is not noticeable in the [[Terms/Product View|Product View]].
 
as otherwise it would not be needed for any feature, thus it would not be needed at all. Certainly features may be related such that they require one another, even if this is not noticeable in the [[Terms/Product View|Product View]].
 +
 +
Every product we define can be assembled out of parts (e.g. RPM packages), which are created along the above categories.
  
 
===One Feature in Two Languages===
 
===One Feature in Two Languages===
In the simplest case, we have exactly one package e.g. for the Writer:
+
In the simplest case, we have exactly one part for every product, e.g. for the Writer:
* '''writer.rpm'''
+
* The '''writer''' part.
This package may include all entities for the Writer for Linux x86, in English, using the OpenOffice.org brand.
+
This part may include all entities for the Writer for Linux x86, in English, applying the OpenOffice.org brand.
  
Later on, we would like to provide the Writer not only in English, but may be also in German:
+
Later on, we would like to provide the Writer not only in English, but may be also in German, which leads to the following parts:
* '''writer_en.rpm'''
+
* '''writer_en''' - The Writer in English.
* '''writer_de.rpm'''
+
* '''writer_de''' - The Writer in German.
Obviously we now need to take care of any redundancy in these packages. We can do so by
+
Obviously we now need to take care of any redundancy in these parts. We can do so by
 
* naming / placing this files differently, or  
 
* naming / placing this files differently, or  
 
* by sharing them.
 
* by sharing them.
  
For obvious reasons, that sharing approach is better, leading to the following packages:
+
For obvious reasons, that sharing approach is better, leading to the following parts:
* '''writer.rpm''' - this is everything bug the locale,
+
* '''writer''' - This is everything but the locale.
* '''writer_en.rpm''' - this is the English locale only,
+
* '''writer_en''' - This is the English locale only.
* '''writer_en.rpm''' - this is the German locale only.
+
* '''writer_en''' - This is the German locale only.
But wait, no we have another problem. What if the user only installs one of the packages? This would be an incomplete / inconsistent and useless installation.
+
But wait, no we have another problem. What if the user only installs one of the parts? This would be an incomplete / inconsistent and useless installation.
  
Package managers typically use dependencies and virtual packages (or provisions) to address this problem.  
+
On UNIX and alike platforms, parts are typically called packages. Package managers typically use dependencies and virtual packages (or provisions) to address the consistency problem. So, lets try to set the above parts into relationship using dependencies and provisions.
  
The Writer package needs at least one Writer locale package to be installed, to function correctly. So may want to model the dependencies as follows:
+
The '''writer''' ("all but the locale") part needs at least one writer locale part to be installed, to function correctly, but must on depend on any concrete locale. So we may want to model the dependencies and provisions as follows:
 
* '''writer''' depends on '''writer_lcl''', provides '''writer'''
 
* '''writer''' depends on '''writer_lcl''', provides '''writer'''
 
* '''writer_en''' depends on '''writer''', provides '''writer_en''', '''writer_lcl'''
 
* '''writer_en''' depends on '''writer''', provides '''writer_en''', '''writer_lcl'''
 
* '''writer_de''' depends on '''writer''', provides '''writer_de''', '''writer_lcl'''
 
* '''writer_de''' depends on '''writer''', provides '''writer_de''', '''writer_lcl'''
By now, we can only install one of the above packages, if we install a completing package, though we certainly can install all three packages.
+
By now, we can only install any of the above parts, if we install a completing part as well, though we certainly can install all three parts.
  
 
===Two Features/Two Layers===
 
===Two Features/Two Layers===
Line 44: Line 46:
 
* Calc.
 
* Calc.
  
As you may know, OOo has a [[Architecture|layered Architecture]], therefore thus providing these two features as
+
As you may know, OOo has a [[Architecture|layered Architecture]], therefore thus providing these two features as two parts:
* '''writer.rpm''',
+
* '''writer''' - The Writer product.
* '''calc.rpm'''
+
* '''calc''' - The Calc product.
 
leads to many same files to be installed twice. So, obviously we need again to take care of this redundancy. And again, we can do so by
 
leads to many same files to be installed twice. So, obviously we need again to take care of this redundancy. And again, we can do so by
 
* naming / placing this files differently, or
 
* naming / placing this files differently, or
 
* by sharing them.  
 
* by sharing them.  
  
For obvious reasons, that sharing approach is better, leading to the following packages
+
For obvious reasons, that sharing approach is better, leading to the following parts:
* '''writer.rpm''',
+
* '''writer''' - Everything needed for Writer, not being needed for Calc.
* '''calc.rpm''',
+
* '''calc''' - Everything needed for Calc, not being needed for Writer.
* '''basis.rpm'''
+
* '''basis''' - Everything needed for both, Calc and Writer.
 
Again, we now need to take care of completeness / consistency etc.
 
Again, we now need to take care of completeness / consistency etc.
  
 
So, lets define some dependencies:
 
So, lets define some dependencies:
* '''writer''' - depends on basis, provides feature, writer
+
* '''writer''' - depends on basis, provides '''writer'''
* '''calc''' - depends on basis, provides feature, calc
+
* '''calc''' - depends on basis, provides '''calc'''
* '''basis''' - optionally depends on feature, provides basis
+
* '''basis''' - depends on nothing, provides '''basis'''
Depending on the usefulness, we may want the basis to require at least one feature to be installed.
+
Now, the '''writer' part respectively the '''calc''' part can only if the '''basis''' part is going to be installed as well.
  
By now, we can only install a feature (writer or calc) if the basis is installed.
+
By now, we can only install a feature (Writer or Calc) in a complete way.
  
  
Line 70: Line 72:
  
 
Applying the above separation, we get
 
Applying the above separation, we get
* '''writer.rpm'''
+
* '''writer'''
* '''calc.rpm'''
+
* '''calc'''
* '''basis.rpm'''
+
* '''basis'''
* '''writer_en.rpm'''
+
* '''writer_en'''
* '''writer_de.rpm'''
+
* '''writer_de'''
* '''calc_en.rpm'''
+
* '''calc_en'''
* '''calc_de.rpm'''
+
* '''calc_de'''
* '''basis_en.rpm'''
+
* '''basis_en'''
* '''basis_de.rpm'''
+
* '''basis_de'''
  
 
So, what do the dependencies should now look like? By combining the above orthogonally we get
 
So, what do the dependencies should now look like? By combining the above orthogonally we get
Line 90: Line 92:
 
* '''basis_en''' depends on '''basis''', optionally on '''feature_en''', provides '''basis_lcl''', '''basis_en''',
 
* '''basis_en''' depends on '''basis''', optionally on '''feature_en''', provides '''basis_lcl''', '''basis_en''',
 
* '''basis_de''' depends on '''basis''', optionally on '''feature_de''', provides '''basis_lcl''', '''basis_de'''.
 
* '''basis_de''' depends on '''basis''', optionally on '''feature_de''', provides '''basis_lcl''', '''basis_de'''.
To ensure consistence among layers, we need to make feature locales (e.g. calc_en) dependent on the lower layer locale (e.g. basis_en).
+
To ensure consistence among layers, we need to make feature locales (e.g. calc_en) dependent on the lower layer locale (e.g. '''basis_en''').
  
Looking at it, we the get the following minimal and consistent installations:
+
Looking at it, we the get the following minimal (and consistent) installations:
 
# '''writer''', '''writer_en''', '''basis''', '''basis_en''', == Writer English
 
# '''writer''', '''writer_en''', '''basis''', '''basis_en''', == Writer English
 
# '''writer''', '''writer_de''', '''basis''', '''basis_de''', == Writer German
 
# '''writer''', '''writer_de''', '''basis''', '''basis_de''', == Writer German
Line 110: Line 112:
 
# 1+2+3+4: '''writer''', '''writer_en''', '''writer_de''', '''calc''', '''calc_en''', '''calc_de''', '''basis''', '''basis_en''', '''basis_de''' == Writer/Calc English/German
 
# 1+2+3+4: '''writer''', '''writer_en''', '''writer_de''', '''calc''', '''calc_en''', '''calc_de''', '''basis''', '''basis_en''', '''basis_de''' == Writer/Calc English/German
 
# 2+3+4: '''writer''', '''writer_de''', '''calc''', '''calc_en''', '''calc_de''', '''basis''', '''basis_en''', '''basis_de''' == Writer German, Calc English/German
 
# 2+3+4: '''writer''', '''writer_de''', '''calc''', '''calc_en''', '''calc_de''', '''basis''', '''basis_en''', '''basis_de''' == Writer German, Calc English/German
Note: Obviously we need to be able, to deal in our implementations with the fact, that different features may only be available in different locales. This is unavoidable, if we want to separate features. Or to phrase it differently, all consistent (depends, provides) sets of packages should be valid.
+
Note: Obviously we need to be able, to deal in our implementations with the fact, that different features may only be available in different locales. This is unavoidable, if we want to separate features. Or to phrase it differently, all consistent (depends, provides) sets of parts should be valid.
  
 
===Rules of Thumb===
 
===Rules of Thumb===
* A package may depend on lower layer packages.
+
* A part may depend on lower layer parts.
* A package may depend on more general packages (e.g. the writer_OOo__en package depends on the writer_OOo__ and writer___en packages)!
+
* A part may depend on more general parts (e.g. the '''writer_OOo__en''' part depends on the '''writer_OOo__''' and the '''writer___en''' parts)!
* A more specific package implies any more general packages (the writer_OOo__en package implies the writer___en package)!
+
* A more specific part implies any more general parts (e.g. the '''writer_OOo__en''' part implies the '''writer___en''' part)!
* A virtual package is more general than a concrete package.
+
* A virtual part is more general than a concrete part.
  
 
===Complex Example===
 
===Complex Example===

Revision as of 15:08, 23 January 2008

De-Composition

Looking at an installed OOo and its files, registry entries etc., we can see, that all these entities belong to one or multiple of the following categories, such that they provide or depend on it.

Brand
This is everything somehow related to a specific product, such as StarOffice or OpenOffice.org.
Operating System
This is everything somehow related to a specific operating system as Solaris, MS Windows or Linux.
Machine Architecture
This is everything related to a native (machine) interpreter, such as x86 or SPARC.
Localization
This is everything related to a human language, such as English or German.
Version
This is everything related to a particular version.

The consequences of this observation are, that entities unrelated to one or multiple categories, but shared by products differing in these categories, are identical and thus may be re-used for creating, changing or updating products respectively installed products.

Additionally every entity exactly belongs to one

  • feature

as otherwise it would not be needed for any feature, thus it would not be needed at all. Certainly features may be related such that they require one another, even if this is not noticeable in the Product View.

Every product we define can be assembled out of parts (e.g. RPM packages), which are created along the above categories.

One Feature in Two Languages

In the simplest case, we have exactly one part for every product, e.g. for the Writer:

  • The writer part.

This part may include all entities for the Writer for Linux x86, in English, applying the OpenOffice.org brand.

Later on, we would like to provide the Writer not only in English, but may be also in German, which leads to the following parts:

  • writer_en - The Writer in English.
  • writer_de - The Writer in German.

Obviously we now need to take care of any redundancy in these parts. We can do so by

  • naming / placing this files differently, or
  • by sharing them.

For obvious reasons, that sharing approach is better, leading to the following parts:

  • writer - This is everything but the locale.
  • writer_en - This is the English locale only.
  • writer_en - This is the German locale only.

But wait, no we have another problem. What if the user only installs one of the parts? This would be an incomplete / inconsistent and useless installation.

On UNIX and alike platforms, parts are typically called packages. Package managers typically use dependencies and virtual packages (or provisions) to address the consistency problem. So, lets try to set the above parts into relationship using dependencies and provisions.

The writer ("all but the locale") part needs at least one writer locale part to be installed, to function correctly, but must on depend on any concrete locale. So we may want to model the dependencies and provisions as follows:

  • writer depends on writer_lcl, provides writer
  • writer_en depends on writer, provides writer_en, writer_lcl
  • writer_de depends on writer, provides writer_de, writer_lcl

By now, we can only install any of the above parts, if we install a completing part as well, though we certainly can install all three parts.

Two Features/Two Layers

In the previous example, our only feature was the Writer. Lets now have two features, e.g.

  • Writer, and
  • Calc.

As you may know, OOo has a layered Architecture, therefore thus providing these two features as two parts:

  • writer - The Writer product.
  • calc - The Calc product.

leads to many same files to be installed twice. So, obviously we need again to take care of this redundancy. And again, we can do so by

  • naming / placing this files differently, or
  • by sharing them.

For obvious reasons, that sharing approach is better, leading to the following parts:

  • writer - Everything needed for Writer, not being needed for Calc.
  • calc - Everything needed for Calc, not being needed for Writer.
  • basis - Everything needed for both, Calc and Writer.

Again, we now need to take care of completeness / consistency etc.

So, lets define some dependencies:

  • writer - depends on basis, provides writer
  • calc - depends on basis, provides calc
  • basis - depends on nothing, provides basis

Now, the writer' part respectively the calc part can only if the basis part is going to be installed as well.

By now, we can only install a feature (Writer or Calc) in a complete way.


Two Features/Two Layers in Two Languages

So, lets see what happens, if we have two features, e.g. Writer and Calc, and two localizations, e.g. English and German.

Applying the above separation, we get

  • writer
  • calc
  • basis
  • writer_en
  • writer_de
  • calc_en
  • calc_de
  • basis_en
  • basis_de

So, what do the dependencies should now look like? By combining the above orthogonally we get

  • writer depends on writer_lcl, basis, provides writer, feature
  • calc depends on calc_lcl, basis, provides calc, feature
  • basis depends on basis_lcl, provides basis,
  • writer_en depends on writer, basis_en, provides writer_lcl, writer_en,
  • writer_de depends on writer, basis_de, provides writer_lcl, writer_de,
  • calc_en depends on calc, basis_en, provides calc_lcl, calc_en,
  • calc_de depends on calc, basis_de, provides calc_lcl, calc_de,
  • basis_en depends on basis, optionally on feature_en, provides basis_lcl, basis_en,
  • basis_de depends on basis, optionally on feature_de, provides basis_lcl, basis_de.

To ensure consistence among layers, we need to make feature locales (e.g. calc_en) dependent on the lower layer locale (e.g. basis_en).

Looking at it, we the get the following minimal (and consistent) installations:

  1. writer, writer_en, basis, basis_en, == Writer English
  2. writer, writer_de, basis, basis_de, == Writer German
  3. calc, calc_en, basis, basis_en, == Calc English
  4. calc, calc_de, basis, basis_de == Calc German

Which we can combine to:

  1. 1+2: writer, writer_en, writer_de, basis, basis_en, basis_de == Writer English/German,
  2. 1+3: writer, writer_en, calc, calc_en, basis, basis_en == Writer/Calc English
  3. 1+4: writer, writer_en, calc, calc_de, basis, basis_en, basis_de == Writer English / Calc German
  4. 2+3: writer, writer_de, calc, calc_en, basis, basis_de, basis_em == Writer German / Calc English
  5. 2+4: writer, writer_de, calc, calc_de, basis, basis_de == Writer/Calc German
  6. 3+4: calc, calc_en, calc_de, basis, basis_en, basis_de == Calc English/German
  7. 1+2+3: writer, writer_en, writer_de, calc, calc_en, basis, basis_en, basis_de == Writer English/German, Calc English
  8. 1+2+4: writer, writer_en, writer_de, calc, calc_de, basis, basis_en, basis_de == Writer English/German, Calc German
  9. 1+3+4: writer, writer_en, calc, calc_en, calc_de, basis, basis_en, basis_de == Writer English, Calc English/German
  10. 1+2+3+4: writer, writer_en, writer_de, calc, calc_en, calc_de, basis, basis_en, basis_de == Writer/Calc English/German
  11. 2+3+4: writer, writer_de, calc, calc_en, calc_de, basis, basis_en, basis_de == Writer German, Calc English/German

Note: Obviously we need to be able, to deal in our implementations with the fact, that different features may only be available in different locales. This is unavoidable, if we want to separate features. Or to phrase it differently, all consistent (depends, provides) sets of parts should be valid.

Rules of Thumb

  • A part may depend on lower layer parts.
  • A part may depend on more general parts (e.g. the writer_OOo__en part depends on the writer_OOo__ and the writer___en parts)!
  • A more specific part implies any more general parts (e.g. the writer_OOo__en part implies the writer___en part)!
  • A virtual part is more general than a concrete part.

Complex Example

For example, splitting the writer along the above "dimensions" (brand, OS, Architecture, locale, rest), we get

  • writer.rpm - this is everything of the writer, which does not provide anything a long the dimensions,
  • writer___en.rpm - containing all English localization content not depending on anything else,
  • writer_OOo__en.rpm - containing all English localization content of the OOo brand,
  • writer___de.rpm - containing all German localization content not depending on anything else,
  • writer_OOo__de.rpm - containing all German localization content of the OOo brand,
  • writer__linux_.rpm - containing all Linux specific stuff,

All product entities (files, registry entries, short cuts etc.) get packaged according their dimensions.

We now need to see, how we can express dependencies. Looking at the above example, we see, that the writer package (writer.rpm) certainly needs some of the other packages, to become usable. It obviously depends on the following

  • writer localization,
  • writer brand,
  • writer platform specific files,

or expressed more general writer.rpm depends on

  • writer_brnd__lcl
  • writer___lcl
  • writer__linux_

While the specific packages do provide

  • writer - writer
  • writer___en - writer___en, writer___lcl
  • writer_OOo__en - writer_brnd__lcl, writer_OOo__lcl, writer_brnd__en, writer_OOo__en,
  • writer___de - writer___de, writer___lcl,
  • wrtier_OOo__de - writer_brnd__lcl, writer_OOo__lcl, writer_brnd__de, writer_OOo__de

Packages with less dimensions are more general than packages with more dimensions, which are more specific.

Composition

Model products by setting them into

  • inheritance, respectively
  • instantiation (template)

relationship.

Inheritance

Inheritance models a "is a" relationship. In practice that would mean, that a StarOffice 8 update 7 is an OOo 2.2.1 (respectively its basis) adding something.

Instantiation

Example

Template Product OOo-Standard {
  Features: writer, calc, impress, draw
}

Abstract Product OOo2.4 {
  Name: OOo 2.4
  Code-Base: SRC680m236
  Implements: OOo-Standard

}

Product OOo2.4-ISO : OOo2.4 {
  Name: OpenOffice 2.4
  Format: ISO-750
  Platform: Linux-x86, Windows-x86, Mac OS X x86
}

Product OOo2.4-download-linux-x86 : OOo2.4 {
  Name: OpenOffice 2.4
  Format: donwload
  Platform: Linux-x86
}

Product OOo2.4-download-windows-x86 : OOo2.4 {
  Name: OpenOffice 2.4
  Format: donwload
  Platform: windows-x86
}

Abstract Product FooOffice3u4 : OOo2.4 {
  Name: FooOffice 3 update 4
  Features: foo-templates, foo-fonts, foo-brand
  Updates: < FooOffice 3 u 4
}

Product FooOOo3u4-ISO : FooOffice3u4 {
  Name: FooOffice 3 update 4 ISO
  Format: ISO-750
  Platform: Linux-x86, Solaris-x86, Solaris-Sparc, Windows-x86, Mac OS X x86
}

Product FooOffice3u4-donwload : FooOffice3u4{
  Name: FooOffice 3 update 4 ISO
  Format: download
  Platform: Linux-x86
}

Abstract Product : OOo_2.4 {
  Name: BarOffice 5 update 6
  Features: bar-templates, bar-fonts, bar-brand
  Updates: < BarOffice 5 u 6
}

Tooling

  • Comparison of Installation Sets
  • Check for conflicts
  • Creation of Installation Sets
  • Visualization
  • Deliverable Table
  • Module Table

Product Pipeline

Product Pipeline.jpg

The modelling by inheritance and instantiation needs to lead to deliverables which are re-usable during productization and after installation, ideally leading to zero redundancy in case of the installation of many variants (OOo and derivatives).

Taking a look at how packages (like RPM) are typically organized, we can see, that the intermediate deliverables should express their needs and offers in terms of

  • dependencies against a (virtual) package, as well as by listing the
  • provisions.

Naming Schema

A name schema reflecting this approach may look like this:

<feature>_<brnd>_<pltfrm>_<lcl>
writer_foo_linux_en

or generalized

 <feature>[_<dimension>]*

Packages independent of a particular dimension just leave this position empty.

Personal tools