notes

Notes are reusable content pages that encapsulate a policy, recommendation, or tip. A Note knows what content pages it has been applied to (and vice-versa). Notes help promote the Don't Repeat Yourself (DRY Principle) principle.

Notes are especially used here to record Webel's guidelines for UML modelling of reverse-engineered PHP for Drupal and the tutorial module OOE = Object Oriented Examples = One Of Each, as applies to using PEAR PHP UML imported into MagicDraw UML via XMI2.

[note] Q: Why aren't you making (more) use of database functionality of the core Drupal7 entities, "fieldable" entities, and the Entity API in your graphical UML for PHP demos ? A: Because I have not yet reversed those aspects of Drupal7 into graphical UML.

Applies to

In order to demonstrate the Webel recipe for PHP the database interactions for the demo modules on this site are made deliberately very simple. This is in part to simplify the representation of those parts of the module involving the database interaction, but largely because I have not yet reverse engineered the Drupal7 core entity/field system of the Entity API system into the Webel UML recipe for UML.

[note] If a code element is not yet reversed from PHP into a design layer UML element it may be represented in the analysis layer by a pure «!analysis» @Interface or a pure «!analysis» @Component (but NOT yet a «!wrapper» @Component).

Type:

Applies to

Note however that an element that has not yet been reversed from PHP into a UML "design(ed)" model element must NOT yet be represented by a «!wrapper» @Component, because there is no "design(ed)" element to wrap.

[note] Graphical UML moral: if the focus/overview diagram of a Class or Package/Model is overly complex DO NOT be discouraged, it is a hint that your system needs refactoring ! Begin by creating "scenario" sub-diagrams that each identify a narrative.

Type:

Applies to

[note] A guiding principle is that a form-related include bridge file should use one and one only helper/builder class with delegation from each of the form _build(), _ajax(), _validate() and _submit() functions of the bridge include file.

Type:

Applies to

[note] Create "bridge" include files that mediate between the classic Drupal7 hooks of the .module file and OO Class libraries that progressively encapsulate define() data and functions as Class attributes, constants, and Interface/Class methods

Type:

Applies to

[note] PHP 'use' statements in a PHP include file or class/interface file are modelled using the UML Usage «use» relationship (from a «!wrapper» @Component corresponding to the file that has the 'use' statement to a «!wrapper» @Component for a Class/Interface).

Type:

Applies to

[note] UML PackageImport «import» relationships are used to model analysis dependencies between Packages/Models. They do not correspond to a PHP artefact, but do imply that a contained element has a matching PHP file with a PHP 'use' to a file in the target.

Type:

Applies to

[note] UML ElementImport «import» relationships are used to model Drupal7 'file' includes for hook_menu() and hook_theme()

Type:

Applies to

[note] UML Package/Model symbols can be useful for graphically organising the symbols of the elements they own but they are fragile against change of ownership. They are essential for Package/Model overview diagrams but not always advised in class diagrams.

Type:

Applies to

[note] It is not always necessary to show the Package/Model symbol in a "focus" class diagram or implementation diagram; one can rely on the indication of ownership of each element (usually displayed under the element's name on its symbol).

Type:

Applies to

[note] MagicDraw UML has a powerful model validation engine that indicates invalid configurations in diagrams (such as indications of invalid Package/Model ownership of child elements).

Applies to

[note] Even in dedicated "focus" class diagrams showing too many Dependency arrow symbols between operations and/or attributes can lead to clutter; sometimes it is useful to create Dependency relationships in the UML model but not show them in all diagrams

Type:

Applies to

[note] In Package/Model overview diagrams it can sometimes be useful to show the operations compartment, as long as it does not lead to clutter; in MagicDraw UML one can choose to show operations without the full operation signature.

Type:

Applies to

[note] IMPORTANT: PEAR:PHP_UML reverses the PHP 'implements' as a UML Realization from a "design(ed)" Class to an Interface; in the Webel recipe this is represented in the analysis domain as an InterfaceRealization from a wrapper @Component to an @Interface !

Type:

Applies to

[note] The «!render» stereotype on an operation or method indicates that it returns a Drupal render array portion for a page (or form).

Applies to

[note] The stereotype «!by» is just shorthand for «!encapsulated by»

Applies to

[note] Convention: Once you are used to the idea that each design(ed) UML Class element is being reversed from a source Artifact you may leave it off such diagrams. (It can always be traced to a source anyway using the «manifest» relationship.)

Applies to

[note] Webel: «!issue» analysis Components can be used to help track issues and bugs graphically via Dependency and Component Realization relationships. Use the name of the component to hold a verbose description of the issue !

Type:

Applies to

[note] Webel: in MagicDraw UML if you move a suitable element symbol IN A DIAGRAM into a Component symbol IN A DIAGRAM that "outer" Component won't "steal ownership", so it can be used as a «!logical» grouping container.

Applies to

[note] Webel: «!logical» Components used for convenient "parasitic" graphical groupings may be shown "unwrapped" in diagrams that reveal the Component Realizations to the logically (and otherwise graphically) grouped participants.

Applies to

[note] TIP: In MagicDraw UML one can include external image resources (such as screenshots) in UML diagrams !

Applies to

[note] In MagicDraw UML, depending on how you manipulate the elements, Components do not automatically "steal ownership" of the elements they graphically contain. In the Webel recipe «!logical» Components are used for convenient "parasitic" graphical groupings.

Applies to

[note] In MagicDraw UML and the best UML tools one can choose to exclude certain information about selected attributes (such as default values) and operations (such as operation signature) in their respective compartments to leave a minimal hint of their roles.

Applies to

[note] Using Dependency arrows between operations in class diagrams can be useful in dedicated mini-diagrams, but it quickly leads to clutter in large overview diagrams.

Type:

Applies to

[note] DRY: Golden Rule: never use the module machine name (or the human-friendly module display name) in a naked string in code, always obtain them via the Common::module constant.

Type:

Applies to

[note] DIRTY TRICK for reverse-engineering "flat" Drupal7-style .module and .inc PHP files into methods of Webel-style wrapper @Components

Type:

Applies to

Because PEAR:PHP_UML can only reverse engineer PHP Class and Interface files (not "flat" Drupal7-style .module or

[note] Q: Why do some diagrams and models contain so many static public methods and basically fully static "Helper" and "Builder" Classes with only a few instantiated objects ? A: It's an interim step for progressive migration to classes and objects.

Applies to

Detailed answer: Because this is part of the migration process from a non-OO Drupal7 project to a more OO one using the Webel process. As a first step, flat functions from Drupal7-style include files are encapsulated - along with relevant data constants - into static public class methods. This is just UML-friendly enough to enable the 1st stage of reverse engineering into graphical UML with PEAR:PHP_UML !

[note] An analysis @Component may replace weakly specific PHP 'object' parameter types with stronger placeholder analysis @Interfaces in its operation signatures.

Type:

Applies to

[note] In MagicDraw UML and the best UML tools one can choose to show only selected attributes and selected operations in their respective compartments.

Applies to

[note] Focus diagrams do not always show every relationship between all elements; usually only the main relationships from the focus element to neighbours are shown. Relationships between its operators and neighbours and between neighbours are not always shown

Applies to

[note] PEAR: PHP_UML does not seem to catch reference parameters like &$form_state in method signatures

Applies to

[note] PEAR:PHP_UML does not seem to see Interface const declarations.

Applies to

[note] The «!page» stereotype on an operation or method indicates that it returns a Drupal render array for a page.

Applies to

[note] A utility or helper Class that will never be swapped or substituted for in its client Class need not implement an Interface; its public methods serve as the interface.

Type:

Applies to

[note] In the best UML tools like MagicDraw UML one can show the structure compartment of Classes and Components and their composite structure as Property symbols in "hybrid" class or implementation diagrams.

Type:

Applies to

[note] A «!new» stereotype assigned to a Usage from a source Classifier (or a creation method) means an instance of the target Classifier is created directly (instead of fetching an Interface product via a factory) and assigned to a «!chosen» Interface var.

Applies to

[note] TIP: If you run out of room sometimes it's handy to draw hierarchies "upside down"

Applies to

[note] When drawing hierarchies of Interfaces it is sometimes easier if you open up the empty attributes compartment of the Interface symbol so that it shows as a rectangle, not just as the Interface circle icon/symbol (but not operations in overview diagrams)

Applies to

[note] In this diagram the UML containment operator is used between Package/Model symbols and their contained elements, rather than graphical containment.

Applies to

[note] MagicDraw UML: it is often handy to open the (usually empty) attributes compartment of an Interface symbol so that it displays as a rectangle and can be more easily targeted by relationships than the Interface icon. This DOESN'T mean it has no operations!

Applies to

[note] UML: just because an operation or attribute is not shown in a compartment of a Class or Component symbol (in a given diagram) does not mean it is not present in the underlying UML model !

Type:

Applies to

[note] OOE: a get() method always returns a Drupal array or string; it means you are leaving the purely object-oriented OOE world and entering the Drupal world of structured PHP arrays enforced only by convention and documentation.

Type:

By a get() method is not meant a property getter, it means literally 'get()' with no arguments and only 3 letters in the method name ! The get() methods are how OOE talks to Drupal core, they assemble everything to return a valid Drupal array (or string).

The UML signature is always one of:

«!drupal» get() : array
«!drupal» get() : string
«!drupal» get() : string|array

[note] OOE: The only class that is ever allowed to extend AbstractProject and implement IProject directly is the CurrentPosts demo, which uses an "old" non-OO style page callback to a function in the .module file ! It is a counter-demo !

Type:

Applies to

[note] OOE: If you want to use a project you should ALWAYS extend AbstractControlledProject (not AbstractProject) so that you have an OO page controller !

Type:

Applies to

The only exception is the CurrentPosts example, which deliberately extends only AbstractProject and uses an explicit page callback function in the .module file to show you the "old" non-OO way of doing it.

[note] Webel/OOE: delegate methods (such as hook and handler implementations) of an OOE bridge Class SHOULD use lower_case_underscore_separated() [not camelCase()]. All other Classes and Interfaces should use camelCase() for operations/methods (as per Drupal8).

Type:

Applies to

A Webel module bridge for Drupal consists of a special Drupal .module file (say 'ooe.module') and a Webel Drupal-PHP-bridge implementation Class such as OoeBridge for the main OOE = Object Oriented Examples = One Of Each tutorial module.

This enables one to (code modules for Drupal7 in a truly, purely object-oriented PHP and (best of all) one can then also model the module system in graphical Unified Modeling Language (UML) !

[note] In the UML-friendly Webel PHP Interface names are always prefixed with capital 'I' thus ICamelCase ! This has many advantages for graphical UML modelling and IDE based prompting (and saves typing) This is knowingly NOT the Drupal coding standard !

Type:

Applies to
This policy is immutable, to work with the OOE = Object Oriented Examples = One Of Each tutorial module and reap all the advantages one must use this naming convention. It is NOT a Drupal7 convention, it is a Webel OOE convention !

[note] It is strongly recommended that implementation Classes use full private property vars with protected lazy creation/configuration methods (rather than just local variables) ! It has many advantages and is UML friendly ! (TIP: use code template expansion.)

Applies to

Please when working with OOE = Object Oriented Examples = One Of Each code like this, with explicit private Interface variables that are "lazily" (as needed) assigned implementations and configured in protected lazy creation/configuration methods. And please only then access the Interfaces via their matching lazy methods:

[note] If you are just writing a Class that demonstrates the usage of an Interface via a given implementation the demo Class does not necessarily need a dedicated Interface. It should however still offer interaction via Interfaces.

Applies to

[note] The «!new» stereotype on a Usage from a Factory class (or a method of a Factory class, or both) to a concrete implementation Class for an Interface product indicates that the Factory (by default) uses that implementation Class as the product.

Applies to

If the factory is subclassed and a creation method is overridden to use a different implementation class, an additional «!new» Usage may be used from the subclass (or the overridden subclass method).


Usages from methods/operations indicate clearly exactly which implementation Class is used for which Interface product, however there are certain graphical disadvantages:

[note] The «!product» stereotype on a Property variable typed by an Interface indicates that a concrete implementation Class is supplied for it by a factory.

Applies to

From OoeBridge:

[note] The «!default» stereotype on a Usage from a composite structure compartment Property symbol to a Class indicates it is assigned as the default (usually in a lazy creator of the same name as the Property) by the managing class.

Applies to

From OoeBridge:

[note] The «!chosen» stereotype on a Property variable typed by an Interface indicates that a default concrete implementation Class is chosen for it by the managing Class (not via a factory), usually in a lazy creator method of the same name as the Property.

Applies to

From OoeBridge:

[note] MagicDraw UML: does not permit drawing a Dependency (or Usage) from a Property name symbol or line end of an Association, makes it hard to indicate a chosen implementation Class. Workaround: draw from Property symbol in composite structure compartment.

Type:

Applies to

Problems applies at least to MagicDraw UML 17.1.

Case: one has a Property variable typed by an Interface in a managing Class and one wishes to indicate (when a factory is not used) which implementation Class is assigned to the variable (say on lazy instantiation).

IMPORTANT: this matter is only of concern when a managing class has knowledge of concrete implementation Classes assigned to its Interface variables (such as for a demonstration class choosing demonstration items), it does not apply when factories are used !

[note] Not sure yet best way to handle Enum in PHP for Drupal, for the meantime using Class with consts (promotes valid input, but not type checked like proper Enum)

Type:

Applies to

[note] Issue: Not sure yet how to document const in PHP compatible with Drupal and PEAR PHP UML.

Type:

Applies to

[note] PEAR: PHP UML: Can't handle Drupal documentation style for mixed return types like /** @return string|array */

Applies to

[note] Often (in the Webel analysis wrapper recipe) when there is a Usage from an analysis @Interface to another analysis @Interface, there will be a matching Association (reference, shared, or composition) from the wrapper analysis @Component

Type:

Applies to

[note] The Webel «!wrapper» @Component strategy enables associative representation of array properties that are not caught by PEAR's PHP UML when applied to Drupal-style array documentation.

Applies to

[note] In the Webel recipe for modelling PHP all associative UML modelling is performed with «!wrapper» @Components in special, completely separate «!analysis» packages

Type:

Applies to

[note] An «!analysis» @Interface in a class diagram may show a UML Usage (requires) to another referenced «!analysis» @Interface type. This can be displayed as a UML "Usage socket" symbol.

Type:

Applies to

[note] An analysis @Interface class diagram may show a "circuit" formed by an analysis @Interface/@Component pair and a design Interface/Class pair with Generalizations on opposing sides, and the «!Trace» and the «!encapsulated by» on opposing sides.

Applies to

[note] PEAR: PHP UML: Can't handle Drupal documentation style for returned typed arrays; Example: '@param IMenuItem[] $menuItems' gives no return type (not even void). This can be fixed in the «!analysis» @Interface and «!wrapper» @Component !

Applies to

[note] The arrow of a ComponentRealization points from a reverse-engineered PHP design(ed) Class to its Webel «!wrapper» (analysis) @Component. However, the analysis @Component owns the relationship ! The design Packages are not changed by the analysis !

Type:

Applies to

[note] MagicDraw UML: you can (you may) show Association end elements within a Component symbol (instead of outside); this can be very useful for graphically organising supplier elements to make the Component look like a self-contained machine. It is valid UML!

Type:

Applies to

[note] Analysis «!local» variables usually represent variables within a method that hold a specific implementation Component, they do not correspond to Class property variables ($this->property) and do not appear in the reverse-engineered PHP design(ed) classes.

Applies to

[note] During analysis modelling, do not include (or expose the contents of) any reverse-engineered design(ed) PHP Class in any analysis diagram EXCEPT the analysis @Interface class diagram of its matching «!analysis» @Interface showing the «!Trace» to design.

Type:

Applies to

[note] Analysis «!wrapper» @Components may extend (have Generalization relationships) to other «!wrapper» @Components (only, not to PHP design Classes); Similarly, «!analysis» @Interfaces may only extend other «!analysis» @Interfaces.

Type:

Applies to

[note] Webel: If any of the «!analysis» @Interfaces or «!wrapper» @Components have Association relationships to any design(ed) PHP Class or Interface elements, the analysis wrapper UML model is broken !

Type:

Applies to

[note] In the Webel UML analysis recipe for PHP, the ComponentRealization between a design(ed) PHP Class and its «!wrapper» @Component (pointing at the «!wrapper» @Component) should (at least) be stereotyped by «!encapsulated by» (even if it is not displayed).

Type:

Applies to

[note] Analysis @Interfaces and wrapper @Components must have operations/methods with parameter types and return types that DO NOT use the pseudo-type 'mixed' (as generated by PEAR PHP UML and imported by MagicDraw UML); only design elements may use 'mixed'.

Type:

Applies to

[note] Analysis @Interfaces and wrapper @Components must have operations/methods with method parameter types and return types that (preferrably) refer to an @Interfaces or concrete implementation @Components. They may also use 'void', PHP scalars, and array.

Type:

Applies to

[note] Webel: No modelling is ever performed directly on reverse-engineered design classes, and no design Package may ever by changed during analysis ! However, an analysis element may carry, for example, a Dependency or Usage to a design element.

Type:

This is necessary because the XMI generated by PEAR PHP UML does not integrate with the MagicDraw UML code engineering sets system, one can however import the XMI (into the design packages).

It is best not to put a single element, not a diagram, no relationships, nothing, that changes the design(ed) packages ! Instead, you use analysis diagrams, under the '@' analysis package root, to pull in design elements where appropriate.

[note] The «!analysis» Packages "observe" the reverse-engineered PHP design(ed) Interfaces and Classes

Type:

Applies to

[note] In Webel's recipe for UML modelling of reverse engineered PHP, the analysis is always, without exception, performed on «!analysis» @Interfaces and «!wrapper» @Components - where «!wrapper» is a sub-stereotype of «!analysis».

Type:

Applies to

[note] Analysis «!wrapper» @Components may have Associations to «!analysis» @Interfaces (preferrably injected or obtained from a factory) or other «!wrapper» @Components (if creating say default implementations).

Type:

Applies to

[note] The entire Webel «!wrapper» @Components analysis of the One Of Each (OOE) project is under a special top-level the «!analysis» @ Package.

Type:

Applies to

This simple policy is extremely important and effective for graphical Unified Modeling Language (UML) models of reverse engineered PHP using PEAR PHP UML. Advantages include:

- Clear separation of the analysis packages/models from reverse-engineered PHP design class representations (imported by MagicDraw UML from the reverse-engineered PHP UML XMI file).

- Clear indication that an Element is an analysis element (even when no stereotype applies).

[note] Analysis diagrams may pull in design(ed) elements (but not vice-versa).

Type:

Applies to

This is because in my current combination of MagicDraw UML with PEAR PHP UML the only way I have found to consistently include coding changes to the PHP classes in the MD UML model is to Import From > Another Project .. where the other project is the reverse engineered XMI2 file generated by PHP UML.

[note] Analysis «!wrapper» @Components and «!analysis» @Interfaces are always prefixed with '@' (in addition to the design class name), except: when a new refactoring ?Class or ?Interface is suggested it is prefixed with '?' (as in "begs the question").

Type:

Applies to

This simple policy is extremely important and effective for graphical Unified Modeling Language (UML) models of reverse engineered PHP using PEAR PHP UML. Advantages include: -

- Easy prompting for analysis elements in a UML tool without any risk of hitting reverse-engineered PHP design(ed) elements (Classes/Interfaces/Artifacts).

- Makes it clear in all diagrams which elements are analysis and which are reverse-engineered design(ed) elements, no matter whether the owner/context or stereotypes are shown.

[note] MagicDraw UML: you can drag a design Class symbol into a «!wrapper» @Component and create a suitable ComponentRealization without changing the ownership (packaging) of the design Class !

Type:

Applies to

[note] The wrapped design Classes are shown here for illustration only; usually it's the job of the «!wrapper» @Component's own linked implementation diagram to show which matching reverse engineered PHP design(ed) Class it wraps.

Type:

Applies to

[note] A «!wrapper» @Component MUST ALWAYS participate in a ComponentRealization with the matching reverse-engineered design(ed) PHP Class of the same name (without the @). The arrow of the ComponentRealization MUST appear to point at the «!wrapper» @Component.

Type:

Applies to

[note] OOE «analysis» @Interfaces (within the @ «analysis» Packages) must always «Trace» to a reverse engineered PHP design Interface (from within PHP UML "design(ed)" Packages) !

Type:

Applies to