Sie sind auf Seite 1von 48

BLAISE

BLAISE PASCAL
PASCAL MAGAZINE
MAGAZINE
D E L P H I, L A Z A R U S, O X Y G E N E, S M A R T M O B I L E,
A N D P A S C AL
A N D R O I D, I O S,
R E L A T E D
M A C,
L A N G U A G E S
W I N D O W S & L I N U X
40

D E L P H I - S T E P H E N B A L L
- I N T E R B A S E C H A N G E V I E W S

D E L P H I XE 8 - P A W E L G L O W A C K I
- I N T R O D U C T I O N T O F L A T B O X 2D

D E L P H I - D E T L E F O V E R B E E K
F R O M D E L P H I T O D E L P H I
W H Y T H E N A M E D E L P H I

D E L P H I - C A R Y J E N S E N - C L I E N T D A T A S E T S
A N D FD M E M T A B L E S C O M P A R E D: P A R T 2

S T A R T W I T H F U N C T I O N T E S T I N G (M A X B O X)
- M A X K L E I N E R

D E L P H I - J E R E M Y N O R T H
W O R K I N G W I T H B E A C O N S I N D E L P H I XE 8

P R I N T E D I S S U E P R I C E 1 5, 0 0
D O W N L O A D I S S U E P R I C E 5, 0 0
BLAISE
BLAISE PASCAL MAGAZINE 40
PASCAL MAGAZINE
D E L P H I, L A Z A R U S, S M A R T M O B I L E S T U D I O,
A N D P A S C A L R E L A T E D L A N G U A G E S
F O R A N D R O I D, I O S, M A C, W I N D O W S & L I N U X

CONTENTS

Articles

Interbase Change Views


- By Stephen Ball Page 5
From Delphi to Delphi, overview of the Delphi history
- By Editor Page 8
Delphi - the city
- By Editor Page 13
Why the name Delphi?
- By Editor Page 14
Introduction to FlatBox2D for Delphi XE8
- By Pawel Glowacki Page 16
ClientDataSets and FDMemTables Compared: Part 2
- Cary Jensen Page 24
Start with Function Testing (maXbox)
- By MaxKleiner Page 31
Working with Bluetooth beacons in Delphi XE8
- Jeremy North Page 40

MOTION

BLAISE
BLAISE PASCAL
PASCAL MAGAZINE
MAGAZINE

Advertisers

Barnsten 11
BetterOffice 36
BLAISE PASCAL MAGAZINE 4
Cary Jensen (Jensen Data Sytems) 30
Components 4 Developers 48
Computer Math & Games 4
Daniel Teti 12
FAST REPORT 22/23
Raize Software 39 Publisher: Foundation for Supporting the Pascal Programming Language
in collaboration with the Dutch Pascal User Group (Pascal Gebruikers Groep)
Visuino MITOV 45 Stichting Ondersteuning Programmeertaal Pascal

2 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


Stephen Ball Peter Bijlsma Michal Van Canneyt,
http://delphiaball.co.uk -Editor peter @ blaisepascal.eu michael @ freepascal.org
@DelphiABall

Marco Cant David Dirkse Daniele Teti


www.marcocantu.com www.davdata.nl www.danieleteti.it
marco.cantu @ gmail.com E-mail: David @ davdata.nl d.teti@bittime.it

Bruno Fierens Primo Gabrijeli


www.tmssoftware.com www.
bruno.fierens @ tmssoftware.com primoz @ gabrijelcic.org

Cary Jensen Max Kleiner Wagner R. Landgraf


www.jensendatasystems.com www.softwareschule.ch wagner @ tmssoftware.com
http://caryjensen.blogspot.nl max@kleiner.com

Kim Madsen
www.component4developers

Jeremy North Benno Evers


jeremy.north @ gmail.com b.evers
@everscustomtechnology.nl

Detlef Overbeek Howard Page Clark Rik Smit


www.blaisepascal.eu E-mail: hdpc @ talktalk.net -Editor rik @ blaisepascal.eu
Email:editor @ blaisepascal.eu

Bob Swart Wim Van Ingen Schenau


www.eBob42.com -Editor
Bob @ eBob42.com wisone @ xs4all.nl

Please note: extra space characters have been deliberately added around the @ symbol in
these email addresses, which need to be removed if you use them.
editor @ blaisepascal.eu
Authors - Christian name in alphabethical order
A Alexander Alexeev, L Wagner R. Landgraf, Sergey Lyubeznyy
B Stephen Ball, Peter Bijlsma, Dmitry Boyarintsev K Max Kleiner
C Michal Van Canneyt, Marco Cant, M Kim Madsen, Felipe Monteiro de Cavalho
D David Dirkse, Daniele Teti N Jeremy North,
F Bruno Fierens O Tim Opsteeg, Inoussa Ouedraogo
G Primo Gabrijeli, Mattias Gaertner P Howard Page-Clark,
H Fikret Hasovic S Rik Smit, Bob Swart,
J Cary Jensen Z Siegfried Zuhr

Editor - in - chief
Detlef D. Overbeek, Netherlands Tel.: +31 (0)30 890.66.44 / Mobile: +31 (0)6 21.23.62.68
News and Press Releases email only to editor@blaisepascal.eu

Editors
Peter Bijlsma, W. (Wim) van Ingen Schenau, Rik Smit,
Correctors
Howard Page-Clark, James D. Duff
Trademarks
All trademarks used are acknowledged as the property of their respective owners.
Caveat Whilst we endeavour to ensure that what is published in the magazine is correct, we cannot accept responsibility for any errors or omissions.
If you notice something which may be incorrect, please contact the Editor and we will publish a correction where relevant.
Subscriptions ( 2013 prices )
1: Printed version: subscription 65.-- Incl. VAT 6 % (including code, programs and printed magazine,
10 issues per year excluding postage).
2: Electronic - non printed subscription 45.-- Incl. VAT 21% (including code, programs and download magazine)

Subscriptions can be taken out online at www.blaisepascal.eu or by written order, or by sending an email to office@blaisepascal.eu
Subscriptions can start at any date. All issues published in the calendar year of the subscription will be sent as well.
Subscriptions run 365 days. Subscriptions will not be prolonged without notice. Receipt of payment will be sent by email.
Subscriptions can be paid by sending the payment to:
ABN AMRO Bank Account no. 44 19 60 863 or by credit card: Paypal
Name: Pro Pascal Foundation-Foundation for Supporting the Pascal Programming Language (Stichting Ondersteuning Programeertaal Pascal)
IBAN: NL82 ABNA 0441960863 BIC ABNANL2A VAT no.: 81 42 54 147 (Stichting Programmeertaal Pascal)
Subscription department Edelstenenbaan 21 / 3402 XA IJsselstein, The Netherlands / Tel.: + 31 (0) 30 890.66.44 / Mobile: + 31 (0) 6 21.23.62.68
office@blaisepascal.eu

Copyright notice
All material published in Blaise Pascal is copyright SOPP Stichting Ondersteuning Programeertaal Pascal unless otherwise noted and may
not be copied, distributed or republished without written permission. Authors agree that code associated with their articles will be made
available to subscribers after publication by placing it on the website of the PGG for download, and that articles and code will be placed on
distributable data storage media. Use of program listings by subscribers for research and study purposes is allowed, but not for commercial
purposes. Commercial use of program listings and code is prohibited without the written permission of the author.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 3


DAVID DIRKSE
presales at
www.blaisepascal.eu/DavidDirkse/ComputerMath_Games.html

procedure ;
var
begin
for i := 1 to 9 do
begin

end;
end;

BLAISE PASCAL MAGAZINE


is proud to announce the first
edition of David Dirkses book:

COMPUTER MATH &


GAMES IN PASCAL
INTERBASE CHANGE VIEWS
starter expert Multiple devices per subscriber
Delphi XE 7 In addition to allowing specific users to
BY STEPHEN BALL subscribe to data, you can use a single user
to have multiple destinations that are
This is an article on InterBase Change subscribing. This allows a user to subscribe
Views and is intended to be a high level
for different devices such as their Phone,
overview of the new powerful change view
technology that is patent pending and part Tablet, Laptop or for a single user to be
of InterBase. Following this post I plan to used programatically to distinguish
show more posts taking the concept of multiple sites e.g. Office 1, Office 2 etc.
Change Views into the real world with This is done using the at verb when
some real application examples. connecting to the subscription.
What Change Views are not!
InterBase Change Views Change Views are not an auditing system.
InterBase XE7 introduces a new way to track
While you can track deleted records, Change
data changes to the database called Change
View are about identifying what has changed
Views.
without keeping every value that it has been. If
you want to do that, then continue to use
Change Views are a new subscription based
Triggers and logging tables for the values you
model allowing you to subscribe to data; once
need to audit.
subscribed you are able to ask the database at a
later time, spanning connections, for what has Creating a Change View
changed. If you have ever spent time planning how to
identify what data has changed, then change
This is an especially cool, low cost way to views is about to simplify the way you develop
reduce network traffic, mobile data costs and for ever!
development time when tasked with keeping
multiple remote database caches up to date. Steps for creating a Change View
(especially if you have large tables to keep up dated). Rather than having to create and manage
triggers to add records into log tables or
Change Views reduce the upfront planning planning additional date fields into your
required, reduce the risk of errors and metadata (and hoping date & time changes
drastically make simpler the task of building in dont effect you) Change View are easily added
data change tracking.. to a project once the simplified architecture is
complete.
Best of all change views has zero impact on
database performance regardless of the number There are two essential steps in creating a
of subscribers! successful change view:

Subscription & Subscribers Defining the purpose of the Change View


A core concept to change views is that of and the data you want to track.
Subscriptions and Subscribers. Defining who can subscribe to the change
InterBase Change view allows multiple view.
subscribers to a subscription.

A subscription is defined once and then can be


connected to by multiple users. Once defined,
you can control who can subscribe thanks to the
InterBase inbuilt user security. InterBase XE7 is a full-featured, high performance,
encryptable, multiplatform and scalable relational
Subscriptions work at field level and can be database for developers who are looking to embed a
low-cost, zero admin, lightweight secure database
defined to track either an entire table or
into their cross platform connected applications.
multiple tables. Subscriptions can also be With InterBase XE7 you get powerful
defined to track Inserts, Updates or Deletes (or access control, data change
a mix of) management, disaster recovery and
journaling, as well as support for
popular database drivers for increased
deployment flexibility.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 5


INTERBASE CHANGE VIEWS (CONTINUATION 1)

1 Creating a change view Example 3 Tracking Deletes


Lets start with a simple example. We want to
keep our sales fulfilment application up-to-date We may also want to track deletions from a
with the latest stock and suppliers information. specific table, lets say ORDERS. A Change
This data is stored in two tables, INVENTORY Views just tracking DELETE activity on a table
and SUPPLIERS.
CREATE SUBSCRIPTION
Example 1 Multiple Tables sub_orderDeletes
ON
CREATE SUBSCRIPTION ORDERS FOR
sub_stock ROW (DELETE)
ON DESCRIPTION 'Track Order Deletions';
INVENTORY FOR ROW (INSERT, UPDATE,
DELETE), Using a Change View to track deletes is a
SUPPLIERS FOR ROW (INSERT, UPDATE, powerful feature as you can completely recover
DELETE) the record at its state when it was deleted.
DESCRIPTION 'Track stock and
supplier changes';
2 Defining who can use a change
Subscriptions are created with the CREATE
view / subscription
SUBSCRIPTION statement followed by a
subscription name that you will need to use in Once a subscription is created, you need to
SQL later on. grant SUBSCRIBE access to the subscription.
The simple example tracks all columns in the To do this use the standard GRANT syntax. e.g.
tables INVENTORY and SUPPLIERS for Inserts, (for user SYSDBA)
Updates and Deletes.
The description allows easy identification of the GRANT SUBSCRIBE ON SUBSCRIPTION
subscriptions purpose later on. sub_stock TO SYSDBA;
Example 2 Specifying Columns
In the comming instructions we are going to
We may have a requirement to track product explore how to use a Change View to collect
name changes for our application. We can do data that has changed in your subscription.
this also with a change view.
CREATE SUBSCRIPTION Using an InterBase Change View to fetch data
sub_stockname deltas
ON
INVENTORY(ITEM_NAME) FOR Once a Change View Subscription has been
ROW (INSERT, UPDATE, DELETE) created and access to it has been granted (to
DESCRIPTION 'Track stock name either users or roles), then its time to start using
changes'; your Change View!
Example 2 is more granular than Example 1
and tracks only a single column ITEM_NAME in The following steps are the high level overview
the INVENTORY table. of using a Change View.
This is done by providing a comma separated
list of field names for the table that you want to Start a Transaction in SnapShot isolation
track. mode.
Set the Subscription active
Run your select statement to fetch you delta
Once you have collected the delta commit
Here you can see the your transaction to bring your Change View up
embedded Video for InterBase. to date.
That means if you click on the
item in the pdf file you can see
the video without use of the
internet...

6 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


INTERBASE CHANGE VIEWS (CONTINUATION 2 - END)

SnapShot Mode Preventing you data changes showing in your


A bit of background as we all love to know how Change View delta
things work..
So we have covered selecting data, but what
InterBase is powered by a multi-generational about updating data? How do you stop the
architecture which is exceptionally useful when changes to data you make appearing in your
data integrity is important. imagine you need to subscription yet still available to others? Well
run multiple financial reports while the system is simply, make the changes while your
live; Imagine a connection drops part way subscription is active.
through a big data change how do you know
what has changed? Multi-generational Start a Transaction in SnapShot isolation
architectures and transactions makes this mode.
possible. Set the Subscription active (using your ID)
Run your update statement to modify the data
Using a transaction set to SnapShot mode we Commit your transaction.
have a stable point in time that means even if
records are updated at the same time as your Simples!
transaction, they are not missed. When you start
your next transaction you will locate those Introduction to Change Views Video on
concurrently made changes! imagine trying to Embarcadero website
do that with date time stamp tracking!

This means you can have multiple users


updating the data at the same time safely
without having to lock the tables

Setting the subscription active


At this point, lets pretend we have a
STOCK table and we run the following
statement

Select * from STOCK

the data returned would be all the


STOCK records. How do we get from
here to just getting changed data deltas? Well, To see a Change View code example see the
first we need to activate the subscription and InterBase XE7 FirstLook webinar:
provide an ID that we are going to track against. https://www.youtube.com/
watch?v=h5E1QvZ1rG8
set subscription sub_stock at
'DeviceID' active; About the Author:
Stephen Ball has lead development teams for
over a decade within the UK and across
With the subscription sub_stock active, running Europe working with a range of blue chip
the initial statement will again return all records companies including Hilton, American
as its the first time data has been requested in the Express, Fitness First, Virgin Active;
subscription.
Stephen is a Chartered IT Professional and is
At this point there are two possible next steps: the Associate Product Manager for InterBase
Commit or Rollback. and also a Product Evangelist for RAD Studio,
regularly speaking across EMEA.

Rollback of the transaction will ensure the data is Stephen Ball


provided again, Commit will bring the http://delphiaball.co.uk/2015/03/06/
Subscription up to date for the start of the interbase-change-views-example-demo-
transaction. skill-sprint/

Running the Select statement again in an active


transaction with the subscription active will now
return only deltas

6
Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 7
OVERVIEW OF DELPHI TO DELPHI HISTORY
DELPHI XE8
On February 8, 2006 Borland announced that it was looking for a
buyer for its IDE and database line of products, including Delphi, to
concentrate on its ALM line. On November 14, 2006 Borland transferred
the development tools group to an independent subsidiary company
named CodeGear, instead of selling it. Borland sold CodeGear to
Embarcadero Technologies in 2008.
Embarcadero Technologies in 2008. Embarcadero retained the
CodeGear division created by Borland to identify its tool and database Codegear Delphi 2007.
offerings, but identified its own database tools under the DatabaseGear
DELPHI 7 released in August 2002

DELPHI
released February 14, 1995
The roots of Turbo Pascal v1.0 started in Denmark.
The first step, in 1981, was the Blue Label Software Pascal Compiler Turbo Pascal
- BLS Pascal Compiler v1.2, copyright 1981 by Poly-Data microcenter ApS, Developer(s) Anders Hejlsberg while
Strandboulvarden 63, DK 2100 Copenhagen - working at Borland
written by Anders Hejlsberg for the NASCOM kit computer. Operating system CP/M, CP/M-86, DOS,
Windows 3.x, Macintosh
Lisa - Pascal was a Pascal implementation for the Apple Lisa workstation. Platform 8080/Z80, 8085, x86
It was an extension of the earlier Apple Pascal for Apple II machines,
but generated object code for 68000 processors that had to be linked
against the required libraries in the Lisa OS workshop. Windows
Lisa Pascal laid the foundation for the development of Clascal and Mac Pascal
the first implementations of Object Pascal.

Charles Babbage - mathematician Niklaus Wirth


conceived of the first programmable computer in the 1830 born February 15, 1934 He is a Swiss
Babbage never built his Difference Engine computer scientist, best known for
- a mechanical calculator with thousands of parts - designing several programming languages,
because of cost overruns and political disagreements, including Pascal, and for pioneering several
but the inventor passed on plans for its completion, classic topics in software engineering.
and in 1991, the Science Museum in London actually
built it (the printing component was finished in 2000).
As suspected, it actually works.

Blaise Pascal (19 June 1623 19 August 1662)


was a French mathematician,
physicist, inventor, writer and Christian philosopher. Discovery of America by Columbus
creates the first calculators Columbus led his three ships - the Nina,
Blaise Pascal starts to gamble - result first statistics the Pinta and the Santa Maria -
out of the Spanish port of Palos on August 3, 1492.

Discovery of Amerca by the Vikings 990 - 1050


Building of Spain 912 and Portugal 800
Building of France 5852 BC
Decay of the Roman Empire 500
Building of Europe

Archimedes Mathematician
Roman Empire 700 BC
Archimedes of Syracuse was an Ancient
Greek mathematician, physicist, engineer,
inventor, and astronomer.
He is regarded as one of the leading scientists
in classical antiquity. Wikipedia
Born: 287 - 212 BC, Syracuse, Italy

Plato in Classical Attic;


428/427 or 424/423 348/347 BC)
was a philosopher, as well as mathematician,
in Classical Greece.

Euclid Mathematician
Born Mid-4th century BC - 3rd century BC
Residence Alexandria, Hellenistic Egypt
Fields Mathematics Known for
Euclidean geometry / Euclid's Elements
Euclidean algorithm

Pythagoras Philosopher

as a separate pdf download in portrait format.


Pythagoras of Samos was an
Ionian Greek philosopher, mathematician,

A combined page 8/9 file is available at page 10


and founder of the religious movement
called Pythagoreanism.
Born: 571 - 495 BC,

Thales Philosopher
Thales of Miletus was a pre-Socratic Greek philosopher Difference Engine No. 1, portion,1832
from Miletus in Asia Minor and one of the
Seven Sages of Greece. Many, most notably Aristotle,
regard him as the first philosopher in the Greek tradition.
Born: 624 BC - 546

DELPHI
The cult of Apollo at

You can enlarge this yourself to view the information in greater detail.
Delphi probably
dates back to
the 700s B . C .,

Our authors plan to address each section of this timeline in future magazine articles.
WATER CLOCK - CHINA - BEGINNING OF TIME (BC 4000)
Some authors claim that water clocks appeared in China
as early as 4000 BC
Babbage Difference Engine No. 2
OVERVIEW OF DELPHI TO DELPHI HISTORY
DELPHI XE8
On February 8, 2006 Borland announced that it was
looking for a buyer for its IDE and database line of products,
including Delphi, to concentrate on its ALM line. On November
14, 2006 Borland transferred the development tools group to
Embarcadero Technologies in 2008.
an independent subsidiary company named CodeGear,
instead of selling it. Borland sold CodeGear to Embarcadero Codegear Delphi 2007.
Technologies in 2008. Embarcadero retained the CodeGear DELPHI 7 released in August 2002
division created by Borland to identify its tool and database
offerings, but identified its own database tools under the
DatabaseGear name. DELPHI
The roots of Turbo Pascal v1.0 started in Denmark. The first step,
released February 14, 1995
in 1981, was the Blue Label Software Pascal Compiler - BLS Pascal Turbo Pascal
Compiler v1.2, copyright 1981 by Poly-Data microcenter ApS, Developer(s) Anders Hejlsberg while
Strandboulvarden 63, DK 2100 Copenhagen - written by Anders working at Borland
Hejlsberg for the NASCOM kit computer. Operating system CP/M, CP/M-86, DOS,
Windows 3.x, Macintosh
Lisa - Pascal was a Pascal implementation for the Apple Lisa workstation. Platform 8080/Z80, 8085, x86
It was an extension of the earlier Apple Pascal for Apple II machines,
but generated object code for 68000 processors that had to be linked
against the required libraries in the Lisa OS workshop. Windows
Lisa Pascal laid the foundation for the development of Clascal and Mac Pascal
the first implementations of Object Pascal.

Charles Babbage - mathematician Niklaus Wirth


conceived of the first programmable computer in the 1830s born February 15, 1934 He is a Swiss
Babbage never built his Difference Engine computer scientist, best known for
- a mechanical calculator with thousands of parts - designing several programming languages,
because of cost overruns and political disagreements, including Pascal, and for pioneering several
but the inventor passed on plans for its completion, classic topics in software engineering.
and in 1991, the Science Museum in London actually
built it (the printing component was finished in 2000).
As suspected, it actually works.

Blaise Pascal (19 June 1623 19 August 1662)


was a French mathematician,
physicist, inventor, writer and Christian philosopher. Discovery of America by Columbus
creates the first calculators Columbus led his three ships - the Nina,
Blaise Pascal starts to gamble - result first statistics the Pinta and the Santa Maria -
out of the Spanish port of Palos on August 3, 1492.

Discovery of Amerca by the Vikings 990 - 1050


Building of Spain 912 and Portugal 800
Building of France 5852 BC

Decay of the Roman Empire 500


Building of Europe

Archimedes Mathematician
Roman Empire 700 BC
Archimedes of Syracuse was an Ancient
Greek mathematician, physicist, engineer,
inventor, and astronomer.
He is regarded as one of the leading scientists
in classical antiquity. Wikipedia
Born: 287 - 212 BC, Syracuse, Italy

Plato in Classical Attic;


428/427 or 424/423 348/347 BC)
was a philosopher, as well as mathematician,
in Classical Greece.

Euclid Mathematician
Born Mid-4th century BC - 3rd century BC
Residence Alexandria, Hellenistic Egypt
Fields Mathematics Known for
Euclidean geometry / Euclid's Elements
Euclidean algorithm

Pythagoras Philosopher
Pythagoras of Samos was an
Ionian Greek philosopher, mathematician,
and founder of the religious movement
called Pythagoreanism.
Born: 571 - 495 BC,

Thales Philosopher
Thales of Miletus was a pre-Socratic Greek philosopher Difference Engine No. 1, portion,1832
from Miletus in Asia Minor and one of the
Seven Sages of Greece. Many, most notably Aristotle,
regard him as the first philosopher in the Greek tradition.
Born: 624 BC - 546

DELPHI
The cult of Apollo at
Delphi probably
dates back to
the 700s B . C .,

WATER CLOCK - CHINA - BEGINNING OF TIME (BC 4000)


Some authors claim that water clocks appeared in China
as early as 4000 BC
Babbage Difference Engine No. 2
Click here for all information
and the introductory offer

or call: +31 (0)235422227


http://www.barnsten.com/default/newxe8
Quick answers to common problems

Delphi Cookbook
HOICE A
SC
50 hands-on recipes to master the power of Delphi for R BLAISE

M
TO

AZING
cross-platform and mobile development on Windows, PASCAL
DI
Mac OS X, Android, and iOS MAGAZINE
E

Daniele Teti

See our special offer:


10,00 if you subscribe
for two years..
30,00 including VAT
39 including the
printed book, ebook
and shipping
http://www.blaisepascal.eu/daniele_teti_book/DanieleTeti.html
DELPHI (THE CITY)

is both an archaeological site and a modern town Others relate that it was named Pytho and that
in Greece on the south-western spur of Mount Pythia, the priestess serving as the oracle, was
Parnassus in the valley of Phocis. In myths chosen from their ranks by a group of priestesses
dating to the classical period of Ancient Greece who officiated at the temple.
(510-323 BC), the site of Delphi was believed to Apollo's sacred precinct in Delphi was a
be determined by Zeus when he sought to find panhellenic sanctuary, where every four years,
the centre of his "Grandmother Earth" (Ge, Gaea, starting in 586 BC athletes from all over the Greek
or Gaia). He sent two eagles flying from the world competed in the Pythian Games, one of the
eastern and western extremities, and the path of four panhellenic (or stephanitic) games, precursors
the eagles crossed over Delphi where the of the Modern Olympics. The victors at Delphi
omphalos, or navel of Gaia was found. were presented with a laurel crown (stephanos)
which was ceremonially cut from a tree by a boy
who re-enacted the slaying of the Python. Delphi
was set apart from the other games sites because it
hosted the mousikos agon, musical competitions.

Earlier myths include traditions that Pythia, or


the Delphic oracle, already was the site of an
important oracle in the pre-classical Greek world
(as early as 1400 BC) and, rededicated, served as
the major site during classical times for the
worship of the god Apollo after he slew Python,
"a dragon" who lived there and protected the
navel of the Earth.
"Python" (derived from the verb pythein, "to rot")
is claimed by some to be the original name of the
site in recognition of Python which Apollo
defeated. The Homeric Hymn to Delphic Apollo
recalled that the ancient name of this site had
been Krisa

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 13


WHY THE NAME "DELPHI?"
Based on an article written in 1999 by building tool, a way to talk to
Danny Thorpe Oracle and other servers.

Borland (for a time Inprise), was the company How do you talk to an oracle?
that first developed Delphi. It later moved "The oracle at Delphi" was the word association
Delphi development to its CodeGear division, that occurred to Danny Thorpe during one of
which was acquired by Embarcadero many conversations in Gary's office about the
Technologies in 2008. Embarcadero continues to best codename.
develop the Delphi XE product line.
His suggestion wasn't an instant hit. It's an old
Borland considered that name, an old place, a pagan temple in the ruins
a new product codename of a dead civilization. Not exactly an inspiring
should have no obvious association for a new product! As some press
connection to the product, articles later noted, the Delphic Oracle was
so that if an eavesdropper famous for giving out cryptic or ambiguous
overheard the name in answers - not a great association for a data
conversation it would be management tool. Asking a question of the oracle
unclear which product was free to all, but having the oracle's answer
was being discussed. interpreted cost the enquirer many drachmas
One of the most memorable (although the marketing guys liked that part).
product codenames coined
at the company was Buddha (the insiders' Overall, though, the "Delphi" codename had a
alias for Quattro Pro 4.0, a direct 1-2-3 classier ring to it than most of the other
competitor). This was because Quattro Pro had suggestions that were offered. Pascal is a classic
to assume the Lotus position! programming language, so it felt appropriate to
associate a Pascal-based development tool with a
"Delphi" started out as a beta codename for a classical Greek brand. Many codenames were
closely guarded, innovative research project at used during the development of that version 1.0
Borland: a next-generation visual development product, a new one being coined for each press
environment for Windows based on Borland's or corporate briefing of the beta product, in the
Object Pascal programming language (until then hope of limiting rumours and allowing Borland
known as Turbo Pascal). to track the source of any leaks. The aim was to
Gary Whizin, the Borland R&D Manager for Microsoft to discover what Borland was up to
favoured the codename Oracle, since by mid- as late as possible.
1993 the strategic decision had been taken to
make database tools and connectivity a central
part of this new Pascal product,
which by then had six months of
intensive research, market
analysis and proof-of-concept
exercises behind it.

The research group involved less


than a dozen Borland staff including
Anders Hejlsberg,
Chuck Jazdzewski,
Allen Bauer, Zack Urlocker,
Richard Nelson, Danny Thorpe
and Gary Whizin.
However Gary's preference was
not shared by the rest of the
group who pointed out
the confusion with the identically
named company and their server
product, whereas the new Pascal
development environment was
(then) envisaged as a client

14 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


WHY THE NAME "DELPHI?" (CONTINUATION- END)

Towards the end of the development cycle,


Borland marketing dropped the temporary
codenames and started using the Delphi
codename across all prepress and corporate
briefings, and also as the codename for the final
beta releases.
That got the rumour mills talking to each other,
and the tools industry was abuzz with talk about
this secret project at Borland codenamed
"Delphi".

When it came time to pick a retail product name,


the nominations were less than inspiring.
The "functional" name (the name that describes what
the product actually does and is therefore easier to
market and sell), would have been AppBuilder.

This name actually still appears in some Delphi


IDE internals, such as the class name of the IDE
main window; but AppBuilder didn't inspire
people or work well internationally.
Functional names are only functional in their
language of origin.

A few months before Delphi was scheduled for


release Novell shipped their own product called
Visual AppBuilder, which finally laid the Borland
AppBuilder debate to rest.

With the functional name taken out of the


running, many Borlanders suggested using the
Delphi codename as the product name.
However the lead marketing person had
legitimate concerns about the extra effort required
to build name recognition in the marketplace for
an "iconic" (the opposite of a functional) product
name, so he requested a vote of the development
team, who had a large majority in favour of
Delphi. Wider market polls were conducted.

The harder people tried to dismiss "Delphi" as the


product name, the more it gained support.
"Delphi" has a classical ring to it.

The name has endured.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 15


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8
Pawe Gowacki (Embarcadero) The name flat comes from the fact that original
Box2D implementation was contained in many
smaller files and XE8 support combines these into
flat namespaces. If you examine the Box2D
Pascal source you will see the Embarcadero
copyright notice together with a note that these
units were generated by Delphi-C++ Library
Bridge. The naming convention adopted is for all
Box2D type names to start with b2
These Delphi units are interfaces to compiled
FlatBox2D libraries that need to be deployed with
a Delphi application target. There are four
potential platforms: two desktop (Windows, Mac
OSX) and two mobile (Android and iOS).
Additionally Windows and iOS have two
different compilers for 32-bit and 64-bit support.
You can find the names of these libraries at the
very beginning of the implementation section of
each FlatBox2D unit. The various versions of the
FlatBox2D libraries can be found in bin and
lib folders inside Delphi XE8 installation folders.
Physics engines They are named as follows, according to the
Welcome to the world of physics! platform and build configuration:
Welcome to the world of physics! It is difficult
Windows: FlatBox2DDyn.dll
to imagine a game or just a modern app with
a sophisticated user interface without Mac OS X: libFlatBox2DDyn.dylib
realistic physics effects. All programmed Android: libFlatBox2D.a
games include a software component called a iOS: libFlatBox2D.a
physics engine that is responsible for realistic
display of physical interactions such as the The source code for the FlatBox2D library units is
bouncing and collision of moving bodies. in the Browsing Path in Delphi's global options.
Complex physics engines can simulate the
A programmer does not need to do anything to
interaction of objects in a 3D space; however
commonly physics simulations are simplified use them beyond adding Box2D to the uses
by being restricted just two dimensions. clauses in your project's units!
Probably the best-known physics engine is
Box2D, used in many popular games,
including super hits like Angry Birds. Box2D
was originally written by Erin Catto and is an
open source C++ library available under the
permissive zlib free software license.

FlatBox2D
Delphi XE8, C++Builder XE8 and RAD
Studio XE8 are introducing support for
a 2D physics engine based on Box2D.
You can find a new FlatBox2D folder
under Source in the default XE8
installation directory.
It contains some C++ header and source files and
five Object Pascal units:
Box2D.Common.pas
Box2D.Collision.pas
Box2D.Dynamics.pas
Box2D.Rope.pas
Box2DTypes.pas

16 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8 (CONTINUATION 1)

Hello World procedure TForm1.Button1Click(Sender: TObject);


We commonly explore new var
software or libraries by trying gravity: b2Vec2;
to build a Hello World app, world: b2WorldWrapper;
begin
and FlatBox2D is no different! // Define the gravity vector
On the Box2D home page there gravity := b2Vec2.Create(0.0, -10.0);
is a very nice manual // Construct a world object, which will hold and simulate the rigid bodies
(http://box2d.org/manual.pdf) world := b2WorldWrapper.Create(gravity);
that explains all the important try
concepts of Box2D. Chapter 2 // work with "world"
finally
contains a Hello World world.Destroy;
project with detailed comments. end;
Delphi XE8 contains a end;
1:1 translation of this demo
project into the Object Pascal
language. Rather than discussing the full Box2D The Box2D engine uses MKS units (short for
functionality which you can gather from the Meter-Kilogram-Second) in simulating the
manual, let's have a walk through the behavior of bodies in the physical world.
FlatBox2DObjPasHelloWorld multi-device For example, when we pass a gravity vector to our
project that you can find in the Object Pascal world's Create method we usually mean the
Mobile Samples in the default installation of Earth's gravity, which points downwards and is
Delphi XE8 approximately 10 meters per second squared
(C:\Users\Public\Documents\Embarcader (m/s2).
o\Studio\16.0\Samples\Object Box2D has been optimized to work well with
Pascal\Mobile
shapes moving between 0.1 and 10 m/s. All angles
Samples\Physics\Box2DHello\).
are expressed in radians (not in degrees).
In the project there is only one form with a
Once we have a world object, we can add
button and a memo. All the demo code is in the
bodies and joints to it. Joints connect bodies
OnClick event of the button.
together by removing certain degrees of freedom
of the physical objects that are part of the
The first thing is to make sure that all relevant
simulation.
Box2D units are in the uses clause of the form.
Box2D is a rigid body engine, which means
uses that bodies are not elastic. In other words the
Box2D.Common, Box2D.Collision, Box2D.Dynamics;
distance between any two points of a given body
is always constant. This contrasts wtih the more
The main class in Box2D is the World. World is complex soft body physics that can be used to
a container for all objects that make up the model behavior of, say, clothing, in which
simulation. The Box2D.Dynamics unit defines a distances between arbitrary points of a sock may
b2WorldWrapper record type that change as it slides down a leg of unchanging
encapsulates FHandle: b2WorldHandle that length.
points to the actual b2World instance inside of It is important to realize that Box2D has its
the compiled FlatBox2D library. own memory management optimized for working
The b2WorldWrapper contains a class with large numbers of transient small objects.
function Create that acts very much like a Hence when you want to add bodies and other
typical Delphi constructor and initializes an objects to the world, you do not use constructors,
internal handle to world object, along with a but instead use special factory functions that will
Destroy procedure that acts like a destructor allocate these objects for you. This also means that
that closes the internal handle. you do not have to free these objects. They will be
The Create method accepts a 2D vector destroyed when the whole world is destroyed.
gravity that represents the gravitational force There are three types of bodies in Box2D and they
that affects all bodies in the simulation. All are defined by the b2BodyType enumerated
method calls to b2WorldWrapper should type in Box2D.Dynamics.
happen after the call to Create and before the
call to Destroy as in the code below.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 17


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8 (CONTINUATION 2)

Dynamic Body (b2_dynamicBody). First we need to create and initialize the ground
It has a mass. Forces have impact on it. It can be body definition. The default type of a body is
put into linear and angular movement. It may static, so we do not need to change it. We only
collide with other dynamic and static bodies. If a specify the position of the body to be 10 meters
dynamic body has zero mass then it behaves below zero.
differently and it always has zero angular velocity. b2BodyDef is a record type. We need the @
In a game dynamic bodies are typically moving operator to pass a pointer to this record, rather than
objects like vehicles, bullets, balls and everything the record itself. The call to Set is prepended with
else that can move through the world and collide. the & operator. This is because set is an Object
Static Body (b2_staticBody). Pascal keyword and to use it as an identifier it
It does not have a mass. Forces do not influence it. needs to be escaped.
It cannot be put into a linear or angular The Box2D body is an abstract notion. It does
movement. Dynamic bodies collide with it. In a not have a shape, mass or any physical properties
typical game static bodies are used to define of the material it simulates. The class that has these
borders and limits of the game, like walls, ground, properties is called a fixture. Fixtures belong to a
bands in a hockey game and so on. body and are created using the CreateFixture
Kinematic Body (b2_kinematicBody): method of a body.
Forces do not influence it. It can be put into The CreateFixture method has two variants.
linear or angular movement. It may collide with One that takes a fixture definition as an argument
dynamic bodies, but it does not collide with other and the other that takes an instance of a shape
kinematic bodies. Collisions between dynamic and class and the density.
kinematic bodies do not
change the movement of b2BodyWrapper = record
FHandle: b2BodyHandle;
a kinematic body. //
For example they can be function CreateFixture(def: Pb2FixtureDef): Pb2Fixture; overload; cdecl;
used in a game as function CreateFixture(shape: b2ShapeHandle; density: Single):
moving platforms that Pb2Fixture; overload; cdecl;
do not react to heavy //
bodies that collide with
them. The movement of
a kinematic body is controlled by vectors of linear There are four different descendants from the
and angular velocity. b2Shape class that defines a shape.
Circle shape (b2CircleShape):
In order to create a body we need to call Circle shapes have a position and radius. Circles
CreateBody factory method of the world object are solid. You cannot make a hollow circle using
and in the parameter we pass an object that the circle shape.
contains the body definition. This is a common Polygon shape (b2PolygonShape):
pattern in Box2D. Factory methods typically Polygon shapes are solid convex polygons.
accept definition objects that provide a lot of A polygon is convex when all line segments
useful defaults (which means there is less for you connecting two points in the interior do not cross
to code). any edge of the polygon. Polygons are solid and
Let's add the ground body to our Hello World never hollow. A polygon must have three or more
simulation. vertices. Polygon vertices are stored with a counter
clockwise winding.
Edge shape (b2EdgeShape):
var
groundBodyDef: b2BodyDef; Edge shapes are line segments.
groundBody: b2BodyWrapper; These are provided to assist in
making a free-form static
// environment for your game.
A major limitation of edge shapes
// Define the ground body
groundBodyDef := b2BodyDef.Create(); is that they can collide with circles
groundBodyDef.position.&Set(0.0, -10.0); and polygons but not with
themselves.
// Call the body factory which allocates memory for the ground body Edge shapes have no volume,
groundBody := world.CreateBody(@groundBodyDef);
so edge-edge collision is not
possible.

18 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8 (CONTINUATION 3)

Chain shape (b2ChainShape):


The chain shape provides an efficient way to The last thing is to clean-up definition
connect many edges together to construct your objects. In Box2D these objects can be reused
static game worlds. Chain shapes automatically and passed to subsequent calls to Create
eliminate ghost collisions and provide two-sided methods with adjusted parameters.
collision.
In our Hello World program the next step is to // Cleanup Shape Wrappers
attach a polygon shape to our ground body. We dynamicBox.Destroy;
groundBox.Destroy;
are using the convenience method SetAsBox
that would define our generic polygon to be a
polygon with four vertices that forms a box. As Our Hello World simulation is now initialized
parameters you need to pass the half-width and and ready to start moving.
half-height of the resulting box. The most important method of the world object
var is Step. Step's first parameter is the amount of
groundBox: b2PolygonShapeWrapper;
time we want to advance our simulation
// Define the ground box shape forward.
groundBox := b2PolygonShapeWrapper.Create();
// The extents are the half-widths of the box Box2D simulation is completely neutral from
groundBox.SetAsBox(50.0, 10.0); any rendering and also does not have its own
// Add the ground fixture to the ground body loop. Basically you create a simulated physics
groundBody.CreateFixture(groundBox, 0.0);
world, add objects to it and call its Update
method whenever you want passing the
Now we have one static ground body in our amount of time you want the simulation to
simulation. The next step is to add a dynamic
advance. Box2D has algorithms that prevent the
body, a smaller box that we are going to put on
tunneling effect which happens when
top of our ground. For this we are going to use the
CreateFixture variant that takes a fixture calculating positions of moving bodies in time.
definition as a parameter. If the time increment is too big, you may end
up with a situation in which objects are
var
penetrating each other instead of colliding.
bodyDef: b2BodyDef;
body: b2BodyWrapper; This is why there are two additional
dynamicBox: b2PolygonShapeWrapper; parameters to the Step method that
fixtureDef: b2FixtureDef; define the number of velocity and position
// Define another box shape for our dynamic body iterations that are calculated in each step.
bodyDef := b2BodyDef.Create();
Typical values are 6 for velocity and 2 for
bodyDef.&type := b2_DynamicBody;
bodyDef.position.&Set(0.0, 4.0); position iterations at each step.
body := world.CreateBody(@bodyDef);
In the Hello World demo we display in
dynamicBox := b2PolygonShapeWrapper.Create(); the memo the position and rotation angle of
dynamicBox.SetAsBox(1.0, 1.0);
the moving dynamic box for the first
fixtureDef := b2FixtureDef.Create(); second of simulation. It is typical in games
fixtureDef.shape := dynamicBox; to use 1/60 second frame rate to achieve
smooth animation of moving objects.
// Set the box density to be non-zero, so it will be dynamic
fixtureDef.density := 1.0;
// Override the default friction timeStep := 1/60;
fixtureDef.friction := 1.0; velocityIterations := 6;
// Add the shape to the body positionIterations := 2;
body.CreateFixture(@fixtureDef);
for i := 0 to 60 do
begin
// Instruct the world to perform a single step of simulation.
// It is generally best to keep the time step and iterations fixed
world.Step(timeStep, velocityIterations, positionIterations);

This is what the output of our FlatBox2D pos := body.GetPosition;


Hello World program looks like - angle := body.GetAngle;
not like Angry Birds at all!
Memo1.Lines.Add(Format
('%4.2f %4.2f %4.2f', [pos^.x, pos^.y, angle]));
end;

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 19


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8 (CONTINUATION 4)

Test Bed
The FlatBox2D Test Bed demo is a very
convenient application that acts a framework for
plugging in different tests into a common
codebase for rendering graphics, providing the
game loop and processing user input. This the
Object Pascal version of the original C++ Test
Bed. You can find FlatBox2D Test Bed in
C:\Users\Public\Documents\Embarcadero\
Studio\16.0\Samples\Object
Pascal\Mobile Samples\Physics\TestBed
\TestBed.dpr
You can learn a lot by playing with one of the six
predefined test cases that experiments with
These are the very basics. To use FlatBox2D in different aspects of the engine. You can create your
applications we need to create the world object own tests by extending the TTest class and
first, add all bodies, shapes and joints to it, build registering your test with the application's main
our own game loop that would call our world's form. Out of the box you got the following tests:
Step method to advance the simulation and we Chain
would also need to provide our own graphics Varying Restitution
rendering. Tiles
In the default Delphi XE8 installation there are two Add Pair
more demo projects that go deeper into using Apply Force
different bodies, shapes and joints to create more
Basic Slider Crank
complex simulations than this Hello World
which has just two boxes.
Here is how Tiles test looks like in action:

18 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


INTRODUCTION TO FLATBOX2D FOR DELPHI XE8 (CONTINUATION 5 - END)

By pressing space you shoot bullets into your The AddControl method is called for every
simulation. That is fun! control on the form to create a box representing
this control inside the world.
Adding physics to apps
The third demo that comes installed with Delphi
Summary
XE8 demonstrates how to add physics to a common
The FlatBox2D physics engine is a great new
FireMonkey multi-device app which uses standard
feature included in the new version of
user interface elements such as buttons, scroll bars, Embarcadero Delphi XE8, C++Builder XE8 and
check boxes and the like. This demo is located RAD Studio XE8. Based on a well-known open
inC:\Users\Public\Documents\Embarcader source C++ Box2D implementation it adds a
o\Studio\16.0\Samples\Object Pascal
solid foundation for building new generation
\FireMonkey Desktop\Physics
apps with realistic graphics user interfaces.
\FormWithBox2D\FMSimplePhysics.dpr
The FlatBox2D demos discussed in this article
When you open the FMSimplePhysics project it
cover the basics of using Box2D
looks like a regular FireMonkey Controls demo.
(Hello World), playing with
more complex combinations of
bodies, shapes, joints (Test
Bed) and adding physics to a
Delphi XE8 multi-device
application (FMSimplePhysics).
The next step is to build a
complete game with its own
graphics, but this I'm going to
leave to the reader!

Have fun with Delphi and


FlatBox2D programming!

After you click on the Drop button all controls gain


physical properties and start falling to the
bottom of the screen!

About the Author


Pawe Gowacki is Embarcadero's
European Technical Lead for Developer
Tools. Previously, Pawe spent over 7 years
working as a senior consultant and trainer
for Delphi within Borland Education
Services and CodeGear. As well as working
with Embarcadero customers across the
region, he also represents Embarcadero
internationally as a conference and seminar
speaker. For more information check out
Pawe's technical blog at
http://community.embarcadero.com

The physics support has been encapsulated into a


TFmxPhysicsDemo class that is defined as a
member of the main form's class. It has two
methods that are called during the construction of
the main form AddScreenSize and
AddControl. AddScreenSize is called once,
and it used to add four static boxes to the internal
Box2D world, boxes that are at the same position as
the borders of the screen.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 21


Fast Report 5 features:
User friendly Report Designer
(Create new reports in few clicks, report wizards, dialog designer, script editor and much more);
Extended Report and script Inheritance;
Many report objects:
Special Bands (Footers, Headers), HTML-formatted Texts, RTF-formatted Texts,
Images, Charts, Linear barcodes, 2D Barcodes, CheckBoxes,
Simple Geometric Objects, Vertical Bands, Cross-tabs;
Export filters :
PDF, RTF, HTML, TXT, JPEG, BMP, TIFF, GIF, EMF, CSV, ODS, ODT,
Excel Binary, Excel XML, Email, DBF;
Built-in script shell that supports 4 languages;
Interactive forms, drill-down (drop) reports, call another report with
detailed information from the preview window with one mouse click;
Acess to many popular database engines:
FireDAC, ADO, BDE, DBX, IBX and FIBPlus,
so providing access to practically all databases,
including Oracle and many third-party libraries;
Acess to any data of your application including classes with using
TfrxUserDataSet component;
Convertors from : Quick Reports, Rave Reports, Report Builder;

New features in Version 5.2:


Support of last Embarcadero RAD Studio XE7 for x32 and x64 windows platforms
Initial support of Lazarus for Fast Report 5 - first beta release witch includes the
report designer and the report preview.
New export filter to SVG format
(SVG is a graphical vector format used in web and now FastReport
allows you to export reports to this format.)
New feature to reset object properties to parents in inherited report
(whole report or single object) - ability to restore object properties of
any object in inherited report to default values introduced in base report.
New multi-selection for data tree and ability to drag whole dataset (create band)
- allow to drag any count of fields from "data tree" or/and include whole data set.
Create your report for few mouse clicks !
Interactive Report Tree with ability to move/select/edit report objects
from report tree window - new enchanted "report objects tree"
gives ability to select move and edit objects more easily.
Transparency and color mask in PDF export (Pictures/HTML-tags/RTF)
- pictures and some objects like RTF may uses alpha mask during export to PDF.
New selection mode in report designer
- new selection modes allow to select all object of the same kind as selected.
Changed preview tabs mechanism.
TfrxPreview.EachReportInTab allows to bind few report components to a
single preview and show each in the separate tab.
Many of bug fixed and improvements.
CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2
by Cary Jensen
starter
include CachedUpdates, StatusFilter
expert
Delphi XE 7
(and its related property,
FilterChanges), and ApplyUpdates.
Delphi now has two distinct in-
memory dataset components, the DEFAULT CACHED UPDATES STATE
ClientDataSet, which has been Let's start this comparison by looking at the
available in the Client/Server editions since Delphi 3, default cached updates state of ClientDataSets. A
and found its way into the Professional edition in Delphi ClientDataSet is in a cached updates mode by
6, and FDMemTable. The FDMemTable is the newcomer,
making its first appearance in Delphi XE3.
default. In other words, LogChanges is True for a
ClientDataSet when it is created. By comparison,
I have long been an advocate for the use of in-memory FDMemTable CachedUpdates is False by default.
datasets, noting that their features can be applied in a
wide range of applications, even those not specifically
CACHED UPDATES AND UPDATEMODE
associated with traditional databases. And now that
there are two in-memory datasets in Delphi, the most
ClientDataSets and FDMemTables use different
frequent question that I get asked is this, "Which one update mode default settings, a value that affects
should I use?". how updates are applied. I spent an entire article
in a recent issue of Blaise Pascal Magazine
The truthful answer is "It depends". They are not
identical, and each has its strengths and weaknesses. discussing this issue, but permit me to recap that
In the last issue of Blaise Pascal I began taking a look discussion here.
at the similarities between these two in-memory
datasets, as well as differences in design time ClientDataSets, by way of the
operations, record persistence, and query
configuration. In this issue I will conclude with a look at DataSetProvider.UpdateMode property, defaults
cached updates differences, nested datasets, DataSnap to upWhereAll. This setting attempts to apply an
operations, and miscellaneous differences. update based on key fields and all non-BLOB
(Binary Large OBject) fields. If some other user
has posted a change to a record since the in-
Cached Updates memory dataset was loaded, a change to that
This section describes some of the differences same record cannot be applied from cache to the
between cached updates in ClientDataSets and underlying database. In this situation, the first
FDMemTables. user to write their changes wins.
FDMEMTABLE NOT REQUIRED FOR CACHED
FireDAC DataSets, including FDMemTable, use
UPDATES
One of the more compelling reasons to use a their UpdateOptions.UpdateMode property to
ClientDataSet is to enable cached updates on a control this process, and this property defaults to
TDataSet. This is not true, however, when it comes upWhereKey. When UpdateMode is set to
upWhereKey, only the key fields are used to
to users of Delphi's FireDAC data access
update data, which has the effect of replacing
framework. The reason why is that FireDAC
existing records with whatever the current user is
datasets support cache updates directly (albeit
writing. In other words, the last user to write to a
through an encapsulated FDMemTable).
particular record (as identified by the table's key
As a result, when you want cached updates you
fields) will replace any changes previously posted
can simply employ that feature as exposed by the
by another user. To put it another way, the last
FireDAC dataset, such as an FDQuery.
user to write wins.
Before continuing, however, I want to point out
Obviously, these are differences in default
that cached updates in FDMemTables works
settings, and you can easily set an FDMemTable's
differently than in other FireDAC datasets,
UpdateOptions.UpdateMode property to
specifically with respect to how the ApplyUpdates
upWhereAll. Nonetheless, you need to be aware
method works. I will address these difference that ClientDataSets and FDMemTables have
when I discuss ApplyUpdates. different defaults, since the difference between
these two settings are significant.
Nonetheless, while both ClientDataSets and
FDMemTables support cached updates operations, APPLYING UPDATES
a number of the properties and methods associated Applying cached updates is another area where
with cached updates work differently. Examples of ClientDataSets and FDMemTables differ
properties and methods that differ in function significantly.
between ClientDataSets and FDMemTables

24 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2 (CONTINUATION 1)

Calling ApplyUpdates on a ClientDataSet clears FireDAC datasets flag records in the cache by
each applied record from the cache (assuming that exposing a property named RowError. When the
MaxErrors is not exceeded). If all updates are current record of the dataset is one whose cached
successfully applied, the change cache will be value raised an error, this property holds the
empty when ApplyUpdates returns. If errors are exception raised during the call to ApplyUpdates,
encountered, and MaxErrors is not exceeded, the otherwise the property is nil.
applied records are cleared from the cache, with
the records that produced errors remaining. FireDAC datasets also support a filter flag (used
with the FilterRecord and StatusFilter properties)
By comparison, following a call to ApplyUpdates named rtHasErrors. You can use this flag to filter
on an FDMemTable, the cache is cleared the FDMemTable records on those for which an
unconditionally. In other words, if AMaxErrors error was raised during ApplyUpdates.
(the name of the parameter passed to ClientDataSets do not support the RowError
property and do not support the rtHasErrors flag.
ApplyUpdates in FireDAC is different), all records
are removed from the cache, including the errors.
However, these values are only useful if the cache is
Yes, ApplyUpdates will return a non-zero value if
intact, and from my tests, calling apply updates to
errors are encountered, but those errant records
an FDMemTable always clears the cache.
are removed from cache. Apparently, if you want
This means that if you are going to try to handle
to process those errors, you must do so by catching
errors in the call to ApplyUpdates, you must do so
them using the OnReconcileError event handler.
from the OnReconcileError event handler of the
FDMemTable.
I mentioned earlier that FireDAC's other datasets,
such as FDQuery, handle ApplyUpdates Regardless, following a call to ApplyUpdates on a
differently, both from ClientDataSets and FireDAC dataset, you must deal with the errors, on
FDMemTables. With an FDQuery, a call to a record by record bases, before flushing the cache.
ApplyUpdates doesn't clear the cache at all, even if In my opinion, the ClientDataSet way of doing this
all changes can be applied. If ApplyUpdates is much easier to deal with.
returns 0, indicating that all updates are applied,
you must then call CommitUpdates to flush the Applying Updates to
cache of all records. If ApplyUpdates returns a Master/Detail Relationships
positive value, indicating that one or more records A ClientDataSet can apply updates to its data, via
could not be applied, you have to manually handle a DataSetProvider, through a single call to
those records before flushing the cache. ApplyUpdates. If the ClientDatasSet includes one
or more nested datasets whose data has changed,
Fortunately, there are easy ways to identify the call to ApplyUpdates on the ClientDataSet
records in cache that could not be applied. applies changes to the nested dataset data as well.

Figure 1. The CentralizedCachedUpdates project

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 25


CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2 (CONTINUATION 2)

This is the mechanism used by ClientDataSets to You must either apply the updates (using
apply updates to master/detail relationships. ApplyUpdates, and in the case of non-
FDMemTable FireDAC datasets, CommitUpdates)
FireDAC uses another method for caching updates or cancel them (using either CancelUpdates or
to master/detail relationships, something that CommitUpdates) before you can exit the cached
FireDAC refers to as centralized cached updates. updates mode.
With centralized cached updates, two or more STATUSFILTER DEFAULT VALUE
FireDAC datasets, related in a master/detail Another difference is that the
relationship, point to a single FDSchemaAdapter. ClientDataSet.StatusFilter property and the
While the FireDAC datasets are placed in a cached FDMemTable.FilterRecords property (the
update mode manually, the FDSchemaAdapter is FDMemTable equivalent of
used to apply the updates to all of the associated ClientDataSet.StatusFilter) operate differently.
FireDAC datasets. The default value for StatusFilter in a
ClientDataSet is an empty set of TUpdateStatus
The use of the centralized model of cached updates flags. For an FDMemTable, it is a set that includes
is demonstrated in the project named usUnmodified, usModified, and usInserted.
CentralizedCachedUpdates. The main form of this Granted, the way that FDMemTable does this is
application is shown in Figure 1, on page23. more intuitive, but it is a difference nonetheless.

Unfortunately, calling ApplyUpdates on an Dynamic Nested DataSets


FDSchemaAdapter works the same way as When a ClientDataSet points to a master table of a
applying updates on an FDMemTable. The cache is dynamic master-detail relationship (one defined
cleared unconditionally. If you want to handle any by MasterSource and MasterFields, or one defined
errors, you must do so from the by a detail query linked to a master table by way
FDSchemaAdapter's OnReconcileRow event of query parameters), the ClientDataSet will load
handler. the detail table as a nested dataset (loading is
actually performed by the DataSetProvider to
ENTERING AND EXITING CACHED UPDATES
which the ClientDataSet points).
Another cached update difference between
ClientDataSets and FDMemTables is related to
An example of a nested dataset can be seen in
entering and exiting the cached updates state.
Figure 2. The top DBGrid holds the values
If a ClientDataSet has cached changes, you can set
returned from a DataSetProvider to a
the LogChanges property to false, thereby
ClientDataSet, where the DataSetProvider pointed
terminating the cached updates state and aborting
to the master query of a dynamic master/detail
all changes. With an FDMemTable, you cannot set
relationship. The detail dataset contains the orders
CachedUpdates to false when there are records in
for the selected customer.
cache.

Figure 2. A ClientDataSet loads linked detail tables from a DataSetProvider into nested dataset fields

26 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2 (CONTINUATION 3)

Note the OrdersQuery field in the top grid. This is data source, typically a database, and passes it to
the nested dataset. When the ellipsis is clicked on a client application. If the client application
the OrdersQuery field, the nested data is display makes changes to that data, a delta is passed
in a dynamically created grid. Also note that the from the ClientDataSet on the client to a
lower DBGrid displays these orders as well, which DataSetProvider on the server, which in turn
was accomplished by pointing another applies those changes to the underlying database.
ClientDataSet to the dataset field
(OrdersQuery).While FDMemTables support the The key to making this work, from a
creation of nested datasets, these can only be the ClientDataSet perspective, is embodied in the
result of creating the FDMemTable based on ClientDataSet/DataSetProvider interaction. The
defined FieldDefs or TFields of the type DataSetProvider resides on the DataSnap server,
DataSetField. An FDMemTable that loads its data and the ClientDataSet interacts with it by way of
from the master table of a dynamic master-detail several client-side components. In the latest
relationship does not obtain a nested dataset field incarnation of DataSnap, those components are a
representing the detail table. dbExpress SQLConnection (employing its
DataSnap driver), and a DSProviderConnection.
Similarly, while FDMemTable supports nested
datasets, these cannot be used to apply cached There are three aspects of ClientDataSets that
updates in the same manner as ClientDataSets. make DataSnap work smoothly. First, opening a
ClientDataSets can apply updates to master-detail ClientDataSet that points to a DataSetProvider on
relationships using nested datasets, FDMemTable a DataSnap server retrieves data, and calling
cannot. ApplyUpdates sends the change cache back to
the DataSetProvider for resolution. Second, the
Nested datasets play an important role in the use of nested datasets permits changes made to
ClientDataSet's ability to support cached updates related data (in a master/detail sense) to be
with master-detail relationships. As I've updated with a single call to ApplyUpdates.
mentioned already, FireDAC datasets support Finally, the Params and CommandText
cached updates directly, meaning that properties of the ClientDataSet permit the
FDMemTables are not necessary is all the only ClientDataSet to effortlessly pass parameter
feature you need from the FDMemTable is cached values, and even entire queries, to the
updates. For FireDAC datasets that need to cache DataSetProvider, permitting a great deal of
updates on master-detail relationships, the flexibility from the client-side of the DataSnap
datasets can employ an FDSchemaAdapter. equation.
DataSnap
ClientDataSets were designed for MIDAS, which The use of ClientDataSets in a DataSnap
was released with Delphi 3. While the name has client/server interaction is demonstrated in a set
subsequently changed to DataSnap, the essential of projects located in the DataSnap directory.
model is the same. A middle-tier server (the Figure 3 shows how the server methods unit
DataSnap server) retrieves data from a looks in the designer.

Figure 3. The server methods module of a traditional DataSnap server

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 27


CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2 (CONTINUATION 4)

Here is the underlying class definition. server can use TFDJSONDeltasApplyUpdates


type class to resolve the changes in the DataSnap
TServerMethods1 = class(TDSServerModule) client's change cache to the underlying database.
FDConnection1: TFDConnection;
CustomersQuery: TFDQuery;
Figure 4 - at the bottom - shows the
CustomersQueryA: TFDQuery; FDMemTable version of a DataSnap server that is
CustomerProvider: TDataSetProvider; similar to the ClientDataSet one
OrdersQueryA: TFDQuery; shown earlier. While there is not much
CustomersSourceA: TDataSource;
complexity in the number of components, the
CustomersOrdersProvider: TDataSetProvider;
private underlying class structure is dramatically
{ Private declarations } different, in order to expose sufficient custom
public methods to transfer the same data as provided
{ Public declarations } for using the ClientDataSet /DataSetProvider
function EchoString(Value: string): string;
function ReverseString(Value: string): string;
model. This can be seen in the following class
end; declaration. FireDACJSONReflect does not
specifically address master/detail relationships,
nor does it provide an infrastructure for passing
Until recently, FDMemTables were not well suited query parameters or SQL statements from the
for the DataSnap environment. Conveying data client to the server.
from the DataSnap server type
to an FDMemTable on the TServerMethods1 = class(TDSServerModule)
DataSnap client had to be CustomerQuery: TFDQuery;
performed manually. FDConnection1: TFDConnection;
FDStanStorageBinLink1: TFDStanStorageBinLink;
The same thing can be FDStanStorageJSONLink1: TFDStanStorageJSONLink;
said regarding the OrdersQuery: TFDQuery;
FDMemTable delta CustomerOrdersQuery: TFDQuery;
(the change cache). private
{ Private declarations }
Beginning with Update 2 public
{ Public declarations }
of Delphi XE5, the function EchoString(Value: string): string;
introduction of the function ReverseString(Value: string): string;
FireDACJSONReflect unit function GetCustomerData: TFDJSONDataSets;
has partially addressed function GetCustomersOrders: TFDJSONDataSets;
both of these issues. function GetOrdersForCustomer(CustNo: Double): TFDJSONDataSets;
procedure ApplyCustomerUpdates(const ADeltaList: TFDJSONDeltas);
Specifically, you can now procedure ApplyCustomersOrdersUpdates(const ADeltaList: TFDJSONDeltas);
use the TFDJSONDataSets end;
class to package one or
more FireDAC datasets
nto a specialized class, which in turn can be Master/detail relationships must be configured
streamed from the DataSnap server to the manually on the DataSnap client (via the
DataSnap client through custom methods that you MasterSource and MasterFields properties of the
add to the server methods unit of the DataSnap client-side FDMemTables, or MasterSource on the
server. Likewise, the TFDJSONDeltas class can be detail table combined with a parameterized query
used to package the deltas of one or more on the detail table). And, if you want to convey
FDMemTables for return to the DataSnap server, parameters or even entire queries from the client
again through custom to the server, you will have to do this through
passed to custom server-side
methods. Yet another feature,
introduced in Delphi XE7,
appears to provide an
alternative for FireDAC, and it
can handle master/detail
relationships. In XE7 the
FDSchemaAdapter received
Figure 4 SaveToFile,
methods that you add to the DataSnap server's
server methods unit. From there, the DataSnap

28 Issue Nr 1 2015 BLAISE PASCAL MAGAZINE


CLIENTDATASETS AND FDMEMTABLES COMPARED: PART 2 (CONTINUATION 5)

SaveToStream, LoadFromFile, and Summary


LoadFromStream methods. These can be used to
Both ClientDataSets and FDMemTables are in-
persist and restore the data managed by an memory datasets that share a large number of
FDSchemaAdapter, whether it is connected to a features. At the same time, there are significant
single FDMemTable (or FDQuery), or several, differences. Which should you use in your
through master/detail relationships. applications?

Using the FDSchemaAdapter, it is possible to The answer is pretty simple. If an FDMemTable


supports the features you need, use it instead of
transfer data from one or more FDMemTables on
a ClientDataSet. FDMemTables are the future of
the DataSnap server, using a stream, to the in-memory datasets in Delphi. All innovations
DataSnap client, and back. There are only two involving in-memory datasets will appear in
problems with this. First, the file or stream created FireDAC as Delphi continues to evolve.
by the FDSchemaAdapter contains every record in ClientDataSets, by comparison, are legacy
the underlying FDMemTable or FDMemTables, components, based on a C library that is only
and, when there are changes in the change cache, modified if very serious bugs are discovered. You
will see no new features being added to
additional data as well. That's a lot of data to push
ClientDataSets by Embarcadero in the future.
back and forth. By comparison, when you call
ApplyUpdates on a ClientDataSet in a DataSnap There are, however, many features not supported
client, only the change cache is returned to the by FDMemTables, or for which an FDMemTable
server. Unless you are working with just a few would otherwise require a more burdensome
records, the amount of data being transferred solution. Clearly, cached updates is one of those
back to the DataSnap server using an areas. In those cases, use, or continue to use, a
FDSchemaAdapter can be significant. ClientDataSet.

About the Author


Bottom line is this. You can implement DataSnap
Cary Jensen is Chief Technology Officer of
clients and servers using FireDAC and Jensen Data Systems. Since 1988 he has built
FDMemTables, but it is going to take more work and deployed database applications in a wide
than the same application built using range of industries, and is available for
ClientDataSets and DataSetProviders. At least this development, consulting, and training. Cary is
statement is true as of the time of this writing. an Embarcadero MVP, a best selling author of
I anticipate that at some time in the future more than 20 books on software development,
and holds a Ph.D. in Engineering Psychology,
FDMemTables will gain additional features which
specializing in human-computer interaction. He
will make them more suitable for the DataSnap is also co-presenter with Ray Konopka on this
server/DataSnap client interaction. year's Delphi Developer Days 2015 tour. Visit
http://www.DelphiDeveloperDays.com to learn
Miscellaneous more.
There are additional differences, and they all
represent advantages of FDMemTables over
ClientDataSets. These are:
ClientDataSets requires MidaLib (a Delphi unit)
or midas.dll (a windows dynamic link library).
FDMemTable is written entirely in Object
Pascal, and does not require any additional
libraries.
For in-memory operations, such as searches
and filtering, FDMemTable is generally faster
than ClientDataSets.
ClientDataSets exhibit a significant
performance decline when holding a large
amount of data, somewhere in the 200,000
record range. FDMemTables do not exhibit this
same loss in performance.
FDMemTable supports copying multiple result
sets from FireDAC datasets. When loading a
ClientDataSet via a DataSetProvider, you can
load only from a single data set.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 29


Group discounts are available

30 Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


START WITH FUNCTION TESTING maXbox
maXbox Starter 36 By Max Kleiner
Measure Correctness and Stability
Today we step through the realm of testing and
bug-finding and his visual representation in
metrics and audits.

The traditional approach to quality control and


testing has been to apply it after the development
process completes. This approach is very limited
as uncovering defects or errors at a late stage can
produce long delays with high costs while the bugs
are corrected, or can result in the publishing of a
low-quality software product.

Lets start with a first function and how to improve and debugging tool that many programmers overlook,
test it: primarily because of a general lack of discussion on
the subject.
function CountPos(const subtxt: string; Text: string): Integer;
begin
if (Length(subtxt)= 0) or (Length(Text)= 0) or
(Pos(subtxt,Text)= 0) then
result:= 0 OutputDebugString(inttoStr(CountPos('max',TESTTEXT))+
else 'CountPos runs..');
result:= (Length(Text)-
Length(StringReplace(Text,subtxt,'',
[rfReplaceAll]))) div Length(subtxt);
end;

This function counts all sub-strings in a text or That's all you have to do. Because Delphi, Lazarus
string. The point is that the function uses another or Free Pascal is installed as the system debugger,
functions like Pos() and StringReplace(). any strings sent using OutputDebugString will
Do we have to test it also? show up in the Event Log. You can place calls to
No, but we need a reference value: OutputDebugString anywhere you want in your
PrintF('CountPos: %d',[CountPos('max','this is max of maXbox a max numbermax')]) code.
To view the value
The result is 3, so we better extract our test-string of a variable, you must format a string and send
in a constant: that string to OutputDebugString, for example:
Const TESTTEXT = 'this is max of maXbox a max numbermax'; procedure GetOutputDebugString;
PrintF('CountPos: %d',[CountPos('max',TESTTEXT)]) var
x : Integer; S : string;
begin
And with Assert we do automate that reference { Some code here...}
value (more on page 34): x:= CountPos('max',TESTTEXT);
with procedure Assert(expr: Boolean; const S:= Format('X := %d', [X]);
OutputDebugString(PChar(S));
msg: string); you set an expression value which
writeln(S)
you expect to be true: end;
Assert(CountPos('max',TESTTEXT)=3, 'count pos assert') // OutputDebugString(PChar(Format('[%s][%s]
%s',[aCaption, GetFormatDT(StartDT), aText])));

Find the position and count of all strings in


another is the function to test but is the function
case sensitive or not? Also the Event Viewer is a Microsoft Management
Console (MMC) snap-in that enables you to
Sometimes it is helpful to track your program's browse and manage event logs. It is an
execution as your program runs. Or maybe you indispensable tool for monitoring the health of
want to see a variable's value without stopping systems and troubleshooting issues when they
program execution at a breakpoint to test. arise. Look at the last entry in the Event Log
The OutputDebugString() function enables you to shown in the next picture. That entry was
do exactly that. This function is a convenient generated using the code on the next page:

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


maXbox 31
START WITH FUNCTION TESTING (CONTINUATION 1) maXbox
WriteToOSEventLog('mX3','maXbox','Details3',TESTTEXT);

When you use Event Viewer to troubleshoot or Analytic or test events are published in high
track a problem, you need to locate events related volume. They describe program operation and
to the problem, regardless of which event log they indicate problems that can't be handled by user
appear in. Event Viewer enables you to filter for tasks or intervention.
specific events across multiple logs as of maXbox.
We need values in
WriteToOSEventLog(const logName, logCaption, logDetails: String; const logRawData: Str);

a logName, logCaption, logDetails and some RawData:


WriteToOSEventLog('mX3','maXbox','ID45:detail3',TESTTEXT);

The Application log (see picture) contains events


logged by applications or programs. For example,
a database program might record a file error in the
application log. You as a developer decide which
events to log. To log a sound in a multimedia app
for e.g. you have to set a song first:
playMP3(mp3path);
closeMP3;
DebugOutputString('closeMP3: '+ mp3path);

In a shortlink
%windir%\system32\eventvwr.msc /s
you start the eventlog:

32
maXbox Issue Nr 1 2015 BLAISE PASCAL MAGAZINE
START WITH FUNCTION TESTING (CONTINUATION 2) maXbox
Lets go back to our function to test and build Or you will look at the web and ask to a search
a test function too. machine: How do I find and count the total
function CountPos(const subtxt: string; Text: string): Integer; amount of times that a
begin particular word
if (Length(subtxt)= 0) or (Length(Text)= 0) or (Pos(subtxt,Text)= 0)
appears?
then result:= 0
else result:= (Length(Text)- Length(StringReplace(Text,subtxt,'', Often, as programmers
[rfReplaceAll]))) div Length(subtxt); gain experience in
end; building applications,
they develop a sixth sense
Such a small function like above contains another for locating the cause of in-correctness or access
3 functions (yellow) and before testing we should violations.
also check the understanding and the design of With asserts you can support that feeling what
the function. For example StringReplace() could crash. An assert function is used to make
which replace one or more substrings found sure that certain conditions which are assumed to
within a string does have more parameters to test be true are never violated. Assert provides an
like the [rfReplaceAll].On the other side we opportunity to intercept an unexpected condition
can trust in a stable function of the runtime library and halt a program rather than allow execution to
otherwise we loose time not to mention the continue under unanticipated conditions.
frustration caused by a bug that is difficult to find.
If you encounter problems using any feature of
I asked a few lines above if the function to test
Event Viewer, first ensure that the Windows Event
is case-sensitive or not, do you remember? Yes it is
Log service is running. If you are working
and we do have to consider that in our test-string
with event subscriptions, ensure that the Windows
and test-function with Uppercase too.
Event Collector service is running.
function CountPosTest: boolean; With this call in maXbox you can run the
begin
result:= false; event log from the script:
if CountPos(Uppercase('max'),Uppercase(TESTTEXT))= 4 ExecuteCommand('cmd','/c %windir%\
then result:= true; system32\eventvwr.msc /s ')
end;
Next we go to the topic of Unit Testing but
Each time we test (or change) our function we call not to generate units (this is another story)
the test-function with a test-string and check the but consuming as a test-function or protocol e.g. in
reference value which must be 4. Normally you maXbox I do have some unit tests to check
test a function by creating a test application or unit conditions before running a script!:
and if something goes wrong or crashes you will // test routines with assert or assert2 builds
run the test application under the debugger and SelftestPEM;
watching the values. SelfTestCFundamentUtils;
A debugger helps you find bugs or errors in SelfTestCFileUtils;
SelfTestCDateTime;
your program at runtime. But the debugging SelfTestCTimer;
process isn't just for finding and fixing bugs - it's a SelfTestCRandom;
development and test tool as well. Another great
way to test a function is to compare the result with Writeln(' 6 Units Tested with success ')
ShowMessageBig(' 6 Units Tests with
a already well known standard function, for
success!');
example CountStr():
Function CountStr(const ASearchFor, ASearchIn: string): Integer;

or check with a subroutine which both of them A unit is the smallest testable part of software. It
uses: Function Unit SysUtils usually has one or a few inputs and usually a
StringReplace: Replace one or more single output. In procedural programming a unit
substrings found within a string may be an individual program, function, routine,
function CountStr(const ASearchFor, ASearchIn: string): Integer; procedure, etc. In object-oriented
var Start: Integer; programming, the smallest unit is
begin a method, which may belong to a
Result:= 0;
base/ super class, abstract class or
Start:= Pos(ASearchFor, ASearchIn);
while Start > 0 do begin derived/ child class.
Inc(Result);
Start:= PosEx(ASearchFor, ASearchIn, Start+ 1);
end;
end;

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


maXbox 33
START WITH FUNCTION TESTING (CONTINUATION 3) maXbox
Lets say you have a program comprising of two
units and the only test you perform is system
testing between Win and Linux:

SelfTestCFileUtils;
SelfTestCDateTime; //as an extract in test-cases:

Assert2(FilePath ('C', '..\X\Y', 'A\B', '\') =


A\X\Y\C', 'FilePath');
Assert2(PathCanonical
('\A\B\..\C\D\..\..\..\..\', '\') = '\',
'PathCanonical');
Assert2(UnixPathToWinPath
('/c/d.f') = '\c\d.f', 'UnixPathToWinPath');
Assert2(WinPathToUnixPath
('\c\d.f') = '/c/d.f', 'WinPathToUnixPath');
A:= EncodeDateTime(2001, 09, 02, 12, 11, 10, 0);
Assert2(Month(A) = 9, 'EncodeDateTime');
S:= GMTTimeToRFC1123TimeA(A, True);
Assert2(S = '12:11:10 GMT','GMT');
S:= GMTDateTimeToRFC1123DateTimeA(A, True);
Assert2(
S = 'Sun, 02 Sep 2001 12:11:10 GMT',
'GMTDateTimeToRFC1123DateTime');
Assert2(TickDeltaW
($FFFFFFF6, 0) = 10,'TrickDelta');
Assert2(
CPUClockFrequency > 0,'RTC Prepare');
Assert2(Length(RandomPassword
(0, 0, True, True, True)) = 0,'random passwd');
Assert2(Length (
RandomPassword(1, 1, True, True, True)) =
1,'random passwd');
CompareDateTime(DateOf(Now),DateOf(Now)+1)

For me the important thing is to isolate the


development environ-ment from the test
environment and make sure you are using a You see the screen with those test scripts notion
version control system to keep track of your test and some calls with external dependencies.
scripts and constants.
One of a question often arises is the following:
V1.2.1 SelftestPEM; Why do I continue getting error messages even
V1.7.0 SelfTestCFundamentUtils; after I have written an exception handler?
V1.2.0 SelfTestCFileUtils;
V1.1.1 SelfTestCDateTime;
V1.2.5 SelfTestCTimer; Answer: In its default settings, the Delphi IDE
V0.9.2 SelfTestCRandom; notifies you whenever an exception occurs in your
program.
Whats important to realize is that at that point,
none of your programs exception-handling code
has run yet. Its all Delphi itself; its special status
as a debugger allows it to get first notification of
any exception in your program, even before your
program knows about it.

Simply put, debugging when using exception


handling can be a bit of a pain. Each runtime an
exception is raised, the debugger pauses program
execution at the except block just as if a breakpoint
were set on that line.

34
maXbox Issue Nr 1 2015 BLAISE PASCAL MAGAZINE
START WITH FUNCTION TESTING (CONTINUATION 4) maXbox

If the except block is in your code, the execution

maXbox
point is displayed as it would be if you had
stopped at a breakpoint.
You can or must restart the program again by
clicking the Run button, or you can step through
your code.

You might not be able to continue execution of


your program after an exception is raised.
Whether you can continue debugging depends on
what went wrong in your program.

If an exception passes through the tryblocks in the


application code, the application automatically
calls the HandleException method. Unless the
exception object is EAbort, HandleException calls
the OnException handler, if one exists. Otherwise,
it calls ShowException to display a message box
indicating an error occurred.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


maXbox 35
START WITH FUNCTION TESTING (CONTINUATION 5) maXbox
Code Review Integration These features enable full support of a Continuous
Inspection process and produce three immediate
Code-coverage use. benefits:
So we have seen testing goes with automation to
test. There are tools which automate your tests They encourage developer adoption by
driven by software metrics.
enabling developers to quickly identify code
improvements and quick wins.
With these tools at hand, quality managers,
developers and technical architects have a They improve quality of code produced by
complete workbench to rate application quality, increasing developer knowledge and
perform quantitative analysis and define understanding of code quality issues.
corrective action. Those tools measure the amount They reduce maintenance cost through early
of test-cases and the metric is called code- identification of quality issues.
coverage.
Every step in your development work-flow that
The cost of fixing a defect detected during unit can be automated should be. You need this
testing or code metrics is lesser in comparison automation to be able to focus all your time on
to that of defects detected at higher levels. Unit
building your product and providing value to your
Testing is the first level of testing and is
performed and logged prior to Integration customers. Testing is one of those steps where
Testing. automation is key.
Test the script with F9 / F2 or press Compile. So
But most of the time we forget to check our code far now well open the test-function example:
twice. To avoid this problem, metric products 587_one_function_assert.txt
provide support for the so called Continuous
Inspection paradigm by enabling real-time http://www.softwareschule.ch/examples
notifications when code quality defects are /587_one_function_assert.txt
introduced in an application. This transparency
ensures that internal quality assurance is an Hope you did already work with the Starter 24 on
integral part of the software development life- Clean Code topics:
cycle, rather than an afterthought. https://bitbucket.org/max_kleiner/max
box3/wiki/maXbox%20Tutorials

better office benelux | asterlaan 6 5582EH waalre | 040 222 26 43 gtan@better-office.com


START WITH FUNCTION TESTING (CONTINUATION 6 - END) maXbox
Conclusion so you exit the procedure after handling the
Stepping through code is one of the most basic exception.
debugging and testing operations, yet it still needs If the brain were so simple we could understand
to be mentioned here. Sometimes you fail to see the it, we would be so simple we couldn't.
Lyall Watson
forest for the trees. (Just as sometimes authors of
programming books fail to include the obvious!) Feedback: max@kleiner.com
Reviewing the basics from time to time can reveal Literature: Kleiner et al., Patterns konkret, 2003,
something you were not previously aware of. Software & Support
http://www.softwareschule.ch/download/
Test functions return a boolean that you can test for codesign_2015.pdf
conditional parts of the functionality (correctness). http://softwaretestingfundamentals.com/
unit-testing/
It is important to understand that when you catch http://www.sonarsource.com/products/features/
an exception, code execution continues after continuous-inspection/
executing the except block. One of the advantages https://www.academia.edu/5129685/
Software_Quality_with_SONAR
to catching exceptions is that you can recover from https://github.com/maxkleiner/maXbox3/releases
the exception and continue program execution.
Notice the Exit statement in a code snippet. In this
case, you don't want to continue code execution
following the exception,
Appendix:
Assert and WriteToOSEventLog Study
PROCEDURE Assert(Cond: boolean; const Msg: string);
var progSeg, progOfs: word;
begin
asm
mov ax, [bp+04]
mov es, ax
mov ax, word ptr es:0
mov progSeg, ax
mov ax, [bp+02]
mov progOfs, ax
end;

if (Cond = FALSE) then begin


mmDebug.Lines.Add(Msg
+ ' at location '
+ IntToHex(progSeg, 4) +':' +IntToHex(progOfs, 4) );
ShowModal;
end;
end;

// WriteToOSEventLog

procedure WriteToOSEventLog(const logName, logCaption,


logDetails : UnicodeString;
const logRawData : String = '');
var eventSource : THandle; detailsPtr : array [0..1] of PWideChar;
begin
if logName<>'' then
eventSource := RegisterEventSourceW(nil, PWideChar(logName))
else eventSource := RegisterEventSourceW(nil,
PWideChar(ChangeFileExt(ExtractFileName(ParamStr(0)), '')));
if eventSource>0 then begin
try
detailsPtr[0]:=PWideChar(logCaption);
detailsPtr[1]:=PWideChar(logDetails);
ReportEventW(eventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, nil,
2, Length(logRawData), @detailsPtr, Pointer(logRawData));
finally
DeregisterEventSource(eventSource);
end;
end;
end;

Check the script! Script Example: maxbox3\examples\318_excel_export3

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE


maXbox 37
SERVICE ARTICLE
In the Adobe PDF file it is possible to view 2 pages side by side:
go to: File Edit g Preferences g Page Layout:
To view some images completely you need to see the two pages side by side.
You can adjust this.
The modern screens allow side-by-side-view.
BLAISE 2015
WORKING WITH BEACONS IN DELPHI XE8

By Jeremy North

With the release of Delphi XE8 one of the new There is an attempt to have a global database of
features added to the RTL is support for proximity UUID allocated to a company to help
Bluetooth beacons. This includes support for prevent collisions
both iBeacon and AltBeacon specifications. - https://openuuid.lime-company.eu/.

What are Beacons? Distance and Proximity Zones


Beacons are low energy Bluetooth devices that A common issue developer's face when interacting
transmit data. The data transmitted enables with beacons is the sometime lack of accuracy in
smart devices to be informed when a beacon is calculating the distance between the beacon and
within range. Every beacon transmits data to a the app interacting with it. This can mainly be
standard as well as being able to transmit
attributed to radio signal interference, as a beacon
manufacturer specific data as well. Each
is just a small radio transmitting a signal.
beacon transmits the following information in
Advertising Mode:
When using the iBeacon (Standard) mode, the
distance is calculated based on the iOS Core
Proximity UUID Unique identifying GUID Location framework. For
Major Integer value used to help identify a specific Beacon Alternate beacons, the
Minor Integer value used to help identify a specific Beacon distance is calculated based
TxPower Indicates the signal strength 1 metre from the device
on a formula provided in an
IEEE Xplore library paper.
Platform Support The paper title and URL is located in the
Beacons are supported using OS X, iOS and RssiToDistance method of the System.Bluetooth
Android in Delphi XE8. There is no support for unit. Since the accuracy of distance calculations can
Windows platforms at this time. be inconsistent an event (OnCalcDistance) is
provided to allow for a custom distance
My Beacon of choice calculation.
The beacons I have used are the Estimote
(http://www.estimote.com/) beacons. Proximity zones indicate the distance from a
There is no specific reason behind using Estimote, beacon you are. The values for Proximity (in the
they just happened to be the first I looked into Embarcadero implementation) are Immediate,
and the development kit (which includes 3 beacons) Near, Far and Away. The following table gives the
costs $99 USD. They took about a week to ship to distance range for each Proximity value.
Australia, which wasn't bad. Proximity Value Distance (metres)
Immediate less than 0.5
Near 0.5 to 3
Identifying a Beacon Far 3 to 30
The UUID, Major and Minor version values are Away 30+
used to identify a beacon. With Estimote (at least)
it is not possible to setup a second beacon with The proximity is based upon the RSSI (received
the same values. signal strength indication) and signal power values
All Estimote beacons are delivered with the same received from the Beacon. Fluctuation will occur in
UUID value and random Major and Minor the calculated distance even if neither the smart
values. Before deploying beacons in the field, you device nor Beacon is moving. This could be caused
should at least change the UUID value from the by other radio signals in the environment or even
default. These three values can be thought to be be caused by the material the building is
hierarchical in nature and allow you some constructed with.
flexibility to make it easier to identify particular
beacons. The values above are taken from the beacon
implementation source code from Embarcadero.
Identification is very important when interacting Manufacturers may assign different ranges to the
with Beacons. With your app you can specify to zones; for example, Estimote provides the
scan for beacons with a UUID value, a UUID and following ranges with their SDK.
Major version combination or for a specific
beacon by specifying all three (UUID, Major and
Minor).

40 Issue Nr 1 2015 BLAISE PASCAL MAGAZINE


WORKING WITH BEACONS IN DELPHI XE8 (CONTINUATION 1)

Using the TBeacon Component


There has been a lot of code written behind the
scenes to make applications that require beacon
support very simple. For this article I will use the
new TBeacon component. This component wraps
the TBeaconManager class defined in the
System.Beacon unit. If you don't want to use the
design time component, you can easily replicate the
functionality using TBeaconManager directly.
The TBeacon component has a number of
As I have three beacons, the apps user interface will
properties and events. Since I am using OS X and
update differently for each beacon.
iOS platforms for deployment, many of the
properties are not used. This is due to using the
I will place a beacon in the office, lounge and
built in iBeacon support for beacons in those
kitchen. When the application is running and
frameworks. Below is a screen capture of the
beacon scanning enabled, the office beacon will
published properties for the component. For the
display a quote on screen, the kitchen beacon will
app I only had to add an entry to the
display a recipe and the lounge will display the title
MonitorizedRegions collection. This can be done at
of a Disney movie.
design time however in the constructor I clear the
design time entry and add the beacon region
While each beacon will be able to do something
details explicitly.
different, remember the beacon has no functionality
it just broadcasts the four pieces of information.
Properties
For this app the Major version value of the beacon
I'll highlight a couple of properties that I believe
determines what is displayed. The interface is
are important / interesting.
very basic; a Switch to toggle the Enabled
property of the TBeacon component and a
couple of labels to output the text that
accompanies each beacon as it comes
into range.

Below is a screen capture of the interface at design


time as well as the structure view to highlight the
simplicity.

Mode
This is the kind of Beacon that will be
monitored. There are two beacon standards,
iBeacon (referred to as Standard in the
Embarcadero framework) and Alternate.
AltBeacon is a competing specification with
iBeacon however fortunately for us
Embarcadero supports both with their
beacon framework.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 41


WORKING WITH BEACONS IN DELPHI XE8 (CONTINUATION 2)

Enabled OnBeaconEnter
Must be set to True to ensure monitoring of The event is called when a beacon has been
specified regions occur. identified in the region specified. The event
parameters include a reference to the IBeacon
CalcMode interface of the internally stored beacon as well as a
This determines how the distance is calculated. full list of beacons within the region.
The default value of Stabilized means the beacon
framework will use a common distance calculation OnBeaconExit
for you. The other value is Raw and this means no The event signature is the same as the
calculation is done. OnBeaconEnter event. The IBeacon parameter
references the beacon that is no longer available, as
SPC well as the full list of beacons within the region.
This is the signal processing constant which is
used when calculating the distance. This property OnBeaconProximity
is not used for iOS deployed apps. This event is called when a monitored beacon has
changed its proximity. In other words you are
Properties of special note either getting closer to the beacon, or further from
The following properties are not used for iOS apps it. This event provides access to the beacon via the
but are important because both affect battery life IBeacon interface as well as the new proximity
and one may be too short depending on the signal value.
frequency of your beacon. It would have been nice if it also provided the
previous proximity value.
ScanningTime
This is the time spent scanning a region. Other Events
The default value of 500ms might be too low if The OnCalcDistance event is called to allow you to
your beacons are setup to only transmit every provide your own distance calculation of the
1000ms. The Estimote beacons default signal beacon. If you are finding the default distance
interval is 950ms. They will still be located, but it calculation is inaccurate with your beacon, you
might take a couple of scans to discover so if speed might try an alternate calculation available on the
is an issue, increasing this value will help. internet. Note: Not many SDK providers publish
the formula used to calculate distance. Estimote do
ScanningSleepingTime not publish the formula used.
This is the elapsed time in milliseconds between
scans. The OnParseManufacturerData event is called once
a beacon is located to allow interpreting the
Events manufacture specific data available from the
A number of events are provided with the TBeacon beacon. Many manufacturers provide additional
component. Three of the events provide the most information apart from the required values which
use. These are OnBeaconEnter, OnBeaconExit and are usually read by using their SDK. If you know
OnBeaconProximity. the layout of the signal data, this event is called to
allow you to interpret this additional data.

Public Methods
There are only three public methods available.
They are StartScan, StopScan and Nearest. The first
two are called internally when changing the
Enabled property so you don't need to call them
directly. The Nearest method could be of use
depending on the app you are creating.

For example in the sample application, since I don't


live in a mansion having three beacons around the
house it is easy to be within the range of at least
two at once.

42 Issue Nr 1 2015 BLAISE PASCAL MAGAZINE


WORKING WITH BEACONS IN DELPHI XE8 (CONTINUATION 3)

By using the Nearest method in procedure TfrmMain.UpdateInterfaceFor(const ABeacon:


conjunction with the OnBeaconProximity, THouseBeacon);
it is possible to also be showing begin
if ABeacon = nil then
information for the beacon the app is ResetInterface
nearest. It is also advisable to use the else
Nearest method when a beacon has begin
BackgroundRectangle.Fill.Color := ABeacon.Color;
triggered the OnBeaconExit event to
// Call the method that gets the beacon specific content
ensure your app interface doesn't go BeaconLabel.Text := ABeacon.Proc;
blank when there is still at least one BeaconLabel.TextSettings.FontColor := ABeacon.FontColor;
beacon within range. HeadingLabel.Text := ABeacon.Title;
NOTE: Since the proximity zone is based HeadingLabel.TextSettings.FontColor :=
BeaconLabel.TextSettings.FontColor;
on the distance calculation, it is possible to end;
see unexpected results for proximity end;
occasionally due to the inaccuracy in
calculating distance.
Handled Events
Code Samples The sample handles three of the available TBeacon
The TBeacon component makes it very easy to events. The first is the OnBeaconEnter event.
interact with beacons so there are only a couple of
interest points to cover from the procedure TfrmMain.MainBeaconBeaconEnter(const Sender: TObject;
accompanying app for this const ABeacon: IBeacon; const CurrentBeaconList: TBeaconList);
article to show. var
LBeacon: THouseBeacon;
begin
Useful Details if ABeacon.Proximity in [TBeaconProximity.Immediate,
A list of available beacons is TBeaconProximity.Near] then
created when the app starts. begin
LBeacon := GetBeacon(ABeacon.Major);
This allows us to update the
UpdateInterfaceFor(LBeacon);
interface based solely on the end;
beacon Major version value. end;
The class that holds the
information is very basic and includes a method
pointer for retrieving the actual content the beacon The second is the OnBeaconProximity event.
needs to display. procedure TfrmMain.MainBeaconBeaconProximity(
THouseBeacon = class const Sender: TObject; const ABeacon: IBeacon;
private Proximity: TBeaconProximity);
FLocation: THouseLocation; begin
FMajor: Word; if Proximity >= TBeaconProximity.Far then
FColor: TAlphaColor; UpdateInterfaceUseNearest;
FTitle: string; end;
FFontColor: TAlphaColor;
FProc: THouseInfoProc;
public
Finally the OnBeaconExit event
constructor Create(const AMajor: Word; const ATitle: string;
const ALocation: THouseLocation; is very simple. It updates the
const AColor, AFontColor: TAlphaColor; interface to display information
const AProc: THouseInfoProc); about the nearest beacon. If no
property Title: string read FTitle; beacon is within range, the user
property Location: THouseLocation read FLocation;
property Major: Word read FMajor;
interface is cleared.
property Color: TAlphaColor read FColor;
property FontColor: TAlphaColor read FFontColor;
property Proc: THouseInfoProc read FProc; procedure TfrmMain.MainBeaconBeaconExit(
end; const Sender: TObject;
const ABeacon: IBeacon;
const CurrentBeaconList: TBeaconList);
Since the beacon details are registered, the
begin
method for updating the user interface is simple UpdateInterfaceUseNearest;
and only contains one conditional statement to end;
cater for when no beacons are within range.

Issue Nr 2 2015 BLAISE PASCAL MAGAZINE 43


WORKING WITH BEACONS IN DELPHI XE8 (CONTINUATION 4)

Before running the code for your beacons be sure


to update the beacon identifying constants for
the app.

Below is a device capture when running the app Using a Manufacturers SDK
on my iPhone 5. It is important to point out that depending on the
beacon manufacturer, additional data outside of the
required information may be broadcasted. Estimote
have a connectivity mode (which is an
authenticated communication) where additional
information can be retrieved from the beacon.
For an Estimote beacon, this includes temperature,
battery life, firmware updates and also the
frequency at which the beacon signals. This
information can only be used with using the official
Estimote SDK with your app. This is not something I
have attempted to do with Delphi yet.

Conclusion
Beacons are an interesting addition to the world
and definitely show promise in the areas of
home automation and retail advertising. As
beacons become more powerful, smaller
(Estimote are releasing sticker Nearables soon)
and additional sensors are added the
possibilities for developers to take advantage of
them will increase.
Hopefully I've provided a little insight into the
world of beacons and have convinced you to
acquire some to play around with.

About the author


Jeremy North
owns a company called JED Services Pty. Ltd,
which includes JED Software.
He sells his components and IDE experts
through JED Software and does contracts under
JED Services.
He works exclusively on Win32 at the
moment and has also done quite a bit of .Net in
the past. He wrote most of the initial release of
the Ribbon controls for Delphi 2009.

44 Issue Nr 1 2015 BLAISE PASCAL MAGAZINE


What is Visuino?
Visuino is the latest innovative software from Mitov Software. A visual programming
environment allowing you to program your Arduino boards. Although it currently
supports the official Arduino boards, it is not restricted to their support alone and
requests to support new hardware are welcome.

INTRODUCTION What is Arduino?


The components found in the Visuino software represent their hardware components and you
will easily be able to create and design your programs using drag and drop. No equipment or
hardware is needed to run the software in design mode. Once you have completed the design,
you can connect Arduino board upload and run it.

For those people who are not strong on writing code then designing, compiling and creating
Arduino programs has never been easier! Why waste time on creating code when we have done
all the hard work for you already? You have your Arduino board, and great hardware design,
see it running in minutes, not hours!

Currently we are running a Beta program which you can be part of by joining our Google group.
Join the group now to download and test the software or send an email to mitov@mitov.com.

IN THE NEXT ISSUE:


ALL ABOUT VISUINO

www.visuino.com

VISUINO IS THE LATEST INNOVATIVE PRODUCT


FROM MITOV SOFTWARE.
Tel: +31 23 542 22 27

Delphi XE8
The Fastest Connected App Platform
for Windows and Beyond

Embarcadero Delphi XE8 is the fastest way for designing, coding, and extending connected apps across
Windows, Mac, iOS, Android and IoT. Build industrial strength and Business ready solutions incorporating multi-
ple native client platforms, mobile extensions, smart devices, cloud services, Enterprise and embedded data.

Extend and Connect Windows Apps


The number and types of devices people interact with on a daily basis have been
expanding at an amazing rate. We now have phones, tablets, wearables, and more in the
ever-growing Internet of Things. Delphi gives developers the solutions to keep up. Within
the single Delphi development environment, you can build high performance, compiled
native applications that easily connect with enterprise data, cloud services, devices,
sensors, gadgetsand more!

Multi-Device, Multi-form UI development


Delphi XE8 multiplies developer productivity again with FireUI, enabling your team to deliver your apps
natively for PCs, tablets, smartphones, and even wearables like smart watches, from a fully single
codebase, in record time. Get connected apps to market faster by developing for multiple platforms
and device form factors simultaneously, with one shared master form and device specific views as
needed. Maintain one shared codebase without sacrificing native platform fidelity.

Mobilize with Enterprise Mobility Services


Use the new Enterprise Mobility Services (EMS), a turnkey middleware server, to connect users and
apps to managed APIs, Enterprise databases and services hosted on-premises or in a private
cloud. With its user management and authentication plus user and API analytics, Enterprise
Mobility Services is ideal for enabling secure access from mobile and desktop apps to Enterprise
SQL Databases such as Oracle, DB2, Microsoft SQL Server, Informix, Sybase, and many more.

Heres what you can do with Delphi XE8

Significantly enhance performance with Extend your existing Windows applications


the new iOS 64 bit targeting native code with tethered mobile companion apps
compiling and Parallel Programming using Wi-Fi and Bluetooth connectivity.
Library.

Easily add proximity and location awareness Easily connect to popular cloud services
to your apps with component level Beacon with REST as well as BaaS providers for push
support. notifications, authentication, storage and
more!

Use the FireUI Multi-Device Designer to Quickly deploy Enterprise Mobility Services
build user interfaces once for multiple (EMS) to publish and manage custom APls,
device form factors and OSs with native Enterprise data, services, and analytics.
fidelity, capabilities, and uniqueness.
Tel: +31 23 542 22 27
Features Architect Ultimate Enterprise Pro Starter
Features
MULTI-DEVICE APPLICATION DEVELOPMENT
The most productive integrated visual development environment (IDE) with UI designers,
code editor, Code Insight, build and debugging tools X X X X X

FireUI Multi-Device Designers, Components, and Services X X X X


Develop natively compiled apps for 32-bit Windows X X X X X
Develop natively compiled apps for 64-bit Windows and for Mac OS X X X X X

Develop natively compiled apps for Android and iOS (now Optional
including 64-bit and Universal iOS apps) X X X

FRAMEWORKS, LIBRARIES, AND COMPONENTS


VCL for Windows framework with hundreds of visual components to create user interfaces,
X X X X X
database access and more (components vary by edition)
VCL source code to modify, extend, and customize the included components X X X X
FireMonkey FMX multi-device framework for Windows 32-bit and 64-bit X X X X X
OS X Yosemite and Mavericks deployment support including Retina and Mac AppStore X X X X

Single-source, mobile app development for Android and iOS with the FireMonkey framework X X X Optional
iOS (now including 64-bit andUniversal iOS apps)

Parallel Programming Library for VCL and FMX X X X X X


RTL with file system access, sensors, Bluetooth, App tethering, parallel threading library
(features vary by edition) X X X X X

DATABASE AND CLOUD SERVICES

Local database connectivity to InterBase, SQLite, MySQL and more X X X X

Client/Server database connectivity for leading database servers including Microsoft SQL Server,
X X X Optional
Oracle, Sybase, DB2, Informix, InterBase, ODBC and more

IBLite embedded database with free unlimited deployment X X X Optional

DataSnap n-tier middleware SDK for building application and data services X X X
Enterprise Mobility Services, a turnkey set of integrated services including user authentication,
middleware database connectivity, custom REST API management and analytics* X X X Optional
*Requires separate per-user runtime agreement
REST client library and Back-end as a Service Components for Parse and Kinvey X X X Optional

Cloud computing with Amazon Web Services and Microsoft Azure X X X X


Fast SQL database development, change management, SQL profiling and SQL tuning with
X
DB PowerStudio Developer Edition

Database modeling and design with ER/Studio Developer Edition X

LICENSING

Indie license for hobbyists and getting started X

Full commercial development and deployment license X X X X


Earlier version access to licenses for Delphi 6 and 2007-XE7 X X X X

Delphi XE8 System Requirements


1 GB RAM (2 GB+ recommended) Mouse or other pointing device
7-37 GB free hard disk space depending on edition and configuration, Microsoft Windows 8 or 8.1 (32-bit and 64-bit)
including space required for temporary files Microsoft Windows 7 SP1 (32-bit and 64-bit)
DVD-ROM drive (if installing from a Media Kit DVD) Microsoft Windows Server 2008 and 2012 (32-bit and 64-bit)
Basic GPU Any vendor DirectX 9.0 class or better (Pixel Shader Level 2) Delphi can also be run on OS X by using a virtual machine (VM) such as
Intel Pentium or compatible, 1.6 GHz minimum (2GHz+ recommended) VMware Fusion or Parallels hosting Windows Vista, 7 or 8
1024x768 or higher-resolution monitor

For developing 64-bit Windows applications For developing Mac OS X applications For developing iOS applications Supported Deployment Platforms

PC running a 64-bit version of Windows or PC running Windows connected with PC running Windows connected with an PCs and tablets with Intel/AMD processors
a 32-bit development PC connected with a an Intel-based Mac or a Mac running Intel-based Mac or a Mac running Win- running Windows 7, 8, 8.1, Server 2008,
PC running a 64-bit version of Windows. Windows in a VM, with 2 GB RAM or more, dows in a VM, with 2 GB RAM or more, or Server 2012. Macs running OS X 10.9
running OS X 10.10 (Yosemite) or 10.9 running OS X 10.10 or 10.9 with Xcode 6 or 10.10. iPhone, iPad, or iPod Touch
(Mavericks). An Apple Developer account is required running iOS 7. Android phones and tablets:
to deploy iOS apps to physical devices. ARMv7 devices with NEON support, running
Ice Cream Sandwich (4.0.3-4.0.4), Jelly Bean
(4.1.x, 4.2.x, 4.3.x) or KitKat (4.4.x) and
Lollipop (5.x).

DownloadDownload
a Free Triala Now! Visitatwww.embarcadero.com/trial
free Trial www.barnsten.com

Barnsten | Tel: +31 23 542 22 27sales@embarcadero.com | www.embarcadero.com


| Fax: +31 84 755 52 60 | P.O. Box 5010 | 2000 GA Haarlem | The Netherlands
2015 Embarcadero Technologies, Inc. Embarcadero, the Embarcadero Technologies logos, and all other Embarcadero Technologies product or service names are trademarks or registered trademarks of
EXTREME PERFORMANCE
NOW FASTER THAN EVER!

KBMMW V. 4.80 AMQP support


( Advanced Message Queuing Protocol)

- Added AMQP 0.91 client side gateway Supports Delphi/C++Builder/RAD Studio 2009
support and sample. to XE7 (32 bit, 64 bit and OSX where applicable).
- Updated StreamSec TLS transport plugin kbmMW for XE5 to XE7 includes full support for
component (by StreamSec). Android and IOS (client and server).!
- Improved performance on Indy TCP/IP
kbmMemTable is the fastest and most feature rich
Client messaging transport for large number in memory table for Embarcadero products.
of inbound messages.
- Easily supports large datasets
- Native high performance 100% developer with millions of records
defined application server with support for - Easy data streaming support
loadbalancing and failover - Optional to use native SQL engine
- Native high performance JSON and XML - Supports nested transactions and undo
- Native and fast build in M/D,
(DOM and SAX) for easy integration with
aggregation /grouping,
external systems range selection features
- Native support for RTTI assisted object - Advanced indexing features for
marshalling to and from XML/JSON, now also extreme performance
with new fullfeatured XML schema
(XSD) import Warning!
- High speed, unified database access kbmMemTable and kbmMW
(35+ supported database APIs) with
connection pooling, metadata and
are highly addictive!
Once used, and you are hooked for life!
data caching on all tiers
- Multi head access to the application server,
via AJAX, native binary, Publish/Subscribe,
SOAP, XML, RTMP from web browsers,
embedded devices, linked application
servers, PCs, mobile devices, Java systems

COMPONENTS
4
and many more clients
- Full FastCGI hosting support.
Host PHP/Ruby/Perl/Python applications in
kbmMW! DEVELOPERS

EESB, SOA,MoM, EAI TOOLS FOR INTELLIGENT SOLUTIONS. kbmMW IS THE PREMIERE N-TIER PRODUCT FOR DELPHI /
C++BUILDER BDS DEVELOPMENT FRAMEWORK FOR WIN 32 / 64, .NET AND LINUX WITH CLIENTS RESIDING ON WIN32 / 64,
.NET, LINUX, UNIX MAINFRAMES, MINIS, EMBEDDED DEVICES, SMART PHONES AND TABLETS.

Das könnte Ihnen auch gefallen