1 / 39

Architecture-Driven Modernization of legacy C++ Components Ira D. Baxter, Michael Mehlich, Robert L. Akers Semantic Desi

Architecture-Driven Modernization of legacy C++ Components Ira D. Baxter, Michael Mehlich, Robert L. Akers Semantic Designs, Inc. 12636 Research Blvd, Suite C214 Austin, Texas 78759 idbaxter@semdesigns.com January, 2005 Overview Reengineering Massive Software requires Massive tools

oshin
Télécharger la présentation

Architecture-Driven Modernization of legacy C++ Components Ira D. Baxter, Michael Mehlich, Robert L. Akers Semantic Desi

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Architecture-Driven Modernization of legacy C++ Components Ira D. Baxter, Michael Mehlich, Robert L. Akers Semantic Designs, Inc. 12636 Research Blvd, Suite C214 Austin, Texas 78759 idbaxter@semdesigns.com January, 2005

  2. Overview • Reengineering Massive Software requires Massive tools • DMS® Software Reengineering Toolkit • Program Transformations as a key technology • Real Transformation rules • Massive Transformations • Migrating application software to new languages • Architectural Restructuring of Legacy Applications

  3. An Egyptian Legacy System 30 years to build 10,000 slaves How can we reengineer this?

  4. … Modernized Requires massive reengineering  tools Tools change your definition of architecture!

  5. Software Change ToolsNeed Infrastructure Too • To build a conventional application • Define specifications • Implement application • Use Operating System to provide standard services • File/Terminal I/O, CPU management, Security • To build an automated software change tool • Define specifications • Implement tool • Use …?… to provide standard services • Lexing/Parsing • Life after Parsing: Tree/Symbol table building, Analysis management, Transformation, PrettyPrinting • This talk • DMS: a practical change-tool infrastructure • BMT: An application of DMS to legacy distributed system in C++

  6. DMS® Software Reengineering ToolkitAutomated, custom code analysis and enhancement • Enables wide variety of SE tasks to be automated • Source Formatters, Hyperlinked Source Browsers • Source code Obfuscation • Documentation and metrics extraction • Preprocessor conditional simplification • Test Coverage and Profiling tools • Clone Detection and removal • XML DTD compilation • DSL code generation: Factory Automation • Migration • Research tasks • Model-driven weaving (U. Alabama) • Architectural extraction/Multi-model consistency checking (JPL) • HTML cleanup (IRST/Italy) Commercial Applications ICSE 2004:DMS: Program Transformationsfor Practical Scalable Software Evolution

  7. Transformation Systems Stepwise Semiautomatic Conversion of Specs to Code Spec Rqmts Prog Transform Engine fS fG ti Transformsaka “rules” like-term combination factoring distributive law unity multiplier remove parentheses t1 t2 tk-2 tk-1 tk ... f1 fG fS fk-1 fk (x-1)y+2y (xy-1y)+2y xy-y+2y xy+y (x+1)y

  8. Expertise == Number of Rules • Mathematics • Novice (9th grade algebra): x+0  x • Amateur (HS Senior): sin^2(x)+cos^2(x)  1 • Journeyman: (Frosh Calculus) integrals • Craftsman: (B.S. Math) Linear Algebra, Group Theory • Expert: (Ph.D. Mathematics) Category Theory, Topology, … • Transformation Engines • Toy: several rules • Useful: 50 rules (simplification/optimization) • Powerful: 250 rules (testing, code generation) • Indispensable: 2000 rules (massive program translation)

  9. … + "how to use rules" knowledge= MetaProgram • Mathematics • Solve for variable, Simplification (novice) • Simultaneous equations • Change of domain (expert) • … • Transformation Engines • Tactic • Apply rules till exhaustion (useful) • Strategy • Metaprograms (sophisticated)

  10. Software Reengineering Toolkit Infrastruture Symbol Table Compiler Data Structures Source Files (Domain Notation) Revised Source Files Lexer/Parser Declarations Unparser Compiler Structures Attribute Evaluator Analyzers Parser Definition Debug Text Transforms Domain Transformation Viewer Definition Engine Reader Procedures Sequencing; Transforms Language Descriptions Unparser definitions Analysis + Transform Descriptions = Tool definition Languages available: C++, Java, C#, C, Ada, Fortran, XML, HTML, SQL, JavaScript, PHP, Verilog, VHDL, custom

  11. Fundamental Issue: Scale • Engineering hard but straightforward • Ugly details: C preprocessors, etc. • Legacy Systems are huge • MSLOC + tens of thousands of files • Careful design of hypergraph to conserve space • Arbitrary languages => robust parsing technology • Need for domain agility: fast domain/dialect definition • Use domain notations to define knowledge • Applications use multiple languages • reasoning and transforms must work with mix • Reasoning/Analysis costs • "Incremental" Knowledge capture => domains • Computers do Symbolic computation slowly => Parallel foundations • Future: RuleSet compilers

  12. Knowledge Capture:DMS Parts Domain • Syntax (domain notation) • External Form (what you can say: string or graphical) • Internal Form (How DMS stores it) • Parser (how to convert external form to internal form) • PrettyPrinter (how to display the Internal Form) • Semantics (what the domain means) • Analyzers (how to analyze in the domain) • Optimizations (how to optimize in the domain) • Refinements (how to transform one domain to another

  13. Rule Specification Language default base domain Cpp; rule unit_quotient(e: expression) = “\e / \e” -> “1” if is_integral(e) /\ no_side_effects(e). ruleset simplify = { unit_quotient, plus_0, times_1, equal_self } + boolean_simplify. pattern getter_method(t: typespecifier, attribute: identifier) = “\t \get\(\attribute\) { return \attribute; }” with side-effect add_new_symbol(get(attribute)). Domain Name Quoted domain Syntax Semantic condition Meta function

  14. Refinement transformsJovial to C default source domain Jovial; default target domain C; private rule refine_data_reference_dereference_NAME (n1:identifier@C,n2:identifier@C) :data_reference->expression = "\n1\:NAME @ \n2\:NAME" -> "\n2->\n1". private rule refine_for_loop_letter_2 (lc:identifier@C,f1:expression@C, f2:expression@C,s:statement@C) :statement->statement = "FOR \lc\:loop_control : \f1\:formula BY \f2\:formula; \s\:statement“ -> "{ int \lc = (\f1); for(;;\lc += (\f2)) { \s } }“ if is_letter_identifier(lc). Domain Name Pattern Variables Source Domain Syntax Target Domain Syntax

  15. Refinement Transforms in ActionJovial to C JOVIAL Source: FOR i: j*3 BY 2 ; x@mydata = x@mydata+I; Translated C Result: { int i = j*3; for (;;i+=2) { mydata->x = mydata->x + i} } Typically lots of small transforms for full translation ~2500 rules to translate full Jovial

  16. A More Complex ExampleJovial to C START TABLE TFP'D'TWRDET (1:109,12:37); BEGIN % Main status boolean % ITEM TFP'G'TWRDET STATUS (V(YES),V(NO)); END TYPE TFP'D'TWRDET'TABLE TABLE (7:23) W 3; BEGIN ITEM TFP'ITM S 3 POS(0,3); "cube axis" END %begin proc% PROC PROC'A(c1) S; BEGIN ITEM match'count U 6; %an item% ITEM c1 C 5; "parameter value" ITEM c2 C 7; IF c1 <= c2 AND c2 > c1; match'count = UBOUND(TFP'D'TWRDET,0) + UBOUND(TFP'D'TWRDET'TABLE,0); "result off by 1 so adjust" match'count = match'count+1; BEGIN match'count=match'count/2; PROC'A = match'count; % return answer % END "cleanup and exit"; END "end proc" TERM #include "jovial.h" static struct { /* Main status boolean */ enum { V(yes$OF$tfp_g_twrdet$OF$tfp_d_twrdet), V(no$OF$tfp_g_twrdet$OF$tfp_d_twrdet) } tfp_g_twrdet _size_as_word; } tfp_d_twrdet[109][26]; typedef union { W(3); struct { POS(0, 3) S(3) tfp_itm:4 _align_to_bit; /* cube axis */ }; } tfp_d_twrdet_table[17]; static S proc_a(C(5) c1);/* begin proc */ static S proc_a(C(5) c1) { __typeof__(proc_a(c1)) RESULT(proc_a); _main: { U(6) match_count; C(7) c2; if (CHARACTER_COMPARE(BYTE_CONVERT(C(7), c1, 7), c2) <= 0 && CHARACTER_COMPARE(c2, BYTE_CONVERT(C(7), c1, 7)) > 0) match_count = UBOUND(tfp_d_twrdet, 2, 0) + 16; /* result off by 1 so adjust */ match_count = (S(6))match_count + 1; { match_count = (S(6))match_count / 2; RESULT(proc_a) = (S(6))match_count; /* return answer */ } /* cleanup and exit */ ; } _return: return RESULT(proc_a); } /* end proc */ packed tables with bit offsets, typedefs, functions, string operations, comments Equivalent C (used with hand-coded macro library)

  17. NaturalLanguageTellers ElectronicFundsTransfer PunchPressControl FighterAircraftNavigation Specific Applications NaturalLanguageParsing MoneyManagement Real Time Control Global Navigation Generic Applications refines to Algebra GraphicalUser Interface Data Structures Parallelism / Distributed Computation Computer Science refines to refines to optimize OOP Logic Functional Data Flow Execution Model refines to optimize analyze to C Prolog Haskell Occam Target Execution opti mize MDA in the large:A Domain Interconnection Network

  18. Reengineering parser ANSI, MSVC6 C++, GCC3 Expansion-controllable preprocessor Builds compact AST, capturing Templates Comments Preprocessor directives Source file position Multiple files C++ scoped name resolution Full symbol table with types Expression types Conditional definitions Accessible from transforms Updateable from transforms Procedural transforms Direct AST manipulation Cross-file transformations Metaprogramming Source-to-source transforms Using C++ syntax Attribute evaluation Arbitrary analyzers Callable as rule conditions Prettyprinting regenerates Comments Whitespace #includes Can generate source browser C++ Refactoring Support

  19. Apply Program Transformation System • DMS operating on C++ • Using Custom Transforms to Revise Architecture • Restructure components into new form ! implement BMT, a practical conversion tool How to Modernize Real Code? Converting Legacy Components into Modern Components Avionics Application Legacy Bold Stroke 6000 components 3M SLOC C++ 1990s Distributed Architecture Modern Bold Stroke 6000 components 3M SLOC C++ MoBIES architecture “PRiSm” ?

  20. BMT: Rearchitecting distributedAvionics Software • Boeing BoldStroke: 6000 C++ modules • Avionics Mission Software (~~ 1M SLOC/plane) • Product Line: Used in several different military airframes • Distributed across multiple CPUs in airplane • Architected 1992 • as components with monolithic APIs • use custom distributed data protocols • Goal: Rearchitect into more reusable parts • Restructure APIs into conceptually clean groups • Move towards CORBA/RT component model • Change communication to use ORBs • Use automated tool

  21. facet1 receptacle1 C o m p o n e n t facet2 receptacleK facetN event sink1 event source1 event sinkM CORBADistributed Component Architecture method calls C o m p o n e n t X C o m p o n e n t A C o m p o n e n t Z Facet: offered service Receptacle: used service Event Sink: trigger Event Source: signal C o m p o n e n t B C o m p o n e n t Y events runtime wiring

  22. Bold Stroke Component Conversion Configuration methods Configuration Facet Class Distribution Facet Class Locking methods DMS xform Distribution methods Locking Facet Class Application1 Facet Class Application methods Component (Data) Class Application2 Facet Class Component Data Component Representative Class Legacy Bold Stroke Component (single C++ class and support classes) PRiSm Bold Stroke Component: Always an Interface (Not shown: any needed support classes) ASPECT: Engineer Specified Facetization

  23. FACET (Aspect) SpecificationDescribes desired component structure COMPONENT GPS FACET GPS_State FACET GPS_UpdateState EVENTSINK GPS_changed PORT EXECUTION Basic PORT EVAPORATION Basic PORT PERSISTANCE Basic PORT LOCK Basic END COMPONENT FACET GPS_State inherit none bool Get_Status () const; bool IsInitDataRequested () const; int GetDuration () const; bool FailedStatus () const; const result_type& Requested () const; result_type Achieved () const; bool ResourceOK () const; END FACET COMPONENT GPS FACET GPS_State FACET GPS_UpdateState EVENTSINK GPS_changed PORT EXECUTION Basic PORT EVAPORATION Basic PORT PERSISTANCE Basic PORT LOCK Basic END COMPONENT FACET GPS_UpdateState void Set_GPS(); void Move_GPS (); END FACET FACET GPS_UpdateState void Set_GPS(); void Move_GPS (); END FACET PORT EXECUTION Basic (… EVENT SINK) // Standard methods for execution need not be mentioned. void Push (const Events& myEventSet); END FACET DELETED Basic // signatures in this section are removed PushSupplier_ptr GetEventSupplierReference (); END FACET PERSISTANCE PORT Basic // Standard methods for execution need not be mentioned. void MapState (Elements& GPS_Elements); void SetPersistenceAdapter (PersistenceAdapter& anAdapterPtr); ACE_Lock& GetLock () const; END FACET PORT LOCK Basic // The lock facet is accessible to the public. ACE_Lock& GetLock () const; END FACET EVENTSINK GPS_change_changed // Optional… only needed if standard push convention not used void Update_GPS(Events& event); END EVENTSINK • A DMS domain • Used to lookup methods • Uses C++ overload name resolution

  24. Several kinds of subtasks • Creation of new classes with predetermined structure • facets, wrappers, EquivalentInterface • Drawn from facet specifications and the legacy code • Event sinks and receptacles • From legacy code fragments recognized by idiom • Some related legacy code to be deleted • Modification of reference access paths in multiple moved methods • in legacy classes • in code relocated to facets and wrappers • Extension and modification of name space • to support new and relocated code

  25. Doing all this requires… • Parsing and name and type resolution of C++ code • preprocessing directives • processed (for semantic analysis) • preserved (as modified source code) • Parsing facet specifications • For targeted component and all of component's neighbors • Looking up facet method signatures in application code • Constructive patterns • for new classes and their constituents • Recognizer patterns • for recognizing idiomatic forms • Rewrite rules • for access path modification • Prettyprinters to display re-engineered component • Sequencing code to wire these pieces together

  26. PRiSm Component Sketch class a_component { facet1_type* facet1; receptacle1_type *receptacle1; … data declarations… }; • Central class • Facet • Receptacle class a_facet { private: a_component* component; component= … ; // somebody does this public: component_data* GetComponent() { return component; } t1method1() { … component->data… } }; class a_receptable { private: a_component* component; Nfacet_references int=0; facet_type target_facet[]; public: component* GetComponent() { return component; } facet_type GetSingletonFacet() { return target_facet[0]; } void AddFacet(facet_type facet) { target_facet[Nfacet_references++] =facet; } };

  27. PRiSm idiom as DMS pattern ComponentEI_impldothFile(ComponentName,ApplicationFacets) pattern ApplicationFacets(members: identifier_list)=tag. pattern GenericComponentEI_Impldoth(ComponentName:identifier, ApplicationFacets: tag): compilation_unit = “\ComponentNameComment\(\ComponentName\) #pragma once #ifndef \ComponentHFileName\(\ComponentName\) #define \ComponentHFileName\(\ComponentName\) #include "GenericComponent.h" \ApplicationFacetClassDeclarations\(\ApplicationFacets\) class \ComponentEI_ImplName\(\ComponentName\): public GenericComponent { public: // Called during first pass of the configurator \ComponentEI_ImplName\(\ComponentName\) (const UUIdentifier& id, // every created component has an object id GenericComponentParameters& parameters, // and some initialization parameters \FacetPointerArgumentDeclarations\(\ApplicationFacets\) // One for every facet: );   ~\ComponentEI_ImplName\(\ComponentName\)();   virtual bool IsNil () const;   virtual const UUIdentifier& GetId () const; \ProvideFacetDeclarations\(\ApplicationFacets\) protected: // Protected Declarations... none needed for MOBIES components private: \ComponentEI_ImplName\(\ComponentName\)(); // parameterless constructor; NEVER CALLED \ComponentName(const \ComponentName &right); // copy constructor; DO NOT USE UUIdentifier id_; \\ component instance name \FacetPtrMemberDeclarations\(\ApplicationFacets\) }; #endif”. The detailed truth Used to generate PRiSm component instance

  28. Rough procedural metaprogram For each faceted component specification Create central class (instantiate pattern) Populate with application data For each specified facet Create class for facet Add facet data member, getter to central class Add central class member, getter to facet class Copy methods for facet into facet class Modify all legacy class members accesses: “\name ->\which_facet_class\(\name\)->\name” For each specified receptable Create class for receptacle Add receptable data member, getter to central class Add central class member, getter to receptacle class Process other PRiSm APIs…

  29. FACETspecification COMPONENT GPS FACET GPS_This FACET GPS_Other END COMPONENT FACET GPS_This "GetStatus"; "ThisFacetStatus"; END FACET FACET GPS_Other "OtherFacetStatus"; END FACET Not explicitly specifiedwhat to do BMT Toy Example: Spec Example "legacy code" unsigned int GlobalStatus(); class GPS { public: unsigned int GetStatus(); unsigned int ThisFacetStatus(); unsigned int OtherFacetStatus(); unsigned int ComponentStatus(); unsigned int status_; }; unsigned int GPS::GetStatus() { return status_; }; unsigned int GPS::ThisFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::OtherFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; }

  30. BMT Toy Example: Component Example "legacy code" Resulting Component.h, ...cpp unsigned int GlobalStatus(); class GPS { public: unsigned int GetStatus(); unsigned int ThisFacetStatus(); unsigned int OtherFacetStatus(); unsigned int ComponentStatus(); unsigned int status_; }; unsigned int GPS::GetStatus() { return status_; }; unsigned int GPS::ThisFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::OtherFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } /*component.h*/ #include "BM__Component/BM__Component.h" class GPS_Component : public BM__Component { public: GPS_Component(UUIdentifier componentId, class GPS_ThisFacet *GPS_ThisFacetPtr, class GPS_OtherFacet *GPS_OtherFacetPtr); ~GPS_Component(); unsigned int ComponentStatus(); class GPS_ThisFacet *GetGPS_ThisFacetPtr(); class GPS_OtherFacet *GetGPS_OtherFacetPtr(); const UUIdentifier &GetId() const; bool IsNil() const; private: UUIdentifier componentId_; class GPS_ThisFacet *GPS_ThisFacetPtr_; class GPS_OtherFacet *GPS_OtherFacetPtr_; }; /*component.cpp*/ GPS_Component::GPS_Component( UUIdentifier componentId, class GPS_ThisFacet *GPS_ThisFacetPtr, class GPS_OtherFacet *GPS_OtherFacetPtr) : componentId_(componentId), GPS_ThisFacetPtr_(GPS_ThisFacetPtr), GPS_OtherFacetPtr_(GPS_OtherFacetPtr) {} GPS_Component::~GPS_Component() { } unsigned int GPS_Component::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = GPS_ThisFacetPtr_ ->ThisFacetStatus(); unsigned int tmp4 = GPS_OtherFacetPtr_ ->OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } class GPS_ThisFacet *GPS_Component::GetGPS_ThisFacetPtr() { return GPS_ThisFacetPtr_; } class GPS_OtherFacet *GPS_Component::GetGPS_OtherFacetPtr() { return GPS_OtherFacetPtr_; } const UUIdentifier &GPS_Component::GetId() const { return componentId_; } bool GPS_Component::IsNil() const { return (componentId_ == UUIdentifier::GetNullId()); } FACETspecification COMPONENT GPS FACET GPS_This FACET GPS_Other END COMPONENT FACET GPS_This "GetStatus"; "ThisFacetStatus"; END FACET FACET GPS_Other "OtherFacetStatus"; END FACET unsigned int GPS_Component::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = GPS_ThisFacetPtr_ ->ThisFacetStatus(); unsigned int tmp4 = GPS_OtherFacetPtr_ ->OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } Not explicitly specifiedwhat to do unsigned int GPS::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; }

  31. BMT Toy Example: Facet1 Example "legacy code" Resulting ThisFacet.h, …cpp unsigned int GlobalStatus(); class GPS { public: unsigned int GetStatus(); unsigned int ThisFacetStatus(); unsigned int OtherFacetStatus(); unsigned int ComponentStatus(); unsigned int status_; }; unsigned int GPS::GetStatus() { return status_; }; unsigned int GPS::ThisFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::OtherFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } /*facet.h*/ #include "BM__Component/BM__Facet.h" class GPS_ThisFacet : public BM__Facet { public: GPS_ThisFacet(const UUIdentifier &facetId, class GPS_Component *const component); ~GPS_ThisFacet(); unsigned int GetStatus(); unsigned int ThisFacetStatus(); const UUIdentifier &GetId() const; bool IsNil() const; private: UUIdentifier facetId_; class GPS_Component *component_; }; /*facet.cpp*/ GPS_ThisFacet::GPS_ThisFacet( const UUIdentifier &facetId, class GPS_Component *const component) : facetId_(facetId), component_(component) { } GPS_ThisFacet::~GPS_ThisFacet() {} unsigned int GPS_ThisFacet::GetStatus() { return component_->status_; } unsigned int GPS_ThisFacet::ThisFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = component_ ->ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = component_ ->GetGPS_OtherFacetPtr()->OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } const UUIdentifier &GPS_ThisFacet::GetId() const { return facetId_; } bool GPS_ThisFacet::IsNil() const { return (facetId_ == UIdentifier::GetNullId()); } FACETspecification COMPONENT GPS FACET GPS_This FACET GPS_Other END COMPONENT FACET GPS_This "GetStatus"; "ThisFacetStatus"; END FACET FACET GPS_Other "OtherFacetStatus"; END FACET Not explicitly specifiedwhat to do

  32. BMT Toy Example: Facet2 Example "legacy code" Resulting OtherFacet.h, ...cpp unsigned int GlobalStatus(); class GPS { public: unsigned int GetStatus(); unsigned int ThisFacetStatus(); unsigned int OtherFacetStatus(); unsigned int ComponentStatus(); unsigned int status_; }; unsigned int GPS::GetStatus() { return status_; }; unsigned int GPS::ThisFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::OtherFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } unsigned int GPS::ComponentStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = ComponentStatus(); unsigned int tmp3 = ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } /*facet.h*/ #include "BM__Component/BM__Facet.h" class GPS_OtherFacet : public BM__Facet { public: GPS_OtherFacet(const UUIdentifier &facetId, class GPS_Component *const component); ~GPS_OtherFacet(); unsigned int OtherFacetStatus(); const UUIdentifier &GetId() const; bool IsNil() const; private: UUIdentifier facetId_; class GPS_Component *component_; }; /*facet.cpp*/ GPS_OtherFacet::GPS_OtherFacet( const UUIdentifier &facetId, class GPS_Component *const component) : facetId_(facetId), component_(component) { } GPS_OtherFacet::~GPS_OtherFacet() { } unsigned int GPS_OtherFacet::OtherFacetStatus() { unsigned int tmp1 = GlobalStatus(); unsigned int tmp2 = component_ ->ComponentStatus(); unsigned int tmp3 = component_ ->GetGPS_ThisFacetPtr()->ThisFacetStatus(); unsigned int tmp4 = OtherFacetStatus(); return tmp1 | tmp2 | tmp3 | tmp4; } const UUIdentifier &GPS_OtherFacet::GetId() const { return facetId_; } bool GPS_OtherFacet::IsNil() const { return (facetId_ == UUIdentifier::GetNullId()); } FACETspecification COMPONENT GPS FACET GPS_This FACET GPS_Other END COMPONENT FACET GPS_This "GetStatus"; "ThisFacetStatus"; END FACET FACET GPS_Other "OtherFacetStatus"; END FACET Not explicitly specifiedwhat to do

  33. BMT Status • DMS Definitions • Domains: C++, FACET • C++ parser, name resolver, prettyprinter • Reads 150K SLOC of MSVC6 include files • FACET parser, attribute evaluator to extract facets • Rules/Patterns: ~400 • organized in sets ("access path update", …) • Metaprogram • Exhaustive application of rule sets • 11K SLOC PARLANSE code • Applied to multiple Boeing components • Currently in experimental evaluation on small set • Does >>90% of hand-work required

  34. (Boeing Report)Project A Code Conversionfrom ‘legacy BoldStroke component model’ to ‘PRiSm component model’ October 11, 2004

  35. Tasks to complete “wrapperized PRiSm” solution after executing BMT • General • After BMT executes, review the updated software files for “ATTENTION_ CONVERTER” comments. This comment indicates the BMT converted a code snippet that a software engineer needs to verify for correctness. • Wrapper • After BMT executes, the Wrapper.cpp is 100% complete. • After BMT executes, the Wrapper.h is 100% complete. • Engineer modifications: • May be some extraneous #include files to delete. • Facet • After BMT executes, the Facet.cpp is 100% complete. • After BMT executes, the Facet.h is 100% complete. • Engineer modifications: • May be some extraneous #include files to delete. • Receptacle • After BMT executes, the Receptacle.cpp is 100% complete. • After BMT executes, the Receptacle.h is 100% complete. • Engineer modifications: • May be some extraneous #include files to delete. • Equivalent Interface • After BMT executes, the EquivalentInterface.cpp is 100% complete. • After BMT executes, the EquivalentInterface.h is 100% complete. • Engineer modifications: • May be some extraneous #include files to delete.

  36. Tasks to complete “wrapperized PRiSm” solution after executing BMT - continued • Event Sink • After BMT executes, the EventSink.cpp is roughly 75% complete. • After BMT executes, the EventSink.h is roughly 90% complete. • Engineer modifications: • May be some extraneous #include files to delete in the .h files. • Event consumer and supplier software and Push methods were completely copied from the old classes to the EventSink classes. The converting engineer shall decide: • what remains • what code is moved back and how to implement this ‘moved back’ code • where to insert pointers to the old classes. • Legacy Classes (Component Impl) • After BMT executes, the Legacy.cpp is roughly 85% complete. • After BMT executes, the Legacy.h is roughly 100% complete. • Engineer modifications: • May be some extraneous #include files to delete in the .h files. • The new correct facet pointers are sometimes not initialized and sometimes missing from the legacy classes. • Factory • Engineer shall build component’s factory from scratch. • After BMT executes, the Factory is 0% complete.

  37. BMT Magnitude • BMT contains ~1.5 M lines of code • Most of this is DMS machinery • BUT only ~ 13K lines are BMT specific •  Huge leverage of DMS infrastructure for task

  38. BMT-user productivity • Trial component • Medium Sized • Estimated hand-conversion effort ~~ 1 man-month • Automated conversion time ~~ 8 minutes on 1 Ghz PC • Legacy classes retained in 10 source files • 2222 of 7347 lines of code changed • 34 new files • 2109 new lines of code and comments • DARPA-planned flight demo with 60+ components • Estimated ~~240K SLOC to modify • Ultimately: ~6000 components • BMT effort: ~~12 mm total • 50% time in defining conversion • Hand conversion: 6000 man-months

  39. Conclusion • Can automate architecture-driven modernization • Many possible custom reengineering possibilities • A key technology for software quality improvement • Need generalized compiler-like infrastructure to amortize tool engineering costs • Definable parsers, prettyprinters, transforms • Must scale to application systems with MSLOCs • DMS provides these capabilities • growing infrastructure and standard language modules • Milestone: usable on C++!! • Knowledge capture as domains • Mechanical basic for MDA in the large www.semanticdesigns.com

More Related