Software-Projekt. Prof. Dr. Rainer Koschke. Fachbereich Mathematik und Informatik Arbeitsgruppe Softwaretechnik Universität Bremen

Ähnliche Dokumente
Software-Projekt. Prof. Dr. Rainer Koschke. Fachbereich Mathematik und Informatik Arbeitsgruppe Softwaretechnik Universität Bremen

Software-Projekt. Prof. Dr. Rainer Koschke. Fachbereich Mathematik und Informatik Arbeitsgruppe Softwaretechnik Universität Bremen

Vorlesung Software-Reengineering

Vorlesung Software-Reengineering

D-BAUG Informatik I. Exercise session: week 1 HS 2018

Zusammenfassung der Testarten

Algebraische Spezifikation von Software und Hardware II

Angewandte Mathematik und Programmierung

Konsolidierung von Software-Varianten in Software-Produktlinien ein Forschungsprogramm

Algorithmen und Datenstrukturen

Modellierung und Programmierung 1

Informatik - Übungsstunde

Pascal Schärli

Introduction to Python. Introduction. First Steps in Python. pseudo random numbers. May 2016

Aufgabe 1.1. Wählen Sie jene Variablendeklarationen mit Initialisierungen aus, die in Java hinsichtlich der Typen korrekt sind:

Klasse Label. class Label { Code code; List<Integer> fixuplist; // code positions to patch int adr; // address of label in code

Einstieg in die Informatik mit Java

Informatik für Mathematiker und Physiker Woche 2. David Sommer

Programmiermethodik 1. Klausur

Info B VL 11: Innere Klassen/Collections

Informatik - Übungsstunde

Java Tools JDK. IDEs. Downloads. Eclipse. IntelliJ. NetBeans. Java SE 8 Java SE 8 Documentation

Magic Figures. We note that in the example magic square the numbers 1 9 are used. All three rows (columns) have equal sum, called the magic number.

Problem: Keine Integers in JavaCard. ToDo: Rechnen mit Bytes und Shorts

Innere Klassen. Innere Klassen. Page 1. Lernziele: innere Klassen, statische geschachtelte Klassen, anonyme Klassen.

Softwaretechnik WS 16/17. Übungsblatt 01

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Informatik II Übung 7 Gruppe 7

Informatik für Mathematiker und Physiker Woche 7. David Sommer

Programmier-Befehle - Woche 10

Software Entwicklung 1. Fallstudie: Arithmetische Ausdrücke. Rekursive Klassen. Überblick. Annette Bieniusa / Arnd Poetzsch-Heffter

Theorie zu Übung 8 Implementierung in Java

Einstieg in die Informatik mit Java

Übungsblatt 10. Thema: Abstrakte Datentypen, Datenstrukturen in Java

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Abstrakte C-Maschine und Stack

Übersetzen des Quelltexts in ausführbaren Maschinen-Code Translation of source code into executable machine code

14 Abstrakte Klassen, finale Klassen, Interfaces

Übungen zu Programmieren - Code-Formatierung -

Bayesian Networks. Syntax Semantics Parametrized Distributions Inference in Bayesian Networks. Exact Inference. Approximate Inference

14 Abstrakte Klassen, finale Klassen, Interfaces. Auswertung von Ausdrücken. Beispiel. Abstrakte Methoden und Klassen

Vorlesung Programmieren

Software Entwicklung 1

14 Abstrakte Klassen, finale Klassen, Interfaces

Assembler (NASM) Crashkurs von Sönke Schmidt

Introduction to Python. Introduction. First Steps in Python. pseudo random numbers. May 2018

Vorlesung Programmieren

12 Abstrakte Klassen, finale Klassen und Interfaces

Algorithmen und Datenstrukturen Musterlösung 5

Informatik II Übung 5

Einstieg in die Informatik mit Java

Vorlesung Software-Reengineering

Prüfung Informatik D-MATH/D-PHYS :00 11:00

Objektorientierung III

Grundlagen der Programmierung in C++ Kontrollstrukturen

! können default arguments haben: ein Endstück der Argumentliste einer Deklaration mit Wertevorgaben

Java-Schulung Grundlagen

1. Erste Schritte 2. Einfache Datentypen 3. Anweisungen und Kontrollstrukturen 4. Verifikation 5. Reihungen (Arrays)

Informatik II - Tutorium 5

Algorithm Theory 3 Fast Fourier Transformation Christian Schindelhauer

Teil 5 - Java. Programmstruktur Operatoren Schlüsselwörter Datentypen

Algorithmen zur Datenanalyse in C++

Übung Informatik I - Programmierung - Blatt 8

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 13. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 12. Listen. Listen 1

Distributed Computing Group

Tutoraufgabe 1 (Implementierung eines ADTs):

Programmier-Befehle - Woche 08

Datenstrukturen. Ziele

C++11. neu in C++11: range-based for. Objektorientierte Programmierung mit C++ Ersetzung durch: 1. Elementares C++ int array[] = { 1, 2, 3, 4, 5 };

Collections und Generics

16. Ausnahmebehandlung Programmieren / Algorithmen und Datenstrukturen 2

Informatik II Übung 5 Gruppe 3

Ausnahmen-Behandlung

Übungsstunde 10. Einführung in die Programmierung I

Struktur des MicroJava-Compilers

Weather forecast in Accra

IT I: Heute. abstrakte Methoden und Klassen. Interfaces. Interfaces List, Set und Collection IT I - VO 7 1

Software Entwicklung 1

19. STL Container Programmieren / Algorithmen und Datenstrukturen 2

Programmiermethodik 3. Klausur Lösung

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

Informatik II. Giuseppe Accaputo, Felix Friedrich, Patrick Gruntz, Tobias Klenze, Max Rossmannek, David Sidler, Thilo Weghorn FS 2017

Computational Models

Nachtragstest in Programmkonstruktion 1. Phase. 1. Multiple-Choice-Aufgaben

JAVA BASICS. 2. Primitive Datentypen. 1. Warum Java? a) Boolean (logische Werte wahr & falsch)

Programmieren in Java

2.2 Spezifikation abstrakter Datentypen. 2.3 Implementierung und Anwendung von ADT. 2.4 Datenabstraktion und Objektorientierung

Übungsstunde: Informatik 1 D-MAVT

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

Unified-E Standard WebHttp Adapter

1. Die rekursive Datenstruktur Liste

Vorbereitende Aufgaben

EINFÜHRUNG IN DIE PROGRAMMIERUNG

JAVA BASICS. 2. Primitive Datentypen. 1. Warum Java? a) Boolean (logische Werte wahr & falsch)

Transkript:

Software-Projekt Prof. Dr. Rainer Koschke Fachbereich Mathematik und Informatik Arbeitsgruppe Softwaretechnik Universität Bremen Wintersemester 2006/07 Überblick I 1

1 Motivation Architekturkonformität Programmierrichtlinien Anhang Wiederholungsfragen Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 3 / 33 Lernziele Feinentwurf eines Systems durchführen können Programmierrichtlinien entwerfen, kennen und einhalten Verständnis für Codequalität entwickeln Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 4 / 33

Feinentwurf Der Feinentwurf ist die Brücke zwischen abstrakter Architektur und detailliertem Code. Er legt fest: Datenstrukturen Klassendiagramme mit zusätzlichen sdetails; (z.b. Navigierbarkeit, von Assoziationen, Behandlung von Mehrfachvererbung oder weiteren sklassen etc.) Abläufe Zustandsautomaten Aktivitätsdiagramme Sequenzdiagramme Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 5 / 33 Architekturkonformität Architekturbeschreibung und Quellcode sind zwei von einander abhängige, aber separate Dokumente in der Weiterentwicklung werden oft Änderungen im Quellcode gemacht, die in der Architekturbeschreibung nicht nachgezogen werden Folge: Architekturbeschreibung wird obsolet Planung erfolgt aber meist auf Basis der Architekturbeschreibung Folge: böses Erwachen in der Umsetzung Reflektionsmethode von Murphy u. a. (1995, 2001) zur Synchronisation von Modulsicht und Quellcode Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 6 / 33

Reflektionsmethode (Murphy u. a. 2001) 1 Stelle Architekturmodell auf 2 Extrahiere smodell 3 Bilde Modelle aufeinander ab 4 Berechne Reflektionsmodell 5 Verfeinere/korrigiere Beispiel H1 H2 H3 Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 7 / 33 Warum Programmierrichtlinien? bis zu 80% der Gesamtkosten für Software sind Wartungskosten Originalautor wartet Software oft nicht selbst Code muss lesbar und verständlich sein Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 9 / 33

Programmierrichtlinien: Schlechte Beispiele i n k o n s i s t e n t e Methodennamen T e x t F i e l d. s e t T e x t ( ) ; L a b e l. s e t T e x t ( ) ; Button. s e t L a b e l ( ) ; A b s t r a c t B u t t o n. s e t T e x t ( ) ; i n k o n s i s t e n t e P a r a m e t e r s o r t i e r u n g S t r i n g B u f f e r. setcharat ( i n t index, c h a r c ) ; Vector. s e t E l e m e n t A t ( Object o, i n t i n d e x ) ; L i s t. s e t ( i n t index, Object o ) ; l e n g t h oder s i z e? l e n O f A r r a y = myarray. l e n g t h ; l e n O f S t r i n g = mystring. l e n g t h ( ) ; mylist. s i z e ( ) ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 11 / 33 Programmierrichtlinien: Sinnvolle Namen S i n n l o s e Namen s t a t i c f i n a l i n t ONE = 1 ; s t a t i c f i n a l i n t TEN = 1 0 ; s t a t i c f i n a l i n t TWENTY = 3 0 ; b e s s e r s t a t i c f i n a l i n t INPUT MODE = 1 ; s t a t i c f i n a l i n t INPUT BUFSIZE = 1 0 ; s t a t i c f i n a l i n t OUTPUT BUFSIZE = 3 0 ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 12 / 33

Programmierrichtlinien: Lokale Variablen Man kann s auch ü b e r t r e i b e n... f o r ( i n t o u t e r I n d e x = 0 ; o u t e r I n d e x < maxouterindex ; o u t e r I n d e x++) f o r ( i n t i n n e r I n d e x = 0 ; i n n e r I n d e x < o u t e r I n d e x ; i n n e r I n d e x++) r e s u l t M a t r i x [ o u t e r I n d e x ] [ i n n e r I n d e x ] = o u t e r I n d e x i n n e r I n d e x ; S c h l e i f e n v a r i a b l e n / I n d i z e s => k u r z e Namen f o r ( i n t i = 0 ; i < max ; i ++) f o r ( i n t j = 0 ; j < i ; j ++) r e s u l t [ i ] [ j ] = i j ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 13 / 33 Ausdrücke in natürlicher Form schwer v e r s t ä n d l i c h e r Ausdruck i f (! ( b l o c k I d < a c t b l k s )! ( b l o c k I d >= u n b l o c k s ) ) b e s s e r i f ( ( b l o c k I d >= a c t b l k s ) ( b l o c k I d < u n b l o c k s ) ) Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 14 / 33

Magische Zahlen Wer v e r s t e h t d i e s e Zahlen? m = 60 h + em ; s = 60 m + e s ; t c = 60 b + l c ; So i s t s b e s s e r. s t a t i c f i n a l s h o r t MINUTES PER HOUR = 6 0 ; s t a t i c f i n a l s h o r t SECONDS PER MINUTE = 6 0 ; s t a t i c f i n a l s h o r t CLIPS PER BOX = 6 0 ;... minutes = MINUTES PER HOUR h o u r s + e x t r a M i n u t e s ; s e c o n d s = SECONDS PER MINUTE minutes + e x t r a S e c o n d s ; t o t a l C l i p s = CLIPS PER BOX boxes + l o o s e C l i p s ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 15 / 33 Hartcodiert: String-Literale im Code t r y s t o r e. o p e n S t o r e (. / c o n f i g. xml, PSA ) ; manager. r e a d C o n f i g u r a t i o n ( s t o r e ) ; c a t c h ( T r e e S t o r e E x c e p t i o n e ) System. e r r. p r i n t l n ( Konnte K o n f i g u r a t i o n s d a t e i n i c h t l e s e n. ) ; c a t c h ( C o n f i g E x c e p t i o n x ) System. e r r. p r i n t l n ( F e h l e r beim A u s l e s e n d e r K o n f i g u r a t i o n s d a t e i. ) ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 16 / 33

Character sind zwar Zahlen, aber Wie b i t t e? i f ( ( c >= 65) && ( c <= 90) )... i f ( ( c >= A ) && ( c <= Z ) )... Ach so! i f ( C h a r a c t e r. i s U p p e r C a s e ( c ) ) Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 17 / 33 Sprachkonstrukte zur Berechnung von Größen Doppelte Z a h l e n r e f e r e n z c h a r buf [ ] = new c h a r [ 1 0 2 4 ] ; f o r ( i n t i = 0 ; i < 1024; i ++) Sprachmechanismus nutzen! c h a r buf [ ] = new c h a r [ 1 0 2 4 ] ; f o r ( i n t i = 0 ; i < buf. l e n g t h ; i ++) Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 18 / 33

Überflüssige Kommentare / d e f a u l t / d e f a u l t : break ; / r e t u r n SUCCESS / r e t u r n SUCCESS ; zerocount++: / I n c r e m e n t z e r o e n t r y c o u n t e r / / I n i t i a l i z e t o t a l to numberreceived. / Node. t o t a l = Node. numberreceived ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 19 / 33 Überflüssige Kommentare w h i l e ( ( ( c = getchar ( ) )!= EOF) && ( i s S p a c e ( c ) ) ) ; / s k i p w h i t e s p a c e / i f ( c == EOF) / end o f f i l e / t y p e = END OF FILE ; e l s e i f ( c == ( ) / l e f t paren / t y p e = LEFT PAREN ; e l s e i f ( c == ) ) / r i g h t paren / t y p e = RIGHT PAREN ; e l s e i f ( c == ; ) / s e m i c o l o n / t y p e = SEMICOLON ; e l s e i f ( isop ( c ) ) / o p e r a t o r / t y p e = OPERATOR; e l s e i f ( i s D i g i t ( c ) ) / number / t y p e = NUMBER;... Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 20 / 33

Verschluckte (hicks) Exceptions t r y F i l e O u t p u t S t r e a m out = new F i l e O u t p u t S t r e a m ( strname ) ;... out. f l u s h ( ) ; out. c l o s e ( ) ; c a t c h ( I O E x c e p t i o n e ) ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 21 / 33 idkldw i n t f ( i n t f [ ], i n t l, Item k ) i n t i ; f o r ( i =0; i < l ; i ++) i f ( f [ i ] == k ) r e t u r n i ; In der Kürze liegt die Würze (idkldw)? i n t I n d e x ( i n t f i e l d, i n t l e n g t h, Item key ) i n t i ; f o r ( i =0; i < l e n g t h ; i ++) i f ( f i e l d [ i ] == key ) r e t u r n i ; Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 22 / 33

Software-Redundanz for (i = 1; i < MAX; i++) x = func() * y + x; for (i = 1; i < MAX; i++) x = func() * y + x; for (j = 1; j < MAX; j++) x = func() * y + x; foo.c bar.c fred.c for (i = 1; i < MAX; i++) x1 = func() * y1 + x1; for (i = 1; i < MAX; i++) x2 = func() * y2 + x2; Typisch: 5 30 % des Codes sind redundant... Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 23 / 33 Software-Redundanz foo.c bar.c fred.c set_coordinate (&x, y); set_coordinate (&x, y); set_coordinate (&x, y); void set_coordinate ( float *x, float y) int i; for (i = 1; i < MAX; i++) *x = func() * y + *x; set_coordinate (&x1, y1); set_coordinate (&x2, y2);... und können abstrahiert werden Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 24 / 33

Mai 31, 05 7:18 Seite 1/12 5 negation (we eliminate it) 10 branch emitted. AstStatement* over) 40 AstConditionalExpression* conditional = p > ConditionalExpressionCast(); 55 65 EmitBranch(OP_GOTO, Dienstag Mai 31, 2005 1/12 Mai 31, 05 7:18 Seite 3/12 EmitBranchIfExpression(conditional > test_expression, false, 150 155 170 180 lab2: EmitBranchIfExpression(conditional > test_expression, false, EmitBranchIfExpression(conditional > test_expression, false, lab1, 190 EmitBranchIfExpression(conditional > false_expression, cond, lab, over); 200 205 semantic.reportsemerror(semanticerror::array_overflow, instanceof > type); 210 Dienstag Mai 31, 2005 3/12 Mai 31, 05 7:18 Seite 5/12 EmitBranch(OP_GOTO, 305 branch_if(a&&b, true, lab) => case AstBinaryExpression::OR_OR: 330 branch_if(true b, cond, lab) => branch_if(true, cond, lab); Dienstag Mai 31, 2005 5/12 Mai 31, 05 7:18 Seite 2/12 80 EmitBranchIfExpression(conditional > false_expression, true, 85 EmitBranch(OP_GOTO, EmitBranchIfExpression(conditional > test_expression, false, 2/12 Dienstag Mai 31, 2005 Mai 31, 05 7:18 Seite 4/12 215 EmitExpression(expr, false); 220 expr > BinaryExpressionCast()) a String concat 265 left_type > IsSubtype(right_type)) AstExpression* right = StripNops(bp > right_expression); 275 switch (bp > Tag()) 280 branch_if(false&&b, cond, lab) => branch_if(false, cond, lab); 4/12 Dienstag Mai 31, 2005 Mai 31, 05 7:18 Seite 6/12 EmitBranch(OP_GOTO, 355 branch_if(a b,true,lab) => 360 branch_if(b,false,lab); case AstBinaryExpression::XOR: ^ on booleans is equavalent to!= 380 case AstBinaryExpression::EQUAL_EQUAL: case AstBinaryExpression::NOT_EQUAL: 390 if (left_type == right_type) 395 405 EmitBranch(OP_GOTO, EmitBranch(cond? OP_IFNONNULL : OP_IFNULL, 410 (IsOne(left) IsOne(right))) EQUAL_EQUAL), 415 6/12 Dienstag Mai 31, 2005 Mai 31, 05 7:18 Seite 7/12 left_type == control.boolean_type) 435 cond == (bp > Tag()!= AstBinaryExpr ession::equal_equal), 460 EmitExpression(IsZero(left)? right : left); EmitBranch((cond? OP_IFNE : OP_IFEQ), EmitExpression(right); 475 EmitBranch((cond? OP_IF_ACMPNE : OP_IF_ACMPEQ), EmitBranchIfExpression(IsZero(left)? right : left, cond, Dienstag Mai 31, 2005 7/12 580 op_false = OP_IFLT; 585 op_false = OP_IFGE; 590 op_false = OP_IFGT; 595 600 EmitExpression(left); case AstBinaryExpression::LESS: 620 assert(false); 625 Mai 31, 05 7:18 Seite 9/12 Dienstag Mai 31, 2005 9/12 case AstBinaryExpression::EQUAL_EQUAL: case AstBinaryExpression::NOT_EQUAL: case AstBinaryExpression::LESS: case AstBinaryExpression::LESS_EQUAL: case AstBinaryExpression::GREATER: case AstBinaryExpression::GREATER_EQUAL: 740 switch (bp > Tag()) 745 op_false = OP_IFNE; 750 op_false = OP_IFEQ; 755 op_false = OP_IFGE; 760 op_false = OP_IFGT; 765 op_false = OP_IFLE; Mai 31, 05 7:18 Seite 11/12 opcode = OP_DCMPL; Dienstag Mai 31, 2005 11/12 Mai 31, 05 7:18 Seite 8/12 490 case AstBinaryExpression::AND: default: 550 8/12 Dienstag Mai 31, 2005 650 case AstBinaryExpression::LESS: EmitExpression(right); opcode = OP_LCMP; 690 assert(false); 695 Mai 31, 05 7:18 Seite 10/12 10/12 Dienstag Mai 31, 2005 775 EmitBranch (cond? op_true : op_false, Mai 31, 05 7:18 Seite 12/12 12/12 Dienstag Mai 31, 2005 Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 25 / 33 Überlange Methoden java provides a variety of conditional branch instructions, so that a number of operators merit special handling: constant operand equality?: && and (partial evaluation) comparisons Other expressions are just evaluated and the appropriate TODO: return a bool that is true if the statement being branched over is even needed (if statements and other places might have a constant false expression, allowing the next block of code to be skipped entirely). 15 void ByteCode::EmitBranchIfExpression(AstExpression* p, bool cond, Label& lab, p = StripNops(p); 20 assert(p > Type() == control.boolean_type); if (p > IsConstant()) if (IsZero(p)!= cond) 25 EmitBranch(OP_GOTO, AstPreUnaryExpression* pre = p > PreUnaryExpressionCast(); 30 if (pre) must be! branch_if(!e,c,l) => branch_if(e,!c,l) 35 assert(pre > Tag() == AstPreUnaryExpression::NOT); if (cond) EmitBranchIfExpression(conditional > test_expression, true, 75 Label skip; EmitBranchIfExpression(conditional > test_expression, true, skip, over); EmitBranchIfExpression(conditional > false_expression, false, DefineLabel(skip); CompleteLabel(skip); 90 if (IsZero(conditional > true_expression)) branch_if(expr?false:true, c, l) => branch_if(expr,! c, l); branch_if(expr?false:false, c, l) => expr, branch if! c 95 branch_if(expr?false:b, c, l) => branch_if(!expr && b, c, l); if (IsOne(conditional > false_expression)) EmitBranchIfExpression(conditional > test_expression, 100! cond, if (IsZero(conditional > false_expression)) EmitExpression(conditional > test_expression, false); 105 if (! cond) 420 if (control.issimpleintegervaluetype(left_type) assert(control.issimpleintegervaluetype(right_type) 425 right_type == control.boolean_type); if (IsZero(left) IsZero(right)) if (left_type == control.boolean_type) 430 One of the operands is false. Branch on the other. EmitBranchIfExpression(IsZero(left)? right : left, 440 One of the operands is zero. Only emit the other. 445 if (bp > Tag() == AstBinaryExpression::EQUAL_EQUAL) EmitBranch((cond? OP_IFEQ : OP_IFNE), 450 EmitExpression(left); EmitExpression(right); One argument is true. Emit the other, and result is true. 495 if (IsOne(left) IsOne(right)) EmitExpression(IsOne(left)? right : left, false); if (cond) EmitBranch(OP_GOTO, 500 505 One argument is true. Branch on other. if (IsOne(left) IsOne(right)) EmitBranchIfExpression(IsOne(left)? right : left, 510 cond, 515 One argument is false. Emit the other, and result is false. if (IsZero(left) IsZero(right)) EmitExpression(IsZero(left)? right : left, false); 520 if (! cond) EmitBranch(OP_GOTO, EmitBranchIfExpression(pre > expression,! cond, if (conditional) if (conditional > test_expression > IsConstant()) 45 branch_if(true?a:b, cond, lab) => branch_if(a, cond, lab); branch_if(false?a:b, cond, lab) => branch_if(b, cond, lab); EmitBranchIfExpression((IsZero(conditional > test_expression) 50? conditional > false_expression : conditional > true_expression), cond, if (IsOne(conditional > true_expression)) branch_if(expr?true:true, c, l) => expr, branch if c branch_if(expr?true:false, c, l) => branch_if(expr, c, l); branch_if(expr?true:b, c, l) => branch_if(expr b, c, l); 60 if (IsOne(conditional > false_expression)) if (! cond) 110 EmitBranchIfExpression(conditional > test_expression, true, EmitBranchIfExpression(conditional > false_expression, false, 115 Label skip; EmitBranchIfExpression(conditional > test_expression, true, skip, over); 120 EmitBranchIfExpression(conditional > false_expression, true, DefineLabel(skip); CompleteLabel(skip); 125 if (IsOne(conditional > false_expression)) branch_if(expr?a:true, c, l) => branch_if(!expr a, c, l); 130 if (cond) 455 if (bp > Tag() == AstBinaryExpression::EQUAL_EQUAL) EmitBranch((cond? OP_IF_ICMPEQ : OP_IF_ICMPNE), EmitBranch((cond? OP_IF_ICMPNE : OP_IF_ICMPEQ), 465 Both operands are reference types: just do the comparison. if (IsReferenceType(left_type)) assert(isreferencetype(right_type)); 470 EmitExpression(left); if (bp > Tag() == AstBinaryExpression::EQUAL_EQUAL) EmitBranch((cond? OP_IF_ACMPEQ : OP_IF_ACMPNE), EmitExpression(conditional > test_expression, false); if (cond) if (IsZero(conditional > false_expression)) EmitBranchIfExpression(conditional > test_expression, 70 cond, 135 EmitBranchIfExpression(conditional > true_expression, true, 140 Label skip; 480 case AstBinaryExpression::IOR: One argument is false. Branch on other. 485 if (IsZero(left) IsZero(right)) 525 default: 530 here if not comparison, comparison for non integral numeric types, or integral comparison for which no special casing needed. Begin by dealing with non comparisons switch (bp > Tag()) 535 case AstBinaryExpression::LESS: case AstBinaryExpression::LESS_EQUAL: case AstBinaryExpression::GREATER: case AstBinaryExpression::GREATER_EQUAL: 540 case AstBinaryExpression::EQUAL_EQUAL: case AstBinaryExpression::NOT_EQUAL: break to continue comparison processing 545 not a comparison, get the (necessarily boolean) value of the expression and branch on the result EmitExpression(p); EmitBranch(cond? OP_IFNE : OP_IFEQ, 555 Opcode opcode = OP_NOP, op_true, op_false; skip, over); EmitBranchIfExpression(conditional > true_expression, false, 145 DefineLabel(skip); CompleteLabel(skip); if (IsZero(conditional > false_expression)) We know the result: false. But emit the left expression, in case of side effects in (expr? null : null). if (! cond) EmitBranch(OP_GOTO, if (expr > IsConstant() a String constant assert(left_type!= control.boolean_type); 560 if (control.issimpleintegervaluetype(left_type)) we have already dealt with EQUAL_EQUAL and NOT_EQUAL for the case of two integers, but still need to look for comparisons for which 565 one operand may be zero. if (IsZero(left)) switch (bp > Tag()) 630 op_true = OP_IF_ICMPLT; op_false = OP_IF_ICMPGE; 635 case AstBinaryExpression::LESS_EQUAL: op_true = OP_IF_ICMPLE; op_false = OP_IF_ICMPGT; branch_if(expr?a:false, c, l) => branch_if(expr && a, c, l); if (! cond) EmitBranchIfExpression(conditional > true_expression, false, 160 We know the result: true, since the expression is non null and String is a final class. 225 assert(left_type == control.string()); EmitExpression(expr, false); if (cond) EmitBranch(OP_GOTO, 230 if ((expr > ThisExpressionCast() EmitExpression(right); 570 switch (bp > Tag()) case AstBinaryExpression::LESS: if (0 < x) same as if (x > 0) op_true = OP_IFGT; 575 op_false = OP_IFLE; case AstBinaryExpression::LESS_EQUAL: if (0 <= x) same as if (x >= 0) op_true = OP_IFGE; case AstBinaryExpression::GREATER: 640 op_true = OP_IF_ICMPGT; op_false = OP_IF_ICMPLE; case AstBinaryExpression::GREATER_EQUAL: op_true = OP_IF_ICMPGE; 645 op_false = OP_IF_ICMPLT; default: assert(false); Label skip; EmitBranchIfExpression(conditional > test_expression, false, 165 skip, over); EmitBranchIfExpression(conditional > true_expression, true, DefineLabel(skip); CompleteLabel(skip); expr > SuperExpressionCast() expr > ClassLiteralCast() expr > ClassCreationExpressionCast() 235 expr > ArrayCreationExpressionCast()) && We know the result: true, since the expression is non null. case AstBinaryExpression::GREATER: if (0 > x) same as if (x < 0) op_true = OP_IFLT; case AstBinaryExpression::GREATER_EQUAL: if (left_type == control.long_type) 655 EmitExpression(left); 175 branch_if(expr?a:b, c, l) => branch_if(expr, false, lab1) branch_if(a, c, l) goto lab2 lab1: branch_if(b, c, l) Label lab1, lab2; over); 185 EmitBranchIfExpression(conditional > true_expression, cond, lab, over); EmitBranch(OP_GOTO, lab2, over); DefineLabel(lab1); CompleteLabel(lab1); DefineLabel(lab2); CompleteLabel(lab2); 240 EmitExpression(expr, false); if (cond) EmitBranch(OP_GOTO, 245 EmitExpression(expr); PutOp(OP_INSTANCEOF); PutU2(RegisterClass(right_type)); 250 EmitBranch((cond? OP_IFNE : OP_IFEQ), 255 dispose of non binary expression case by just evaluating operand and emitting appropiate test. AstBinaryExpression* bp = p > BinaryExpressionCast(); 260 if (! bp) EmitExpression(p); EmitBranch((cond? OP_IFNE : OP_IFEQ), if (0 >= x) same as if (x <= 0) op_true = OP_IFLE; default: assert(false); if (IsZero(right)) switch (bp > Tag()) op_true = OP_IFLT; 605 op_false = OP_IFGE; case AstBinaryExpression::LESS_EQUAL: op_true = OP_IFLE; op_false = OP_IFGT; 610 case AstBinaryExpression::GREATER: 660 branch according to result value on stack switch (bp > Tag()) 665 case AstBinaryExpression::EQUAL_EQUAL: op_true = OP_IFEQ; op_false = OP_IFNE; case AstBinaryExpression::NOT_EQUAL: 670 op_true = OP_IFNE; op_false = OP_IFEQ; case AstBinaryExpression::LESS: op_true = OP_IFLT; 675 op_false = OP_IFGE; case AstBinaryExpression::LESS_EQUAL: op_true = OP_IFLE; op_false = OP_IFGT; 680 case AstBinaryExpression::GREATER: 195 AstInstanceofExpression* instanceof = p > InstanceofExpressionCast(); if (instanceof) AstExpression* expr = StripNops(instanceof > expression); TypeSymbol* left_type = expr > Type(); TypeSymbol* right_type = instanceof > type > symbol; if (right_type > num_dimensions > 255) if (left_type == control.null_type) Here if binary expression, so extract operands 270 AstExpression* left = StripNops(bp > left_expression); TypeSymbol* left_type = left > Type(); TypeSymbol* right_type = right > Type(); case AstBinaryExpression::AND_AND: branch_if(true&&b, cond, lab) => branch_if(b, cond, lab); op_true = OP_IFGT; op_false = OP_IFLE; 615 case AstBinaryExpression::GREATER_EQUAL: op_true = OP_IFGE; op_false = OP_IFLT; default: EmitExpression(left); EmitExpression(right); op_true = OP_IFGT; op_false = OP_IFLE; 685 case AstBinaryExpression::GREATER_EQUAL: op_true = OP_IFGE; op_false = OP_IFLT; default: if (left_type == control.float_type) EmitExpression(left); EmitExpression(right); if (left > IsConstant()) if (IsOne(left)) 285 EmitBranchIfExpression(right, cond, if (! cond) EmitBranch(OP_GOTO, 290 branch_if(a&&true, cond, lab) => branch_if(a, cond, lab); branch_if(a&&false, cond, lab) => emit(a), pop; for side effects if (right > IsConstant()) 295 if (IsOne(right)) EmitBranchIfExpression(left, cond, EmitExpression(left, false); 300 if (! cond) branch_if(a,false,skip); branch_if(b,true,lab); skip: branch_if(a&&b, false, lab) => 310 branch_if(a,false,lab); branch_if(b,false,lab); if (cond) 315 Label skip; EmitBranchIfExpression(left, false, skip, over); EmitBranchIfExpression(right, true, DefineLabel(skip); CompleteLabel(skip); 320 EmitBranchIfExpression(left, false, EmitBranchIfExpression(right, false, 325 branch_if(false b, cond, lab) => branch_if(b, cond, lab); if (left > IsConstant()) if (IsZero(left)) 335 EmitBranchIfExpression(right, cond, if (cond) EmitBranch(OP_GOTO, 340 branch_if(a false, cond, lab) => branch_if(a, cond, lab); branch_if(a true, cond, lab) => emit(a), pop; for side effects if (right > IsConstant()) 345 if (IsZero(right)) EmitBranchIfExpression(left, cond, EmitExpression(left, false); 350 if (cond) branch_if(a,true,lab); branch_if(b,true,lab); branch_if(a b,false,lab) => branch_if(a,true,skip); skip: if (cond) 365 EmitBranchIfExpression(left, true, EmitBranchIfExpression(right, true, 370 Label skip; EmitBranchIfExpression(left, true, skip, over); EmitBranchIfExpression(right, false, DefineLabel(skip); CompleteLabel(skip); 375 assert(left_type == control.boolean_type); Fallthrough! One of the operands is null. We must evaluate both operands, to get any side effects in (expr? null : null). 385 if (left_type == control.null_type right_type == control.null_type) EmitExpression(left, left_type!= control.null_type); EmitExpression(right, right_type!= control.null_type); if (cond == (bp > Tag() == AstBinaryExpression::EQUAL_EQUAL)) if (bp > Tag() == AstBinaryExpression::EQUAL_EQUAL) 400 EmitBranch(cond? OP_IFNULL : OP_IFNONNULL, One of the operands is true. Branch on the other. if (left_type == control.boolean_type && EmitBranchIfExpression(IsOne(left)? right : left, cond == (bp > Tag() == AstBinaryExpression:: Both operands are integer. switch (bp > Tag()) 700 opcode = OP_FCMPL; op_true = OP_IFEQ; op_false = OP_IFNE; 705 opcode = OP_FCMPL; op_true = OP_IFNE; op_false = OP_IFEQ; 710 opcode = OP_FCMPG; op_true = OP_IFLT; op_false = OP_IFGE; 715 opcode = OP_FCMPG; op_true = OP_IFLE; op_false = OP_IFGT; 720 opcode = OP_FCMPL; op_true = OP_IFGT; op_false = OP_IFLE; 725 opcode = OP_FCMPL; op_true = OP_IFGE; op_false = OP_IFLT; 730 default: assert(false); 735 if (left_type == control.double_type) EmitExpression(left); EmitExpression(right); case AstBinaryExpression::EQUAL_EQUAL: opcode = OP_DCMPL; op_true = OP_IFEQ; case AstBinaryExpression::NOT_EQUAL: opcode = OP_DCMPL; op_true = OP_IFNE; case AstBinaryExpression::LESS: opcode = OP_DCMPG; op_true = OP_IFLT; case AstBinaryExpression::LESS_EQUAL: opcode = OP_DCMPG; op_true = OP_IFLE; case AstBinaryExpression::GREATER: opcode = OP_DCMPL; op_true = OP_IFGT; case AstBinaryExpression::GREATER_EQUAL: op_true = OP_IFGE; 770 op_false = OP_IFLT; default: assert(false); assert(false && "comparison of unsupported type"); if (opcode!= OP_NOP) 780 PutOp(opcode); if need to emit comparison before branch Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 26 / 33

Ignoranz, Not-Invented-Here-Syndrom oder die neuerfundenen Räder p u b l i c c l a s s A r t i c l e s p r i v a t e A r t i c l e item ; p r i v a t e A r t i c l e s n e x t ; p u b l i c A r t i c l e s ( )... p u b l i c v o i d Add ( A r t i c l e a r t )... p u b l i c v o i d Show ( )... p u b l i c c l a s s A r t i c l e s p r i v a t e j a v a. u t i l. L i n k e d L i s t a r t i c l e s ; p u b l i c A r t i c l e s ( )... p u b l i c v o i d Add ( A r t i c l e a r t )... p u b l i c v o i d Show ( )... Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 27 / 33 Die Oglala des 21. Jahrhunderts p u b l i c c l a s s A r t i c l e s p r i v a t e j a v a. u t i l. L i n k e d L i s t a r t i c l e s ; p u b l i c A r t i c l e s ( )... p u b l i c v o i d Add ( A r t i c l e a r t ) a r t i c l e s. addlast ( a r t ) ; p u b l i c v o i d Show ( ) L i s t I t e r a t o r l i s t I t r = a r t i c l e s. l i s t I t e r a t o r ( ) ; w h i l e ( l i s t I t r. hasnext ( ) ) A r t i c l e a r t = ( A r t i c l e ) l i s t I t r. n e x t ( ) ; a r t. show ( ) ; Oglala (bedeutet: Die ihre Habe verschleudern im Sinne von Großzügigkeit) sind ein Stamm der Lakota-Sioux-Indianer. Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 28 / 33

Prinzipien einheitlich so einfach wie möglich sprechend, direkt verständlich prägnant frei von Redundanz übersichtlich strukturiert abgeschlossen abstrakt Separation of Concerns Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 29 / 33 Was alles in den Code-Inspektionen 2004/05 auffiel Verwendung von verketteten Listen, wo Maps angebracht wären; manuelle der entsprechenden Map-Zugriffe Verwendung von verketteten Listen, wo ArrayList angebrachter wäre; z.b. Iterieren durch die LinkedList über Indexzugriffe alle Methoden einer Klasse static; die statischen Variablen werden über den Konstruktor initialisiert alle Methoden einer Klasse static, die Instanz, auf der die Methoden arbeiten, werden z.b. als LinkedList jeweils übergeben Neuimplementierung von Sortieralgorithmen die gesamte GUI wird in einer einzigen Klasse implementiert Datenbankzugriffe werden über alle Klassen verteilt, statt gekapselt Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 30 / 33

Was alles in den Code-Inspektionen 2004/05 auffiel Query wird mit select * gemacht, danach werden manuell die benötigten Spalten rausgefiltert Datenbanknamen usw. werden hartcodiert manuelle von Parsern für verschiedene Zwecke (wo z.b. XML oder Properties-Datei angebracht wäre) mehrfache der gleichen Hilfsklassen von verschiedenen Leuten, z.b. Übersetzungen (dementsprechend auch mit verschiedenen Dateiformaten) keine Berücksichtigung von Performance (z.b. bei Operationen auf verketteter Liste, Dateioperationen; Konfigurationsdatei wird bei jedem Methodenaufruf neu eingelesen) Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 31 / 33 Wiederholungsfragen Was sind Refactorings und Bad Smells? Wie wird Refactoring durchgeführt? Nennen Sie Beispiele für Bad Smells. Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 32 / 33

1 Murphy u. a. 1995 Murphy, Gail C. ; Notkin, David ; Sullivan, Kevin: Software Reflexion Models: Bridging the Gap Between Source and High-Level Models. In: Proc. of the Third ACM SIGSOFT Symposium on the Foundations of Software Engineering, 1995, S. 18 28 2 Murphy u. a. 2001 Murphy, Gail C. ; Notkin, David ; Sullivan, Kevin J.: Software Reflexion Models: Bridging the Gap between Design and Implementation. In: IEEE Transactions on Software Engineering 27 (2001), April, Nr. 4, S. 364 380 3 Object Management Group 2003 Object Management Group: OMG Unified Modeling Language Specification. March 2003. Version 1.5 4 Sun microsystems 1999 Sun microsystems: Code Conventions for the Java TM Programming Language. April 1999. URL http: java.sun.com/docs/codeconv/html/codeconvtoc.doc.html Rainer Koschke (Uni Bremen) Software-Projekt Wintersemester 2006/07 33 / 33