MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
2
MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
4
MediaGeniXMediaGeniX
Application Overview
WHATS‟On
Client – Server Application
Client = Smalltalk
Server = Oracle Relational Database
5
MediaGeniXMediaGeniX
Application Overview
1.6 Million Lines Of Code
+12.000 Classes
+4.500 System Classes
190.000 Methods
6
MediaGeniXMediaGeniX
Application Overview
600 database tables
9000 table columns
40+ million rows of data
200 concurrent users
7
MediaGeniXMediaGeniX
Application Overview
Many customisations
Product(12.000 classes)
MTV50 classes
VRT100 classes
RTBF20 classes
VT4200 classes
VTM250 classes
YLE/fi300 classesTV2/dk
120 classes
NRK/No500 classes
Pro7/ger600 classes
11
MediaGeniXMediaGeniX
Application Overview
Multi Language
300 Application Windows
40 Optional Modules
12
MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
14
MediaGeniXMediaGeniX
Smalltalk
Wikipedia:
“Object oriented, dynamically typed,
reflective programming language”
Created during the 70s16
MediaGeniXMediaGeniX
Smalltalk
Dynamically Typed
exampleMethod
| a b |
a := „Hello ‟.
b := „World‟.
^a, b
„Hello World‟
17
MediaGeniXMediaGeniX
Smalltalk
Everything is an object
Every class can be extended
Integer>>abs
^ self < 0
ifTrue: [0 - self]
ifFalse: [self]
18
MediaGeniXMediaGeniX
Smalltalk
-5 abs
Integer>>abs
^ self < 0
ifTrue: [0 - self]
ifFalse: [self]
-5
19
MediaGeniXMediaGeniX
Smalltalk
Code is an object – a “BlockClosure”
anArray do: [:item | item doSomething]
In Scheme:
(lambda(item) (…))
Java is working on this
20
MediaGeniXMediaGeniX
Smalltalk
“Sort all persons alphabetically on
firstName”
persons sortedOn: #firstName
22
MediaGeniXMediaGeniX
Smalltalk
“Which persons are married?”
persons select: [:each | each isMarried]
23
MediaGeniXMediaGeniX
Smalltalk
Smalltalk is written in itself
Classes
Methods
Compiled code
Objects that can be accessed by your own
code
Very good reflection capabilities
26
MediaGeniXMediaGeniX
Smalltalk
Incremental Compilation
Smalltalk system is „alive‟
Your code is always running
Code changes take effect immediately
No compilation/build wait times
Huge timesaver
27
MediaGeniXMediaGeniX
Smalltalk
Easy to dynamically generate code
Used for performance tuning[:t1 :t2 :t3 :t4 :t5 :t6 |
| t7 |
t7 := t2 at: t3.
t1 basicStateAt: 1 put: t7.
(t7 := t2 at: t3 + 1) == nil ifFalse: [t7 := t5 unprotectedObjectStateOrProxyForStorageClassIndex: 125 basicId: t7].
t1 basicStateAt: 2 put: t7.
(t7 := t2 at: t3 + 2) == nil ifFalse: [t7 := t5 unprotectedObjectStateOrProxyForStorageClassIndex: 125 basicId: t7].
t1 basicStateAt: 3 put: t7.
t7 := t2 at: t3 + 3.
t1 basicStateAt: 4 put: t7.
t7 := t2 at: t3 + 4.
t1 basicStateAt: 5 put: t7.
t7 := t2 at: t3 + 5.
t1 basicStateAt: 6 put: t7.
t7 := t2 at: t3 + 6.
t1 basicStateAt: 7 put: t7.
t7 := t2 at: t3 + 7.
t1 basicStateAt: 8 put: t7]28
MediaGeniXMediaGeniX
Smalltalk
IDE is written in Smalltalk
Source code is available
Easily extensible
Keyboard Shortcuts
Change the Compiler
30
MediaGeniXMediaGeniX
Smalltalk
Is Smalltalk better than the rest?
I wouldn‟t say that
It was a given
Product started early „90s
A failed attempt to move to Java
Smalltalk has very interesting features
32
MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
33
MediaGeniXMediaGeniX
Development
Database interaction
Building user interfaces
Customer specific changes
34
MediaGeniXMediaGeniX
Development
Model driven approach
Use meta information about domain model to
automate tasks and to promote reuse
35
MediaGeniXMediaGeniX
Example Model
Requirements:
User interface for editing
Store in relational database
Possibility to export as XML file
36
MediaGeniXMediaGeniX
XML
<Person>
<firstName>Angelina</firstName>
<lastName>Jolie</lastName>
<birthDate>04/06/1975</birthDate>
<isMarried>Yes</isMarried>
</Person>
39
MediaGeniXMediaGeniX
Super Model
Person>>buildSuperModelWith: aBuilder
aBuilder
dbTableName: „Person';
xmlTagName: 'Person'.
aBuilder
addString: #firstName dbName: 'firstName' uiName: 'Voornaam' xmlTag: 'firstName';
beMandatory;
addString: #lastName dbName: 'lastName' uiName: 'Familienaam' xmlTag: 'lastName';
beMandatory;
addDate: #birthDate dbName: 'birthDate' uiName: 'Geboortedatum' xmlTag: 'birthDate';
addBoolean: #isMarried dbName: 'isMarried' uiName: 'Getrouwd' xmlTag: 'isMarried' initialValue: false
41
MediaGeniXMediaGeniX
DB Mapping
Generate DB creation scripts
create table person(
firstname varchar2(100) not null,
lastname varchar2(100) not null,
birthdate date,
ismarried number(1,0));
43
MediaGeniXMediaGeniX
DB Mapping
Put objects into databasedbSession inTransactionWhile: [
person := Person new.
person firstName: „Angelina‟.
person lastName: „Jolie‟].
INSERT INTO person(oid, firstName, lastName)
VALUES (12345, „Angelina‟, „Jolie‟);
45
MediaGeniXMediaGeniX
DB Mapping
Read objects from DB
Person retrieveWhere: [:each |
(each firstName = „Angelina‟) &
(each isMarried)]
SELECT * FROM person
WHERE firstName = ‘Angelina’ AND isMarried = 1;
46
MediaGeniXMediaGeniX
DB Installation
Automation possible because of meta
information
Automate repetitive work
47
MediaGeniXMediaGeniX
Super Model
addString: #firstName dbName: „firstName' uiName: „Voornaam' xmlTag: „firstName';
addBoolean: #isMarried dbName: „isMarried' uiName: „Getrouwd' xmlTag: „isMarried';
51
MediaGeniXMediaGeniX
Form Panel
| panel |
panel := self newFormPanel: 1.
panel
addFormEntryFor: #firstName;
addFormEntryFor: #lastName;
addFormEntryFor: #birthDate;
addFormEntryFor: #isMarried.
^panel
52
MediaGeniXMediaGeniX
Form Panel
Adding fields is easy
| panel |
panel := self newFormPanel: 1.
panel
addFormEntryFor: #firstName;
addFormEntryFor: #lastName;
addFormEntryFor: #hobby;
addFormEntryFor: #birthDate;
addFormEntryFor: #isMarried.
^panel
53
MediaGeniXMediaGeniX
Form Panel
Customisations?
Product(12.000 classes)
MTV50 classes
We want a „Hobby‟ field
55
MediaGeniXMediaGeniX
Customer Specific Layout
Standard Product/All customers
MTVExtra field „Hobby‟
56
MediaGeniXMediaGeniX
Customer Specific Layout
Customer specific layouts
| panel |
panel := self newFormPanel: 1.
panel
addFormEntryFor: #firstName;
addFormEntryFor: #lastName.
self addCustomerSpecificFieldsTo: panel.
panel
addFormEntryFor: #birthDate;
addFormEntryFor: #isMarried.
^panel
58
MediaGeniXMediaGeniX
Customer Specific Layout
addCustomerSpecificFieldsTo: aFormPanel
aFormPanel addFormEntryFor: #hobby
addCustomerSpecificFieldsTo: aFormPanel
“Do nothing”
59
MediaGeniXMediaGeniX
Customer Specific Layout
Customer specific layouts
| panel |
panel := self newFormPanel: 1.
panel
addFormEntryFor: #firstName;
addFormEntryFor: #lastName.
self addCustomerSpecificFieldsTo: panel.
panel
addFormEntryFor: #birthDate;
addFormEntryFor: #isMarried.
^panel
Will add a #hobby field for MTV customer
60
MediaGeniXMediaGeniX
Customer Specific Layout
If product evolves, MTV will evolve too
| panel |
panel := self newFormPanel: 1.
panel
addFormEntryFor: #firstName;
addFormEntryFor: #lastName;
addFormEntryFor: #address.
self addCustomerSpecificFieldsTo: panel.
panel
addFormEntryFor: #birthDate;
addFormEntryFor: #isMarried.
^panel62
MediaGeniXMediaGeniX
Multi Language UI
Person>>buildSuperModelWith: aBuilder
aBuilder
dbTableName: „Person';
xmlTagName: 'Person'.
aBuilder
addString: #firstName dbName: 'firstName' uiName: 'Voornaam' xmlTag: 'firstName';
beMandatory;
addString: #lastName dbName: 'lastName' uiName: 'Familienaam' xmlTag: 'lastName';
beMandatory;
addDate: #birthDate dbName: 'birthDate' uiName: 'Geboortedatum' xmlTag: 'birthDate';
addBoolean: #isMarried dbName: 'isMarried' uiName: 'Getrouwd' xmlTag: 'isMarried'
initialValue: false;
64
MediaGeniXMediaGeniX
UI
SuperModel rules applied in *every*
application window
Write once – reuse many times
Avoid repetitive work
66
MediaGeniXMediaGeniX
Super Model
Person>>buildSuperModelWith: aBuilder
aBuilder
dbTableName: „Person';
xmlTagName: 'Person'.
aBuilder
addString: #firstName dbName: 'firstName' uiName: 'Voornaam' xmlTag: 'firstName';
beMandatory;
addString: #lastName dbName: 'lastName' uiName: 'Familienaam' xmlTag: 'lastName';
beMandatory;
addDate: #birthDate dbName: 'birthDate' uiName: 'Geboortedatum' xmlTag: 'birthDate';
addBoolean: #isMarried dbName: 'isMarried' uiName: 'Getrouwd' xmlTag: 'isMarried' initialValue: false
68
MediaGeniXMediaGeniX
XML
aPerson asXML
„<Person>
<firstName>Angelina</firstName>
<lastName>Jolie</lastName>
<birthDate>04/06/1975</birthDate>
<isMarried>Yes</isMarried>
</Person>‟69
MediaGeniXMediaGeniX
Development Conclusion
Meta information
Automate database interaction
UI building
Reuse UI logic
XML
End-user tools that navigate through model
72
MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
73
MediaGeniXMediaGeniX
Automated Testing
How can you guarantee that your software
keeps on running when changes are made to
the code?
74
MediaGeniXMediaGeniX
Automated Testing
Manual testing…
…1.6 million lines of code
…and +30 customers
77
MediaGeniXMediaGeniX
Automated Testing
Manual testing…
…1.6 million lines of code
…and +30 customers
…repetitive work 78
MediaGeniXMediaGeniX
Automated Testing
“TestCase classes” (JUnit, SUnit)
InvoiceTestCase
PersonTestCase
…
+1.300 TestCase classes
+20.000 test_<something> methods
80
MediaGeniXMediaGeniX
Automated Testing
Acceptance tests
Test the application logic from the point of view of
an end user
No individual methods
Complete flow from user interface to database and
back
We have lots of them (+20.000)
82
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: „Angelina‟ lastName: „Jolie‟.
self deny: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)]).
PersonEditor openOn: person.
self editField: #firstName value: „Bruce‟.
self editField: #lastName value: „Willis‟.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)])
83
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: ‘Angelina’ lastName: ‘Jolie’.
self deny: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)]).
PersonEditor openOn: person.
self editField: #firstName value: „Bruce‟.
self editField: #lastName value: „Willis‟.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)])
85
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: „Angelina‟ lastName: „Jolie‟.
self deny: (Person
existsWhere: [:person | (person firstName = ‘Bruce’) & (person lastName = ‘Willis’)].
PersonEditor openOn: person.
self editField: #firstName value: „Bruce‟.
self editField: #lastName value: „Willis‟.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)])
86
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: „Angelina‟ lastName: „Jolie‟.
self deny: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)]).
PersonEditor openOn: person.
self editField: #firstName value: „Bruce‟.
self editField: #lastName value: „Willis‟.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)])
87
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: „Angelina‟ lastName: „Jolie‟.
self deny: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)]).
PersonEditor openOn: person.
self editField: #firstName value: ‘Bruce’.
self editField: #lastName value: ‘Willis’.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)])
89
MediaGeniXMediaGeniX
Automated Testing
test_editPerson
| person|
person := self personPopulator createPersonWithFirstName: „Angelina‟ lastName: „Jolie‟.
self deny: (Person
existsWhere: [:person | (person firstName = „Bruce‟) & (person lastName = „Willis‟)]).
PersonEditor openOn: person.
self editField: #firstName value: „Bruce‟.
self editField: #lastName value: „Willis‟.
self toolBarPress: #saveCommand.
self assert: (Person
existsWhere: [:person | (person firstName = ‘Bruce’) & (person lastName = ‘Willis’)])
91
MediaGeniXMediaGeniX
Automated Testing
Typical scenario
Set up initial data
Assert that the condition you‟re going to test is
NOT met
Do some stuff
Assert that the condition you‟re going to test IS met
92
MediaGeniXMediaGeniX
Automated Testing
Regression tests
If someone inadvertently changes behavior the
tests should detect it
93
MediaGeniXMediaGeniX
Automated Testing
They are crucial
You cannot manually test a large
application
94
MediaGeniXMediaGeniX
Automated Testing
Parallel execution
16 computers
30 minutes to get results
DEMO “Autoblader”
DEMO “Test Slave”96
MediaGeniXMediaGeniX
Tests
Tests need to be maintained
Functionality changes
tests need to be changed
100
MediaGeniXMediaGeniX
Tests
Conclusion
Automated – avoid repetitive work
Crucial
Impact on project time
102
MediaGeniXMediaGeniX
Agenda
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
103
MediaGeniXMediaGeniX
Agile Software Development
25 Developers
10 Analysts
30 Customers wanting new stuff
Product itself has to evolve too
104
MediaGeniXMediaGeniX
Agile Software Development
Group of software development
methodologies
“Lightweight”
107
MediaGeniXMediaGeniX
Agile Software Development
Based on natural principles
Ask customer what he wants
Regularly show him what you made
Continuously ask his feedback
Customer gets what he wants
108
MediaGeniXMediaGeniX
Agile Software Development
Agile Manifesto
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
109
MediaGeniXMediaGeniX
Agile Software Development
Example implementations
Scrum
Extreme programming (XP)
110
MediaGeniXMediaGeniX
Agile Software Development
Not always that easy
Customers don‟t want to be
bothered all the time
They have a real job to do
111
MediaGeniXMediaGeniX
Agile Software Development
Customers don‟t want to install
and test a new version every
day
113
MediaGeniXMediaGeniX
Agile Software Development
Customers want contractual
agreement
Required functionality
Deadline
Fixed price
114
MediaGeniXMediaGeniX
Agile Software Development
Proxy Customer
Knows everything about the
customer
116
MediaGeniXMediaGeniX
Agile Software Development
Analyst = Proxy Customer
3 analysts for every 10 customers
They talk with development team
They give demo‟s to customer
117
MediaGeniXMediaGeniX
Scrum
Divide work into “sprints”
2 weeks
Divide sprints into “user stories”
1-3 days of work
All tests should be running
119
MediaGeniXMediaGeniX
Extreme programming
Code Reviews
Somebody else reviews your code
You can work concentrated
You get the chance to learn things, try things out
*Before* it gets published in code repository
126
MediaGeniXMediaGeniX
Extreme programming
Code Reviews
We only review beginners code
Not enough time to review everything
127
MediaGeniXMediaGeniX
Final conclusion
Application Overview
Smalltalk
Model Driven Development
Automated Testing
Agile Software Development
129