2016-10-30 – Align project dictionary

Single Point of Reference

The script

.../_test/refactor_20161028.tcl

helps me to compare the outputs of geometry-Model implementations

  • bikeGeometry
  • bikeFacade

The project dictionary is referenced by

cleanup myGUI::modelAdapter::modelDICT

supplied by:

 [$modelContext getModelDictionary]

The current situation shows that parameters are held in owning objects (e.g. Scalar Fork Rake) and sometimes in Geometry context (e.g. Geometry Fork_Rake) too.

There is a need to have a single point of reference by dont modify GUI if possible. Therefore  I do this cleanup in

myGUI::modelAdapter::updateModel_...

and handle the related exceptions in

myGUI::modelAdapter::updateModel_Edit

To update these parameters the related exceptions are handle in

myGUI::modelAdapter::AdapterBikeFacade ->  set_Scalar

Decission

Parameters have to be supplied in their object context.
The geometry context is for exceptions only, if parameter does not belong to an object

myGUI::cvCustom::createRearMockup
myGUI::modelAdapter::updateModel_XY
myGUI::modelAdapter::AdapterBikeGeometry -> getModelDictionary

Example: ChainStay-Length

There is a length between BottomBracket and Rearwheel called ChainStay-Length. There is also a tube called Chainstay with a specic length. At the end this leads to the following result

  • Scalar / Geometry / ChainStay_Length
    • distance between BottomBracket and Rearwheel
  • Scalar / ChainStay / Length
    • length of the ChainStay Tube

 

Rename Parameters

... Polygon/ChainStay_RearMockup
    ... to Polygon/ChainStay_XY
... Position/ChainStay_RearMockup
    ... to Position/ChainStay_XY
... Polygon/ChainStay_XY
    ... to Profile/ChainStay_XY

 

2016-10-27 – rattleCAD 3.4.03.21

Addintional MVC-Model model_Info

The rattleCAD GUI needs a view to share values that does not belong to the geometry model. These non-geometry values are e.g. information about the current project.

  • Project Name
  • last update …

Therefore a new model-namespace is created and will be updated by the MVC-control.

myGUI::modelAdapter::updateModel_Info   ::myGUI::model::model_Info

A Middle-Man procedure found

see a definition here: https://sourcemaking.com/refactoring/smells/middle-man

The procedure

 myGUI::modelAdapter::updateModel

refered to

 myGUI::modelAdapter::get_projectDICT

In this case the procedure get_projectDICT will be removed and its call of

$modelContext getModelDictionary

will be transfered to updateModel.

Introduce a Debug-Option for later comparison

Target of the current refactoring steps is to get a situation to change between the current geometry-Model

bikeGeometry ... referenced by myGUI::modelAdapter::AdapterBikeGeometry

and the future model

bikeFacade ... referenced by myGUI::modelAdapter::AdapterBikeFacade

In this case I implement a feature in the GUI to export the content of the project dictionary (projectDICT). This will help me to compare a future Refactoring-Version of rattleCAD with this one. This feature will be removed from rattleCAD when the refactoring process is closed.

This representation of the project dictionary can be found:

Menu Bar: Info -> Info - Project

Extend the interface dictionary

The rattleCAD GUI requires information about the size of the bicycle frame to be displayed. Therefore a new key is introduced in the dictionary.

BoundingBox    Summary 
...

Found a central procedure for the model-namespaces

There was a procedure

myGUI::modelAdapter::coords_xy_index

called by sub-namespaces of

myGUI::model::model_X...

Therefore this procedure was moved to

myGUI::model::coords_xy_index

and all references to the previous procedure are referenced to the new on now.

2016-10-26 – A model for every view

Extract model_XY from model_XZ

My understanding of the MVC – pattern is to have specialised model for every view. Therefore I have to extract a model_XY from the model_XZ.

myGUI::modelAdapter::updateModel_XY
    ${targetNamespace}::setScalar  RearMockup  DiscDiameter

This parameter is referenced by

myGUI::cvCustom::create_BrakeDisc    
    set disc_DiameterDisc   [myGUI::model::model_XY::getScalar RearMockup DiscDiameter]

Found a property in the wrong context

DiscDiameter is a parameter of a brakedisc and in this case part of RearBrake. So this value should be handled in context of the Rearbrake (object-view) and not in  the RearMockup (function-view).

bikeGeometry::get_dictionaryGUIModel         
    dict set projDict   Scalar      RearBrake   DiscWidth       $::bikeGeometry::RearMockup(DiscWidth)      
    dict set projDict   Scalar      RearBrake   DiscDiameter    $::bikeGeometry::RearMockup(DiscDiameter)

This requires a name cleanup in the GUI and in the modelAdapter

RearMockup::DiscDiameter in the GUI

and

RearBrake::DiscDiameter in the modelAdapter

Dont touch the existing package: bikeGeometry

In a previous refactoring step i built the procedure to create the project dictionara in

bikeGeometry::get_dictionaryGUIModel

By doing a smaller update on this procedure and in a reflexion of this implementation I think it is a better decission to place this functionality in the class

myGUI::modelAdapter::AdapterBikeGeometry

This class is part of the refactoring strategy pattern. So I created

method getModelDictionary

and copied the full body from

proc bikeGeometry::get_dictionaryGUIModel

Handle different names in GUI and Model for the same

The problem

Every parameter update in the GUI is handled here:

myGUI::control::setValue

a switch-control forwards this call to

myGUI::modelAdapter::set_Config        
myGUI::modelAdapter::set_Component         
myGUI::modelAdapter::set_ListValue     
myGUI::modelAdapter::set_Scalar

The procedure

myGUI::modelAdapter::set_Scalar

handles an exception for

CrankSet:SpyderArmCount

and forwards this call to

set_Config CrankSet_SpyderArmCount

And this should be managed in

myGUI::modelAdapter::AdapterBikeGeometry

Option

A view on the current situation shows, that it is much easier to handle this definition in the GUI – without any later exception.

Found a property in the wrong context II

  • RearBrake::DiscDiameter
  • RearBrake::DiscWidth

This change is definitly handled here:

myGUI::modelAdapter::AdapterBikeGeometry -> set_Scalar        
        object  -> RearMockup
        key     -> DiscDiameter or DiscWidth
        switch -exact $object/$key {
             RearBrake/DiscDiameter -
             RearBrake/DiscWidth {
                     set object RearMockup
                 }
        }

rattleCAD – 3.4.03.15 – what has happened so far

I decided to document my thoughts and decissions of this refactoring project for other people at the beginning of October 2016. I started with a simple text file and sorry for this – in german.

There will be time in the future to translate this text in englisch.

Zusammenfassung – 2016-10-07

rattleCAD ist eine Open Source CAD-Software für das Design von Fahrradrahmen und in erweiterter Form auch für Fahrräder. Mit rattleCAD können maßstabsgetreue Zeichnungen vor allem für die Rahmenbauwerkstatt erstellt werden. Die mit rattleCAD erstellten Zeichnungen können zudem auch als Vorlagen für die farbliche Gestaltung (Lackierung) verwendet werden. Das Softwareprojekt startete 2007 mit der Absicht mich stärker in die Programmiersprache tclTk zu vertiefen.
Zusammen mit meinem Interesse für Fahrräder und speziel dem Bau von Fahrradrahmen hat sich auch Thema für dieses Vorhaben gefunden. Erste verwendbare Versionen von rattleCAD gibt es seit 2008.
rattleCAD wird seit 2010 auf sourceforge.net (https://sourceforge.net/projects/rattlecad/)  gehostet. Die Webseite von rattleCAD steht unter folgender URL zur Verfügung: http://rattlecad.sourceforge.net/

rattleCAD ist eine Desktop-Software und hat keine Anbindung an ein Webservice oder eine Datenbank. Die einzelnen Designs (Projekte) werden in einem definierten Arbeitsverzeichnis als xml-Dateien abgespeichert.

rattleCAD ist in der dynamischen Programmiersprache tclTK implementiert.
Seit der Version 8.6 ist dem TclOO package eine objektorienterte Erweiterung innerhalb von TclTk standardmäßig verfügbar (https://www.tcl.tk/software/tcltk/8.6.html).
Bis hierher wurden alle Funktionalitäten über funktionale Prozeduren implementiert.
Eine objektorientierte Herangehensweise gibt es in rattleCAD derzeit noch nicht.
Funktionale Gruppierungen wurden über namespaces realisiert.
Dazu gehört ein Modul, in dem alle geometrischen Berechnungen durchgeführt werden und ein zweites Modul welches das tcl-canvas modul für eine CAD-typische Verwendung erweitert.
Die Benutzeroberfläche und ihre Logik, sowie die Verwaltung der Projekt(Design)-Dateien sind in einem eigenen zentralen Modul enthalten und stark miteinander verwoben.
rattleCAD wurde ständig um neue Funktionen und Konfigurationsmöglichkeiten erweitert, was die Komplexität des Aufbaus der Software erhöhte und damite die Implementierung einer wartbaren Strukturierung bzw. Architektur erforderte.
Mit mehreren Versuchen in diese Richtung wurden zwar Teilerfolge erzielt, eine einfache Wartung und Erweiterung von rattleCAD mit neuen Funktionen ist aber nach wie vor nicht zufriedenstellend möglich.

In diesem Blog möchte ich mein Vorhaben dokumentieren, definitiv eine wartbare und modulare Architektur für die Software rattleCAD zu implementieren.
Konzepte, Muster, Best Practices aber auch Fehlinterpretationen, Irrtümer und Fallstricke werden sich durch diesen Blog ziehen.
Frei nach dem Motto “Softwarearchitektur mit einer Lizenz zum Scheitern” will ich genau diese Erfahrungen mit ihnen teilen.

Mit Stand 2016-10-07 wurden 82,015 unterschiedliche Versionen von rattleCAD von sourceforge heruntergeladen.

Download statistics

Architekturmaßnahmen

Aktuelle Herausforderungen:

getter und setter greifen von der Benutzeroberfläche bis zur Businesslogik (Geometrieberechung) durch, teilweise mit unterschiedlichsten Strategien
Das Datenformat, bzw. die Struktur der Projekt-Dateien ist sowohl mit der Geometrieberechung als auch mit der Benutzeroberfläche auf mittlerweile fast undurchschaubare Weise verdrahtet
Funktionserweiterungen können nicht separiert von der Benutzeroberfläche implementiert und getestet werden, bzw muss zum Testen auch berits die Benutzeroberfläche angepasst werden.

Rahmenbedingung:

In diesem Refactoring-Prozess werden keine neuen fachlichen Funktionen, Wünsche und Anforderungen umgesetzt.

Ansätze:

Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)

Was bisher schon geschah

Ganz ehrlich, ich habe mit dem refactoring Projekt schon im Main 2016, also vor 5 Monaten begonnen. Die Erfahrungen und Erkenntnisse versuche ich hier zumindest zusammenzufassen:

Mai-Juli 2016

das Paket, welches aus vielen einzelnen Parametern die Rechtecke, Kreise und Polygone berechnet, bzw. aus einem Katalog von SVG-Dateien die Komponenten für die Darstellung in der Benutzeroberfläche zur Verfügung stellt, ist prozedural aufgebaut.
Der Reihe nach wird zuerst die Geometrie des Fahrrades und damit zum großen Teil auch die Geometrie des Fahrradrahmens festgelegt. Im nächsten Schritt wird die Form und Position der einzelnen Rahmenrohre berechnet – dazu gehören auch die Rohrverschneidungen zwischen den einzelnen Rohren.
Die Verwaltung der Komponentenbibliothek geschieht großteils unabhängig auch in diesem Paket. Die Berechnung der Geometrie erfolt über verschiedene Interfaces (tcl-Ensemble) und unterstützt vier verschiedene Methoden die Geometrie festzulegen.

es geht noch schlimmer:

Es gibt Fahrradgabeln mit vorgegebener Geometrie.
Dazu gehören Carbongabeln oder Federgabeln, die direkt vom Hersteller bezogen werden können. Andererseits kann gewünschte Geometrie nur durch speziell vom Fahrrad-Rahmenbauer gefertigte Fahrradgabeln erreicht werden.
Dabei müssen z.B. unterschiedliche Gabelscheiden verwendet, oder die Gabelvorbiegung, bzw. der Radius mit dem Gabelscheiden gebogen werden, angepasst werden.
Für andere Komponenten, wie z.B. der Fahrradkurbel ist es erforderlich unterschiedlichste Modelle zumindest entsprechend darstellen zu können.

  • … die Darstellung von Fahrradgabeln ist an eine eigene Logik in der Benutzeroberfläche geknüpft.
  • … die Berechnung und Darstellung von gebogenen Rohren (auch Gabelscheiden) ist in mehreren Unterfunktionen versteckt und kaum nach nachzuvollziehen – läuft aber 🙂
  • … die Berechnung der Darstellung der Fahrradkurbel wird aus der Benutzeroberfläche gesteuert und bedient sich spezieller Funktionen aus der Geometrieberechnung.

Erster Ansatz, erste Frage?

wie ist das eigentlich mit der Objektorientierten Erweiterung in tcl/Tk seit der Version 8.6
Zuerst einmal: Die Dokumentation von tclTk ist für Experten bestimmt gut lesbar und man findet hier die verfügbaren Parameter für die einzelnen tcl-Kommandos.
Wenn Du dir aber eine neues tcl-Kommando aneignen willst, dann bist Du mit der offiziellen tcl-Dokumentation ziemlich verlassen.
Daher habe ich mich auf die Suche nach einer gut beschriebenen Anleitung gemacht und auch gefunden.
http://www.magicsplat.com/articles/oo.html (Ashok P. Nadkarni) … besten Dank!

Was habe ich zur Objektorientierung in tclTk gelernt:

  • Nicht alle von GoF vorgeschlagenen Patterns für die objektorientierte Programmierung sind auch für tclTk relevant.
  • tclTk ist wie auch python im Unterschied z.B. zu Java eine dynamische und keine statische Programmiersprache, bzw. muss nicht compiliert werden.
  • z.B: das Interface:
    tclTk benötigt an und für sich keine Interfaces.
    Das zeigt sich z.B. beim Strategie Pattern.
    Das Strategie Pattern ist in tcl/Tk auch ganz gut ohne dem Kontext-Objekt realisierbar.
    http://wiki.tcl.tk/44401
    oder sogar noch einfacher …

Benutzeroberfläche und MVC

Es zwickt in der Benutzeroberfläche :

Ich hatte ja erwähnt, dass die Benutzeroberfläche und ihre Logik, sowie die Verwaltung der Projekt(Design)-Dateien in einem eigenen zentralen Modul enthalten und stark miteinander verwoben sind.
Was spricht den dagegen, die Inhalte dieses Packages aufzuteilen.

Model – View – Controller vs. GUI – Logic – Persistance

Da fällt mir das Model-View-Controller Pattern ein und das Modell mit den Ebenen: Benutzeroberfläche – Buisness Logik – Datenhaltung.
Das ist doch nicht das gleiche, obwohl es ähnlich klingt.
Ich gehe mal davon aus, dass beide Muster jeweils etwas ganz anderes adressieren.
Dennoch bleibt die Frage, wie beide Pattern in einer Architektur Platz finden sollen.

Meine Erkenntnis dazu:

  • das MVC-Pattern kann sich in allen Paketen wiederfinden, die zur Laufzeit Daten halten müssen, sollen oder wollen.
  • Die View entspricht:
    • dem Interface bei einer untergeordneten Bibliothek.
    • dem UserInterface der Benutzeroberfläche beim Ebenenmodell.
  • und wo findet die Persistenz Platz?
    • ich denke mal, dass ist abhängig davon, wie viel Logik in der Ansteuerung der Persistenz erforderlich ist.
      • Ist die Anbindung straiht forward, dann kann die Persistenz direkt an das Model aus dem MVC angebunden sein. Das Model delegiert dann die Anweisung aus dem Controller an die Persistenz weiter.
      • Eine Anbindung der Persistenz an den Controller ermöglicht die direkte Steuerung der Persistenz durch den Kontroller, z.B bei der gleichzeitigen Anbindung einer Datenverwaltung
        mit einer Datenbank
        und einem Filesystem.
        Da macht es dann vielleicht Sinn, dass das Model sich nicht darum kümmern muss, ob die Daten aus einer verwalteten Datenbank oder einer einzelnen Projektdatei kommen.
  • … ruft nach einer Architekturentscheidung!

Model – View – Controller (MVC)

Warum hat mir keiner gesagt – vielleicht kann ich auch nicht lesen – dass das MVC-Pattern durch mehrere Views und mehrere Models dargestellt werden kann. Es sollte aber ein Controller ausreichen.
Im Fall von rattleCAD gibt es mehrere Views.

  • Jede einzelne Darstellung (nur Geometrie, nur der Fahrradrahmen mit Gabel, das gesamte Fahrrad) sind einzelne (physische) Views auf das Gesamt-“Model”.
  • Dann gibt es auf diesen vielen Views auch noch interaktive Bemaßungen.
    Die Events auf diesen Bemaßung öffnen Eingabemasken, in denen die einzelnen Parameter verändert werden können. Grafische Darstellungen sind hier eher nicht enthalten.

Aus einer anderen Perspektive betrachtet ergeben sich zwei unterschiedliche Views:

  • die Darstellung von Geometrie, Fahrradrahmen mit Gabel und das gesamte Fahrrad, sowie
  • die Darstellung der Eingabeparameter, welche die Darstellung von Geometrie, Fahrradrahmen mit Gabel und dem gesamten Fahrrad beeinflussen.

Das entspricht einer Aufteilung in:

  •     Eingabe-View (Input-Parameter) und
  •     Ausgabe-View (Output-Parameter).

… ruft nach einer Architekturentscheidung.

  • eine Edit-View mit dem dazugehörigen Edit-Model und Parametern,
  • eine Grafik-View mit dem dazugehörigen Grafik-Model und den Rechtecken, Polygonen und Kreisen,
  •  ein Controller für beide Views.

Eine mögliche Architekturoption  

Um die Übersichtlichkeit zu erhöhen kann zu einem späteren Zeitpunkt die View und das Model für die Darstellung der Kettenstreben noch einmal aus den obigen Views und Models extrahiert werden

Das Model im MVC:

Nach meiner Interpretation des MVC-Pattern kann das Model gar nichts – also fast gar nichts.  Ausser vielleicht einen aktuellen Snapshot der Business Logik, zu halten.

Architekturproblem

bislang hatte ich das Model ja als Business Logik verstanden, was nicht sein kann, wenn das Model nur einen Zustands-Snapshot halten kann und sonst kaum Funktionalitäten unterstützt.

Erster Ansatz

Erster Ansatz ist also in der Benutzeroberfläche das MVC-Pattern einzuführen.
Welche Views und welche Models habe ich schon zuvor vorgestellt.
Derzeit wird die View der Benutzeroberfläche einerseits über ein strukturiertes tcl-Dictionary mit Daten versorgt und andererseits wird aus der Benutzeroberfläche direkt auf getter der Business Logik zugegriffen.

Architekturentscheidung für die Benutzeroberfläche:

  • … alle für die Benutzeroberfläche relevanten Informationen aus der Business-Logik werden über ein strukturiertes tcl-Dictionary an das MVC-Model übergeben.
  • … damit wird der Durchgriff der getter-Aufrufe auf die Business-Logik abgestellt, bzw. greifen die getter-Aufrufe nur mehr auf die durch das tcl-Dictionary zur Verfügung gestellten Information zu.
  • … damit in den einzelnen Input-Views die Werte von Variablen gebunden werden können, werden die Informationen aus dem tcl-Dictionary in dem Datenmodell entsprechende array-Variablen umgewandelt.

Architekturmmaßnahme – 2016-10-09

  • … proc bikeGeometry::get_dictionaryGUIModel
    • … die Business-Logik stellt eine Funktion zur Verfügung, die alle für die GUI relevanten Informationen in einem strukturierten tcl-Dictionary zurückgibt.
    • … die bestehende Funktion (bikeGeometry::get_projectDICT), welche nur die Input-Parameter als tcl-Dictionary zurück gibt bleibt unverändert erhalten.
  • … proc myGUI::modelAdapter::updateModel_Edit
    • … hier mündet das bisherige tcl-Dictionary.
    • … da sollte sich also nicht allzu viel ändern
  • … proc myGUI::modelAdapter::updateModel_XZ
    • … hier greifen die getter direkt auf die Business-Logik
    • … ab jetzt zieht diese Prozedut die Werte aus dem strukturierten tcl-Dictionary
    • … am Endes dieses Refactoring Schrittes, sollen aus dem Model-Adapter Namespace keine getter mehr direkt auf die Business-Logik zugreifen können
    • … außer auf die Prozedur bikeGeometry::get_dictionaryGUIModel natürlich

… betrachten wir die Sache einmal statisch:

  • … es geht noch nicht darum, die Geometrie zu aktualisiern, nachdem ein einzelner Parameter verändert wurde.

alles der Reihe nach:

Commit – a

  • Revision:   4ee959c56be0e1bb390fe4e38610d8e14b4821bd
  • Message:    Refactoring-Maßnahme – 2016-10-01

Commit – b

  • Revision:   f814d68bb1865237279baa40dfc6af49cfa9eb6f
  • Message:    modelAdapter/_modelAdapter.tcl …

Erkenntnisse:

  • was man da so alles findet:
    • was hat denn die Zähnezahl-Definition der Kettenblätter zwischen den Kreisen, Polygonen und Rechtecken des Grafik-Models zu suchen …
      • … diese beiden Funktionen sollten im Namespace modelAdapter nicht mehr verfügbar sein:
        • get_BoundingBox
        • get_paramComponent
      • … bisher wurden diese Funktionen direct aus dem Geometrie-Paket importiert:
        • namespace import ::bikeGeometry::get_BoundingBox
        • namespace import ::bikeGeometry::get_paramComponent
        • namespace import ::bikeGeometry::get_TubeMiterDICT

Benutzeranforderung – 2016-10-09

so nebenbei eine Anfrage aus China:

How to translate rattleCAD into other language?

  • das betrifft die GUI
  • soweit ich das recherchiert habe gibt es in tcl msgcat.
  • Mal schauen, was das macht?

Architekturentscheidung:

  • msgcat
  • Die Umsetzung erfolgt erst, wenn die Benutzeroberfläche sauber über den Controller vom modelAdapter getrennt wurde!

Architekturmaßnahme – 2016-10-08

get_BoundingBox

  • myGUI::modelAdapter::get_BoundingBox

Die Procedure bikeGeometry::get_BoundingBox wird derzeit noch aus der Benutzer-oberfläche aufgerufen, was nach aktueller Architekturfestlegung ja nicht sein.
das entsprechende Ergebnis wird daher ab jetzt mit dem tcl-Dictionary mit ausgeliefert.

  • … bisherige Referenz: bikeGeometry::get_BoundingBox  Summary_Size
  • … neu: [dict get $_modelDict BoundingBox  Summary]

get_TubeMiterDICT

  • myGUI::modelAdapter::get_TubeMiterDICT

Mit dieser Prozedur verhält es sich ähnlich:

  • … bisherige Referenz: bikeGeometry::get_TubeMiterDICT
  • … neu: [dict get $modelDICT TubeMiter]
  • Kommentar:
    • … die Ansicht mit den Rohrverschneidungen ist eine eigene View auf das gesamte Model.

Warum also nicht ein eigenes Model für diese View erzeugen?

  • z.B.: model_TubeMiter?

Aber belassen wir die Benutzeroberfläche derzeit bei einer Referenz auf myGUI::modelAdapter::get_TubeMiterDICT und erzeugen wir das entsprechende Model für die TubeMiter-View später, wenn die GUI zur gänze bereinigt wird.

Derzeit geht es darum, alle “import procedure …” aus modelAdapter zu entfernen.

Commit

  • Revision:   aac168496acd77c24e8e55c8ee083061581d7a9a
  • Message:    continue: refactor_20161008.tcl

Fehlermeldung – 2016-10-11

… wieder mal so nebenbei:

https://sourceforge.net/p/rattlecad/tickets/7/

I have designed a frame with fixed lug angles. 
It all appears to work out as I expected from my own simple tube length calculations. 
However, when I look at the Tube Mitre page, the angles stated for the TopTube / HeadTube and the TopTube / SeatTube are not correct. 
(The correct angle for the TopTube / Seat Tube is shown on the FrameDetails page as 79'.) 
The SeatTube is shown correctly on the Summary page as 71.37' to the horizontal. 
The TopTube is 7.63' to the horizontal. 
Therfore the included angle for the TopTube / SeatTube should be 71.37 + 7.63 = 79.00' but it is shown on the Tube Mitre page as being 63.74' (i.e. 71.37 - 7.63). 
Is this just an error in what is printed or an actual error in the Mitre calculation?
The same error occurs at the TopTube / HeadTube mitre: The included angle should be 102' but is marked as 117.25'.

Architekturentscheidung:

  • Liegt der Fehler jetzt nur in der in der Beschriftung in der View (GUI) oder doch in der Geometrie?
    • daher: den Verschneidungswinkel direkt aus der Berechnung über das tcl-Dictionary in die GUI transportieren und nicht extra wo anders berechnen.

Architekturmaßnahme – 2016-10-12

zurück zum Architekturproblem – refactor_20161008.tcl

get_paramComponent

  • myGUI::modelAdapter::get_paramComponent

Die erste Frage:

  • Mit welchen Parametern wird denn diese Prozedur aufgerufen?
  • das ist geklärt:
    1. # myGUI::modelAdapter::get_paramComponent ChainWheelDefinition
    2. # myGUI::modelAdapter::get_paramComponent ChainWheel 39 {1019.0787082983509 524.8875562218891} polyline __default__ 130
    3. # myGUI::modelAdapter::get_paramComponent ChainWheel 53 {1019.0787082983509 524.8875562218891} polyline __default__ 130
    4. # myGUI::modelAdapter::get_paramComponent CrankSpyder 130 {1019.0787082983509 524.8875562218891}
    5. # myGUI::modelAdapter::get_paramComponent ChainWheelBoltPosition 130 {1019.0787082983509 524.8875562218891}
    6. # myGUI::modelAdapter::get_paramComponent CrankArm 172.50 {1019.0787082983509 524.8875562218891}
      #
    7. # myGUI::modelAdapter::get_paramComponent ChainWheelDefinition
    8. # myGUI::modelAdapter::get_paramComponent ChainWheel 22 {1027.0933882829045 573.428895612708} polyline __default__ 60
    9. # myGUI::modelAdapter::get_paramComponent ChainWheel 32 {1027.0933882829045 573.428895612708} polyline __default__ 100
    10. # myGUI::modelAdapter::get_paramComponent ChainWheel 44 {1027.0933882829045 573.428895612708} polyline __default__ 100
    11. # myGUI::modelAdapter::get_paramComponent CrankSpyder 100 {1027.0933882829045 573.428895612708}
    12. # myGUI::modelAdapter::get_paramComponent ChainWheelBoltPosition 100 {1027.0933882829045 573.428895612708}
    13. # myGUI::modelAdapter::get_paramComponent CrankArm 175 {1027.0933882829045 573.428895612708}

Architekturentscheidung I

dafür muss das Geometrie-Package aktualisiert werden

  • neue Prozedur:  bikeGeometry::create_CrankCustom_XZ
    • neue array Variable: CustomCrank
  • neue Prozedur:  myGUI::modelAdapter::get_CustomCrankSetDICT
    • … das passt nicht ganz zu meinem festgelegten Design des MVC
    • … diese Umsetzung wird aber beim refactoring des geometrie-Pakets sowieso anders gelöst
      • dann werden alle Komponenten als tdom-Nodes (svg-Nodes) an die Benutzeroberfläche übertragen

Architekturentscheidung II

  • jetzt packts mich aber:
    • weg mit dieser Prozedur
    • dafür wird die Prozedur:  myGUI::modelAdapter::updateModel_XZ den Content des Dictionary übertragen …

Commit

  • Revision:   e68588208bf151e94ae7696c302984aba3922443
  • Message:    Refactoring-Maßnahme – 2016-10-14

Architekturmaßnahme – 2016-10-14

model_TubeMiter:

Aus den einzelnen Views soll es nur mehr Referenzen auf die jeweiligen Views geben.
Referenzen auf myGUI::modelAdapter … soll es nicht mehr geben

Architekturentscheidung

  • hier reicht fürs erste ein tcl-Dictionary

Commit

  • Revision: ba62fc8abc6b0055a7b2938ae76e69748138b002
  •  Message: refactor_20161008.tcl

Architekturmaßnahme – 2016-10-15

Alle Aufrufe aus modelAdapter in Richtung bikeGeometry dürfen nicht mehr direkt erfolgen. Dafür wurde bereits zu einem früheren Zeitpunkt ein Strategie-Objekt eingeführt.

Architekturentscheidung

Die Aufrufe sollen nun über den Strategie-Kontext:

  • $modelContext

erfolgen.

Aufrufkette über die einzelnen Klassen und Namespaces sieht wie folgt aus:

  1. Controller
  2. modelAdapter
  3. modelContext (Strategy-Object)
  4. AdapterObject (AdapterBikeGeometry)
  5. bikeGeometry

Commit

  • Revision:   54b961b40db2d4ca30aa9b207fbc585f4d3cf417
  • Message:
    • Refactoring-Maßnahme – 2016-10-15
    • procedure Chain:  Controller -> modelAdapter -> modelContext (Strategy-Object) -> AdapterObject (AdapterBikeGeometry) -> bikeGeometry (IF_…)

Architekturmaßnahme – 2016-10-15

die Aufrufkette konrollieren und dann die zweite Strategie (bikeFacade) implementieren (anpassen).

Architekturentscheidung

Dabei gilt wiederum vorerst keine neuen Funktionen zu implementieren und nur sicherzustellen, dass sich die beiden Strategien gleich verhalten.

Zuerst einmal ein commit, bevor wir die Bibliotheken von Kommentaren bereinigen

Commit

  • Revision:   1881671cbd08b6e573c4d4c3a329f6f1215e93e1
  • Message:    Refactoring-Maßnahme – 2016-10-15
    cleanup procedure references to myGUI::modelAdapter

Debugging -2016-10-16

Bereinigen der bikeGeometry Aufrufe über importierte Prozeduren aus bikeGeometry
Alle Prozedur-Importe bereinigen …

get_dictionaryGUIModel

Es gibt einen Fehler in:

  • proc bikeGeometry::get_dictionaryGUIModel
    • dict set projDict   TubeMiter   $key    baseDiameter    $HeadTube(DiameterTaperedBase)
    • die dazugehörige Prozesskette:
      • modelAdapter::
        1. open_ProjectFile
          1. $modelContext initDomainParameters                   -> bikeGeometry::get_domainParameters
          2. $modelContext updateProjectValues $persistenceDOM
            1. modelDOM [my updateModelDOM $persistDOM]
              1. bikeGeometry::set_newProject
                1. bikeGeometry::update_Geometry
        2. updateModel
          1. get_projectDICT
            1. modelContext getModelDictionary
      • bikeGeometry::
        • get_dictionaryGUIModel

und das war der Fehler:

  • proc bikeGeometry::get_dictionaryGUIModel
    • fail:   dict set projDict   TubeMiter   $key    baseDiameter    $HeadTube(DiameterTaperedBase)
    • ok:     dict set projDict   TubeMiter   $key    baseDiameter    $::bikeGeometry::HeadTube(DiameterTaperedBase)

Commit

  • Revision:   36059fb5ae8bc078de1721146a4f291c6c50ae1d
  • Message:
    • Refactoring-Maßnahme – 2016-10-15
    • cleanup procedure calls
    • cleanup procedures
    • debug bikeGeometry::get_dictionaryGUIModel

Debugging -2016-10-17

add_ConfigChainStay

ChainStay details did not update

  • myGUI::gui::add_ConfigChainStay

Commit

  • Revision:   1b4c9ec40832cffc62d948af60e91a6eaaf21136
  • Message:    refactor:
    • … centralize all procedures to
      • … myGUI::control::…
      • … myGUI::modelAdapter::……
    • refer bikeGoemetry via Strategy in
      • … myGUI::modelAdapter::ModelContext

Tag – 3.4.03.16

Debugging -2016-10-18

… ChainStay Details did not update correctly
… straight / bent / hidden

Commit

  • Revision:   cd7bc34af39c443ee21dc1305a71b8c22080cf53
  • Message:
    • Refactoring-Maßnahme – 2016-10-18
      • small cleanups in
        • model_XY.tcl
        • model_XZ.tcl

Debugging -2016-10-xx

frameJig selection failed

  • … read options from rattleCAD_init.xml instead of bikeGeometry
  • … update selection list for “Component” Tab on enter Tab
  • … windows title … myGUI::control::updateControl

Architekturentscheidung:

Beim Aufbau der Benutzeroberfläche sind Auswahlparameter aus dem Geometrie-Paket erforderlich. Da sollte vielleicht noch etwas getrennt werden (Auswahlparameter & projektDomain)

Das ist aber vorerst noch nicht das Thema. Jetzt geht es darum die Business Logik zu gliedern.

Image

rattleCAD – the software refactoring project

 

Current Situation and Challenge

rattleCAD is written in Tcl/Tk, a dynamic programming language.

The current stable Version of rattleCAD is 3.4.02.100. A zipped version of rattleCAD 3.4.02.100 can be downloaded here: https://sourceforge.net/projects/rattlecad/files/3.4.02/rattleCAD_3.4.02.100.zip/download.

The coresponding git repository is available here: https://sourceforge.net/p/rattlecad/git/ci/3.4.02.100/tree/.

After a integration of many features and without a mature concept for a system architecture it is necessary to introduce an architecture concept to maintain the software code and to make rattleCAD fit for the future and new features.