Refactoring by gabyion


									   Design Issues
     Design to Code
       GUI design
     RDBMS design
Performance Optimization
UML to code
Smalltalk class for each UML class
Instance variable for each attribute
Instance variables for each relationship
    possibly bidirectional

    possibly a collection
      pet owner
Dog               Person

   pet owner
Dog *        Person
Bidirectional relationships
Dog has „owner‟, person has „pet‟

owner: aPerson        owner: aPerson
 aPerson pet: self.       aPerson setPet: self.
 owner := aPerson         owner := aPerson

pet: anAnimal         setPet: anAnimal
  pet := anAnimal          pet := anAnimal
One to many relationships
Instance variable holds a collection
Initialization creates empty collection
addPet:, removePet:, petDo:
The rest of UML
UML good at specifying easy stuff
 classes, instance variables, accessing
UML not good at specifying hard stuff
How to build GUIs
1) GUI first approach
    Paint screen, build application model

    Build domain model

2) Domain model first approach
    Build domain model and tests

    Paint screen, build application model
1) GUI first approach
    discover inputs and outputs

    weak domain model, too much in

     application model
    can be hard to test

2) Domain model first approach
    good, tested, domain model

    changes needed when GUI added
How to build GUIs
Build the domain model first unless the
 application is focused on graphics
Counter examples:
   The Incredible Machine

   Drawing editor (HotDraw)
How to build DBMS interface
1) DBMS first approach
    design tables

    build an application to talk to tables

2) Domain model first approach
    design application with no DBMS

    make a good, tested, domain model

    design tables and make objects read and

     write the database
1) DBMS first approach
    good RDBMS design

    unnatural object design, odd factoring

    large systems get VERY complex

2) Domain model first approach
    good object design

    unnatural RDBMS design
Modularizing DB access
1) ApplicationModel knows how to read and
  write objects from database
2) “Persistent objects” know how to write
  themselves to database, their class knows
  how to read them
3) “Database access layer” knows which
  objects are persistent and how to read and
  write them.
Modularizing Database access
Two choices:
1) Embed SQL in Smalltalk methods
2) Describe tables and classes with
  “metadata” and generate SQL from them
  Modularizing Database access
                      Embed SQL            Metadata
ApplicationModel    Simple, unscalable        Lens

Persistent Object      Do this!

DB access layer      Ugly, unscalable Hard to implement,
                                        most scalable
Persistent Object
Implement “read”, “update” and “delete”
  operation as instance method.
Class knows its key.
Read a record by making an object with only
  its key filled in, then reading it.
Class methods for queries.
Persistent Object
VisualWorks has
  EXDI - direct access to database, SQL
  Object Lens - high layer access, hides SQL
      Kent Beck‟s formula
       for fast software

Make it work.
Make it right.
Make it fast.
Make it work.    (Analysis) 50%
Make it right.   (Design) 35%
Make it fast.    (Implementation) 15%
Facts of Life
C is 10 times faster than Smalltalk on small

Smalltalk business applications are as fast as
 C business applications.
Why is Smalltalk so fast?
Smalltalkers can spend more time on
Well-written Smalltalk programs are easy to
Most business programs are limited by
 network and database, not by CPU.
How to make fast software
Make your software correct and easy to
Measure the performance of each part of your
Find bottlenecks.
   (80% of the time is spent in 20% of the
Fix them.
Wrong way to make fast software
Choose most efficient language possible.
Make each line of code as efficient as
Choose fastest algorithms possible.
How to measure performance
Profilers are in the parcel
Read “atug.pdf”

TimeProfiler profile: [3 + 4]

TimeProfiler openView
Profiling a Server
 profile:[100 timesRepeat:
  [| req |
  req := WikiClientRequest new.
       action: 'GET';
 WikiServer current handleRequest: req]].
100.0 WikiServer>>handleRequest:
 100.0 Wiki>>replyToRequest:
   94.6 PageRendering>>renderBody
    78.3 PageRendering>>renderCommands
      61.7 WikiRendering>>linkTo:titled:
       34.2 WikiRendering>>putUrlForCommand:
         17.9 WikiRendering>>&=
         16.3 WikiRendering>>encodedPageTitle
             10.9 WikiRendering>>page
               10.9 Wiki>>pageTitled:
                 5.4 CharacterArray>>asUppercase
  ^wiki pageTitled: request identifier last

This method is called several times, so cache it.
Add an instance variable called “page”.
  page isNil
     ifTrue: [page := wiki pageTitled:
                        request identifier last].

Reduced time from .31 seconds to .28 seconds.
Process of improving performance
Measure performance.
Make change.
Run tests, measure performance.
Undo changes if they don’t improve
Repeat until performance is good enough.
Performance Strategy
Make performance targets
  (e.g.<2 seconds)
Try out improvements
Only install ones that help
Stop when you reach your targets
Better algorithms
Optimize low-level design
   cache

   simplify

   reuse objects

   inline objects and methods

   Smalltalk specific
Store result in variable and reuse it instead of
  recomputing it.
    Move expression out of loop.

    Store method result in instance variable.

You must recompute the result when the
  values it depends on change.
Instead of using powerful, easy to use objects,
  use simple and efficient ones.
    Arrays instead of OrderedCollection

    Symbol instead of String
Reuse objects
Creating and collecting objects can take a lot
  of time.
Use AllocationProfiler
1) Keep a list of unused objects
2) Change object rather than make new one
Make sure object is really unused!
Inline objects and methods
Lots of small methods can take time.
Replace messages in inner loops with the
bodies of the methods they call.
To eliminate access to an object‟s instance
  variables, eliminate object and put its
  instance variables in the calling class.

This is ugly -- a step of last resort.
Smalltalk specific
Make collections of right sizes
Use streams to concatenate
Avoid blocks
Avoid reflective programming
Make Collections of Right Size
Many Collections grow: Set, Dictionary,
Growing requires copying, which takes time.
Make Collections large enough that they don‟t
 have to grow very often.

OrderedCollection new: 20
Use Streams to Concatenate
result := „‟.
names do: [:each | result := result , each].

result := WriteStream on: (String new: 50).
names do: [:each | result nextPutAll: each].
result contents
Avoid Blocks
Blocks are used for
   powerful control structures

   parameterizing objects

   in-line the algorithms

   make subclasses
Inlining blocks
Compiler optimizes whileTrue:, to:do:, ifTrue:
 and does not create a block for them.

(1 to: 100) collect: [:each | each * each]

result := Array new: 100.
1 to: 100 do: [:each | result at: each put: each
  * each]
Avoid Reflection
perform:, doesNotUnderstand: can make
  programs much smaller and eliminate
  coding work.
They are slower than a normal message send.
60% - Functionality
25% - Refactoring
15% - Performance tuning

Good performance takes work, so schedule
 time for it.
Performance depends more on the
  programmer than on the programming
Functionality and good design are harder to
  achieve than good performance.
Don‟t let your need for good performance
  prevent you from making a good design.

To top