Citation preview
SDN Magazine 110Nummer 110 augustus 2011 SDN Magazine verschijnt
elk kwartaal en is een uitgave van Software Development
Network
www.sdn.nl
Skin Widgets in DotNetNuke <
Input validatie en output encoding <
voor een veiligere ASP.NET webapplicatie
SOFTWARE DEVELOPMENT NETWORK
Colofon Uitgave:
Roel Hans Bethlehem, Christiaan Heidema,
Bob Swart, Stefan Kamphuis, Peter Donker,
Maarten van Stam, Alexander Meijers, Remi
Caron, Marcel Meijer en natuurlijk alle
auteurs!
Listings:
source files uit deze uitgave.
Contact:
E-mail: info@sdn.nl
schriftelijke toestemming van SDN. Tenzij
anders vermeld zijn artikelen op persoonlijke
titel geschreven en verwoorden zij dus niet
noodzakelijkerwijs de mening van het be-
stuur en/of de redactie. Alle in dit magazine
genoemde handelsmerken zijn het eigen-
dom van hun respectievelijke eigenaren.
Adverteerders Bergler 2
onder de rubriek Magazine.
voorwoord Beste SDN Magazine lezer,
jammer, in mijn vorige voorwoord had ik het over een lange hete
zomer. De zomer is
qua weer een beetje tegengevallen ondanks het mooie begin in het
voorjaar. Helaas
heeft die warmte niet doorgezet in de zomer. We hopen, dat jullie
toch allemaal
genoten hebben van een vakantie al dan niet in verre warme
oorden.
Qua nieuwe ontwikkelingen voor ontwikkelaars was het toch een hete
zomer. Aan het
einde van de maand juli werd LightSwitch gereleased en werd Windows
Phone
Mango vrijgegeven voor de Windows Phone 7 hardware leveranciers.
Daarnaast zijn
er nieuwe Visual Studio tools voor Windows Azure vrijgegeven en is
er een nieuwe
Windows Azure trainingskit beschikbaar. Kortom er was genoeg om de
natte zo-
merdagen door te komen.
Dit magazine bevat weer een geweldige diversiteit aan artikelen.
Deze keer zijn ze in-
gedeeld volgens de industriestromingen waar wij als SDN op
focussen. Deze
stromingen zijn Web, Desktop, Mobile en Cloud. Ook Delphi en
DotNetNuke
artikelen vallen in deze categorieën. Sterker nog deze keer hebben
we een heel
aardig artikel over Delphi en Azure. Wie zegt dat Delphi een legacy
omgeving is, dit
artikel bewijst het tegendeel. Voor de Software Architecten een
uitgebreid artikel over
DYA. Dat wij als SDN niet gebonden zijn aan het Microsoft platform
bewijzen de
artikelen over Andriod en iPhone wel. Oké, C# is in beide gevallen
wel de program-
meer taal.
Ondertussen zijn we ook al weer bezig met de organisatie van de SDN
Conferences
2011. Deze keer organiseren we deze voor de 20-ste keer. Helaas
kunnen we nog
niet heel veel kwijt over de precieze invulling, maar het belooft
wel een mooi spekta-
kel te worden. Ook deze keer gaan we over de industrie-assen, dus
hebben we
aparte tracks voor Desktop, Web, Mobile en Cloud. Daarnaast komen
ook DotNet-
Nuke en Delphi met eigen tracks weer volledig tot hun recht. De
maandag avond
belooft voor de Delphi track reuze interessant te worden! Voor de
andere conferences
zijn we met een echte knaller bezig! Als je hier niet geweest bent,
dan heb je wel iets
gemist! Kortom, hou de website www.sdc.nl in de gaten en schrijf je
in! Kosten tech-
nisch is de SDN Conferences 2011 heel aantrekkelijk en zoals altijd
is de content
perfect! Laat de ingesloten flyer vooral zien aan vrienden en
collega’s.
Rest mij jullie nog heel veel leesplezier! We hebben onze uiterste
best gedaan er weer
een erg mooi magazine van te maken. Volgens ons is dat gelukt.
Mochten jullie
vragen c.q. opmerkingen hebben, laat het dan weten op
redactie@sdn.nl of
marcel.meijer@sdn.nl.
Marcel •
04 Inhoudsopgave
04 Agenda
05 Foto’s maken met Mono for Android Willem Meints
10 Azure Applications with Delphi XE Marco Cantù
14 MVVM met Catel Geert van Horrik
17 Ik weet alles beter! (Of toch niet?)
Michiel van Otegem
Hubert Klein Ikkink
Theo Neeskens
30 Querying nested groups in Active Directory
Mark Dirksma
33 iOS en C#, een mooi koppel Roy Cornelissen
40 Input validatie en output encoding voor een veiligere ASP.NET
webapplicatie
Alex Thissen
Robert Deckers
49 Skin Widgets in DotNetNuke
Will Strohl & Armand Datema
• Delphi XE2 Seminar (Helmond)
magazine voor software development 5
Foto’s maken met Mono for Android Het ontwikkelen van mobile apps
is helemaal in. Via de appstores van Apple en Google kun je de
wereld aan apps vinden voor zo ongeveer alles wat je maar wilt
hebben. Ik kan mij voorstellen dat je zelf een app wilt ontwikkelen
om deze vervolgens in de appstore te publiceren. Je kan dat doen
met de standaard ontwikkeltools van Google of Apple, maar als je
.NET programmeert in het dagelijks leven dan is er ook een andere
manier om apps te ontwikkelen.
In dit artikel laat ik je zien hoe je met Mono for Android een
Android app kan ontwikkelen waarmee je een foto kan maken en
weergeven op het scherm.
Wat is het Mono for Android framework? Het Mono for Android
framework is een implementatie van Mono op het Android platform.
Novell heeft ervoor gezorgd dat je als .NET ontwikkelaar met je
bestaande .NET kennis een app kan ontwikkelen op het Android
platform. Daarbij kun je gebruik maken van alle bekende
programmeerinterfaces zoals LINQ, WCF, Threading, Sys- tem.Xml en
andere veelgebruikte onderdelen van het .NET framework.
Fig. 1: Architectuur Mono for Android
In figuur 1 is te zien hoe de architectuur van het Mono for Android
framework er uit ziet.
Om het Mono framework te laten communiceren met het Android plat-
form heeft Novell een aantal specifieke architectuur keuzes
gemaakt. Zo is het Mono framework niet boven op de Dalvik runtime
gebouwd. De Dalvik runtime is de java virtuele machine waarop alle
apps binnen Android worden uitgevoerd. In plaats van Mono bovenop
de Dalvik engine te draaien is er een apart systeem ontwikkeld dat
rechtstreeks op de Linux kernel van het Android OS draait. Dit
maakt het mogelijk om de reguliere Mono JIT compiler te gebruiken
samen met de eigen garbage collector.
Apps op Android kunnen worden gestart vanuit de launcher of door op
de widget te drukken op het bureaublad van je telefoon. Zowel de
launcher als de widgets kunnen alleen worden geimplementeerd
door
het schrijven van Java code. Om toch Mono for Android apps te
kunnen starten wordt er voor elke .NET class, die aangeroepen moet
kunnen worden vanuit Android, een Android Callable Wrapper (ACW)
gegenereerd door de Mono for Android compiler. Een ACW kan het
beste worden gezien als de stunt-double van een .NET class.
Er is door Novell gekozen om met Mono for Android zo dicht mogelijk
de native omgeving te benaderen op het Android platform. Net als
reguliere Android apps bestaat daarom een Mono for Android app uit
een serie activities waarvan er een is geregistreerd in de eerder
genoemde launcher. Een Activity is echter een Java class. Om deze
class te kunnen gebruiken is het noodzakelijk om hiervoor een
zogenaamde Mono Callable Wrapper (MCW) te gebruiken. Dit is net als
de ACW een stunt-double, maar dan voor een Java class. ACW
componenten en MCW componenten zijn componenten die intern
communiceren via de JNI (Java Native Interface). Java en Mono
praten nooit rechtstreeks tegen elkaar, maar altijd via de Mono
runtime die op de Linux kernel draait. Deze vertaalt daarbij
allerhande zaken op een zodanige manier dat als er wordt verwezen
naar een Java object er aan de Mono kant een .NET object bestaat en
andersom.
Het Mono for Android framework draait voor een groot deel om
vertaalslagen tussen Android en Mono. Novell heeft er voor gezorgd
dat ontwikkelaars hier geen grote hinder van ondervinden. De gehele
Android API is voorzien van een .NET saus zodat je geen
getProperty() en setProperty() methodes meer ziet, al dit soort
constructies zijn omgezet in .NET native constructies.
Je eerste app ontwikkelen Voordat je kan beginnen met het
ontwikkelen Mono for Android moet je de nodige voorbereidingen
treffen. Voor het kunnen compileren voor Android heb je de Android
SDK nodig. Deze kan je downloaden vanaf de Android developer
website. Nadat je hem hebt gedownload moet je de SDK manager van de
Android SDK eenmalig starten om de rest van de SDK te installeren
op je computer.
Naast de Android SDK heb je ook de Mono for Android componen- ten
nodig. Deze kun je vinden op de website van Mono for Android
(http://mono-android.net/).
MOBILE
MAGAZINE
6
Als je na de installatie Visual Studio 2010 opstart en een nieuw
project gaat aanmaken zal je een nieuwe categorie project templates
aantreffen in het dialoogvenster.
Fig. 2: Mono for Android projecttypes
Mono for Android ondersteunt een drie tal verschillende soorten
projecten. Je kan een Mono for Android Application maken, dit is
een reguliere Android app. Daarnaast kan je een OpenGL app maken,
hiermee kun je een game ontwikkelen voor Android. Tot slot kun je
een Mono for Android library ontwikkelen, je kan dit vergelijken
met een JAR library voor Android.
Voor het voorbeeld heb ik gebruik gemaakt van de Mono for Android
application template. Als je op basis hiervan een project aanmaakt
krijg je een structuur waarbij een Activity class is aangemaakt in
het project en er een setje mappen is neergezet met wat standaard
resource files. In figuur 3 is de structuur weergegeven zoals je
hem in Visual Studio 2010 ziet.
Fig. 3: Projectstructuur
Het Android besturingssysteem werkt met zogenaamde activities om
delen van apps aan te duiden. Je kan een activity vergelijken met
een enkel scherm in een Windows Forms applicatie. Activities zijn
echter
wel meer geïsoleerd van elkaar dan dat je gewend zult zijn vanuit
Windows Forms. Je kan activities namelijk alleen opstarten
doormiddel van intents. Intents zijn berich- ten die je kan
versturen richting het Android OS. Deze berichten bevatten een
soort adres, namelijk de actie. Daarnaast kun je zogenaamde extra’s
meesturen, dit is een dictionary met key-value pairs waarin je
extra gegevens kan doorgeven aan de ontvanger van de intent.
Intents worden gebroadcast en de eerste app die reageert wint en
mag de intent afhandelen. Alles en iedereen mag zich inschrijven
voor intents. Je kan bijvoorbeeld je inschrijven op een intent voor
het adresboek. Je vervangt dan het normale adresboek van Android
met je eigen implementatie.
Het voorbeeld dat ik ga gebruiken is een app waarmee je een foto
kan nemen en deze vervolgens kan e-mailen naar iemand
in je adresboek. De eerste stap om richting het kunnen nemen van
een foto is het implementeren van de root activity van de app. Er
is minimaal één activity in je app die gekoppeld dient te zijn aan
de Android launcher om hem te kunnen starten.
[Activity(Label = "PhotoMailer", MainLauncher = true, Icon =
"@drawable/icon")]
{
SetContentView(Resource.Layout.Main);
tArgs e)
Codevoorbeeld 1: FotoMailer activity
In codevoorbeeld 1 is te zien hoe de MainActivity van de app eruit
ziet. Boven de class staat een attribuut om aan te geven dat het
een acti- vity is en dat hij in de launcher moet worden
weergegeven. Dit attribuut wordt door de Mono for Android compiler
gebruikt om de juiste infor- matie in het app manifest te zetten.
Dit manifest beschrijft hoe je app eruit ziet en welke rechten hij
nodig heeft op het Android OS.
In de OnCreate methode kun je de benodigde configuratie doen van je
activity, zoals het inladen van een layout file voor de user
interface. Dit doe je door de methode SetContentView(…) aan te
roepen.
MOBILE
magazine voor software development 7
Aan deze methode geef je het ID van de layout resource mee die je
wilt inladen. Deze ID’s worden automatisch voor je gegenereerd op
het moment dat je het project een keer compileert. De layout
resource ID’s vind je na het compileren terug in Resource.Layout.XX
properties.
Je kan in Android op twee manieren met user interface omgaan. Je
kan in code de user interface opbouwen of een layout file inladen.
Het laatste is een stuk praktischer dan de user interface in code
op- bouwen. Je kan namelijk voor allerlei uitgangssituaties layout
files pro- duceren. Zo kun je bijvoorbeeld een layout file maken
voor portrait en landscape. Je plaatst dan de ene file in
Resources\layout-portrait en de andere in
Resources\layout-landscape. Zolang je ze dezelfde naam geeft zal
Android zelf kunnen uitzoeken welke hij moet weergeven.
De layout van de voorbeeld app bestaat uit twee knoppen en een
imageview. De imageview kan je gebruiken om een afbeelding weer te
geven op het scherm. De layout is in codevoorbeeld 2
weergegeven.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
Codevoorbeeld 2: Layout file
Zowel de button als de imageview zijn voorzien van een android:id
attribuut, met een @+id constructie. Door deze constructie te
gebrui- ken maak je duidelijk aan de resource generator dat je
graag een nieuw ID wilt hebben. Je kan ook gebruik maken van
bestaande ID’s uit de Android omgeving. Dit gebruik je voor
constructies waarbij je een bestaande user interface wilt aanpassen
specifiek voor jouw app. In het codevoorbeeld zie je op een aantal
punten een vermelden met @string staan. In Android kun je gebruik
maken van zogenaamde string files waarin je de teksten die je wilt
gebruiken in de user inter- face kan bewaren. Op deze manier kun je
de user interface vertalen in meerdere talen. Om gebruik te maken
van deze teksten geef je ze in de string file een naam en refereer
je naar deze naam doormiddel van de @string/naam constructie in je
layout files.
Een foto nemen Nu de basis van de applicatie staat, is de volgende
stap het toevoe- gen van functionaliteit om een foto te nemen. Het
nemen van een foto op Android doe je door een intent op te starten
en het resultaat ervan weer op te vangen in je activity. Zoals je
eerder hebt kunnen lezen wor- den intents gebruikt om te
communiceren met het OS. Je hebt dit in het geval van een foto
maken nodig, omdat je niet weet welke app de gebruiker van de
telefoon heeft geïnstalleerd voor het maken van foto’s.
Voor het nemen van een foto heb je de intent
“android.media.ac-
tion.IMAGE_CAPTURE” nodig. Aan deze intent kun je een output file
mee geven, maar dat hoeft niet. Geef je het niet mee dan is het de
bedoeling dat de activity die de intent implementeert, zelf een
naam verzint.
private const int TakePictureRequestCode = 1001;
private void OnTakePictureClicked(object sender, EventArgs
e)
Intent intent = new Intent(MediaStore.ActionImageCap-
Codevoorbeeld 3: Een foto nemen
In codevoorbeeld 3 is te zien hoe je de camera kan starten. Je ziet
de naam van de intent niet meer terug in de code, omdat Novell
hiervoor een constante heeft gegenereerd in de Mono for Android
library. Je vind de intent voor het nemen van een foto en andere
media gerelateerde intents terug op de MediaStore class.
Om het resultaat van de camera op te kunnen vangen start je de
intent op met de methode StartActivityForResult. Bij het starten
kun je een requestcode opgeven. In het volgende codevoorbeeld zal
je zien hoe je hier handig gebruik van kunt maken. De app kan met
de code in codevoorbeeld 3 prima foto´s maken alleen krijg je ze
nooit meer terug. Om de foto namelijk terug te halen moet je de
methode OnActivityResult overriden in je activity.
protected override void OnActivityResult(
Codevoorbeeld 4: Resultaat van de camera opvangen
In de OnActivityResult methode krijg je een intent terug met
daaraan de data van de activiteit. Daarnaast krijg je een
requestcode en een resultaatcode terug. De requestcode die je hier
terugkrijgt komt overeen met de requestcode die je bij het starten
van de intent hebt opgegeven. Als je in deze methode terechtkomt is
het belangrijk om te controleren of de activiteit gelukt is. Dit
doe je door te controleren de resultCode overeenkomt met de waarde
Result.OK. Daarnaast moet je controleren voor welke intent je data
terug hebt gekregen. Als je namelijk meerdere intents tegelijk
opstart in je app kan het zijn dat het resultaat van de ene intent
eerder terug is dan van de andere.
MOBILE
MAGAZINE
8
Als je een foto hebt genomen met de camera intent krijg je een URI
terug van de afbeelding die is genomen door de camera. Deze URI kun
je vervolgens koppelen aan een imageview om de foto weer te
geven.
Hinken op twee gedachten In de voorbeeld app merk je niet veel van
het feit dat Android op Java is gebaseerd. Maar hoewel je .NET
programmeert met Mono for Android zul je het Java aspect toch nog
overal terug vinden in de apps die je ontwikkelt.
Onderdelen van de app die gebruik maken van de Android voorzie-
ningen hebben dikwijls classes nodig die zijn afgeleid van
Java.Lang.Object. Je zult merken dat het gehele Mono for Android
framework eigenlijk een beetje op twee gedachten hinkt. De ene keer
heb je te maken met System.Object en de andere keer heb je te maken
met Java.Lang.Object. In de praktijk levert dit niet heel vaak
problemen op. Het punt waarop je er wel mee te maken krijgt is
bijvoorbeeeld op het moment dat je een web service reference aan je
app hebt toegevoegd en je objecten daaruit wilt weergeven op de
user interface. Om objecten in een lijst op het scherm te tonen
maak je gebruik van een zogenaamde ListAdapter. Een ListAdapter
vertaalt elk object in zijn data source naar een view op het
scherm. De List Adapter gaat uit van Java.Lang.Object gebaseerde
objecten in zijn data source. Deze heb je echter niet als je
objecten ophaalt van een webservice die je via een service
reference hebt gekoppeld aan je app.
Een oplossing voor dit scenario en vergelijkbare scenario’s is
gelukkig eenvoudig te implementeren. In codevoorbeeld 5 is een
wrapper geschreven die het mogelijk maakt om objecten die niet zijn
afgeleid van Java.Lang.Object toch als zodanig te behandelen.
public class JavaObjectWrapper<T> : Java.Lang.Object
{
JavaObjectWrapper<T> input)
Codevoorbeeld 5: Java object wrapper
Wanneer je zelf een ListAdapter gaat implementeren kun je handig
gebruik maken van de wrapper uit codevoorbeeld 5 op het moment dat
je een bepaald item uit de gekoppelde lijst moet teruggeven aan het
Android OS. Een voorbeeld hiervan zie je in code voorbeeld 6.
public class MyListAdapter<T>: BaseAdapter
{
{
}
// ...
}
Codevoorbeeld 6: Java object wrapper in combinatie met een list
adapter
De toegevoegde waarde van Mono for Android De standaard omgeving
voor Android is eclipse met de Android SDK. Het Java platform is op
zichzelf een prima keuze om Android mee te ontwikkelen, dus waarom
zou je wat anders willen? De reden om wat anders te willen doen zit
hem niet zozeer in de extra mogelijkheden die Mono for Android
biedt. Dit zijn er namelijk maar een beperkt aantal. De echte
kracht van Mono for Android zit hem in de mogelijkheid om de C#
code, die je hebt geschreven voor je Android app, te kunnen
hergebruiken in bijvoorbeeld een Windows Phone 7 app of een
MonoTouch app. Om de hoeveelheid code die je kan hergebruiken zo
groot mogelijk te maken is het wel zaak om de logica van je app zo
in te delen dat je de business logica gescheiden houdt van de
logica om de user interface aan te sturen. Op deze manier heb je
een groot geheel dat je kan hergebruiken. Het user interface
gedeelte kun je vervolgens helemaal toespitsen op Android en er het
maximale uit halen qua mogelijkheden die Android biedt. Als je
alleen .NET programmeert is Mono for Android ook een prima keuze.
Je hoeft namelijk op dat moment alleen de Android specifieke zaken
te leren. Je hoeft geen nieuwe programmeertaal te leren en je hoeft
ook niet te leren omgaan met de standaard Java classes. Je kan in
plaats daarvan gebruik blijven maken van de bestaande kennis die je
in de loop van de tijd hebt opgedaan op het .NET platform.
Conclusie Zoals je hebt kunnen zien voelt het ontwikkelen met C# op
Android heel natuurlijk aan als je .NET gewend bent. Er zijn en
blijven altijd kleine details, die net even anders werken dan je
gewend bent, maar over het algemeen is het een solide combinatie.
Het wordt zelfs nog krachtiger als je slim nadenkt over de opzet
van je app en delen ervan apart zet, zodat je deze code ook kan
hergebruiken voor Windows Phone 7 en MonoTouch. De smartphone markt
is dusdanig gefrag- menteerd dat als je apps wilt ontwikkelen, voor
de diverse populaire platforms, je enorme investeringen moet doen
in kennis en tools. Door te investeren in het cross-platform
ontwikkelen van apps door middel van C# zul je merken dat je beter
in staat bent om apps te produce- ren voor zowel Android, iPhone
als Windows Phone 7. Daarnaast zal je merken dat je apps vooral
goedkoper kunt produceren.
Links • http://www.mono-android.net/ - Website van Mono for Android
• http://developer.android.com/ - Android developer website •
Willem Meints
Support voor het Professional De-
velopment Centre. Naast zijn werk
is hij een actief blogger waarbij hij
zich voornamelijk bezighoudt met
user interface technologieën als
ASP.NET, Silverlight en natuurlijk
with
30009
3000emplo
eesyemplo
op-quality softwers tCSC deliv echnology serviction tormainf
t ideas, prs the beso harnesus t e do amazing things. Find out
morors. Wsect
e the we aro its clients. We tarop-quality softw e acrxperienc. Our
eyompanes cechnology servic
om both the public and prives and solutions fractict ideas, pr
om.ct csc.e ae do amazing things. Find out mor
s leading independent orld’e the w tries enables s all indusose
acr
e taom both the public and priv
Marco Cantù
Delphi XE Components for Azure Delphi XE includes some components
for Azure, but also and moreover a number of lower level classes,
which is where the real power is. These classes provide
ready-to-use methods for performing the various operations and deal
with the complicated security requi- rements of the Azure
platform.
The core non-visual component is the one used to configure the
connection to the service, called TAzureConnectionString. Although
this component has a few quirks in its user interface (it messes up
the Object Inspector in the IDE1) it is a handy starting point in
which to enter the user name and password of your account. Other
visual components offer direct navigation and management of the
respective data structures: • TAzureTableManagement is for NoSQL
tables2 • TAzureBlobManagement is for binary data (that is, files,
images, documents...)
• TAzureQueueManagement is for managing queuing services
These management components are very nice to learn about these
services and examine their status, but aren't generally a good end
user tool, safe for the real power users. In practical terms,
you'll ge- nerally use the low-level classes behind these
components rather than the visual “management” TreeView controls.
The three core classes, defined in the DSAzure unit, are: • The
TAzureTableService class • The TAzureBlobService class • The
TAzureQueueService class
Building an introductory Demo, Azure101 In the Azure101 project I
introduce both the visual components and the low level classes,
focusing on the Table and Blob services. The programs loads the
account settings from an INI file. There are two Azure visual
controls hooked to this configuration component, as you can see in
Listing 1:
object AzureTableManagement1: TAzureTableManagement
ConnectionInfo = AzureConnectionString1
In Delphi XE there is native and specific support for three of the
Microsoft's Azure cloud services: Queue, Tables, and Blobs. This
article provides a short introduction to these components and the
underlying classes, and shows a practical demo of how to use the
Azure service compo- nents to publish some database data on a
hosted database, and also consume that data. This article is based
on the last section of my new Delphi XE Handbook, and the source
code is also available from the book Subversion repository at
code.marcocantu.com.
Azure Applications with Delphi XE
Active = False
end
Listing 1: The simple properties of the Azure Management components
of the demo
As with a database component, you won't generally activate them at
design time. Given they might take some time for the setup, you
won't probably even turn them on in the OnCreate event handler. In
this demo I do it when a button is pressed, turning the Active
property of both management components to True. At this point you
can use the two controls for browsing the current Tables and Blob
containers of your account. You can double click on each of them to
open a dialog box with more details. In Figure 1 you can see the
information displayed by the TreeViews.
Fig. 1: The Azure101 demo lets you browse your Azure Tables and
Blobs
As you can see in the figure, the information about tables is
limited, and you'll have to double click on a table to open a
dialog and see more. For the Blobs, instead, you can drill into the
list of elements in each container and also see the list of the
properties, the meta data, and the access control list right into
the main TreeView. For the Blobs you can
DELPHI / CLOUD
DELPHI / CLOUD
also use this view to load new files and set their permissions. The
button on the side will copy to the clipboard the main URL for your
azure data, which in my case is:
http://marcocantu.blob.core.windows.net You can combine this URL,
the container name, and the object name to figure out its public
URL, like (if you look again at the image above):
http://marcocantu.blob.core.windows.net/mydata/euro.jpg This can be
properly seen in a browser only because I set its Content- Type
property to a format browsers should recognize (see the details in
the image below). Using a URL like the one above anyone can see the
image I uploaded with a Delphi program. In Figure 2 you can see the
set of properties for the object:
Fig. 2: The properties of an Azure Blob object in the AzureBlob
Management component
In terms of the tables, you need to open the details of one to see
its structure, as displayed in Figure 3. Differently from what you
might expect, the table data is not displayed in a grid. In fact,
this is not a relational database table, but rather a NoSQL table
structure, in which each row can have different fields or, to be
more precise, named attributes.
Fig. 3: The detailed view of an Azure Table in a dialog displayed
by the AzureTableManagement component
Now what is more interesting, of course, is to interact with this
table in your code. For example, you can add a new row to a table
using the InsertEntity method of the TAzureTableService class. The
row infor- mation is passed in JSON format, so you can use Delphi's
TJSON- Object class (from the DBXJSON unit) to define the proper
data structure. This must have the RowKey and PartitionKey
attributes, defined in Delphi with two constants called XML_ROWKEY
and XML_PARTITION. The other element is that some rows can have
extra fields, which doesn't mean that other rows have those fields
empty, but that they won't have them. In fact there is no schema or
definition of a table: the table structure is defined by the
contents of the records you add to it. In listing 2 there is the
code used to add a new row to the table.
procedure TAzure101Form.btnAddRowClick(Sender: TObject);
Log (TableService.InsertEntity('marco1', RowObj));
finally
TableService.Free;
end;
end;
Listing 2: The code used to add new rows to an Azure Table
The other operation done by the program is to query the table for
the list of records. This is accomplished by calling the
QueryEntities method of a TableService object. The result of this
call, however, uses an XML format (basically an ATOM format) that
the program logs without parsing it. The interesting element of
this approach is that once we have created this data structure (or
table), it can be used by anyone with the proper permissions and an
Internet connection. There is a cost associated, of course, but
quite minimal compared to alternative hosting solutions.
The Azure Publish and Consume Demo The Azure101 demo can get you
started using Delphi's Azure support, but it certainly falls short
in terms of demonstrating its usefulness. The “management” views
are quite nice, but that's hardly the interface you'll want to
present to an average end user. That's why I decided to add a
second demo, made of two programs: • The first is a publishing
application that pulls data from a database and makes it available
in an online Azure Table, while the content of graphical fields is
published in an Azure Blob.
• The second is a browsing application that pulls the data from the
Azure cloud storage and shows it to the end user. Notice that this
way the end user doesn't require a connection to the database and
can benefit from the high bandwidth offered by Azure.
Publishing the Data to Azure To stick to a classic Delphi theme,
the database in question is the Biolife table from the FishFact
database. In this case I'm using the ClientDataSet version for
simplicity. Let's look at the CloudPublish application first. The
main form of this program has two fields referring to the services
we are going to use. These are initialized in the OnCreate event
handler after loading the account settings from the INI file, like
in the previous example. Before publishing the data, you have to
create the corresponding containers. To publish the data of a
single record, we have to create a JSON data structure, include a
row key (in this case the record id) and a partition key (in this
case a time stamp), and also post a stream with the image
magazine voor software development 11
DELPHI / CLOUD
Fig. 4: The simple user interface of the CloudPublish example
The first specific operation of the browsing demo is a call to
Query- Entities to get a list of the records as XML. This return
string is processed using an XML-mapper generated interface.
However, to parse the actual content of each node we cannot use the
interface, as the presence of a nested XML name space causes the
interface to fail whilst reading the information (as requests
return empty strings in case of a name space mismatch). The code
that parses the XML will add to a list the row and partition keys,
which are used later to retrieve the details as a user double
clicks on a list item, with the code in Listing 4, and display the
information like shown in Figure 5.
procedure TFormCloudBrowse.ListBox1DblClick(Sender: TObject);
Image1.Picture.Graphic.LoadFromStream(memStream);
finally
MemStream.Free;
end;
end;
Listing 4: The code used to retrieve the data and image of a
specific record
Again, notice that this browsing application doesn't require a
connection to the original database or to a custom web server, but
relies only on the tables and images provided by Azure cloud
storage, which has almost infinite bandwidth.
using as name the same record id, as you can see in Listing 4
(which incldues also the method used transform the original bitmap
image in a JPEG, using a temporary memory stream).
procedure TFormCloudPublish.btnPostOneClick(Sender: TObject);
finally
jpgImg.Free;
aStream.Free;
end;
end;
Listing 3: The code used to publish the database data to
Azure
Another button let's you scan the database table and post each
record. I haven't told much about the user interface of this
program because it is very bare bones, as you can see in Figure
4.
Now let's look at the browsing application, called CloudBrowse.
When this form is created, it does an initialization similar to the
other Azure programs. For this demo, I'm using a single account,
but you can set up Azure to have a separate user with read-only
rights.
MAGAZINE
12
magazine voor software development 13
Fig. 5: The user interface of the CloudBrowse example, showing both
record data and images
Conclusion It is hard to tell how much cloud computing will be a
temporary fad and how much of our computing power will reside in
web farms owned by a few companies in a few years time, but what is
relevant to notice here is that Delphi can be used in this scenario
and that there is no
“single preferred vendor” (like in other architectures) but rather
the ability to use services of multiple companies. The net result
is that in many cases you can extend your native Windows
application with a new reach to the Internet, without having to
rewrite them as Web applications. •
Marco Cantù
best-selling Delphi books, including
recent Delphi Handbook series (the
last being a Delphi XE Handbook).
He's also an active user and deve-
loper in the Web 2.0 world and
social web, like Twitter.
cantu.com, blog.marcocantu.com, and twitter.com/marcocantu
De toekomst van MonoTouch en Mono for Android
Miguel de Icaza en zijn team zijn di- rect na hun ontslag gestart
met een nieuw bedrijf met de naam Xamarin. Xamarin herbouwt op dit
moment MonoTouch en Mono for Android. Het ziet ernaar uit dat ze
het intellectueel eigendom van Novell niet meekrijgen, maar omdat
bijna het volledige team bij Xamarin in dienst is gegaan, is alle
kennis aanwezig die nodig is om de producten nieuw leven in te
blazen. Xamarin mikt op een release aan het eind van de zomer en
belooft daarbij dat alle Mo- noTouch code “source code compa-
tible” zal zijn met hun nieuwe tool.We krijgen vaak vragen over de
risico’s rondom de investering in Mono- Touch. Wij zijn ervan
overtuigd dat
Xamarin een uitstekende job zal doen bij het herbouwen van deze
produc- ten. Tot die tijd loont het zeker de moeite om alvast met
de gratis trial versie aan de slag te gaan. En weg- gegooide kennis
is het nooit, want je benut enerzijds herbruikbare C#/.NET kennis
en anderszijds investeer je in kennis van Cocoa Touch. Mocht het
zover komen dat je in Objective-C aan de slag moet, dan zijn de
concepten en het framework precies hetzelfde. De kracht van .NET en
C# op iOS is echter zo groot dat dit zeer zeker een success gaat
worden. Houd vooral de website van Xamarin in de gaten voor nieuws
rondom hun producten! http://www.xamarin.com
Veryant Releases New Options for COBOL Modernization CHICAGO, April
11, 2011 – Veryant, the COBOL and Java techno- logy innovator,
today announced the immediate availability of isCOBOL Evolve 2011
Release 1. To lower software licensing fees and simplify
application modernization, isCOBOL Evolve enables developers to
continue programming in a familiar COBOL environ- ment, and at the
same time, deploy and enhance applications across multiple
platforms in an open Java framework without rewriting code.
Organizations upda- ting legacy COBOL applications with mo- dern
Web 2.0 user interfaces can build dynamic GUIs directly in the
COBOL langu-
age with the graphical isCOBOL Integrated Development Environ- ment
(IDE). Developers can quickly add functionality such as
customizable docking windows to GUIs and automatically propose
values from a preset list or a user’s history to end users
completing form entry fields. In addition to COBOL, the isCOBOL IDE
now supports Java, XML, and HTML editing capabilities, as well as a
Hex editor and version control with CVS and Subversion, providing a
streamlined, industry-standard environment for building, deploying,
and testing applications across the entire software lifecycle,
regardless of language.
Lees het hele artikel op:
http://www.mainframecobol.info/2011/04/veryant-releases-new-
options-for-cobol-modernization/
Het zal velen niet ontgaan zijn dat MonoTouch en Mono for Android
roerige tijden doormaken. Novell, de leveran- cier van deze
producten, is begin dit jaar overgenomen door AttachMate. Die waren
met name geinteresseerd in alle Novell patenten. Het Mono team,
verantwoordelijk voor de bouw en support van MonoTouch en Mono for
Android, is onlangs ontslagen. Daarbij zat ook Miguel de Icaza.
Inmiddels staat ook het support voor MonoTouch door Novell op een
laag pitje.
registreren van properties veel eenvoudiger (en foutloos)
maken.
Een ander voordeel van Catel is dat het werkt met services. Een
view model kan gebruik maken van externe services die door middel
van een IoC container bepaald kunnen worden. Een voorbeeld hoe men
een message box toont is te vinden in listing 2.
var messageService = GetService<IMessageService>();
Catel levert standaard veel services, zoals een
IUIVisualizerService (tonen van UI dialogs), IProcessService
(starten van processen), INavigationService (navigeren tussen view
models), en meer.
Waarom Catel Veel ontwikkelaars zullen zich afvragen waarom er
gekozen is om (weer) een nieuw MVVM framework te ontwikkelen. Als
we strict kijken zijn er maar enkele serieuze MVVM frameworks. De
meest bekende zijn MVVM Light en Caliburn (Micro).
MVVM Light implementeert slechts de basis van MVVM en mist veel
“convenience” functionaliteit. Zo is het bijvoorbeeld noodzaak om
altijd zelf een PropertyChanged aan te roepen na het zetten van de
waarde van een property. Caliburn (Micro) is een framework dat een
bootstrapper nodig heeft en dat uitgaat van conventies.
De ontwikkelaars vonden dat beide frameworks niet volledig volde-
den aan de wensen van de ontwikkelaars, dus besloten ze een com-
binatie te maken die de ruime mogelijkheden van Caliburn(Micro)
biedt, maar toch de eenvoud van MVVM Light.
MVVM met Catel
Een ander groot probleem in MVVM is nested user controls, ofwel
hierarchie in view models. Het probleem is dat geen enkel framework
een oplossing biedt voor dit probleem. De enige mogelijkheden die
een programmeur heeft zijn ofwel in een view model een lijst van
view models maken en deze binden ofwel een top view model dat ook
implementatie verzorgd voor onderliggende user controls. Beide
opties waren voor de ontwikkelaars van Catel geen optie, vandaar de
behoefte om een eigen framework te schrijven en te delen met de
rest van de wereld.
Dit artikel gaat niet in op de basis van MVVM, daar is immers
genoeg over geschreven. Mocht MVVM een nieuw begrip zijn, dan wordt
aangeraden om eerst de basisbegrippen eigen te maken.
Basis van Catel De basis van Catel is bijzonder eenvoudig. In Catel
zit, net zoals in ieder ander framework, een belangrijke class
genaamd ViewModel- Base. Dit is de base class voor alle view
models. Het verschil met andere frameworks is echter dat de
ViewModelBase niet alleen de INotifyPropertyChanged implementeert,
maar ook IDataErrorInfo en vele andere interfaces.
Door gebruik te maken van een “dependency properties”-a-like
property registratie kan veel plumbing uit handen worden genomen
die een developer anders zelf voor zijn rekening moet nemen. Voor-
beelden hiervan zijn het aanroepen van het PropertyChanged event en
het (opnieuw) aanroepen van validatie. Onderstaande code-voor-
beeld geeft aan hoe eenvoudig het is om een property te registreren
in een view model:
public string Name
set { SetValue(NameProperty, value); }
RegisterProperty("Name", typeof(string));
Listing 1: Registreren van een property in een view model
Zoals te zien in listing 1 is het bijzonder eenvoudig om een
property te declareren. Omdat het registreren van properties soms
als boiler plate kan worden beschouwd biedt Catel ook code snippets
die het
Geert van Horrik
Catel is een relatief nieuwe MVVM toolkit dat probeert MVVM zo
eenvoudig mogelijk te maken zonder daarmee functionaliteit in te
leveren. Catel is ontwikkeld omdat de makers op zoek waren naar een
MVVM framework dat voldeed aan veel eisen die in grotere
applicaties van belang zijn. Zo vonden zij het onnodig om steeds
handmatig het PropertyChanged event te moeten aanroepen wanneer ze
een property waarde zetten.
Catel werkt met eenvoudige property registratie en services voor
externe functionaliteit
Catel combineert de mogelijkheden van Caliburn (Micro) met de
eenvoud van MVVM Light
MAGAZINE
14
GENERAL
magazine voor software development 15
Het prettige van Catel is dat het in delen gebruikt kan worden. Een
uitstekend voorbeeld hiervan is dat het mogelijk is om alleen de
view models te gebruiken in een applicatie. Wanneer men echter meer
wil bereiken is het aanbevolen om ook te kijken naar de
meegeleverde user controls.
Ondersteunde Platformen Op het moment van schrijven is de nieuwste
versie van Catel 1.4. Sinds deze versie ondersteund Catel niet
alleen WPF en Silverlight, maar ook Windows Phone 7.
Het voordeel van de Windows Phone 7 implementatie van Catel is dat
het veel overhead wegneemt van de ontwikkelaar. Zo is er een navi-
gatie service waarmee eenvoudig tussen view models genavigeerd kan
worden. Ook ondersteund Catel een GPS emulatie service waarmee
eenvou- dig GPS locaties geemuleerd kunnen worden. Een laatste
voordeel is dat tombstoning ook geintegreerd is in MVVM waardoor
het bijzonder eenvoudig is om hiervoor support in een applicatie in
te bouwen.
Nested User Controls Problem Één van de problemen waar veel MVVM
ontwikkelaars tegen aan lopen is het “nested user controls”
probleem. Het probleem is dat er vaak hierarchie is in een UI die
niet opgelost kan worden met één view model. Wat men vaak doet is
een view model maken die weer een lijst van andere (sub) view
models bevat. Echter, de master view model krijgt dan teveel
functionaliteit en ook het unit testen van de functio- naliteit
wordt erg lastig. Catel biedt hier een oplossing voor met de
UserControl<TViewMo- del> die automatisch zorgt dat een view
model aangemaakt wordt voor de control. Het bijzondere van deze
user control is dat deze in staat is om de DataContext van zichzelf
te injecten in de view model. Op deze manier is het dus mogelijk om
een PersonControl te maken met bijbehorende PersonViewModel.
Fig. 1: Schematische weergave “nested user controls” probleem
De constructor van de PersonViewModel accepteert dan een IPerson
instantie. Zodra de DataContext van de control een instantie van
IPerson bevat zal de user control deze automatisch injecten in de
Per- sonViewModel en vervolgens de DataContext vervangen door een
in- stantie van de zojuist gecreëerde view model. Onder water zorgt
Catel dat alles in originele staat blijft, dus als er wijzigingen
komen op de DataContext zal er een nieuwe view model gemaakt worden
met de nieuwe DataContext. Figure 1 geeft het probleem schematisch
weer.
Unit Testing Één van de sterke argumenten om MVVM te gebruiken is
de testbaarheid van loosely coupled applicaties. Catel gaat nog een
stap verder door van veel services een test variant aan te bieden.
Dankzij deze test varianten kan eenvoudig via een IoC container
(Unity) de test variant worden gebruikt in unit tests.
De test implementaties van de services zorgen ervoor dat de
services zelf niet gemockt hoeven te worden, al kan dat natuurlijk
wel als daar behoefte aan is. Een voorbeeld van het gebruik van een
test imple- mentatie is te vinden in Listing 3. In het
codevoorbeeld wordt gesi- muleerd dat een gebruiker een modal
dialog annuleert en de test controleert of de view model dan
inderdaad geen nieuw object aan de Items property toevoegt.
// Check if there are no persons
Assert.AreEqual(0, viewModel.Items.Count,
// Return false on next call to ShowDialog of the service
service.ExpectedShowDialogResults.Enqueue(() => false);
// Call “Add” command, but it should be canceled by user
viewModel.Add.Execute(null);
Assert.AreEqual(0, viewModel.Items.Count,
Listing 3: Voorbeeld van een unit test
User Controls Catel biedt buiten het MVVM framework ook nog user
controls aan die het gemak van het ontwikkelen van software kunnen
vergroten. Zo is er de DataWindow die afleidt van de Window (of in
Silverlight van de ChildWindow) die automatisch veel gebruikte
buttons gene- reert zoals OK, Cancel, Apply, maar ook eigen buttons
kunnen worden toegevoegd. Ook wordt er automatisch een
InfoBarMessageControl toegevoegd die de fouten overzichtelijk
weergeeft voor de eind gebrui- ker. Op deze manier kan een
ontwikkelaar zich echt concentreren op de functionaliteit in plaats
van plumbing.
Ook is er voor WPF een PleaseWaitWindow, een equivalent van de
BusyIndicator control van Silverlight.
Catel ondersteunt een GPS service waarmee eenvoudig GPS locaties
geemuleerd kunnen worden
Met behulp van de UserControl<TViewModel> class is het
mogelijk om user controls met een eigen view model te
ontwikkelen
GENERAL
MAGAZINE
16
Fig. 2: DataWindow met InfoBarMessageControl
Fig. 3: PleaseWaitWindow voor WPF
Toekomst Momenteel is het team van Catel druk bezig met het
realiseren van Catel 2.0. Dit wordt een grote release waarin de
volgende nieuwe features ondersteund worden:
• Auditing (maakt bijv. analytics mogelijk) • WP7 Mango support
(inclusief emulatie service voor alle beschikbare sensoren)
• MEF support • Service locator zodat andere IoC containers dan
Unity gebruikt kunnen worden
• en veel meer!
De doelstelling is om minstens eens per twee maanden een officiële
release uit te brengen. Mocht je niet kunnen wachten tot de
officiële release, dan is de volledige source code beschikbaar op
http://catel.codeplex.com. Ook is daar meer informatie te vinden
zoals documentatie, artikelen en demo applicaties. •
Geert van Horrik
cialiseerd in het ontwikkelen van
xaml based software m.b.v. WPF,
Silverlight en Windows Phone 7.
In zijn vrije tijd vind Geert het leuk
om andere ontwikkelaars te helpen
op verschillende forums zoals die
van MSDN. Naast het helpen van
andere werkt Geert ook aan het Catel framework, een open-
source MVVM toolkit voor WPF, Silverlight en Windows Phone 7.
Twitter account: @GeertvanHorrik
Blog: http://blog.catenalogic.com
World Tour Kom ook en zie wat je kunt verwachten van
de meest indrukwekkende release ooit!
RAD XE 2
Spreker: David Intersimone
Er was een tijd dat applicatie ontwikkeling binnen het Microsoft
plat- form simpel en overzichtelijk was. ASP voor het web, VB voor
client applicaties, COM voor (business) componenten en SQL Server
(of Access) als database. Tegenwoordig is hebben we zoveel dat we
door de bomen het bos niet meer zien. Geen industrie die zo snel
nieuwe dingen oplevert als de software industrie. Dit verklaart ook
waarom we ons steeds minder kunnen veroorloven om eigenwijs te
zijn. Er is simpelweg zoveel technologie en zoveel ontwikkeling dat
je niet meer overal de fijne kneepjes van kan weten. Wat dat
betreft moet een soft- ware ontwikkelaar tegenwoordig net zo
general purpose zijn als de computers waarvoor ze software
schrijven. De enige manier om dat vol te kunnen houden als een
handje vol specialisten ervoor zorgt dat we snel en eenvoudig de
beste oplossing kiezen. Binnen bedrijven zie je dit terug in
referentie applicaties die door de guru’s opgezet zijn. Jammer
genoeg zijn zelfs die guru’s niet onfeilbaar.
Developer Guidance Microsoft is al jaren geleden tot de conclusie
gekomen dat ze het ontwikkelaars makkelijk moeten maken om software
te ontwikkelen volgens beproefde patronen. Dit is waar onder andere
Enterprise Library (inmiddels al op versie 5.0) uit voortgekomen
is. Ben je Microsoft .NET ontwikkelaar en heb je nog nooit van
Enterprise Library gehoord? Shame On You! (Als je snel kijkt op
http://entlib. codeplex.com/ zal ik het niet tegen je baas zeggen.)
Recent heeft Microsoft binnen de Developer Guidance groep even
flink het gas - pedaal ingedrukt en wordt allerlei nieuwe guidance
ontwikkeld, zoals het Silverlight Integration Pack voor Enterprise
Library 5.0. Dit Inte- gration Pack bevat modules voor onder andere
caching, foutafhan- deling en logging, en validatie. Met de logging
module kun je bijvoorbeeld eenvoudig logging toevoegen die
automatisch logt naar Silverlight Isolated Storage en dat
vervolgens door kan zetten naar de server. Een ander voorbeeld is
de validatie module waarmee je onder andere cross-tier validatie
kunt verzorgen. Dit zijn basisfuncties die ie- dere applicatie
eigenlijk altijd moet hebben. Tenzij je hele specifieke
requirements hebt ben je een idioot als je basisfuncties als
logging zelf gaat implementeren. De mensen die deze Developer
Guidance ont- wikkelen en de vele meer die het reviewen, waaronder
Microsoft MVPs weten gezamenlijk echt meer dan jij en hebben
scenario’s bedacht waar jij nog niet aan gedacht had. Er zijn
overigens ook andere goede logging frameworks, zoals Log4Net, en
daarvoor geldt hetzelfde: zij weten meer dan jij.
SOA & Composite Services Een van de nieuwe telgen in de familie
van Developer Guidance is de Composite Services Guidance
(http://compositeservices.codeplex. com/). Deze is nauw verwant aan
de BizTalk ESB Toolkit 2.0
(http://msdn.microsoft.com/en-us/biztalk/dd876606) en gebruikt hier
ook dingen van. Echter, daar waar de ESB Toolkit helemaal gericht
is op BizTalk, is de Composite Services Guidance ook van toepassing
op WCF, Workflow Services en Windows Server App Fabric. Dit brengt
het implementeren van zaken die voorheen erg prijzig waren binnen
het bereik van de gewone stervelingen. De Composite Services
Guidance bevat onder andere kant en klare voorbeelden voor het
centraliseren van webservices schema’s, metadata en policies, en
wat je daar dan mee kunt. Mijn favoriet is echter de implementatie
van Repair & Resubmit met behulp van een Workflow Service.
Repair & Resumbit is een patroon dat je kunt gebruiken in
(complexe) proces- sen die aan elkaar gekoppeld zijn met
webservices. Het idee is dat wanneer er een fout optreedt omdat de
ontvangende partij de inhoud van het bericht niet slikt, een
functioneel beheerder in staat is om de inhoud van een bericht aan
te passen en dan opnieuw naar de ont- vangende partij te sturen.
Met de ESB Toolkit was dit in BizTalk al goed te doen, maar nu kan
het ook met Workflow Services gehost in Wind- ows Server AppFabric.
Ondanks dat de ESB Toolkit bedoeld is voor gebruik met BizTalk,
gebruikt de Composite Services Guidance onderdelen waarvoor BizTalk
niet vereist is. Welke onderdelen gebruikt worden zie je in
Afbeelding 1.
Afbeelding 1, Repair & Resubmit met Composite Services
Guidance
Het Repair & Resubmit patroon stelt ons in staat om robuuste,
fout- tolerante webservices te ontwikkelen, zonder dat we hier heel
veel tijd aan hoeven te besteden. En vooral om dat laatste is het
Developer Guidance te doen. Het moet een no-brainer zijn om dit
soort zaken standaard in te bouwen als het nodig is en daarvoor
moet het niet nodig zijn om tot in de puntjes te weten hoe alles
werkt. Alles wat je hoeft te weten is dat het goed werkt. Zoals
Michael Okuda, een van de technische breinen achter Star Trek: The
Next Generation, op de vraag "How does the Heisenberg compensator
work?" antwoorde "It works very well, thank you." •
Software ontwikkeling is een vak voor eigenwijze mensen. Ik kan het
weten, want ik ben zelf ook vreselijk eigenwijs. Ik heb daar ook
een goede reden voor: ik ben vreselijk goed in mijn vak. Al die
andere architecten en ontwikkelaars zijn idioten. Toch moet ik
erkennen dat ik steeds vaker moet steunen op de kennis en het werk
van anderen.
Michiel van Otegem
Ik weet alles beter! (Of toch niet?)
Er is simpelweg zoveel technologie en zoveel ontwikkeling dat je
niet meer overal de fijne kneepjes van kan weten
magazine voor software development 17
DESKTOP Hubert Klein Ikkink
CodeNarc heeft op dit moment 241 regels die we kunnen toepassen op
onze Groovy code. De regels variëren van simpele syntax zaken tot
naamgevingsconventie of specifieke implementatie regels. Naast de
bestaande regels is het ook mogelijk om zelf regels nog aan te
passen of nieuw aan te maken. Hierdoor is het mogelijk om voor onze
eigen projecten de juiste set van regels te maken en toe te
passen.
Laten we eens kijken wat CodeNarc kan signaleren in de volgende
Groovy code:
package com.vxcompany
import java.text.*
import java.util.logging.*
class SampleClass {
Double sum
}
}
De volgende figuren tonen de resultaten van de analyse die CodeNarc
heeft uitgevoerd in de gegenereerde HTML rapportage:
We gaan eens in meer detail kijken naar de resultaten. Een
duidelijke regel die overtreden wordt is EmptyCatchBlock. In de
code zien we dat het try/catch blok in de methode
setSumAsString(String) geen implementatie heeft in het catch
gedeelte. Hierdoor wordt een even- tuele fout bij het vertalen van
de String waarde naar een Double niet doorgegeven aan de code die
deze methode aanroept en zal de exceptie niet naar voren komen bij
de uitvoering van de applicatie. We moeten wel iets zinnigs doen
met de exceptie of gebruik maken
Code reviews zijn een krachtig middel om de kwaliteit en
consistentie van code op een project te verhogen. Deze reviews
kunnen worden gedaan door bijvoorbeeld andere ontwikkelaars op een
project als peer-review. Maar we kunnen bepaalde zaken ook vinden
en signaleren door het gebruik van code analyse tools. We kunnen
voor Groovy code gebruik maken van een code analysis tool met de
naam CodeNarc. CodeNarc is te vergelijken met Checkstyle, PMD of
Find- Bugs dat we kennen voor Java code. CodeNarc maakt het
mogelijk om geautomatiseerd regels los te laten op de source code.
Afwijkingen op de regels worden gerapporteerd en eventueel wordt
een alternatieve implementatie getoond.
CodeNarc Analyseer je dynamische Groovy code
MAGAZINE
18
DESKTOP
van Groovy’s exceptie mechanisme, waarbij excepties automatisch
vertaald worden naar run-time excepties. De EqualsAndHashCode regel
kijkt of we een equals(Object) methode definiëren en als dat zo is
dat we dan ook de hashCode() methode hebben geïmplementeerd. Het is
erg verstandig om beide methoden te definiëren in een klasse, zodat
een object van deze klasse goed te gebruiken is bij sorteren of als
key in Map klassen.
CodeNarc bevat een hoop regels die specifiek kijken naar code om te
zien of de code meer kan voldoen aan de Groovy syntax. Deze regels
zijn erg handig voor ontwikkelaars met een Java achtergrond en nu
Groovy code schrijven. CodeNarc geeft bij de regels meteen aan
welke alternatieve Groovy syntax gebruikt kan worden. In ons
voorbeeld zien we dat de regels ExplicitCallToEqualsMethod en
ExplicitCallToPlus- Method aangeven dat we in plaats van methode
aanroepen ook operators kunnen gebruiken.
ExplicitHashMapInstantiation geeft aan dat we de simpele syntax [:]
kunnen gebruiken voor het aanmaken van een HashMap. En we zien hoe
we in Groovy minder code hoeven te schrijven met de regels
UnnecessaryDefInMethodDeclaration, UnnecessaryReturnKeyword en
UnnecessarySemicolon.
Een groot voordeel van een analyse met een tool als CodeNarc is dat
ook kleine typefouten of copy-paste foutjes ook ontdekt worden. Dit
zijn vaak zaken die je met een handmatige code review over het
hoofd kan zien. Was het bijvoorbeeld opgevallen dat de tostring()
methode fout is gespeld? We bedoelen hier toString() en dat is ook
wat de regel ObjectOverrideMisspelledMethodName aangeeft. De regel
Logger- ForDifferentClass geeft aan dat een Logger object wordt
aangemaakt voor de Sample klasse, maar we bedoelen de SampleClass
klasse. Deze fout kan bijvoorbeeld komen door het kopiëren van een
stuk code uit een andere klasse en dan vergeten we de waarde aan te
pas- sen. Wanneer we een tijdje bezig zijn met een applicatie kan
het gebeuren dat we code hebben geschreven die niet meer wordt
aangeroepen. In ons voorbeeld zien we met de regels
UnusedPrivateField en UnusedPrivateMethod dat we een variabele en
methode hebben ge- maakt die helemaal niet worden aangeroepen. Deze
code kunnen we dus rustig verwijderen.
We kunnen ook regels configureren, zodat we code richtlijnen en
stan- daarden voor een project kunnen maken en toepassen op alle
code. Denk bijvoorbeeld aan naamgeving van variabelen of het
toevoegen van een copyright statement in de bron code. De regels
FieldName en RequiredCopyright geven in ons voorbeeld aan dat we
niet aan deze richtlijnen voldoen. De variabele naam voor het
Logger object is een constante en de naam moet dan bestaan uit
hoofdletters. Verder heb- ben we een specifieke regel
geconfigureerd die kijkt of er een copyright statement in de code
aanwezig is.
Het is mogelijk om bij het uitvoeren van CodeNarc op de code
bepaalde regels te negeren. Allereerst kunnen we met een configura-
tie bestand aangeven welke regels we wel of niet willen toepassen.
Verder kunnen we ook de prioriteit definiëren voor een regel. Deze
configuratie is beschreven in een Groovy bestand.
In de bron code zelf kunnen we met de annotatie @SuppressWarnings
opgeven dat een bepaalde regel genegeerd kan worden voor een stuk
code. Hierdoor worden we niet lastig gevallen in de rapportage met
zaken waarvan we weten dat ze een regel niet volgen, maar dat we
dat ook niet erg vinden voor dit specifieke stuk code.
We hebben nu een klein gedeelte gezien van de regels die CodeNarc
ondersteunt. Maar het is niet moeilijk om zelf regels te schrijven.
Voor een eigen regel moeten we een visitor klasse maken die de
Abstract Syntax Tree (AST) van de code kan doorlopen. De AST bevat
alle code
vlak voordat die gecompileerd gaat worden. We kunnen deze structuur
bekijken en analyseren, zodat we weten of de code voldoet aan de
door ons gestelde regels. De CodeNarc API bevat allerlei handige
methoden waarbij we specifieke onderdelen van de AST kunnen
bekijken en daar dan ook analyses op toe te passen.
Conclusie De conclusie is dat CodeNarc een erg nuttige tool is om
toe te passen op projecten met Groovy code. Er is ook een plugin
voor Grails beschikbaar, zodat we ook CodeNarc voor Grails
projecten kunnen gebruiken. De standaard regels die beschikbaar
zijn zorgen ervoor dat we makkelijk kunnen leren hoe we code moeten
schrijven die voldoet aan de Groovy syntax, maar ook hoe we betere
klasse implementa- ties kunnen maken. Voor specifieke regels voor
onze projecten kunnen we de regels ook configureren, zodat we
bijvoorbeeld een standaard naamgevingsconventie binnen het project
kunnen gebruiken. Naast het configureren van de regels, is het niet
moeilijk om zelf nieuwe regels te maken en toe te passen binnen een
project. CodeNarc is hiermee een uitstekende code analyse tool om
te gebruiken. •
Hubert Klein Ikkink
werkt sinds 1996 met Java en sinds
2008 met Groovy. Hij werkt op ver-
schillende projecten met Groovy/
kwaliteit van de geschreven code
goed is.
Wat is Uniface
Uniface is een modelgedreven en -gebaseerde ontwikkelomgeving voor
het bouwen van bedrijfsapplicaties die er toe doen. Superpro-
ductief, toekomstvast en veelzijdig inzetbaar. Je hebt tot zeven
keer minder regels code nodig dan bij Java of .Net voor hetzelfde
resul- taat. Uniface kent een open architectuur die goed toepasbaar
is voor de bouw van moderne bedrijfssystemen, zowel voor RIA
applica- ties voor de Cloud als voor geavanceerde Client/Server
systemen. Uniface applicaties leven lang en laten zich eenvoudig
transforme- ren naar nieuwe eisen, wensen en technologieën.
Uniface proberen? Als je de mogelijkheden van Uniface gratis en
zonder verdere verplichtingen wilt uitproberen ga dan naar
http://www.compu- ware.com/forms/uniface-trial.html en vul het
aanvraagformulier in. Je krijgt dan de nieuwste Uniface versie voor
drie maanden ter beschikking.
Ook als je Uniface al kent en je wilt graag snel een Rich Internet
Applicatie bouwen, vraag dan een gratis download aan op boven-
staand adres.
DESKTOP Theo Neeskens
In Uniface beginnen we met het bouwen van de informatie structuur
van de pagina in een Dynamic Server Page. Daarop zetten we een
dummy entiteit met knop om de gegevens op te halen, en een aantal
velden om ze in te stoppen:
Deze structuur kopiëren we naar de Server Page Layout Editor. Hier
zouden we de opmaak van de pagina nog kunnen verfraaien, maar de
standaard opmaak volstaat voor dit voorbeeld:
Social Media koppelingen in Uniface Enterprise Systemen
Er zijn guru’s die zeggen dat je Social Media en Enterprise Systems
niet mag vermengen. Ik ben het daar niet mee eens. Als jouw
marketing manager denkt jullie omzet te kunnen vergroten door alle
prijs verla- gingen in het artikelbestand automatisch op de
Facebook pagina van je bedrijf te posten, dan zou ik daar zeker
iets voor gaan bouwen. Voor de kosten hoef je het niet te laten. Je
zou ook kunnen denken aan een koppeling tussen je Enterprise CRM
systeem en LinkedIn. Dan kan je accountmanager nieuwe klanten
automatisch uitnodigen om een connectie te worden.
Bij de verschillende Social Media worden verschillende technieken
gebruikt. Veel voorkomende technieken zijn bijvoorbeeld REST
webservices, JavaScript API’s en het autorisatieprotocol Oauth.
Over het algemeen zijn de koppelingen goed gedocumenteerd en is er
een forum beschikbaar om ervaringen uit te wisselen met andere
ontwik- kelaars. Met een beetje geluk is er een library beschikbaar
waar de basis protocollen voor je in geïmplementeerd zijn, wat het
gebruik vanuit jouw programmeertaal vergemakkelijkt.
Als Uniface developer hebben we helaas nog niet de luxe dat er
complete libraries voor ons gemaakt zijn. Maar de meeste basis
protocollen zijn gelukkig vrij eenvoudig te implementeren. Om te
laten zien hoe je dit kunt aanpakken leg ik hier uit hoe je een
koppeling tussen een Uniface web applicatie en LinkedIn kunt maken.
Hiervoor gebruik ik de Uniface JavaScript API die nieuw is in
Uniface 9.5 die binnenkort op de markt komt. Ik heb geprobeerd het
voorbeeld zo eenvoudig mogelijk te houden, zodat je goed kunt zien
hoe de principes werken. Daarna zou het vrij gemakkelijk moeten
zijn om het naar eigen inzicht uit te breiden.
LinkedIn In dit voorbeeld gaan we inloggen bij LinkedIn en enkele
gegevens uit ons eigen profiel ophalen. Wij doen dit vanuit een
webpagina die gebouwd is als Uniface Dynamic Server Page. We
beginnen met het registreren van onze applicatie bij LinkedIn,
zodat we een API key krijgen. NB: Voor het testen van je applicatie
kun je een localhost URL gebruiken.
MAGAZINE
20
DESKTOP
In de HTML source moeten twee stukjes JavaScript opgenomen worden.
In de Header moet een verwijzing komen naar de LinkedIn JavaScript
API en de API key die je gekregen hebt bij het registreren van je
applicatie bij LinkedIn. In de Body staat een stukje script wat er
voor zorgt dat er een Login button getoond wordt, die na een
geslaagde login vervangen wordt door Hello Voornaam
Achternaam.
Als laatste hebben we dan nog een stukje code nodig om de gege-
vens uit het LinkedIn profiel te halen en in de Uniface velden te
zetten.:
Als we nu compileren en testen ziet de pagina er zo uit:
Als je op de “Sign in with LinkedIn” button klikt verschijnt er een
pagina van LinkedIn. Wat daar op staat is afhankelijk van de
situatie. Meestal zal dit een standaard login pagina zijn, gevolgd
door een pagina waarop je toestemming aan de applicatie moet geven
om jouw LinkedIn account te gebruiken. Ik krijg nu een ietwat
andere pagina omdat ik al toestemming verleend heb, maar dit al een
tijd niet meer gebruikt heb:
Nu ben ik ingelogd en LinkedIn heeft de button vervangen door een
welkomtekst met mijn naam er in:
Als ik nu op de “Get your profile” button klik, worden enkele
gegevens uit mijn LinkedIn profiel opgehaald en in de Uniface
velden gezet:
En zo hebben we dus met een paar regeltjes code een koppeling
gemaakt tussen een Uniface web applicatie en LinkedIn. Lees vooral
de documentatie van LinkedIn over hun API om te zien hoe je dit uit
kunt breiden tot een koppeling die zinvol is voor jouw business.
•
magazine voor software development 21
Theo Neeskens
bij de Uniface Services afdeling van
Compuware. Met inmiddels 19 jaar
productervaring helpt hij Uniface ge-
bruikers wereldwijd met implemen-
online Uniface community. Bezoek
ook zijn blog op http://theunifaceuniverse.blogspot.com
Microsoft-specialisten Stel, je hebt een passie voor Microsoft. Je
bent een
kei in applicatieontwikkeling en -architectuur. En je
wilt verder in je vakgebied. Dan is Sogeti het bedrijf
voor jou. Met 700 Microsoft-professionals behoren
we tot de grootste Microsoft-communities van
Nederland. Bovendien verwachten onze klanten
innovatie, zodat je echt al je kennis inzet. Wat ons
betreft wordt die kennis steeds breder en dieper;
we dagen je uit om het maximale uit jezelf te halen.
Bijvoorbeeld door je cursussen en opleidingen
aan te bieden. We zijn niet voor niets een van de
meest gecerti ceerde organisaties in de branche.
Qua omgeving kun je denken aan ALM, VSTS 2010,
.NET4.0, O ce 2010, SharePoint 2010, Azure en
BPOS. Terwijl de projecten enorm gevarieerd zijn.
Van BizTalk-implementaties en end-user BI-oplos-
singen tot de omvangrijkste integratie ooit van
SharePoint in Dynamics CRM.
JAVA-specialisten Als je passie hebt voor het Java vakgebied,
dan
wil je natuurlijk ook werken bij het bedrijf met de
beste Java Community van Nederland. Bij Sogeti
ben je dan aan het juiste adres. Ruim 100 ervaren
Javanen werken bij Sogeti aan het realiseren van
complexe en innovatieve oplossingen voor haar
klanten. Aangezien vakmanschap bij Sogeti hoog
in het vaandel staat, wordt er veel tijd geïnvesteerd
in het vergroten van kennis en de persoonlijke
ontwikkeling van de Java professionals. Het behalen
van Java certiceringen is daar onlosmakelijk mee
verbonden. Sogeti heeft dan ook niet voor niets de
best gecerticeerde Java Community van Nederland.
Wil jij met jouw kennis en ervaring onze Microsoft
Community of Java Community versterken?
Neem dan gerust contact met ons op of kijk op
werkenbijsogeti.nl.
Wat kun je? Die vraag stelt ieder bedrijf met een vacature. Wie ben
je? Die vraag stelt Sogeti
meteen daarna. We vinden het belangrijk dat je bij ons past. Want
een ICT-er van Sogeti is
geen gemiddelde ICT-er. Het is er een met uitgesproken
eigenschappen.
Gedreven. Resultaatgericht. En niet snel tevreden. Natuurlijk:
plezier hoort erbij. Maar we
gaan op de eerste plaats voor de inhoud. Zo kennen klanten ons. Zo
kennen we elkaar.
Als het een ICT-er is, zit hij bij Sogeti.
DELPHI Cary Jensen
Record Basics The traditional style of record definition is
somewhat similar to an array, in that it can hold more than one
data value. But there are a number of features that distinguish
records from arrays.
In an array the various values are identified using an ordinal
index. Records, by comparison, make use of named fields.
Furthermore, arrays consist of a collection of elements that are
all of the same data type (even if all elements of the array are
variants). In records, the individual fields can be almost any
valid Delphi type, including integers, Booleans, real numbers,
object references, arrays, interfaces, and enumerations.
Declaring a Record Consider the following type declarations.
Together, these types define a record type, TDog, that includes
four fields: A double, an enumera- tion, a TDateTime, and a TObject
reference.
type
constructor Create(Name: String);
TDog = record
Weight: Double;
Breed: TBreed;
Born: TDatetime;
Owner: TPerson;
end;
Using a Record Once you have defined a record type, it is easy to
create an instance of that record. Simply declare a variable of
that record type and use it. It is not even necessary to allocate
memory for the record - Delphi does that for you. For example, the
following code demonstrates how to declare and use a record of type
TDog.
Records are data structures that hold one or more pieces of
information. While records have been around since the earliest days
of Pascal, they have taken on a much larger role in the most recent
versions of Delphi. Today's records possess many features
previously only found in objects.
This article begins with a brief overview of records. It continues
with a discussion of features that have been added to records since
Delphi 2005. This article concludes with a look at several of the
important new record types that have been introduced to Delphi in
recent versions.
For The Record
procedure TForm1.Button2Click(Sender: TObject);
...
Actually, it's not necessary to declare a record type in order to
use a record. Instead, a variable can be defined as a record in its
declara- tion. This might look something like the following:
procedure TForm1.Button3Click(Sender: TObject);
// ...
More Variations There are a couple of additional variations that
are somewhat unique to records, and these are associated with
enumerations and variant parts. Let's consider enumerations
first.
In the TDog record type, Breed was declared as a field of type
TBreed. An alternative would be to declare the Breed field to be an
enumera- tion directly, without the TBreed declaration. Here is
another record type declaration that uses this syntax:
type
MeetingWith: TPerson;
DELPHI
of a record were public. Since Delphi 2005, the same visibility
directives that you can use in class declarations can now also be
used in record declarations.
But Delphi 2006 is the version in which the really big changes were
introduced, giving records many features previously reserved for
classes, and greatly improving their utility in your Delphi
applications. These features include methods, properties,
constructors, class constants, class variables, class static
methods, class properties, nested types, overloaded operators, and
record helpers. Each of these features are consider in the
following sections.
Methods and Properties A record's methods are functions and
procedures associated with the record. Like their class cousins, a
record's methods can access all of the other members of the record,
including fields, properties, and other methods. Similar to the
methods of a class, a record's methods have a reference to the
record's instance through a variable named Self.
Record methods also permit overloading. When overloading a record's
method, you follow the same rules that you follow when overloading
the methods of a class. Specifically, the compiler must be able to
distinguish between each overloaded version based on the signature
of the method (including whether the method is a function or
procedure). Record properties are also similar to their class
counterparts. A record's properties can be implemented with read
and/or write parts, and can use either direct access (reading and
writing from fields of the record) or accessor methods
(implementing reading and writing through specified methods of the
record. Accessor methods permit a property to perform side
effects).
The following is a simple example of a record with two fields
(variables), a method, and three properties.
type
property Width: Double read FWidth write FWidth;
property Depth: Double read FWidth write FDepth;
end;
The methods declared in a record must be implemented (records do
not permit abstract methods). Furthermore, after declaring a method
in a record you can use class completion (Ctrl-Shift-C) to generate
the necessary implementation stubs for your record's methods. The
following is the implementation of the GetArea method of the
TRectangle record.
function TRectangle.GetArea: Double;
end;
Record Constructors All records have an implicit, zero parameter
constructor that is called when you attempt to use a record for the
first time. If you want, you can add additional constructors. These
constructors, however, must have at least one parameter, and must
be distinguishable from any
MeedtingBy: TPerson;
end;
In the TAppointment record type, the DayOfWeek field is an
enumeration, which is defined in the record type declaration
directly.
Another interesting feature of traditional records is the optional
variant part. A variant part is a conditional portion of the record
structure that can hold variable pieces of information. The variant
part, if present, always appear at the end of a record
declaration.
For example, consider the following declaration of Delphi's TRect,
which appears in the Types unit.
TRect = record
1: (TopLeft, BottomRight: TPoint);
end;
Using this syntax, you can use one or the other variant record
struc- tures (four Longints or two TPoints, though you cannot mix
them in an individual instance of a record). For example, the
following code de- clares and assigns data to two TRect instances
(which are identical):
var
r2.Top := 5;
r2.Left := 5;
r2.Bottom := 100;
r2.Right := 200;
There is a second syntax, in which the value of one of the record's
fields determines which of the alternative structures the record
uses. For example, consider the following record type
declaration:
type
StartDate: TDate;
EndDate: TDate;
end;
In this record, when the Boolean field MilitaryService is assigned
the value True the WhichService, StartDate, and EndDate fields are
avai- lable. If MilitaryService is False, a single enumerated
field, Reason, can be used.
Class-Like Records Beginning with Delphi 2005, records began to
receive a major overhaul with the introduction of member
visibility. Until this time, all members
MAGAZINE
24
DELPHI
other overloaded constructor based on their signatures.
The following shows the TRectangle record with an overloaded
constructor (note that the overload directive was not required, but
makes the code clearer). The implementation of the constructor
follows in this code segment.
type
property Width: Double read FWidth write FWidth;
property Depth: Double read FWidth write FDepth;
constructor Create(Width, Depth: Double); overload;
end;
end;
Class Constants and Class Variables While each instance of a record
has one memory location for each of its fields, class constants and
class variables are shared between all instances of a given record
type. A class constant is a constant value, and its declaration
looks a lot like a regular declaration of a constant. The
difference is that the class constant is a characteristic of the
specific record type. The class constant can be read using a
reference to an instance of the record type, or through the record
type itself.
A class variable is a field that is shared by all instances of a
particular record type. Changing the value of a class variable has
the effect of changing the one memory location shared by the record
type and all instances of it. Class constants appear within a const
clause of a record declaration, and class variables appear within a
class var clause. These clauses conclude at the end of the record
declaration, or when a method, type, variable, property,
constructor, visibility directive, or variant part is
encountered.
The following record type includes two class constants and two
class variables:
TRectangle = record
strict private
FWidth: Double;
FDepth: Double;
property Width: Double read FWidth write FWidth;
property Depth: Double read FWidth write FDepth;
constructor Create(Width, Depth: Double); overload;
end;
Class Static Methods and Class Properties Unlike classes, which
have both class methods and class static methods, records support
only class static methods (as far as class methods go). A class
static method is one that can be called on an instance of a record
or through a reference to the record type itself. Like the class
static methods in a class declaration, a record's class static
methods have no reference to Self, and therefore cannot access any
other members of the class, other than other class static methods
or class variables. Class properties are properties that can be
referenced using an instance of a record type, or the record type
itself. While class properties support both direct access and
accessor methods (like normal properties), direct access can only
employ class variables, and accessor methods must use only class
static methods.
The following is a portion of a record type declaration that
includes two class variables, a class static method, and two class
properties. The implementation of the class static method
follows.
type
class property PreferredMinWidth: Double
read FPreferredMinWidth write FPreferredMinWidth;
class property PreferredMinDepth: Double
read FPreferredMinDepth write FPreferredMinDepth;
end;
Nested Types A nested type in a record is identical to a nested
type in a class declaration. A nested type is a type declaration
internal to a record. The nested type is often a class type that is
designed to act as a helper class. Specifically, it is designed to
perform tasks related to the record in which it is declared.
The following is another record class segment, which includes a
simple nested type declaration.
type
DELPHI
end;
property Width: Double read FWidth write FWidth;
property Depth: Double read FWidth write FDepth;
end;
Operator Overloading One additional feature added to records that
is not shared by classes is operator overloading. In short, you can
explicitly define what happens when an operator is applied to a
particular record (unary operators) are to two records (binary
operators). For example, you can define what happens when two of
your records are added together using the addition (+) operator, or
what happens if you implicitly cast your record to another
type.
There are almost 30 operators that can be overloaded. These
operators are shown in Listing 1.
Listing 1 Record operators that can be overloaded
To overload one of these operators, you implement the specified
method name using the class operator syntax (instead of function)
in your record type definition. You must also define the type of
value that the operator will return. For those operators that are
declared to return a Boolean value, the operator must return a
Boolean value. All other operators can return whatever type is
appropriate for that operator. In other words, a non-Boolean
operator can return a value other than the record type.
The following code segment includes a portion of the TRectangle
class with an overloaded addition operator, the implementation of
this operator overload, and an event handle that uses the
operator.
type
//...
end;
begin
end;
Record Helpers Like classes in Delphi 2005, records can also have
helpers. Record helpers serve essentially the same purpose as class
helpers, though they only apply to records. Specifically, record
helpers permit you to attach additional methods, properties, and
class variables to an existing record. Record helpers can also
replace existing methods of a class, if they use the same name and
signature, since methods of a record helper supercede those of the
record they are helping.
While the use of class helpers is largely discouraged, record
helpers can play a role that cannot be provided through any other
means. Specifically, record helpers provide the only mechanism for
extending an existing record type. Classes, on the other hand,
support inheritance. As a result, it is often better to descend a
new class from an existing class, and introduce new methods and
properties in the descendant than to use a class helper.
Record helpers have the same limitations as class helpers. A given
record can be supported by only one record helper. If there is more
than one record helper for a given record, the record will employ
the record helper that is closer in scope.
The following code shows the declaration of a record helper for the
TRectangle record, along with the implementation of the single
method declared within the record helper. Notice in the GetMaxArea
implementation that Self refers to the record instance.
type
function GetMaxArea: Double;
begin
ShowMessage(FloatToStr(a.GetMaxArea));
end;
Records Versus Classes At this point you might be inclined to think
that the enhanced record syntax makes records nearly identical to
classes, making it difficult to
MAGAZINE
26
DELPHI
choose between them. The truth is that there are very significant
differences between records and classes, and these differences can
help you decide which to use in a particular situation.
First of all, records are allocated on the stack, as long as they
are not declared globally or managed using New and Dispose. Class
instances, by comparison, are allocated on the heap.
This has a significant impact on memory management. Specifically,
while classes that do not have an owner must be explicitly freed,
memory allocated for record instances is automatically freed when
the record goes out of scope merely by its data being removed from
the stack. Of course, if your record creates class instances during
its lifecycle, that memory must be managed by you or your record,
or a memory leak may exist. This is made a bit more difficult since
records do not support destructors.
Another significant difference between classes and records is that
you do not need to call a record's constructor, while a class
instance must be explicitly created. You can declare a variable of
a record type and then immediately use it. In this case, Delphi
will call the zero parame- ter constructor for you.
You are still free to call a record's constructor if you want. In
fact, if you've declared one or more additional constructors, it is
probably because you want to create your record in a particular
fashion, and you can do so by calling one of those overloaded
constructors.
Another major difference between records and classes is that
records do not support inheritance. A record never descends from an
existing record. Similarly, records cannot implement interfaces
(though they may have fields or properties of interface type, but
that is different). The bottom line here is that records do not
support polymorphism. A corollary of this is that record methods
are necessarily static. Records do not support virtual, dynamic, or
abstract methods.
As you learned earlier, records can also include a variant part. A
variant part permits a record to hold data that is specific to its
nature, and may vary from record instance to record instance. All
instances of a class have the same set of members, regardless of
their data.
Finally, records are value types, as opposed to reference types.
Consider the following code:
var
a.Width := 5;
a.Depth := 5;
b := a;
The TRectangle named b in this code segment is a completely new
record that contains a copy of the data held within record a. By
comparison, if TRectangle was a class type, following the
assignment of variable a to variable b, variable b would point to
the same memory address as a.
Finally, records support operator overloading, while classes do
not. Operator overloading provides you with a rich tool for
managing exactly what happens when records are used in expressions,
and the results can get very interesting.
Examples of Useful Records in Delphi Record types are playing an
increasingly important role in the latest
versions of Delphi, and this is due in large part to the
differences between record types and class types described in the
preceding section. Let's consider a few of the more significant
record types. Delphi 2009 saw the introduction of the
System.TMonitor type. TMonitor is a record that can be used to
acquire and manage a lock on any TObject. It provides a convenient
and powerful synchronization mechanism for multithreaded
applications. A major new layer of runtime type information (RTTI)
was introduced in Delphi 2010. The principle type for working with
the new RTTI, TRTTIContext, is a record type.
Additional records types introduced in Delphi 2010, and further
enhanced in Delphi XE, include TFile, TPath, and TDirectory. These
types, which are declared in the IOUtils unit, are record
types.
Summary It is no longer safe to assume that the entity you are
calling a method on, or are reading a property from, is an object.
It might be a type of record. Indeed, records types posses a unique
blend of features that make them better suited for a variety of
situations in which you would have previously used a class type.
•
Cary Jensen
author of more than 20 books on
software development and winner of
the 2002 and 2003 Delphi Informant
Reader's Choice Award for Best
Training. A frequent speaker at
conferences, workshops, and semi-
nars throughout much of the world, he is widely regarded for
his
self-effacing humor and practical approaches to complex
issues.
Cary's company web site is at: http://www.JensenData
Systems.com. Cary has a Ph.D. from Rice University in Human
Factors Psychology, specializing in human-computer
interaction.
COBOL is terug: Visual COBOL R3 Om COBOL gebruikers in staat te
stellen hun systemen te migre- ren naar nieuwe technologieën en
moderne platforms, lanceert Micro Focus Visual COBOL R3. Met deze
oplossing krijgen ontwikkelaars de mogelijkheid om COBOL eenvoudig
uit te breiden naar de nieuwste applicatie-ontwikkelomgevingen
zonder de nood- zaak om de code te herschrijven.
Met Micro Focus Visual COBOL R3 is COBOL toegankelijk voor een
brede reeks platforms. Naast Windows, UNIX, Linux en .NET zijn
COBOL-applicaties ook voor het eerst inzetbaar in de Java Virtual
Machine- (JVM) en Microsoft Azure-cloud-platforms. Ontwikkelaars
hebben de keus uit Visual Studio 2010 of Eclipse als geïntegreerde
ontwikkelomgeving. Zij kunnen zonder platform- specifieke ingrepen
tevens kernapplicaties in COBOL vanuit één bron op verschillende
platforms inzetten…
Het volledige artikel is te lezen op:
http://www.release.nl/Nieuws/70780/COBOL-is-terug--Visual-
COBOL-R3
magazine voor software development 27
Mijn innovatieve geest denkt in Windows Azure. Windows Azure is het
ontwikkelplatform in de cloud dat developers vrij baan geeft in hun
denken.
Bouw en draai applicaties in de cloud. Lanceer applicaties in
minuten, in plaats van uren. Programmeer
in meerdere talen en technologieën, zoals .NET, PHP en Java. Begin
vandaag nog met innoveren.
2QJHKLQGHUGGRRUUHGXQGDQWLHEDQGEUHHGWHRIGHEHSHUNLQJHQYDQXZVHUYHUFRQÀJXUDWLH
Dat is Cloud Power.
Probeer* Windows Azure gratis. Ga naar microsoft.nl/azure
Download de gratis app op http://gettag.mobi
figure 1. System.DirectoryServices architecture, taken from
http://msdn.microsoft.com/en-us/magazine/cc135979.aspx
In .NET Framework 1.1 there was only System.DirectoryServices. In
.NET Framework 2.0 they've added Active Directory which provides a
high level abstraction model for things like forest, domain, site
etc. They also added the Protocols API. This API provides access to
an Active Directory through LDAP or DSML. In the .NET Framework 3.0
they've added the AccountManagement API. The goal of this API was
to abstract away the underlying principal store. It shouldn't
matter if you talk to Active Directory Domain Services, Active
Directory Lightweight Directory Services or your local computer
store (SAM).
If you want to read more details about the setup of this namespace,
i'd suggest to take a look at http://msdn.microsoft.com/en-us/
library/ms180826(v=VS.100).aspx Querying Active Directory is not
really hard and a lot of examples are on the internet. One problem
that is relatively undocumented though is that when you query a
user for its groups it will only return the groups where the user
is directly a member of. Say you have the following
structure:
AD forest root App_Group_1
App_Group_2 User 1
When querying User 1 for its groups, it will only return
App_Group_2
Querying nested groups in Active Directory A lot of companies for
which we write software have the need to integr