You are on page 1of 137

“I have to admit that, at first, the informal tone of the book took me by

surprise. After reading it carefully, I see that the “informal tone" is


another of the many great ideas that the authors have had. In my
opinion, this book is a great contribution to the knowledge of the Rocha
Version and the huge change it represents, so that the GeneXus
Community can prepare for its launch in 2008."

Episode One
Breogán Gonda, Engineer
Artech President
Cecilia Fernández is GeneXus instructor
and has worked in Artech's Training
Department since 2001. She teaches
Diego and Mary run into each other after many years. Long gone are the GeneXus courses in Uruguay and abroad,
days and nights of studying, laughing and talking in the classrooms and writes manuals and creates distance-
hallways of the School of Engineering, when Mary was always so full of learning courses. She attended the School
life and Diego would let himself be carried away by her laughter. Until of Engineering, University of Uruguay, and
the chance meeting shakes the dust off that memory... and Diego happily is currently pursuing a Bachelor of Arts in
finds himself able to help his old friend solve some big problems at work Literature at the School of Humanities and
and get back to being the cheerful, outgoing woman he knew (and Educational Sciences.
loved?) so long ago.

Diego, Mike and Julia have three weeks to develop a web application for
a travel agency, including the application's back-end and front-end.
Mary is going through a difficult time professionally; she's a project
manager who is so overburdened by maintenance chores that it's
affecting her health.

GeneXus is the thread that interweaves the characters' journeys through


these pages. Discovering and showing. Showing and discovering. Over
and over again: the Rocha Version.

Daniel Márquez Lisboa, is a GeneXus


analyst, technical writer and consultant, as
well as a freelance writer, who has
developed large systems in GeneXus and
other languages. He has authored or co-
authored four books, including "GeneXus
Knowledge-based Development," which
wa s p re s e n t e d a t t h e G e n e X us
International Meeting in 2006.

Episode One
GeneXus Rocha
Episode One
GeneXus Rocha
Episode One

Daniel Márquez Lisboa - Cecilia Fernández


GeneXus Rocha - Episode One

No part of this book may be reproduced, digitized, or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording, or by any other
means, without prior written permission from the Copyright holders.

EDITORIAL GRUPO MAGRO


Dr. Gastón Ramón 2312 bis
Tel. (598 2) 708 54 98 - 708 03 86
Email: info@grupomagro.com
www.grupomagro.com
Montevideo - Uruguay

© Daniel Márquez Lisboa - Cecilia Fernández

Editor: Fernando Díaz


Design: Claudio de los Santos
Cover art: Fiorella Franzini
Translation: Rosario Pérez

Legal Dep. No. 343,109 / 07

Printing and binding: ZONALIBRO


Gral. Palleja 2478 - Tel. (598 2) 208 78 19
Email: zonalibro@adinet.com.uy
Montevideo - Uruguay

Printed in Uruguay - Impreso en Uruguay


Foreword

The entire Artech team is working intensively on the Rocha Version of GeneXus,
which is not just another version: in many ways it represents a great leap forward,
especially with regard to its capability of being integrated and extended whether by
Artech or the GeneXus Community itself.
The GeneXus Community has been enthusiastically testing the product’s CTP ver-
sions, using them and, in many cases, building extensions. At the XVII GeneXus
Meeting, the first beta version will be launched.
Within this context, we have entrusted Daniel Márquez Lisboa (author of “GeneXus,
Knowledge-Based Development – A Practical Guide,” published by Magró in 2006)
and Cecilia Fernández, a highly experienced instructor of our courses, to write an
introductory book about the Rocha Version of GeneXus.
I have to admit that, at first, the informal tone of the book took me by surprise.
After reading it carefully, I see that the “informal tone” is another of the many great
ideas that the authors have had. In my opinion, this book is a great contribution to
the knowledge of the Rocha Version and the huge change it represents, so that the
GeneXus Community can prepare well for its launch in 2008.
I hope this book will be very well received and I congratulate in advance the au-
thors on their work, wishing them great success.
Breogán Gonda, Engineer
Artech President
Dear reader

Some time ago we were asked to write about a version of GeneXus that was still
under development: the Rocha version. At first, we were suspicious. “They want us
to write a book about a version that is going to be continuously changing as we
write?!” And as if that weren’t bad enough, it was rumored that the version we were
being asked to write about was more than just a new version: the product was
being refounded. When we were told that they also wanted a book that would bare
GeneXus, a book that would reveal its personality and appearance, its body and
soul, that would bring it closer to those who wished to discover or rediscover it, a
book that would be enjoyable, entertaining, that could be read like a story…” when
we heard that… we were delighted!
Because, how could we not have fun making up characters, incidents, understand-
ings and misunderstandings! Discovering and showing. Showing and discovering.
Over and over again: the Rocha version.
We thought a lot about you, dear reader, trying to picture who you’d be, what you’d
want to know, and how, when, and just how much you’d want to learn, whether you
knew a lot, a little or nothing at all about GeneXus… what you’d find amusing, what
would bore you… but when it got to the point that we were dizzy with so much
speculation, and our hands were starting to tremble, we decided to do the healthy
thing: enjoy ourselves. So we moved on, confident that a job done with pleasure
would produce a contagious result. And if it turns out we were wrong, we hope
you’ll forgive us. In any case, nothing will spoil the fun we had writing it!!
You may be an expert on GeneXus that picks up this book to discover the Rocha
version, or this might be your very first experience with the tool. We hope that
when you read these pages you’ll share the excitement we felt when we were
writing them, and that you can adapt your reading to your interest and needs.
Some chapters are more technical than others; in particular, Chapter 3, which
deals with Patterns. We couldn’t resist the temptation of showing it in all its power,
and that led to our peeling away more and more layers as we moved forward.
Those who want to see more will read it all thoroughly, and those who don’t can
simply browse the pages. You’re free to choose either path, just as we felt free to
unleash our enthusiasm and discover, discover, discover. The last chapters are prob-
ably the lightest and most enjoyable. This is where the story gets really interesting
— because the best is always saved for last. We have also included an annex,
where we focus on the most outstanding features of the Rocha version. This annex
will be particularly useful for those with experience in previous versions of GeneXus.
It differs from the natural structure of the book, which is why we included it sepa-
rately.
The version of GeneXus Rocha on which we based this “novel” is the CTP 5, build
7304. When this book reaches your hands, the first beta version will probably be
available. For this reason, you’ll have to forgive any changes you find. We trust
they won’t be too many or too great.
A good idea would be for you to follow the application that our characters develop
throughout the book. You can choose the generator and DBMS you prefer; we
chose the default options.
In this book you’ll find several quotes from a white paper by Breogán Gonda and
Nicolás Jodal, titled “Knowledge-based Development. Philosophy and Theoretical
Foundation of GeneXus,” published in May 2007.
Lastly, we’d like to thank everyone who contributed to this task by reading the
drafts of the chapters, criticizing them, giving us their feedback or simply cheering
us on. Alejandra Pereiro, Armin Bachmann, Gustavo Carriquiry, Gustavo Proto, Gastón
Milano, Eugenio García, José Luis Chalar, Alfredo Bordagorry, Pablo Mazzilli, Flavio
Caiafa, Dane Drotts. Also Matías Hernández, Silvia Keymetlián, Ana Berta, José
Lamas Ríos, Rodrigo Álvarez, Jorge Mastropietro and David Waszuk for their tech-
nical support. Marcela Fernández for the inspiration she gave us over lunch one
day, and Rodolfo Roballo, for his ideas and permanent support. María José Serrés,
who worked with us until we had the graphic design we wanted. Rosario Pérez, our
translator, for her infinite patience. Nicolás Jodal, this project’s predecessor, and in
particular Breogán Gonda, for carefully reviewing the text, for his constant joy, and
for the support he gave us, working side by side.
To everyone: Thank you!
Mary, Diego, Mike and Julia are anxiously waiting to be discovered…
Read and enjoy!
The authors
Montevideo, September 2007
Abstract

Chapter 1: The Encounter. A man and a woman who haven’t seen each other
since college meet unexpectedly after many years, and set out on a journey, hand
in hand with GeneXus.

Chapter 2: Once Upon a Time... There Was a Project. Julia, Mike and Diego
define and begin the analysis and development of a Web system for a travel agency.
At the same time, Diego introduces Mary to the GeneXus Rocha’s IDE and the
creation of the first objects in the project.

Chapter 3: Machine-made, Hand-finished. As Julia’s productivity sky-rockets


thanks to GeneXus patterns, Diego unleashes his creativity, proving that customer
demands don’t always translate to insurmountable obstacles. There are also Work
With Patterns, Web Panels, Web Components, Master Pages and User Controls to
discover.

Chapter 4: Flight to the World of Subtypes. Working at high speed, Diego


shows Mary why Subtypes are the solution to problems like multiple references in
the design as he finishes the last transactions. He also introduces her to the GeneXus
Community and Extensions.

Chapter 5: When the “What” Is Not Enough. Mary’s enthusiasm grows every
day as she learns more about GeneXus. She still has many questions, and Diego
knows it. She discovers the Procedure object, Business Components and the capa-
bility to display pdf reports.

Chapter 6: Winds of Change. We know that all good things come to an end, but
Mary has just realized that this could only be the beginning. Categorization, Full
Text Search, Themes, Versioning, Data Providers, Data Selectors, Built-in GXflow
and GXportal also take the stage in this chapter.

Annex: Building the Future. Discover why Artech, and the Community as a whole,
are also part of the GeneXus Rocha machinery. Creating GeneXus is a comprehen-
sive and cooperative group effort.
Chapter 1
The Encounter

Two old college friends ran into each other while waiting in line at a bank.
They hadn’t seen each other in many years and were very happy about the unex-
pected reunion. They were immediately comfortable and picked up right where
they had left off – it was just like old times.

“How are you, Mary? How are things going?” the man asked in his deep, firm
voice, an intent look in his eyes.

“I’m fine, Diego; things are well,” Mary said, although she looked tired. “I was
promoted to development team manager two years ago, actually.”

“I guess I should congratulate you! But why do you look so down? Trouble in
the department? I’ve heard that your systems are not only big but trustworthy...”

“They are. But they are really difficult to maintain!” Mary said, obviously
upset. “I’m getting sick, Diego. I can’t sleep; I have far too many responsibilities,
long hours, not enough sleep. I feel in my chest...”

“...this pressure,” Diego finished. “I get it, Mary,” he continued, gently touch-
ing his old friend’s arm. “How are you working? What tools are you using?”

“A bit of this, a bit of that... In the end, they’re all the same. We’re still using
the traditional schema with traditional tools –they’ve been upgraded, of course,”
Mary answered, seemingly unaware of how close Diego was. “I have this large
team working on maintenance and development, but we can’t keep up.”

“Mmm... Not all of them are the same! Would you like to get a cup of coffee
after we finish up here so you can tell me more?” suggested Diego.

1
GeneXus?
At the coffee shop, Diego listened attentively to Mary’s problems. He remem-
bered how strong and driven she used to be, and was concerned about how much
she seemed to have changed. He was excited to share some information and expe-
rience that would be able to help his old friend.

“How many projects are you working on right now?” asked Diego.

“Just one. It involves mostly maintenance tasks. Our clients are asking for
new things all the time, but we can’t meet the new requirements. Besides, mainte-
nance is really expensive and I can’t justify hiring more people. It’d mean too much
overhead.”

“Maybe the systems are too old... Have you thought about reengineering
everything?” he asked lightly.

“Yes, I have suggested that but we’re on a really tight schedule. And as I said,
we may have already exceeded our budget. I don’t know what to do... I’m ex-
hausted Diego, and I don’t see a way out.”

“I know exactly what you mean! Do you know how many people are in your
situation? I’ve seen it a million times. Applications are increasingly complex, and
manual tools make it impossible to develop or even maintain those systems. They’re
becoming unmanageable. But there’s hope, Mary; solutions exist today. The alter-
native is to automate the work done by humans, so that we can focus on new
complexities instead of coding, which can be done by a program. For instance, at
my company, we’re handling several large projects at once somewhat easily. Have
you heard of GeneXus?”

“GeneXus... Yes, I’ve heard something but I haven’t had time to look into it.
Do you use this tool? As far as I know, even non-technical people can use it and
that’s why I’m curious.”

“Look, I’m not saying GeneXus is a cure-all but I know it solves many of
the problems your company is facing. It’s a program that makes programs. It
automates the creation and maintenance of your applications and database. Of
course, it’s in a higher abstraction level than other tools. Tell me, if you had a
program that allowed you to do this automatically, would you use it?”

“Absolutely!” she said, sitting up straight. “See, that’s exactly our problem,
we have to do almost everything manually.”

2
In Diego’s opinion, the problems Mary’s company was facing were very com-
mon. They find it impossible to take on new projects due to maintenance times of
current systems, which are based on traditional technologies. For a software devel-
opment company, this is a red flag alert.

And as for you, dear reader, the question you may be asking (even if you
don’t say it out loud) is “How does it work?”

“How does it work?” asked Mary enthusiastically.

“Isn’t it reasonable to think that given a set of views on data,” interrupted


Diego, “there’s a unique minimum relational model for it?”

“Hmmm… Maybe, I’m not sure.”

“And if that’s true,” Diego continued, ignoring her hesitation, “don’t you think
it’s possible that a reverse engineering process can use the set of views to create
this minimum relational database schema? If you need to see it to believe it... let’s
make a bet, for old times’ sake. Believe me, you’re going to lose!”

A Bet

The objective of GeneXus is to achieve high-quality automated management of


business systems knowledge [by describing users’ views].
Breogán Gonda, Nicolás Jodal

GeneXus is a tool that starts from users’ views, captures their knowledge and
systematizes it in a Knowledge Base. Using this Knowledge Base, GeneXus auto-
matically designs, generates and maintains the database structure and application
programs; that is to say, programs that users need to manage their own views on
data.

3
GeneXus works with pure knowledge, which is relevant regardless of the then cur-
rent technologies.

«GeneXus stores in a Knowledge Base all the necessary elements to build the
application and then uses it to develop the system. It automatically builds the
normalized data model, using the desired programming language and database. In
this way, you obtain a project with the company’s knowledge...»

“Okay! That’s it!”

“Yes,” Diego interrupted eager to finish the idea. “It provides you with some-
thing very valuable, the future portability of your application. All that knowledge –
business rules, dialogs, controls, reports- that are now in a certain programming
language, can be converted to other languages without starting from scratch. This
means that knowledge is reused because the Knowledge Base is platform-indepen-
dent.”

4
Knowledge Base and External, Relational Models

The two friends continued talking at the coffee shop. At that point, Mary was
particularly interested in this software tool and Diego in...

“On one hand, we have the Relational Model that, as you know, is aimed at
accurately representing data in a database by satisfying certain conditions.”

“True...” she said, “eliminating redundancies and introducing a small set of


rules to avoid the greatest sources of data inconsistency.”

“That’s right, rules that check uniqueness and referential integrity. Also, they
provide a set of operators for quality data management,” added Diego, satisfied
with how things were flowing.

“Sure, that’s why everyone uses it. Doesn’t GeneXus use it?”

“Well, yes, I’m coming to that. Do you remember the External Model,
where external views are represented? GeneXus focuses on this model be-
cause that’s where the actual knowledge is located; that’s the most important
model for users and developers. It gathers the external knowledge and every-
thing else, such as auxiliary models, can be automatically inferred from this
External Model.”

“The External Model... It can’t contain any physical or internal elements such
as files, tables, entities, entity relationships, indexes... right?”

“Exactly! Or any other element that can be automatically inferred,” said Di-
ego; he’d always liked talking to Mary, and was enjoying his time with her. “The
External Model will be used to obtain and store knowledge. It aims at representing
reality in the most direct and objective way possible.”

“And you’re free from implementation concerns, thanks to a high-level sys-


tem description that doesn’t change unless user views are modified. Am I right?”
Mary asked

“Exactly! That’s why we take users’ views and store them in the model. Then,
all the knowledge contained in them is captured and systematized to maximize its
inference capabilities.”

5
“Okay, I find that hard to believe. It sounds a bit far-fetched... Are you saying
that I only have to provide a description, and a tool will magically create the appli-
cation?” Mary asked, sounding skeptical.

“Well, I wouldn’t say it’s


magic. After all, it’s a piece of soft-
ware. And you have to do a bit of
programming, but it’s minimal. In
GeneXus you’ll have some proce-
dural code, but the language that
you write is not the one you’re used
to. You don’t need to name tables,
indexes or any physical element of
a database.”

“But... I don’t understand where the Relational Model comes in,” Mary said.

“It’s the one used to represent and handle data, that’s the internal or physical
model. But it won’t be created by you; it will be inferred by GeneXus using reverse
engineering. It was a tricky bet.”

“And how do you describe users’ views, the External Model, so that reverse
engineering can be applied to them and obtain everything you say? This descrip-
tion must be accurate to avoid ambiguities and allow a program to infer everything
that programmers still do by hand.”

“Yes, it is,” Diego assured her. “Descriptions are made through certain
GeneXus object types that represent the ‘what.’ Through them, GeneXus finds the
‘how.’ That’s why to use GeneXus, you need to learn to describe, that is, to use
these object types. You don’t need deep technical knowledge... far from it, actu-
ally.”

Diego kept talking. Even though they hadn’t seen each other for so long, he
still knew Mary very well. He knew that her silence meant that he could go on. He
couldn’t believe his good luck. Thank you, GeneXus, he said to himself and went on
slowly and confidently.

“To achieve all this, GeneXus has a Knowledge Base that is initially associated
with a set of inference mechanisms and general rules, such as those that ensure
consistency. For instance, referential integrity rules. When the GeneXus analyst
describes reality by creating objects, these descriptions –the External Model- are

6
automatically systematized and stored in the Knowledge Base. Besides, from this
knowledge it obtains a set of results that enhance the accuracy of future infer-
ences.”

“It’s an inference ma-


chine!” said Mary.

“Exactly! For example,


given a set of views on data,
it can automatically infer the
necessary program to
handle it.”

GeneXus works permanently over the Knowledge Base. All the knowledge in the Knowledge
Base is equivalent to that of the External Model (a subset of the Knowledge Base). It consists
of the External Model, plus rules and inference mechanisms which are independent from this
External Model, and a set of other elements automatically inferred from it.
The developer can change the External Model by changing objects of the user’s reality. Those
changes will automatically propagate to all the elements that need it, such as other elements
of the Knowledge Base, database and application programs. Likewise, the developer can’t
directly change any element that doesn’t belong to the External Model.
ALL the knowledge is contained in the External Model and because of that, we could support
the Knowledge Base in a completely different way tomorrow, and our customers’ knowledge
would still be reusable without any problems at all.
Breogán Gonda, Nicolás Jodal

«Diego, I have to go now, but I want to know more. Let’s meet next week,
same place, same time. Sounds good?»

“Sure,” he replied, trying to sound calm.

7
8
Chapter 2
Once Upon a Time,
There Was a Project

Travel Agency & Co., a new tourism operator, has hired the software firm
ACME Business Software Solutions to develop a Web site that allows customers to
search for destinations, flights and services offered, as well as book flights and
make travel reservations. The project also includes the creation of a backend sys-
tem to maintain the data.

ACME, which has used successive versions of GeneXus for quite some time,
employs several IT specialists. The team members selected for this project are
Julia, Diego and Mike. Diego and Mike are GeneXus Analysts who work on any
project assigned to them. In particular, Diego usually develops applications and
Mike is in charge of testing them. Julia, on the other hand, is not proficient in
GeneXus. Even though she has gathered requirements for many projects, her area
of expertise is documentation and moderation of team meetings as benchmarks
are achieved. In this workgroup everyone has a voice and decision-making power.

The first tasks fall on Julia and Diego, while Mike tests other applications
being developed by ACME for other customers.

Julia has long used text processors for her documentation work. In large
projects, it’s very difficult for her to manage dozens of folders with hundreds of
files, share them with the developers, and coordinate team discussions, among
other tasks. Surely you’ll understand why she was thrilled to know that GeneXus
Rocha provided an embedded documentation feature that would make her life easier.

9
Time is of the Essence
A short while ago, the board of directors and the development team agreed
on a short-term project of approximately three weeks. They reduced the usual time
frame by half because they would start working with GeneXus Rocha, and they
knew its great usability and increased productivity would expedite the project.

«A dramatic increase in [system development] productivity is necessary, but pro-


gramming language productivity has long reached a plateau. ... So, how can we
achieve this necessary increase in productivity? With knowledge-based –not pro-
gramming-based– development: the solution is to describe instead of programming!»
Breogán Gonda, Nicolás Jodal

Luckily, Travel Agency & Co.’s internal operations were rather efficient and
well documented. This was a great advantage for the development team. Julia,
Diego and Mike decided that they had to meet with people involved in different
areas and gather their views.

“Every user has one or more views of the data he/she uses daily. Among these
views, we can make a first group with those used to manage data (with restricted
permissions to add, modify, delete and view it). These user views are called Transac-
tions and are the first GeneXus object type.»
Breogán Gonda, Nicolás Jodal

They wanted to start representing the company’s reality as soon as possible.


Among other things, they learned that Travel Agency & Co. focused on leisure
travel to a variety of destinations worldwide. What did this mean? First of all, since
destinations were tourist attractions in cities around the world, they needed a place
to store this data.

The team met and, after exchanging notes and ideas, decided that Julia should
describe the first guidelines obtained. Meanwhile, the rest –especially Diego– would
use GeneXus to represent the most clearly described user views.

10
The IDE at a Glance

It’s time to go into the GeneXus Rocha development environment. If you like,
you can follow Julia’s steps to get to know the elements that make up this environ-
ment. In this way, you’ll create the project Knowledge Base and the first Transac-
tion object.

Commonly known by its initials, this IDE (Integrated Development Environ-


ment) goes way beyond its name. Why? Because an IDE is an environment that
offers a high level of comfort, windows to choose elements, windows to write code,
toolboxes, source codes, and so on. In this case, the functionality of GeneXus
Rocha’s IDE exceeds basic requirements.

Julia opens a session and sees a start page similar to the one below:Initially,
we can see two clearly defined content areas. On the left is the KnowledgeBase
Navigator, which offers different views. It’s made up by an area in the middle (now
blank) that will display a tree with the elements of the opened Knowledge Base,
and a set of horizontal panels with the names of other views.

Panels

11
On the right is a main window (that’s how we will refer to it, as we’ll do most
of our tasks there). It is basically another item with multiple functions. In the top
left corner of the main window is the Start Page tab, which is the first opened item
in the main window. As you work, new tabs will indicate other work spaces contain-
ing project elements such as navigation reports, diagrams, transaction structures,
and so on.

Now, let’s look at the only tab we have, which includes other sections con-
taining information. For example, Recent Knowledge Bases displays a list of re-
cently opened Knowledge Bases with last updated dates, and provides links to
create new Knowledge Bases or open existing ones.

Below is an Extensions section with tools developed by Artech or third par-


ties. They are free to install and use, and allow increasing the tool’s power.

The section labeled GeneXus Community displays an RSS feed of Rocha Com-
munity news, with “More...” links to read the complete stories.

The Address cell allows you to search the Web or your file system without
leaving the IDE.

After this first look at the IDE, let’s see what Julia is doing.

12
New Project, New Knowledge Base

The first task of developing an application with GeneXus is to create the


Knowledge Base.

The next time Diego and Mary met at the coffee shop, she asked with a
concerned look on her face:

“You said that GeneXus automates the creation of databases and programs.
How does it know in which environment and in which language to build these
programs? For example, if you had to develop an application in Java and another
application, or the same one, in C# (.Net)...”

“Let’s see... When you create the Knowledge Base –we usually call it KB–
you can set the project to be generated in Java. As we said, the KB is platform-
independent: if you generate the application in Java, you can later reuse this
knowledge to generate it in C#. You don’t have to describe the objects from
reality again, and you only have to associate this knowledge with another envi-
ronment. When you associate an environment, you’ll find a place to set every-
thing related to it. For example, in Java, you’ll have to set the location of the
classes in the webapp, which doesn’t make sense in .Net. This means that de-
pending on the selected environment, the program displays the properties needed
to set it. That’s how GeneXus can make your application come true and imple-
ment it as you asked.”

As it happens, while Diego and Mary exchanged words and looks at the coffee
shop, Julia followed the steps below, which you can follow, as well.

1. On the File menu, click New, and then click Knowledge Base (or click the
New Knowledge Base link in the Start Page). Following is the dialog box
displayed.

13
TravelAgency

From here, the project is associated with an implementation environment.


Leave «C# Environment,» which is the default option.

2. Click [Create]. GeneXus will create an empty Knowledge Base. After that, the
screen displayed should be similar to the one below.

14
Note that some contents have changed. There’s a tree in the Folder View
panel; the parent node is the Knowledge Base (with the name that you gave it) and
the children are the elements that make it up: Domains, Tables, Themes,
Images, Documentation, Objects, etc.

A new section called Knowledge Navigator has been added to the Start Page.
It has shortcuts to the most common tasks that you most commonly do after cre-
ating or opening a Knowledge Base.

This Knowledge Base will also be used by the rest of the team. Julia is now
ready to start documenting the project.

Documenting from the Inside

Documents, notes, task lists are only examples of the documentation sur-
rounding any software development process. Documentation, when it’s up-to-date
and easily accessible, is an important part of any application.

This is why GeneXus’ documentation features are built into the KB.

Documents, files, diagrams, and objects can all be linked, and easily acces-
sible to every team member. For this reason, we say that it’s active, integrated
documentation that constitutes an actual wiki.

15
Files

The department managers had emailed Julia several documents describing


their system requirements, priorities and descriptions of their areas, some process
flows, and so on.

Because the documents were created by the end users, she decided that they
had to be added, unchanged, to the Knowledge Base for future reference. The
actual words of the users are very important.

So, she expanded the Documentation tree node and double-clicked Files. In
the new Files tab that was displayed in the main window, she clicked Add New File.
A window was displayed to search her file system and choose each file to be added
to the KB. Below is the resulting Files tab.

Images

She had also received the company’s logo, so she clicked the Images node
of the Folder View tree, imported the Logo.bmp file and saved it in the KB. Later,
it would be used as a header for the application’s pages. In the same email, she
received dozens of image files of tourist attractions that later would be stored in
the database. She temporarily saved them here as well, to have them centralized
in the KB.

16
Main Document

Now, Julia gets ready to write the main page of the KB’s wiki. Note that below
the Documentation node is a Main Document object. Each team has different ap-
proaches to documentation. In ACME, this main page is used to describe an over-
view of the system being developed, and to access documentation elements.

The project’s Master Plan may also be created here, instead of inserting it as
a file. But you and your development team are free to use this page as you see fit.

Julia opens Main Document and a new tab called Document: main is dis-
played in the main window. Since she wants to start writing, she clicks the Edit
selector in the lower menu bar and enters the text shown below. Next, she clicks
Preview and obtains a normalized view of the text. Finally, she saves the changes
(Preview changes to Browse).

Note that we’ve done some formatting changes to the text through the for-
matting toolbar.

17
Julia has changed the font type and size, and set the topic
title in bold.

In addition, she needed to add links to the documents she


has received and just saved in the KB, which is crucial for an
integrated documentation. To do so, she dragged the Table item
from the toolbox1 to the page. After inserting the table, she
wrote the following.

She wanted a preview so she clicked the Preview selector. Satisfied with her
work, she saved it and the following window was displayed.

Note that due to the symbols she used in the table’s second column, the
documents are now underlined: they are links to the stored files.

1
The GeneXus IDE provides dockable function panels that stick to any side of the window. Also, they
can be automatically hidden when the focus shifts so that they don’t take up space in the main window.
To activate them, open the View menu and choose Tool Windows.

18
As a result, the documentation is very dynamic and actively integrated to the
project through the KB.

The GeneXus documentation editor uses two opening square brackets ([[)
and two closing brackets (]]) in the text to create links.

If you’re following this example, you may have noticed that right after typing
the second opening bracket, the editor prompted you with a list of valid objects to
choose from, as shown in the figure below.

Julia selected File and after typing a period (.) the list of available files was
displayed (she could also have dragged the File object from the toolbox, obtaining
the same result as by writing «[[File.»).

Next, she selected each desired file and pressed <Enter>. The text was ended
with two closing square brackets.

19
Creating the First Transaction: Attraction

Back at the coffee shop, while talking to Mary, Diego thinks that he should
enter the first views obtained by interviewing staff from Travel Agency & Co.’s
Tourist Information Section. This section searches for information to add or remove
destinations and itineraries that the company offers to customers. He thinks that
as soon as he gets back to work, he should create the Attraction transaction, when
Mary interrupts his thoughts:

“You know, I don’t understand how you can accurately describe users’ views
to avoid ambiguities and automatically infer everything.”

“Do you remember the new project we’re working on? Well, I’ve been meet-
ing with users who handle data on tourist attractions in every country and city, in
order to offer them to customers. They use the attraction’s name, such as
“Centenario Stadium,” “Roman Coliseum” or “Disney World,” and the name of the
country and city where the attraction is located, with images of each attraction.
They also told me that attractions are grouped in categories. For example, the
Centenario Stadium belongs to a Great Monuments category, and Disney World to
Entertainment. These are their views on the data.”

“I see... And how do you objectively describe these views?”

“With attributes... and Transaction objects. Let me explain …. Attributes are


the reference framework for other descriptions. It’s not exactly the same as a
relational model attribute. Here, attributes are the basic semantic element. Pre-
cise, unique semantics are assigned to their names, and that’s why attributes are
so important in GeneXus.”

Diego scribbled a few names on a napkin: AttractionName, CountryName,


CityName, AttractionImage, AttractionCategoryDescription. Then, he went on:

“These attribute names have clear semantic content that any person can
understand without any context. They are not just ‘Name’ or ‘Description.’ There
is a strong relationship between an attribute’s name and its meaning. That name,
in turn, is a sequence of characters, something syntactic, unique, with which
a ny p r o g ra m c a n w o r k w i t h o u t a m b i g u i t y. I f I w r i t e o r s p e a k o f

20
AttractionCategoryDescription anywhere, we both know it’s a description of the
attraction category. GeneXus knows this too.”

“So,” she cut in, “you can’t use the same attribute name to refer to other
data, because that would cause confusion and ambiguity.”

“Exactly. An attribute must have the same name everywhere it’s used, and
there won’t be two different attributes –with different meanings– that share the
same name. That’s the basic concept. There’s one exception, but I don’t want to
confuse things. These views described by users are used to handle data (add,
edit, delete, view it) and are represented in GeneXus through the Transaction
object type. Every transaction has a set of elements: structure, rules, formulas,
display elements. In other words, in one object we’re killing several birds with
one stone: when you set what information will be used, you’ll also design the
screen that the end user will work with, define the data’s behavior as it is entered,
and so on.”

Diego grabbed his napkin and wrote the following:

Then he said: “Data is displayed according to a structure that must be accu-


rately represented. This would be the structure of the Attraction transaction. The
asterisk next to AttractionId stands for uniqueness: there’s only one AttractionId.
That is, it’s an identifier that makes an attraction unique. All the information has
to be identifiable, so an attraction must be identified through one or more at-
tributes.”

21
“Hold on Diego, I have some questions... Are you talking about the concept of
primary key of a relational model table? The attributes you listed, won’t they be
columns of a physical table that will store this information? Ultimately, aren’t you
designing a table with this transaction?”

“Yes, indirectly. And no, because I’m not concerned about designing a physical
table of the relational model. I’ve only specified the attributes that the end user
will interact with to enter attractions into the system. I’ve specified a user view,
not a table. Here comes the reverse engineering and Relational Model inferred by
GeneXus. If the KB didn’t have any more transactions than this one, GeneXus
would infer a physical table containing all the listed attributes. However, when
related transactions are added, things change and normalization may occur. But I
don’t want to rush so I’ll explain that later.”

“I think I’m getting it, Diego. However, I see that in the transaction structure
you added attributes without saying that they were mentioned by the users. All the
ones ended in Id... Also, why didn’t you use the attraction’s name as identifier?”

“Because the attraction’s name may be used in many places all over the
world. For instance, Disney World is in Paris, Miami, Las Vegas, Orlando. I may
have chosen a set of attributes like AttractionName, CityName, CountryName but
I’m not sure there are no exceptions (attractions with the same name, in the
same city and country). In this case, we need a unique attribute for the set of
information elements that make up an attraction. Every transaction structure
should have one or more attributes that identify each instance. In this transac-
tion, it will match the inferred table’s primary key, but that’s not always the case.
Later, you’ll see it in a two-level transaction; don’t worry about it now. Now, we
can tell GeneXus that AttractionId will be a numeric attribute and set it as
Autonumber.”

“What about the AttractionCategoryId, CountryId, and CityId attributes? Are


they identifiers too?”

“Yes, they’ll be identifiers in other transactions. Countries, cities, and attrac-


tion categories belong to entities that are independent from tourist attractions. For
example, we haven’t discussed this with the customer yet, but flights will also have
arrival and departure cities. Obviously, we’ll have to create a transaction to repre-
sent and enter data about countries and cities, as well as existing attraction cat-

22
egories. As it happens, these identifiers you mentioned will identify each one of
their details (instances).”

“Let’s see if I have this right. Once you define the other transactions,
GeneXus will infer tables to store their data, and will know that the attributes
you added to the Attraction transaction structure (AttractionCategoryId, CountryId
and CityId) will be turned into foreign keys in the associated relational table.”

“You’re as sharp as ever!” Diego exclaimed, with an admiring look.

“But then, why are CountryName, CityName, and AttractionCategoryDescription


in that structure? In a normalized relational model, they’d never be in that table.”

“And they won’t be. That’s why I was saying that a transaction structure
doesn’t exactly match that of the associated physical table. I’ll explain that later in
more detail. Next time, I’ll bring my notebook. Because there will be a next time,
right?” he asked a bit shyly, “then I’ll show you...”

The following day at work, Diego created the first transaction using the GeneXus
IDE. Below are the steps he followed.

First, he clicked the New Object link in the Start Page and a dialog box for
creating objects in the KB was displayed. Next, he clicked Transaction in the Select
a Type dialog box containing the GeneXus objects available, and typed Attraction
in the Name field. Following is the screen displayed.

23
Finally, he clicked [Create] and the transaction was opened.

Note that in the following figure a new tab with the transaction name has
been added to the main window. What’s being edited? The transaction’s structure.

Objects or elements opened in the IDE’s main window are displayed as tabs. Only
the active one is displayed in the middle of the screen. The opened object can have
several elements or sections, and only one of them will be active. At the bottom of
the window there is a bar to select other sections of the active object.

The structure edit window features a set of columns to create attributes,


name them, and set their data types and descriptions.

24
Selectors

In GeneXus, the structure Diego drew on a paper napkin is represented as


shown above. He named the attributes according to the GIK (GeneXus Incremental
Knowledge) naming convention, a standard created by Artech and adopted by the
Community. Its purpose is to give each attribute a unique name that clearly con-
veys its concept, or semantic meaning.

As you may have noticed, in the Type column you can give each attribute a
GeneXus-supported data type.

25
The Blob data type allows a wide range of data (videos, worksheets, all kinds
of documents, audio files, images, etc.) to be stored in the database. The purpose
of the AttractionImage attribute is to store an image of the attraction in .bmp, .jpg,
or any other format.

In the Description column, you can enter an extended description of the at-
tribute. For the moment, we’ll leave the suggestions provided by GeneXus based
on the attribute name.

To add more attributes, press <Enter> after completing a definition and re-
peat the process.

Key Attributes: In his drawing on a napkin, Diego marked the key attribute
with an asterisk. In GeneXus, key attributes are marked with a key icon.

Descriptor Attribute: What does the magnifying glass icon next to the
AttractionName attribute mean? It indicates that if you had to keep only one at-
tribute, the one that best describes the entity, this would be the chosen one (the
one with more semantic meaning). This information will be used by automation
tools, so we won’t deal with it right now.

While setting the AttractionName attribute data type in the Type column,
Diego created a Name domain for all the attributes that name something. He also
created an Id domain for numeric identifiers.

If you’re not used to working with domains, read the following paragraph for
an explanation.

Domains?: Applications usually have attributes that share the same data
type, size and other features. For example, the Attraction transaction has several
“Id” attributes (AttractionId, AttractionCategoryId, CityId, and CountryId). Diego
has created a domain called Id containing all the features of identifiers, and will
apply it to all the attributes that represent a value which doesn’t exist in reality but
which is necessary for uniqueness.

26
Each domain is a set of unique features that may be shared by several attributes.
This allows for consistency and ease of maintenance, as changing a domain feature
propagates the change to all the attributes based on that domain.

Defining Domains2

Diego double-clicked the Domains node in the Folder View tree, and the tab
for displaying and editing domains was opened in the main window. There, he
entered the Id and Name domains. The process is similar to that of creating trans-
action attributes.

Some domains are automatically created by GeneXus together with the KB.

After Diego defined the first domains, he finished the transaction as shown
above. The Numeric and Character data types in the Attraction transaction are now
displayed as Id and Name.

2
GeneXus often provides several ways to do the same thing, so that you can always find a way that
suits you. This isn’t the only way to define a domain; in fact, you can also do it when setting an
attribute’s data type.

27
The ATTRACTION Table

By default, when designing tables GeneXus names them after the transac-
tions they are based on.3 At any time, you can view the table’s design (structure,
indexes, etc.) by opening the Tables node of the tree in the Folder View panel.
Following is the ATTRACTION table structure.

Given the transaction structure, GeneXus will design a form for it. This will be
the screen that end users will use to enter attractions. It can be viewed by clicking
the WebForm selector in the access bar.

3
From now on, table names will be written in uppercase to distinguish them from transaction names.

28
This form can be customized by moving controls around, by adding, chang-
ing, or deleting them, by changing their appearance, and so on. End users will
manage attractions through this screen at execution time.

Satisfied with his work, Diego remembered that he hadn’t documented the
transaction. As a rule, ACME’s team members create documentation as they move
forward, especially regarding entities such as the Attraction transaction.

So, he opened the Main Document, inserted a new table called Objects, and
in the first row he added a link to the newly created transaction (just like Julia did
a few pages back when she added links to the documents) with a brief description.

We can see that Attraction is a link. What will happen when Diego clicks it? A
new documentation tab will be opened for the transaction, where he will be able to
edit or even open the transaction.

29
Suppose that you need to open the transaction to view its structure before
documenting it. You can do so by clicking the Open Transaction: Attraction link.
Then, to open the documentation edit window you can click the Documentation
selector. As you can see, dear reader, in GeneXus it’s also true that many roads lead
to Rome.

30
Creating the Second Transaction: Country

Next, Diego created the transaction that would contain data on countries and
cities. Its structure was drawn on the paper napkin that he had kept in his pocket
after saying goodbye to Mary the last time they met:

Since he had already opened Main Document, he started from there. He added
a new link in the table, this time to the Country transaction. But he hadn’t created
it yet! Note that the link displayed has a question mark (?) next to it.

When Diego clicks the ?, the transaction will be automatically created and
opened in the structure, ready for him to enter attributes. The link will be defined
in Main Document. (We don’t want to insist but, what was that about the roads to
Rome?)

31
Country: A Two-Level Transaction

As we all know, countries have cities, which means that reality determines
that there are n cities per country. GeneXus can easily represent this reality with
two-level transactions.

That’s why the Country transaction has two levels. The first level, also known
as prolog or just header, is implicit and we don’t need to identify it. In this case, the
header’s attributes imply that there’s only one instance for each country.

However, since each country has several cities, the method used to represent
it (on paper: a set of brackets) determines a set of attributes that are repeated in
the header: it is known as “body” or second level.

Note that both levels (header and body) have unique identifiers: the CountryId
attribute is the first level identifier, and CityId is the second level identifier. This
means that for any given country (CountryId), a city can’t be used more than once
(CityId).

Based on this structure, GeneXus creates two tables: COUNTRY and


COUNTRYCITY. The primary key of the first table is CountryId, and the primary key
of the second table is made up by CountryId and CityId.

The following figure shows the structure after Diego entered it.4

4
Note that new domains have appeared. We assume that Diego created them either before or as he
entered those attributes. For example, when entering CountryFullName, in the Type column he could
have entered: “LongName = Character(50)” with the same result. In the event that Diego had already
defined a Details domain as VarChar(500,200), it’s worth noting that when he entered the CountryDetails
attribute, GeneXus would infer the Details domain as its data type (because it’s in the last part of its
name).

32
To add a second level to a transaction, click the preceding attribute and press
<Ctrl+L> (in this case, click the CountryFlag attribute). Continue with the rest of
the attributes as usual. You can also do this by right-clicking the attribute and
displaying a menu to add a new level, move the attribute and so on. Also, note that
Diego has named the level.

Database Normalization

When the Country transaction was created, important changes took place.
More precisely, the contents of the ATTRACTION table have changed because GeneXus
has normalized it according to the new functional dependencies that were added.
Following are the new table structures.

33
Can you spot the differences? By creating the Country transaction and setting
the CountryId and CityId attributes as identifiers of their levels you’re defining
that:

1. Every country will be (uniquely) identified by a CountryId value; this value will
be associated with (determine) only one CountryName, CountryFullName, etc.
In a normalized Relational Model, this causes the creation of a physical table
with the CountryId primary key to store this data while preserving uniqueness.

2. Every city will be assigned to a country (CountryId) through the CityId value.
Therefore, the (CountryId, CityId) pair will determine a CityName and
CityInformation. Thus, there must be a physical table with the {CountryId,
CityId} primary key to store data about each city.5

So, what does GeneXus do with attributes having the same name in different
transactions?

Remember the two most important statements of the GeneXus philosophy:

• Identical concepts must have identical attribute names, and


• Different concepts must not have the same attribute names.

5
Note that GeneXus names the table by concatenating the transaction name to the level name:
COUNTRYCITY.

34
Normalization takes place when attributes having the same name are found
in different transactions. For example, a new COUNTRY table is defined with CountryId
as primary key, and other attributes including CountryName. A COUNTRYCITY table
is also defined with CountryId and CityId as primary key and other attributes in-
cluding CityName. Attributes CountryName and CityName are no longer stored in
the ATTRACTION table. In fact, a foreign key reference to COUNTRYCITY table is
defined as well.

Stored Attributes and Inferred Attributes

Here comes the question that Mary asked Diego about the CountryName and
CityName attributes referenced in the Attraction transaction structure. Since they
won’t be included in the associated physical table... why did Diego add them to
Attraction?

If you look at the transaction form a few pages back, you’ll find those at-
tributes. Why?

That’s because the transaction will be turned into a program that end users
will access through their browsers. In a form designed with the WebForm Editor,
users will be able to add attractions (new records in the underlying ATTRACTION
table).

When end users type a country identifier in the CountryId field and a city
identifier in CityId, they should view the country’s name (CountryName) and the
city’s name (CityName). This means that CountryName and CityName are invoked
at execution time from the COUNTRY and COUNTRYCITY tables through the com-
bined {CountryId, CityId} foreign key. In order to be added to the form, attributes
accessed through foreign keys must be in the structure, inferred.

What would happen if the user entered nonexistent values for CountryId,
CityId? What if, through the Country transaction, the user tried to delete a city with
attractions? If we were allowed to do that, we’d be breaking one of the most impor-
tant data consistency rules of relational models: referential integrity.

35
Referential Integrity

Diego told Julia that he had defined the first two transactions. In order to
confirm that the model accurately reflected reality, she drew a Bachman Diagram
of the tables inferred by GeneXus based on the transactions.

To do so, she expanded the Tables node in Folder View and pressed <Ctrl+N>.
In the New Object window that was displayed, she selected the Diagrams object
and clicked [Create]. Next, she selected all three tables at once and dragged them
to the new diagram. The resulting screen is shown in the following figure.

In this diagram, the single arrow head indicates that there’s one instance of
the pointed table for each instance of the first table; that is to say, for each city
there’s only one country, and for each tourist attraction there’s only one city. Like-
wise, the double arrow head indicates several instances of the pointed table for
each instance of the first table; that is to say, for each country there are many
related cities, and for each city there are many attractions.

This allows determining the relationships between them. For example, the
relationship between COUNTRY and COUNTRYCITY is 1 to n (one to many); the
opposite is n to 1 (many to one). COUNTRYCITY and ATTRACTION also have a 1 to
n relationship.

36
When adding or editing a record in the ATTRACTION table, the COUNTRYCITY
table must have a related record to ensure referential integrity. When a record is
deleted from the COUNTRYCITY table, there mustn’t be any related records in the
ATTRACTION table. GeneXus automatically solves this by adding this logic to the
Attraction and Country transactions in a way that’s transparent for developers.
Similar considerations can be made regarding controls performed on the related
COUNTRY and COUNTRYCITY tables.

Base Table and Extended Table

While Julia confirmed that everything was correct, Diego remembered bits of
the last conversation at the coffee shop:

“Listen, Mary, for practical reasons, the table where you’re positioned at a
certain time, the one that you’re focusing on when trying to do something to its
records, in any context, is called base table. That’s why we say that the Attraction
transaction’s base table has the same name: every time you work with the transac-
tion, you’ll add, change or delete a record of that table. Then, you’ll move to an-
other one, and another one, and another one. Besides, when working with one
base table record, you can access data that’s directly related to it and stored in
other tables.”

“Following n to 1 relationships, from the record of the –base table?– where


we’re positioned, to the record containing the information we want. It’s nothing
new.”

“That’s true, only the terminology is new. The extended table of a given
base table will be the set of tables reached from the base table through n to 1
relationships.”

“Let’s see if I’m getting this... If data didn’t have to be scattered in sev-
eral tables to avoid redundancies, you’d have it all in one physical table. For
attractions, you’d have one big table with all ATTRACTION attributes, plus the
COUNTRYCITY and COUNTRY attributes. You can’t do that because of the po-
tential inconsistencies created by redundant data, but anyway, you name the
table that you’d have. And that’s the idea of an extended table: it’s a table
that you imagine, even though it doesn’t exist physically.”

37
“Absolutely true. You’ll see that in GeneXus we use this concept extensively,
and that’s why it has a name.”

While Diego was lost in his memories, Julia confirmed that data access be-
tween tables was ensured.

By looking at a Bachman Diagram you can easily determine the extended table of
each (base) table. All the tables that can be reached from the base table by following
single head arrows (n-1 relationships) will be part of its extended table. The ex-
tended table is a concept and is not actually materialized. It allows us to refer to
information univocally related to the record that we’re using.

Creating the First Prototypes

In order to let Mike play his role as project tester, Diego pressed <F5> to start
prototyping.

In GeneXus, there’s no difference between prototyping and implementing a system.


A prototype is nothing less than the application generated in a certain platform: just
like the final application! The only difference between them is how they are used.

Remember that the environment had already been selected when the KB was
created. Therefore, several properties were already set;6 for example, SQL Server,
the default DBMS. But something is missing to implement the system... An assis-
tant will ask Diego for the DBMS server and database details only once. So, Diego
entered localhost and TravelAgencyTest, respectively.

6
To change one of them, just select the Preferences panel in the KnowledgeBase Navigator and find the
preference to be set; for example, the associated DBMS, implementation language, etc. Then, access
its properties by pressing <F4> (in the window that is opened).

38
Then, GeneXus will generate and execute the Developer Menu,7 so that devel-
opers can immediately test the applications. Once the environment is completely
set, every time you press <F5> GeneXus will carry out all the steps needed to
execute the application. Diego expected to see what’s shown in the following fig-
ure: the first Impact Analysis of this Knowledge Base.

This Impact Analysis Report (IAR) told him that GeneXus would create the
tables shown on the left. Their structures and other details such as indexes, etc.,8
are displayed on the right.

What’s an Impact Analysis Report? GeneXus uses the Knowledge Base to


design the database. The existing objects can be changed at any time, and new
objects may be added to modify the KB. The IAR is obtained from an analysis
performed by GeneXus of the impact of new definitions or changes to the KB on the
associated physical database. Through this analysis, the developer knows about
the structural changes that GeneXus will make on the database to update it and
make it consistent with the KB.

7
A simple prototyping menu created by GeneXus (it’s an xml file containing links to the GeneXus
objects created, in order to invoke them quickly and easily as we’ll explain soon.)
8
Below are the SQL sentences that will be used to reorganize (in this case, create) that table.

39
Diego agreed with the IAR and clicked [Create] to reorganize the database.9
Since the database didn’t exist yet, it would be created in this first step. Later on,
it will be reorganized after being changed and restructured. When are the pro-
grams generated? Right now, ready for testing! Barely a minute went by since
Diego pressed <F5> and entered the platform details that were missing until a
browser window was displayed with the ready-to-run Developer Menu. He looked
closely at some reports previously displayed by GeneXus to make sure that he was
going in the right direction.... But don’t rush, dear reader, because we’ll come back
to this later and Mike is anxious to step in.

Mike 007... With a License to Kill

It was his turn. He had to destroy them; the transactions, of course.

Looking steadily at the Developer Menu displayed in the browser containing


links to the transactions, Mike clasped his hands together and cracked his knuck-
les. Then he paused. Here we go, he said to himself.

9
The term reorganize means to make physical changes.

40
The idea was to start the testing immediately –by entering data into the
database that GeneXus had just created– and check the transactions’ behavior. He
is going to take notes, so he also gets ready to start a conversation in the transaction’s
documentation.

He clicked Country and the screen displayed was similar to the following
figure.

This is the Country transaction at execution time.

Soon, he noticed that the CountryId attribute should be autonumbered. This


means that the user shouldn’t have to worry about assigning it a specific value
because CountryId doesn’t represent an object from reality. It’s just a number that
makes new records unique.

41
Likewise, when he found CountryWorldRegion, a one-digit attribute, he didn’t
know which numeric value belonged to each world region (how could they indicate
whether a country is in Africa, North America, Europe, etc.?). We have to show the
end user the names of regions and continents to choose from! he thought.

So, he decided to start a conversation with Diego to discuss the subject; this
way, they could all agree to his suggestion. He returned to the KB, accessing the
Country documentation section.

Adding a Conversation

When opening the documentation, Talk is one of the selectors provided. It


allows us to create a space and talk with other users about the object at hand.

Note that the title at the top indicates a Talk document for the transaction. It
ends with a question mark, which means that there isn’t a Talk page for this object
yet and that it should be created before writing. When Mike saves this space, a
page will be generated with its content.

Upon clicking the question mark, the view switched to edit mode. Next, he
entered the text, saved it and viewed it:

42
Setting an Identifier Attribute
as Autonumber

Later that day, Diego read what Mike had written and replied in the Country
transaction’s Talk area. He accepted Mike’s suggestion, and proceeded to do the
changes.

He wanted to automatically number the CountryId attribute, a numeric iden-


tifier, through the autonumber feature of the DBMSs that support it.

All GeneXus objects have properties that affect both their look and feel.

Every object’s or attribute’s properties can be edited at any time by pressing <F4>
to display them in a floating window.

So, Diego selected the CountryId attribute and pressed <F4>.

43
First, he changed the Autonumber property to True, and set the properties
shown in the figure above.

An attribute undergoes cosmetic surgery

To complete Mike’s next request in the Talk, Diego went to the transaction’s
WebForm, selected the CountryWorldRegion attribute control and pressed <F4>.
Inside the control properties window, he set the ControlType property to Combo
Box. Next, he selected the Values property to open the Values Editor window and
entered the possible attribute values. That was all.

44
If, instead of doing this in the CountryWorldRegion control properties in the
form, he had done it in the CountryWorldRegion attribute properties in the struc-
ture, the scalpel would have cut deeper: it would mean that every time this at-
tribute was added to a form, by default it would be displayed as a Combo Box and
not as an Edit control. When he realized his mistake, Diego made this definition at
the structure level. This is a good example of how knowledge is inferred and reused
in the Knowledge Base.

Reorganizing (reorg)

Diego has changed some properties of two Country transaction attributes.


Will this indirectly trigger any changes in the physical table? Following is the Im-
pact Analysis Report displayed after Diego pressed <F5>.

45
Yes, GeneXus found that a table needs to be reorganized. Note the word
Autonumber to the right of the CountryId attribute data type. The reorganization
will have to activate this property at the DBMS level. But, what happened with the
other change, the one to CountryWorldRegion? Nothing! It’s not a database change,
only the KB was affected. It’s cosmetic, and indicates that in all forms where this
attribute is shown, it should be displayed as a Combo Box. This proves that not all
changes done to a GeneXus object necessarily cause the database to be reorga-
nized. We’ll give another example when we explain the transaction’s rules.

Diego can have GeneXus do the reported changes ([Reorganize]) or cancel


the reorganization. If he cancels it, the IAR will be redone the next time he presses
<F5>. He chooses to reorganize.

When rereading the talk to reply that everything has been done, Diego
realizes that Mike suggested autonumbering all transaction Ids by default. (His
confusion was caused by Mike documenting this in the Country transaction Talk,
instead of doing it in the Main Document Talk). To implement this, would he have
to change the attribute properties one by one? No! He remembered that those
attributes were based on the Id domain. He only had to edit the domain proper-
ties and set the Autonumber property at the domain level, just as for CountryId.
All current and future attributes based on that domain will automatically inherit
this property!

46
But... Here’s a problem! Diego thought. CityId is not a single primary key. To
be set as autonumber, attributes must be a single primary key. CityId is part of
COUNTRYCITY’s primary key.10

How can he prevent this attribute from taking the Autonumber True property
from its Id domain?11 Simply by editing the CityId attribute properties (as with
CountryId) and changing the Autonumber property to False. In this way, the
domain’s default behavior is changed for this attribute.

The same applies to the AttractionCategoryId attribute which currently be-


longs to Attraction and is not a primary key. However, it will soon become a primary
key when Diego creates the new AttractionCategory transaction. For this reason,
Diego decided not to change the Id domain definition at the moment (to activate
the Autonumber). He’ll do it later, when he creates the new transaction (he docu-
mented this “To-Do Diego”).

Transactions: Not just a pretty face;


they also have personality

Diego added to the transactions the behavior described by users regarding


data management.

“An attraction must never be entered into the system if it doesn’t have a
name.” Thus, he opened the Attraction transaction, clicked the Rules selector and
typed the following rule:

Error(‘Attraction must have a name’)


if AttractionName.IsEmpty();

If users don’t complete the AttractionName field, the previous message will
be displayed at execution time, and the control won’t let them move on to another
field. Saving the record in the corresponding table won’t be allowed, either.

10
To assign consecutive values to this attribute, Diego will have to use the Serial rule. We suggest
that you read about it after looking at the introduction to rules.
11
GeneXus is aware of this restriction. For this reason, even if Diego hadn’t spotted the problem, it
would have acted intelligently: it wouldn’t have defined the attribute as autonumber in the database.
For didactic purposes, we preferred to make Diego work.

47
“A country must never be entered into the system without a name and full
name. The country’s details can be left blank, but a warning message should be
displayed to the user in case they were overlooked.” So, he clicked the Rules selec-
tor in the Country transaction and typed these three rules, in random order:

Error(‘Country must have a name’)


if CountryName.IsEmpty();

Error(‘Country name must be in full’)


if CountryFullName.IsEmpty();

Msg(‘No country details were provided. Do you want to continue?)


if CountryDetails.IsEmpty();

The third rule also triggers a message, but unlike the Error rule, it allows the
user to move on to the next field and save the record.

Many other rules can be used to program the transaction’s behavior. Note
that they are written in declarative style and, with few exceptions, the order in
which they are added is not relevant. In our case, they will be triggered depending
on the order of the CountryName, CountryFullName and CountryDetails attributes
in the form.

In a two-level transaction, the records of two tables are being handled. There-
fore, when the user enters a new country and its n cities through the Country
transaction form, n+1 records will be added: 1 in the COUNTRY table and n in the
COUNTRYCITY table. They will be added following the same order used to enter
them into the form. A rule may be triggered immediately before or after one of
these save operations. To this end, rules can be conditioned not only through if
clauses as shown above, but also through trigger events such as BeforeInsert or
AfterInsert.

After saving the transaction’s n+1 records (1 header and n lines) a Commit is
automatically performed. It can be disabled by the GeneXus analyst through a
transaction property. In addition, rule triggering events capture the moment
immediately before or after the Commit operation. For example, to get a list of the
newly entered country and its cities, you can invoke another kind of GeneXus ob-
ject: Procedure. You must invoke it after entering the n+1 records, by sending the
newly entered country Id by parameter. To obtain it before the Commit operation,
write the following rule in the rules section:

48
PrintCountry.call(CountryId) on BeforeComplete;12

If you want it after the Commit operation, use the following rule:

PrintCountry.call( CountryId ) on AfterComplete;

Diego documents the changes already made. Think about the changes made
to the KB since pressing <F5> for the last time.

What’s hiding behind <F5>

1. When you press <F5>, GeneXus first makes an impact analysis of the KB
changes on the database. When there’s an impact, it will display the Impact
Analysis Report, which can be confirmed to physically reorganize the data-
base. As we’ve seen, it can also be cancelled.

Diego knows that the changes he made since he last pressed <F5> involve
rules (of the Country transaction); that’s why he doesn’t expect a reorganization
the next time he presses <F5>. However, he knows that the following steps will be
carried out.

2. GeneXus steps into the specification stage, which is an analysis of every-


thing defined in the elements making up the objects that you have changed,
be they structures, forms, new rules, etc. This task results in a navigation
report where GeneXus shows the logic interpreted for each object that has
been changed since the last <F5>, together with warnings and errors, if any.

In the example involving our friends, Country is the only object that has been
changed. That’s why after pressing <F5> Diego will view the following report.

12
The Call, a common invocation method in GeneXus, is being used as a rule. Note that the invoked
object’s name appears before the call; in this case it is a Procedure, another GeneXus object. Finally,
note that trigger events are identified in the syntax of a rule:
Rule if condition on Event
Condition is a Boolean condition and Event is a valid trigger event. In the product’s documentation you
can read more about other trigger events such as AfterValidate, BeforeInsert, BeforeUpdate, BeforeDelete,
AfterInsert, AfterUpdate, AfterDelete, BeforeComplete, AfterComplete, etc.

49
There weren’t any warnings or errors. Note that it shows the tables that will
be saved and the referential integrity checks that will be performed when you try to
delete a country or city.

3. After the specification stage comes the generation of the object(s) that
GeneXus deems necessary (if there are objects that haven’t been changed
and were generated in a previous <F5>, why do it again?) to completely
perform the execution. The generation entails writing lines of code to imple-
ment the programming of objects in your chosen language.

4. Lastly, GeneXus compiles and executes the application in the browser in-
stalled in that machine.

This is a completely automatic process. You’ll never have to specify and/or


generate an object explicitly, because GeneXus is intelligent enough to determine
which actions to trigger at each time.

That’s how, warned by Diego, Mike opened the Developer Menu and executed
Country, where he added, updated and deleted a few records. Finally, he docu-
mented the results in the transaction’s Documentation, changing its status to OK.
He still hadn’t tested Attraction (he had found things to change in Country, so he
had decided to put it on hold for a while) when he read in the Talk that Diego had
asked him to delay the test until he created the related transaction that came next.

50
Creating the AttractionCategory Transaction

Diego added the attribute pair AttractionCategoryId and


AttractionCategoryDescription to the Attraction transaction, even though he knew
that later he’d create an AttractionCategory transaction to contain them.

This transaction categorizes the attractions of each country’s cities: «Build-


ings/Structures,» «Nightlife,» «Relaxation,» «Adventure,» «Gastronomy,» «Safa-
ris,» «Business,» etc.

With the Attraction and AttractionCategory transaction structures we’re im-


plicitly saying that an attraction belongs to only one category, while a category can
contain n attractions.

The next time <F5> is pressed, GeneXus will have to reorganize the database
by creating the new ATTRACTIONCATEGORY table and removing the
AttractionCategoryDescription attribute from the ATTRACTION table. From now on,
this attribute will be inferred from the new foreign key AttractionCategoryId.13

Following is a Bachman Diagram that shows the new relationship between


the tables added to the project so far.

13
Suppose that Mike had tested the Attraction transaction and inserted records to it before this reorga-
nization. If he had entered an attraction of category Id 1 and Nightlife description, we could ask the
following: what would happen in the reorganization when the ATTRACTIONCATEGORY table was cre-
ated, and AttractionCategoryId became a foreign key in ATTRACTION, and AttractionCategoryDescription
was inferred? What would happen with the ATTRACTION record? For the database to be consistent, a
record of Id 1 and Nightlife description will have to be created in ATTRACTIONCATEGORY. This will be
done by the reorganization program itself. What would happen if there were two or more attractions
with the same category Id and different descriptions? You can give it a try.

51
Before pressing <F5>, Diego remembered to set the Id domain as Autonumber
(he had left a note to do it when he created the AttractionCategory transaction.)

Finally, he pressed <F5> and read the corresponding Impact Analysis Re-
ports. After clicking [Reorganize] he obtained a new database and newly generated
programs. He closed the browser because Mike would be in charge of testing, and
documented the new transaction and Autonumber settings.

Mike read Diego’s notes, prototyped all transactions again, and pressed <F5>...

To free end users from memorizing foreign key codes, GeneXus automatically cre-
ates objects called Prompts, which are invoked through the icon displayed next to all
foreign key fields at execution time. They are selection lists that show the entire
data of the referenced table for the user to choose from.

While testing the Attraction transaction, Mike tried to enter the attraction
category of the Eiffel Tower but couldn’t remember the code of the corresponding
Buildings/Structures attraction category. So, he pressed the icon next to the
category Id field. A category selection list, automatically created by GeneXus,
was displayed as shown in the following figure.

52
Mike will select the first option on the list, Buildings/Structures, and the con-
trol will return to the Attraction transaction. The AttractionCategoryId field will
display the value 1; the focus will be there and the user will be able to move on to
the next field (in this case, country Id, for which the process can be repeated).

To confirm that the referential integrity checks were being made, he entered
a nonexistent category value in AttractionCategoryId. At execution time, he ob-
tained an error message about it.14

14
Seconds later, he would try to delete a category with related attractions from the AttractionCategory
transaction. He expected it to fail in order to ensure referential integrity. Dear reader, you can also try
this for yourself.

53
GeneXus can «disguise» an attribute at execution time so that end users
don’t have to open these selection lists every time they enter foreign key values.
Mike suggested this and Diego implemented it by changing two properties of the
AttractionCategoryId attribute. As a result, to enter the Buildings/Structures cat-
egory, Mike only needs to remember and type the first letters, and they will be
autocompleted.

The attribute where the end user will enter the description is actually the
AttractionCategoryId foreign key, which is «disguised» as AttractionCategoryDescription.
In this way, even though the end user enters descriptions, the corresponding Id is
retrieved from the table and stored in a transparent way.

They still had to improve the project’s usability and appearance, so they
wrote about the need to use other GeneXus tools, such as GXpatterns. Maybe
they could all meet and discuss whether to put a part of the application in produc-
tion in the agency’s Tourism section. This would allow them to test it, enter coun-
tries and cities, and send the feedback they found.

“Prototyping is a great resource and, if used appropriately, it avoids an exaggerated


dependency on the final test, or even on deployment (D-Day, when everything hap-
pens and Murphy’s Law especially applies).”
Breogán Gonda, Nicolás Jodal

GeneXus’ features allow testing everything at any time, so that every object
can be prototyped at the most convenient time. This is a crucial capability that
stems directly from the GeneXus theory, more specifically from the automatic propa-
gation of changes.

54
Chapter 3
Machine-made,
Hand-finished

Immediate Plans

The Travel Agency & Co. project is well under way, enough to move several
parts to pre-production. It’s time to be tested by the end users as the system
continues to be developed.

Problem: A Pretty Plain Application

Julia meets with the end users to get their first impressions and address
possible sidetracks. When they try entering data through the transactions, they
like the controls and data input method, but ask for queries with more sophisti-
cated views and increased functionality. For example, they want to work with coun-
tries in a more visual and user-friendly way. They’d like to view all existing coun-
tries in a grid and be able to choose one to update or delete it, or even view all the
country’s details, including their cities and related data.

Solution: An Appealing Application 3 Clicks Away

Patterns, here we go, Julia said to herself without hesitation. With the Coun-
try transaction in Edit view, three clicks and one <F5>, she asked the users, “Is
this what you have in mind?”

55
The end users view a new link in the Developer Menu, Work With Country.
Clicking it opens a new object in the browser, WWCountry, which not only displays
a grid with all the existing countries in the system, sorted by their most meaningful
attribute, name1 , but also allows filtering by name in that same grid (as the end
user enters data in the filter variable, it is automatically filtered in the grid). In
addition, it provides automatic paging of the grid.2

Grid filter

For browsing
grid pages

In addition, it allows performing the following tasks:

• Insert a new country by clicking the icon displayed in the grid’s upper
right corner. This will call the Country transaction in Insert3 mode (to add a
country and its cities) and return.

1
See Chapter 2, p18. When entering attributes in a transaction structure, the first attribute of Charac-
ter or VarChar type is marked as descriptor. You can change descriptors by right-clicking the new
descriptor in the structure and clicking the Toggle Description Attribute option in the displayed context
menu. But, as we’ll see soon, Julia will have another option to do it.
2
The default value is 10 records per page (that is, it loads 10 grid lines). We’ve changed it down to 3
in a centralized location of the Work With pattern that we’ll talk about later.
3
The Transaction object has a predefined variable, &Mode, which identifies its mode at a certain
time (Insert, Update, Delete, Display) depending on the operation to be performed. If the mode is
sent by parameter and this variable is received, the transaction will know what operation will be
performed.

56
• Update a country’s data by clicking the icon displayed on the grid line
corresponding to that country (it will also call the Country transaction, in
Update mode this time, to update that country and return).

• Delete a country from the system (by clicking the icon). It will also call the
transaction in Delete mode and return.

• Display all the information on a certain country (note the link on the country’s
name). Clicking it opens ViewCountry, a new object (automatically created)
that will show all the country’s related data (in tabs):

Essentially, a real Work With Countries has been created. Users could ask for
the same functionality to work with other entities such as attractions and attraction
categories.

Patterns Anyone?

Overall, you may already know what patterns are about: they are common
knowledge that can be applied to different situations. A GeneXus pattern is very
powerful; not only does it free you from manually creating functionally versatile

57
objects, it also enables knowledge reuse. In addition, it’s an open tool: if you need
it, you can create your own patterns. They greatly enhance productivity and gener-
ate high-quality applications with more uniform interfaces and consistent logic.
Patterns generate knowledge from knowledge.

All Julia did was apply the Work With pattern (one of the available ones) to
the Country transaction, obtaining part of an application that implements every-
thing needed to “Work With...” the related information, in our case: “countries.”

We can think of the Work With pattern (and of many others) as a machine
whose input is a transaction (and the KB), and whose output is a set of new GeneXus
objects (some of them were shown running), plus changes to some KB properties,
plus the modified transaction itself4...

Customization: There’s Always a «But»

The end users’ answer to Julia’s question was “Yes, that’s what we wanted but...

1. In the grid we only want to view the country’s name and world region (the
other details are not relevant to us).

2. We also want the displayed countries to be sortable not only by name, but
also by world region and by the {world region, country name} pair. Finally,
we want the ability to:

3. ... filter the grid by world region (in addition to by name.)”

4
More specifically, the transaction must declare that it receives parameters, as now we want to invoke
it from the Work With Countries object (WWCountry).

58
To apply the Work With pattern, Julia only opened the Country transaction,
clicked the Work With selector at the bottom (1st click), selected the “Apply this
pattern on save” check box (2nd click) as you can see in the following figure, and
saved (3rd click). Then she pressed <F5> (after which the users could see the
application running).

However, in the figure below you can see that the Work With selector not only
lets you select the check box, but also edit a tree structure that Julia didn’t even
look at in the previous steps. Here’s where she will have to work to make the
requested changes.

Sets up the
WWCountry
web panel:

Sets up the
WWCountry
web panel:

This figure shows an «instance» of the Work With pattern, the Country in-
stance, which lets you customize it.5 We can view a hierarchical structure with

5
We still haven’t defined “instance”. It can be thought of as the statement of how the pattern will be
applied to the particular case of this object.

59
nodes and a set of properties whose values determine the appearance and behav-
ior of what’s generated by the pattern for this instance.

Among other things, the Work With pattern will generate two new GeneXus
objects that we’ve seen running, and that we’ve included for you over the instance
figure. They are of a type that we haven’t discussed yet: Web Panel. Overall, it
lets you make user-friendly, interactive queries to the database.6

In the figure we’ve indicated which nodes of the pattern instance allow set-
ting up which web panel’s features. The end users have asked Julia to change the
first web panel. For the moment, they haven’t said anything about the second web
panel (but they may do so...).

Look at the first thing displayed under the «Level (Country)» node. Remem-
ber that CountryName was the transaction’s descriptor attribute (the one with
more semantic meaning): you can also update it from here. Does the descriptor
attribute have any effects on what’s generated by the pattern? Yes, many. For
example, it defines which attribute of the WWCountry grid will be linked to the
ViewCountry web panel that is automatically created to display this country’s de-
tails. But this is just an example; as we’ll see, it is used in many places...

WWCountry web Panel: Selection


(Work With Countries)
Note that the Selection node has three subnodes: Attributes, Orders and
Filter (besides these actions: Ins, Upd, Del, Dis).

By default, the Attributes subnode shows all the attributes of the Country
transaction’s first level, and they are those listed (by chance?) in the grid of the
generated WWCountry (Work With Country)7 web panel.

6
On one hand we have a web panel that, among other things, lets us list countries filtered by name.
And on the other hand, we have another web panel that shows all the information on a given country
and its cities (the latter in a grid within a tab).
7
In the GeneXus Rocha version used to write this book, the WWCountry web panel’s description is in
the singular: “Work With Country.” However, in its screen it’s displayed as “Work With Countries.”
Hence, to mention it we’ll use either the singular or the plural, depending on what sounds more natural
for the context in which it is referenced.

60
The users asked Julia to display only CountryName and CountryWorldRegion,
so she simply has to delete from this node, by pressing <Del>, the rest of the
attributes except for CountryId. This last attribute cannot be deleted carelessly.
Even though it’s not displayed to the end user in the grid, it must be included
(hidden) as we will justify soon. Therefore, in this case Julia will click that attribute
node and press <F4> to edit its properties, setting the Visible property to False.
The resulting instance is shown below, where you can view the effects running.

Requirement No. 1 is ready!

The Orders subnode indicates the desired default order to retrieve the data
that will be loaded in the grid. This default order is (by chance?) that of CountryName,
the descriptor attribute. The end users asked to be able to choose between this
order and CountryWorldRegion, as well as another one made up by both.

How can the user decide, at execution time, by which order to sort the infor-
mation to be retrieved? Through a combo box that shows all the available options.
Julia will have to add the new sorting orders requested under the Orders subnode,
and give them names (World Region, Both) that will be the options viewed by the
end user at execution time in the combo box automatically inserted by the pattern.

Following is the resulting instance and the generated web panel (running):

61
Note this: at execution time, you can also order what you have loaded in the grid at a certain
time, by one column, simply by clicking it. But, be careful! If you’re working with paging,
only the loaded page is ordered here.

Requirement No. 2 is ready! Only No. 3 to go.

The end users also want the ability to filter the countries to be loaded in the
grid by world region. The obvious answer: Filter subnode. Note what’s displayed
by default below this node (see p.5). Again, it happens to be CountryName. Take a
moment, dear reader, to deduce what the Attributes and Conditions subnodes mean,
by looking at the WWCountry web panel implemented by GeneXus and the in-
stance in page 5. How about we show you what Julia did in the instance and the
effects it had on the web panel?

62
When the CountryWorldRegion attribute is added under the Attributes subnode,
a variable with the same name, &CountryWorldRegion8, will be automatically cre-
ated. It will be placed on the web panel grid and allow the end user to select a
world region, causing the grid to display only the countries in that region (why is it
displayed as a combo box9 ?

How does it know that it has to apply this filter? From what Julia wrote under
the Conditions subnode. Note some details: two filters were defined (country name
and world region). Which one should be applied? Both, unless one of them must not
be applied (look at each filter’s “when” clauses. For example, &CountryWorldRegion
is empty (IsEmpty()) when it has the value 0, that is, with the “(None)” description
of the combo box. In this case, the filter will not be applied).

Requirement No. 3 is ready!

Interestingly, and not by chance, when Julia explained to the users how to
update or delete a country at execution time, the Country transaction was opened,
and the country selected from the grid was edited. To do so, the Work With pattern
had to change the transaction’s rules by adding some to the ones we had declared.
What for? To instantiate, edit, the country received by parameter. Let’s take a look:

8
You may have noticed that throughout the GeneXus code, variables are identified by an ‘&’ added as
a prefix to the variable name.
9
Remember that in the CountryWorldRegion attribute properties, Diego indicated that when it is a form
control, it should be displayed as a combo box with the values he set (to the first one, 0, he gave it the
“(None)” description). This is a variable based on that attribute, so look how it inherits the same
behavior, without setting anything.

63
To declare the parameters received and returned, all GeneXus objects use the
Parm rule.

When you use «Work With Countries» to choose a country from the grid to
update it, this transaction will be invoked through the «UPD» mode that is received
in the &Mode variable. In addition, the corresponding CountryId will be sent (that’s
why we had to leave it hidden in the grid). To insert, ‘INS’ is sent together with the
empty value as second parameter, and so on...

ViewCountry web Panel:


View (Country Information)

When we click the country name at execution time, the ViewCountry web
panel is opened to display the data on that country (see page 3). Let’s see what
data is displayed: the country name received by parameter (again, CountryName,
by chance?). Then, in a General tab, it displays all the attributes of the Country

64
transaction’s first level for that country and two buttons for calling the transaction,
passing that country by parameter (to update and delete it, respectively). In a City
tab, it displays a grid with all the country’s cities.

Pay close attention to the “View (Country in-


formation)” node of the Country Work With in-
stance. If, in addition to the country’s name, the user
asked to view the country’s full name, only the
CountryWorldRegion, CountryDetails and CountryFlag
attributes would be displayed in the General tab;
and if he also wanted the City tab, the cities’ grid, to
display only their names, what changes would he
have to do to these nodes? What if the user didn’t
want a City tab at all?

In the instance, there will be a “Tab” for each


subordinate table (many to 1)10... but Julia could add
other Tabs... with other things... but let’s not rush...

In sum: when Julia selects “Apply this pattern on save” in the Country Work
With selector, GeneXus objects such as those we’ve seen running will be generated
upon saving. They can be accessed in the Folder View, below the transaction. Like-
wise, every time the instance is modified, saving will cause the automatic regen-
eration of the corresponding objects.

10
COUNTRY only has COUNTRYCITY in this relationship (many cities for each country) and that’s why
there’s only one Tab. Note that the chosen name was the description of the Country transaction’s level
2 (the description of the lines, which was City).

65
More?

End users asked Julia that after updating a country, they didn’t want to go
back to the caller, WWCountry. Instead, they wanted to view the entire data on the
newly updated country (that is, go to the “View Country”).

Without batting an eyelash, Julia clicked the instance root node and changed
the AfterUpdate property value shown here to «Go to View»...

Note that first it takes a “<default>” value, which has to be indicated some-
where (the same goes for the others). This value sets the default behavior of all
instances (this one is Country, but we may also want Work With Attractions and
Work With AttractionCategories). If we want most or all of the application’s Work
With objects to default to View after updating, we don’t need to manually edit this
property in each transaction instance. Instead, we can change the “<default>”
value in one centralized location. Where is this centralized location?

It’s below the Pattern Settings node of the Folder View. Note that in the
following figure only the Work With is displayed. But there will be other patterns
created by you, by Artech, and by others...

(“Extensibility”... “Integrability”... these are key pieces of the Rocha ideol-


ogy).

66
This figure shows all the default behaviors to be inherited by individual Work
With instances for each transaction. For example, all the features related to the
Work With grids, such as paging, are displayed as properties of the Grid node.11
Interested readers can search for more about the general settings that can be
configured here. For example, you can change the appearance and names of the
pages, the icons for Insert, Update, Delete operations and much more.

Reflect upon what it means to “work with.” What else could the difficult end
user ask for? Just ask Julia and she’ll tell you that in that same meeting, it occurred
to this end user that he wanted to:

A. Export the country data that he was working with to an Excel spreadsheet.
Can you believe it? Also, they didn’t want:

B. Countries to be deleted from the Work With Countries. If this weren’t enough,
they wanted to:

C. Add another action for countries besides Insert and Update . It would
open a new window with each country and its cities –together!– in a more
visually appealing format. (It sounds a bit vague to us... and to Julia as well.)

11
If you look at the Page property of the Grid node in your KB, you’ll find that it has the “Page.Rows”
value. What’s a Page? It’s a numbered domain, automatically created, which contains only one value,
Rows; its default value is 10 and we have changed it to 3.

67
Julia was secretly amused: every time the demanding end user asked for a
new requirement, she made a few clicks and that was it. Except for the last one —
don’t forget that Julia isn’t an IT specialist, so back at the office she’d ask Diego for
help.

Actions Available from Work With Countries

Here are the actions offered by the


Work With pattern for implementation on
the WWCountry data that it works with.
Note that there’s an Export option. “De-
fault” values, again! Yes, again. They will
be set in the WorkWith object that we’ve
seen before, which centralizes all this. In
our case, the “default” values for Delete Export
and Export were True and False, respec-
tively. To disable the delete action and
enable the export action for a country,
Julia only had to change the above combo
boxes, setting them to False and True,
respectively. Requirements A and B are
ready to go!

Now only the last requirement, C, is missing: adding an action that is not
predefined. But the object to be invoked by this action is not created by the Work
With pattern; it should be custom-made for this specific data, so it’s not like any
usual “work with.” This is a job for Diego, who’ll implement that object in GeneXus.
In the WorkWithCountry Documentation selector, under a “To-Do Diego” title,

68
Julia writes that this task is pending. It will be implemented by Diego when he
gets down to it.12

Insatiable as Usual: “I Want More!”

Back from her meeting with the users, Julia received an email from… the users!
They wanted the list of countries from “Work with” to include at least part of each
country’s details, CountryDetails, so they could provide their customers with brief infor-
mation on each. They also wanted to view the number of attractions in each country.

So she needed to add two new columns to the Work With Countries grid –one
for the brief description and another for the number of attractions. But she didn’t
know how to do this, since this information wasn’t stored in database attributes.
Instead, it had to be obtained through some data processing. She was planning to
call Diego anyway so he could teach her how to implement the pending require-
ment, C; that’s why she called him immediately.

Diego created a ShortDetails domain


of the Character(30) type. Then he opened
the Country Work With Pattern Instance.
Through the “Add” command he added a
variable to the grid.

12
Coming up, you’ll see that Diego will easily find Julia’s note in the documentation that seems to be
“scattered” among so many KB objects, thanks to the Dynamic Categories that he’ll talk about in
chapter 6.

69
Note that, in the properties dialog, a name and a domain must be assigned to
the variable being inserted (that’s what the icon means). Diego names it ShortDetails
and assigns it the newly created domain of the same name. He only needs to
determine the value to be taken for each line in the grid.

“As you can rightly guess, Julia, when you put the attributes under this node,
you didn’t need to do more: GeneXus would run through the COUNTRY table and,
for each record complying with the conditions in the specified filters (in our case,
they are CountryName and CountryWorldRegion), it would load a new line in the
“Work with” grid, with those attribute values in each column. If users wanted the
full country description, you’d only need to include the CountryDetails attribute,
but what they actually want is to shorten it to 30 characters. So, all we need to do
is specify, in the LoadCode property of the variable we’ve entered, the value to be
taken for each line. This will mean keeping the first 30 characters in the string,13
that is: &ShortDetails = Substr(CountryDetails,1,30). Yes, CountryDetails is the attribute.
That simple. You can do it on your own now.”

“I see. Then for the other requirement, for displaying the number of attrac-
tions in each country…”

«Well, that’s not as simple because the processing needed to load the vari-
able containing that information is more complex. Think of this: every time a coun-
try is being loaded in a grid line, all the country’s attractions have to be run through
to count them. There are two choices here. One is to program the code that allows
you to run through the information,14 in the LoadCode, again. The other is to add
an attribute containing that information to the Country transaction, let’s say, a
CountryTotalAttractions. This way, you only need to add this attribute to the At-
tributes instance node and that’s it!”

“But, I don’t understand... When entering information on a given country


through the transaction, will the user enter the number of attractions it will con-
tain? What if it doesn’t match the actual number of attractions? Users won’t like
that.”

13
GeneXus offers multiple functions for working with different data types. In particular, there is the
substr function, which allows retrieving a substring from a given string.
14
The for each command, which will be described later.

70
“Julia, you’ll be able to do my job soon! That’s exactly right. It wouldn’t make
any sense if the user had to enter a number that results from a calculation of
database values. This attribute, CountryTotalAttractions, will be of a special kind.
In GeneXus it’s called a formula. Look, I’ll just enter this new attribute in the
Country transaction structure and then I’ll let GeneXus know that I have more
information –that I know how it must be calculated, so it mustn’t store it in the
database but calculate it every time its value is requested, as I’ve determined.”

«Count(AttractionName)? Uh-huh, this indicates that you want the number


of associated values15 in AttractionName to be counted for that country, right? Now,
how does GeneXus know that it needs to count the number of attractions for that
country and not for all others?”

“Well, remember that GeneXus knows the relationships between data and
that a given attraction belongs to a given country and a given city. Also, that each
country-city belongs to one country. That’s enough.”

“And what advantage does this solution offer us, as compared to the other
one –adding a variable in the pattern instance and establishing how to make the
calculation (which, by the way, I don’t know how to do)?”

15
For you as an IT expert (because you are one, aren’t you?): for each country, count the number of
associated records in the table where AttractionName is located; right now it’s ATTRACTION.

71
“Well, you’ve implemented a general solution here. In other cases, in other
objects, when you retrieve a country and want to know the number of attractions it
offers, you’ll only need the formula attribute and the calculation will be triggered –
you won’t have to program it manually. Now, you just have to add this formula
attribute to the instance Attributes node. Voila! The two requirements in the email
are solved!”

There are various kinds of formulas in GeneXus (for adding, counting, searching,
maximizing, minimizing, etc). Note that they are virtual attributes –they won’t be
stored in the database.

Quod Pattern Non Dat, GeneXus Praestat 16

In the time it took Julia to pour herself a cup of coffee, say hi to a coworker and
walk back with her cup of steaming coffee, Diego was able to implement the last
requirement (C, which was pending). Since they were not sure whether what they had
implemented was what the users wanted, they emailed them the following screenshot:

16
Author’s note: The Latin phrase “Quod natura non dat, Salmantica non praestat” means that “what
nature does not give, Salamanca does not provide.” In other words, the Spanish University of Salamanca
cannot miraculously make a person intelligent.

72
“How could you do it so quickly, Diego? Will you show me? I’m sure it’s not
that difficult.”

“Of course it’s not. All I did was create a new object in GeneXus, of the Web
Panel type. It’s the one you can see running on the screen. What you want to do is
display information on countries and cities (each country’s cities). Forget the coun-
tries for a moment, and let’s say you only want to list information on the cities, in
a grid. All you need to do is insert a control of this type in the web panel form and
specify which attributes will make up the columns. Simply by doing this, when you
press <F5> you’ll see all existing cities listed at execution time. From the at-
tributes present, GeneXus infers which table you want to browse (called a base
table). Look, it created a Cities web panel in a snap, inserted the grid through the
toolbox offering all the controls that may be inserted in a form and chose the
CityName attribute. The resulting object form can be seen in this figure. In our
case, the attributes we included in the grid (CityName) come from the COUNTRYCITY
table, which will be the one that GeneXus will navigate.”

«The grid we’ve inserted is known just as Grid, standard grid, since it allows
displaying the information from a record in a table (and in its extended table), with
one information element per column (note that our grid has only one column, with
one title, corresponding to the CityName attribute, but if we had another one, it
would place it in another column). Now, forget the cities for a moment and suppose
that you want to do something very similar with the countries. However, you want
to display each country’s information in a more flexible way and not in fixed col-
umns, as you can see in the screen we’ve sent to the customers. Look at the web
panel I made while you went to get your cup of coffee:»

73
«Note that now the cities grid is displayed, with the CountryFlag and
CountryName attributes, within a rectangle. What’s that? Another type of grid. It’s
called Free Style, since, as you can see, the information on the country you want to
list is displayed not in columns but together, in any design you choose. But it’s also
a grid. Therefore, it’ll display as many countries as there are in the country table.
Note that among its properties, there’s one called Columns where I changed its
value from ‘1’ to ‘3.’ That’s why you can see three countries per row in the image we
sent to the users. Rows ‘0’ means that there’s no paging; all existing countries will
be displayed. Then, note that within Free Style we can enter any control, including
another grid. By doing this, we allow GeneXus to find the relationships among
tables. That’s why it’s listing cities per country in the grid, without us needing to
indicate anything; it does it automatically. You can see it for yourself in the naviga-
tion report that will be displayed after the specification, following the <F5>. Let’s
see if you can figure it out...»

74
The country
being loaded
in the grid…

«What I can figure is why you implemented this so quickly... it’s not that
‘Nature gave it to you;’ rather, ‘GeneXus lent it to you.’ You pretty much didn’t have
to do anything! Don’t give me that look, Diego. I was just joking. Will your girl-
friend come over today?»

“Hmmm... We could also make another web panel (invoked through a Tab
from the country View) that, given the country, graphically displays the number of
attractions per city. For example, in a 3D pie chart. I’d like to do something to
impress…” Diego fell silent.

“Impress users? … Well, Diego, you are not getting my jokes today. Before
you go on, we still need to be able to call this web panel that you’ve just imple-
mented from the Work With Countries.”

“True. But you already know how to do that. Simply add a new action to the
predetermined ones (insert, update, etc.) in the Country Work With instance. We’ll
associate it with a button outside the grid and indicate that, as a result of the action,
we want to invoke the CitiesPerCountry web panel I’ve just created.”

75
Right-click the Selection (Work With Countries) node, select “Add ac-
tions” and then repeat the procedure while positioned on the new Actions node.
Look what our friends have done, and its effects at execution time:

Requirement C is ready!

New Tab in View Country

Diego wanted to impress someone… (may be you, dear reader) with a new
requirement: adding a new Tab control to the ViewCountry that shows a 3D pie
chart with the number of attractions per city in that country. In order to do this,
he adds a Tab node in the Work With pattern instance corresponding to the
View, which will be loaded with the content from another GeneXus object that

76
Diego will have to program. It could be a web panel, but in fact it needs to be an
object that can be executed within another (in our case, within ViewCountry).
It’ll be a Web Component. To all other purposes, it’ll be the same as a web
panel.17 He’ll call it AttractionsXCity and he’ll indicate, in the new Tab, that it
will be loaded with it.

CountryId must be passed as a


parameter to the Web Component
implementing the chart.

Another Side to Extensibility: User Controls

GXchart is an online service that instantly creates any chart you need to view
in an HTML page. You only need to define the desired chart and the GXchart server
will provide you with the relevant image.

In addition to the standard controls you usually insert in your panels (at-
tribute, grid, text block, etc.), GeneXus Rocha allows you to create your own cus-
tomized controls: user controls. Once a user control is installed, it can be used in
the same way as any standard control. GeneXus Rocha comes with some preinstalled
user controls: GXchart is one of them. In the image below we can see that Diego
inserted a control of this kind in the web component form. Then, all he had to do
was set its properties and load the values he wanted to see in the X axis (the
country’s cities) and those he wanted to see in the Y axis (the number of attrac-
tions). Upon inserting this control in the form, a structured data type is automati-

17
Actually, it will be a web panel with the Type property set as Type = “Component”

77
cally created, better known as SDT, which allows building record lists of variable
length in a flexible way. In turn, it creates two variables, &GxChartData and
&GxChartSeries, and uses them to load these lists (cities and attractions). The
code by which they are loaded can be seen within the Start system event, pro-
grammed by Diego. Don’t worry if you don’t understand this code right now. We
just wanted to show you how easy it is to comply with this requirement.

Consistent Look & Feel without Sweating?

“Having a consistent look & feel is today’s must for any Web application.
Creating and maintaining each page in a Web application, ensuring consistency
throughout the site, takes a great deal of programming time,” Julia read out from a
technology magazine on Diego’s desk.

“Not with Master Pages,” Diego replied. “As I’ve said before, a web panel
can implement an ordinary web page like the one we made, CitiesPerCountry (with
the Free Style and standard grids). That is, an independent web page that will be
invoked by another (in our case, by WWCountry). Or it can implement a web page
that will be a component of another page, like the chart that was a Web Component
part of the ViewCountry. Or, finally, a master page, which is a page that centralizes
what will be common to all the pages in the site, such as the header and footer

78
you’ve seen everywhere. They even tend to have
a vertical menu on the left, so that it is only in
one location and, if you want to change it, you
only need to do it once.”

“Of course! At the beginning of the project I


saw Mike running transactions that had all the same header and footer (now I see
that Work With Countries and View Country also have them). Since those sections
weren’t included in the objects’ form, I wondered how it was done. A master page
programs that common look, right?”

«Exactly. Look at this,» Diego said while se-


lecting the Country transaction and accessing its
properties. «You’ll see the same in all transactions
and web panels created by patterns: AppMasterPage
is a master page automatically created with the KB,
and contains that header and footer that keeps show-
ing up.

Let’s open this web panel and look at its prop-


erties. What does this tell you?

And not only the com-


mon form is programmed
here, but you can also pro-
gram common behavior. Pages
in a site are quite usually re-
stricted to authorized users,
who must log in to the system
to be able to browse them. In
the past, validation of a user
authorization had to be re-
peated for every web page
accessed. However, with mas-
ter pages, the validation code
only needs to be written once,
here, and that’s it! We make
sure all associated pages will carry out this validation and the code will not be
scattered everywhere.”

“That’s great! I mean, for you, because less work is needed to achieve consis-
tency. I’m going out to lunch and then I’ll impact the pattern on the rest of the
transactions we have. Have you had lunch already?”

79
80
Chapter 4
Flight to the World
of Subtypes

The project was moving forward on schedule, and the team members were
focused on their specific roles. Thanks to GeneXus’ incremental philosophy, they
felt confident about facing changes or innovations that may arise. The model en-
compassed everything necessary, and nothing else.

Completing Transactions on the Fly

It was past lunch time, but Diego wasn’t hungry. He decided to wait a while
before creating the remaining transactions. The truth is, he had offered to show
Mary GeneXus Rocha in action, and wanted to make a good impression. Instead of
taking his notebook to the coffee shop, he had suggested meeting that afternoon in
his office at ACME.

“Hi, Mary! You look good, how are you?”

“Hi, I’m doing better. I appreciate your offer, considering that we’re in com-
peting companies. It’s really kind of you.”

“Hmmm... It’s not like that,” he mumbled as he wrote ‘the Community’ on the
board. “Please, don’t get me wrong. I mean, the rivalry, the competition isn’t like
that. There are thousands of GeneXus developers and they’re all linked by what’s
called the Community. It’s very motivating. ‘Synergistic,’ some would say. You may
be wondering whether it’s a club. Well, there aren’t any social or sports activities –
for now,” he added with a smile, trying not to sound nervous. “It’s like a network for
sharing knowledge and solutions related to GeneXus and its associated tools.

81
Many programs and extensions have been created by Community members to
meet different needs. There’re many Web sites to download them, and to publish
them as well. The Community is very active, with dozens of forums to exchange all
kinds of solutions. I’m on several subscription lists and consider myself an active
member.”

“It sounds nice, but... Does it work? Do they really help you out or is it a
joke?”

“As the saying goes, ‘one hand washes the other...’ Everyone needs help some-
times. If, instead of competitors we’re collaborators, we all benefit; we work better,
are more motivated and reach better solutions. We have a common goal: to make
the Community grow for everybody’s sake. It may sound naive, but the truth is it
works. GeneXus Rocha itself is formed by GeneXus extensions. That is to say,
Community members can expand GeneXus Rocha with their own extensions. In
fact, GeneXus itself can be considered as an extension.”

Diego was happy to see her bright, familiar look and went on, more confi-
dently:

“Look,” he said, opening the Extensions Manager window through the Tools
option in the GeneXus menu. “This is the current list of extensions in GeneXus
Rocha. Most of them were developed by Artech and the rest by Community mem-
bers who made them available to everyone.”

“I see that the Start Page has a section called ‘Extensions,’ with an abstract
by the author and a link to install it.”

“Yeah, and if you read it through, you’ll notice that some of them don’t say By
Artech. These extensions were created by third-party Community members.”

As far as the project was concerned, at that


point reality required that more transactions be
added. After a quick review, Diego created the Air-
line transaction to store the names of airlines re-
lated to Travel Agency & Co.

82
Flight Transaction: Destination Subtypes

Diego read his notes and was glad that the next transaction was a complex
one. Mary used to like a challenge.

“We’re going to create the next transaction, but you’ll have to focus,” he
warned, as this could be a surprise. “Take a look at this case. The transaction will
contain flight information such as description, airline, departure time, and maxi-
mum number of passengers; this data is easy to understand and infer. On the other
hand, we’ll have a departure and arrival city,1 which is data from reality that we
need to know and store. At the coffee shop I told you that when attributes share
the same concept they must have the same name. Do you remember?”

“Yes, when you showed me how to create the Country transaction. I remem-
ber there was an exception...”

“It’s time to clear that up. Sometimes, we have to use different names for
basically the same attributes, which breaks the rule. The flight transaction has a
problem that causes this exception. In every flight there are two countries and two
cities involved, which play different roles: one departure country and city, and one
arrival country and city. We have two references to the same table, COUNTRYCITY.
Look, if we only wrote this that I’m drawing on a paper:

We could say that the CountryId and CityId attributes in the Flight transac-
tion represent a country’s city, because they have the same name as the Country
transaction identifiers. This means
that they’ll be a foreign key of the
COUNTRYCITY table. So far so good,
but now we need to add another city2
with another role: the arrival city. In
other words, a city has to be refer-
enced twice: as departure city in one
role and as

1
Since we’re simplifying reality, we assume that there will never be more than one airport per
city.
2
When we say “city” we always mean a real city, such as Paris. To identify a city, we must provide the
{CountryId, CityId} pair. Due to the transactions’ design, there can’t be any cities that aren’t related to
their countries. For example, there’s a city called Rosario in Argentina and another one in Uruguay, but
Rosario doesn’t exist independently from a country.

83
arrival city in the other. How do we do this? We won’t be able to add one
attribute pair to the same transaction twice. Otherwise, how could those attributes
be distinguished? However, we could do something like this...” He took a pen and
added two new attributes; the first two were prefixed with a D (Departure) and the
last two with an A (Arrival).

“Hmm... But if GeneXus infers that they’re different things because they
have different names, there’ll be no connection between flights and cities, right?”

“Right. The solution is to tell


GeneXus that these attributes are
still the same concept, even though
their names have been changed to
distinguish them. Although
DCountryId is no longer called
CountryId, it still has the same func-
tion so GeneXus has to maintain ref-
erential integrity as before. This is the same as saying that DCountryId is a sub-
type of CountryId.3 The complete solution is to group these pairs in two subtype
groups,” he said while redrawing the diagram.

“I see...! Because of that, DCountryId and DCityId will be a FLIGHT foreign


key to the COUNTRYCITY table, just like ACountryId and ACityId. You have two
foreign keys to the same table.”

“That’s right. And all


referential integrity checks
must be automatic,” he
added, discovering a new
enthusiasm in her. He won-
dered if he’d be able to take
back control of the key-
board.

“Anyway, the problem doesn’t end here,”


continued Diego. “In this transaction, besides
indicating that a flight has departure and arrival
countries-cities, we want to infer each country
and city name to view them in the form. That is
to say, we want to display attributes of the FLIGHT

3
Thus, CountryId is a supertype of DCountryId.

84
extended table. How can we infer them if we have two references to the table? We
can’t use only CityName because there are two of them. GeneXus wouldn’t know
whether to use the {DCountryId, DCityId} foreign key, or the other {ACountryId,
ACityId} foreign key. There’s an ambiguity!”

“Well, you’ll also have to change the names of the (CountryName, CityName)
attributes to be inferred and put them in the corresponding subtype group, Mary
thought. Then she said, “Show me how to define these groups in GeneXus; go
ahead, this way you can explain it better.”

As if he had read her mind, Diego selected Subtype Group from the New
Object window and named it Departure. Mary smiled and didn’t say anything.

“As I told you, they really are groups. You create one, name it and add the
‘new’ attributes4 pointing to their corresponding supertypes. In this way, GeneXus
will know that the FlightDepartureCountryName attribute will be inferred only through
the FlightDepartureCountryId attribute, because they belong to the same group –
Departure. See the connection?”

4
Note that subtype names follow the GIK naming convention. That’s why they begin with “Flight” (the
transaction’s name) and continue with “Departure” (the group’s name). In this way, the roles they play
in the transaction are easy to understand.

85
“Sure,” she replied. “When the user enters a value on the
{FlightDepartureCountryId, FlightDepartureCityId} foreign key, the referential in-
tegrity check on COUNTRYCITY will be
made. In addition, this country-city code’s
name will be inferred from the
FlightDepartureCityName attribute, and
the country’s CountryName will be inferred
through the extended table in
FlightDepartureCountryName. Now we
should create the arrivals subtype group.
Right?”

“Not necessarily, because the two


groups are clearly separated. The one I’ve just created is the explicit one. The
other is implicit if I add the CountryId, CityId attributes to the transaction struc-
ture.5 But for the sake of clarity, we usually group all occurrences. Otherwise, one
role (arrival) wouldn’t be clearly identified. How about you create the other group?”
asked Diego, pointing at his laptop.

“Ok, I’ll give it a try...” said Mary, who was excited by what she was learning.

5
This ambiguity can be removed by changing the name of one CountryId and CityId occurrence.

86
“Great!” Everything was ready to create the Flight transaction. “It’ll be a two-
level transaction. Each flight has three classes (First, Business and Economy) with
up to three different fares, which makes it a price list (1-n relationship). All flights
have only three different fares. Keep in mind that the flight ID mustn’t be
autonumbered because this number is defined by an international standard that
includes their route and time. For example, Pluna Flight 0174 from Montevideo to
Buenos Aires operates on Saturday mornings. If it’s moved to the afternoons, the
flight number will change as well.”

The following figure shows the final structure. Note the icon that indicates a
subtype attribute.

Maximum number of passengers

Since the FlightClassId attribute can only have up to three possible values (First, Business and Economy
class), do you know, dear reader, what can Diego do to let the user easily select one?

Diego was documenting his work on the KB’s Wiki, when suddenly Mary an-
nounced she had to leave. “Thank you so much, Diego. I’ll call you soon.”

87
An Actual Flight: FlightInstance Transaction

The Flight transaction handles flight information; for instance, Pluna Flight
0174 from Montevideo to Buenos Aires departs daily at 11:15 AM. For each flight
0174, there’ll be an actual plane flying on a certain date, with a certain number of
passengers on board.

The following transaction represents the actual flight, with information such
as date and departure time, number of passengers, reservations, names and seat
numbers. Here, the ID will be autonumbered.

COUNT(FlightInstancePassengerSeatNumber)

With this design, FlightNumber will be a foreign key. How many FlightInstances can there be for the
same flight (FlightNumber)? Is it as expected?

Some of the attributes here are worth noting. For instance,


FlightDepartureTime6 is the scheduled departure time of the flight (it’s inferred
from FlightNumber). FlightInstanceDate and FlightInstanceTime are the actual date
and time of the actual flight. The actual flight time is predetermined by
FlightDepartureTime and can be changed by the user. So, Diego created the follow-
ing rule, which is executed only in Insert mode:

default(FlightInstanceTime,FlightDepartureTime);

6
Even if the FlightDepartureTime and FlightInstanceTime attributes are of DateTime type (they allow
storing a date + time), we’re only interested in time.

88
He also added another rule:

error(‘Maximum number of passengers has been reached’)


if FlightInstanceNumberOfPassengers > FlightTotalCapacity;

The FlightTotalCapacity attribute is inferred through FlightNumber. What about


FlightInstanceNumberOfPassengers? It’s a formula that counts the number of lines
entered in the sublevel. Every time a new passenger is added to the form’s grid, a
seat number (FlightInstancePassengerSeatNumber) is added for that actual flight,
and the formula is updated. When a passenger exceeds the maximum number, the
error will be triggered so that no more passengers can be entered into the database
for that flight.

Lastly, Diego declares this rule:

error(‘The flight departure cannot be advanced’) if update and


FlightInstanceTime < FlightInstanceTime.GetOldValue()
and FlightInstanceDate < FlightInstanceDate.GetOldValue();

In other words, when updating an actual flight, only the departure date and/
or time can be changed, as long as it’s not advanced. Note that the GetOldValue()
attribute method is used. It returns the value stored in the database, whereas the
attribute now has the value that the user has just entered in the form (it’s in
memory).

The passengers’ information will have to be stored, so Diego will create the
last transaction of this stage.

In the Flesh: Passenger Transaction

89
Once this transaction is created, the PassengerId attribute of the FlightInstance
transaction becomes a foreign key. The following Bachman Diagram represents the
relationships between old and new tables.

Everything seemed right, so Diego accessed the Wiki, documented the end of
this stage, and left to Julia the implementation of Work With objects.

90
Chapter 5
When the “What”
Is Not Enough

Just declare? What about Procedural Descriptions?

That’s what Mary asked a couple of dates later, at the usual coffee shop.
They had started seeing each other more often, at his office or the coffee shop,
and had discussed several topics such as patterns, web panels and so on. Today,
she was in a quiet mood. She understood that transactions allowed describing
users’ views on data in a declarative way, but it didn’t seem enough. She wanted
to know about the batch or similar processes that are needed in all applications,
because these processes can’t be inferred from the knowledge provided by views
on data.

“So?” she asked.

“A procedural language is missing, I agree,” Diego affirmed. “Considering the


GeneXus philosophy, it’ll probably be a very high level language. What’s more, it
should only use references to the External Model, not to the Relational Model. For
instance, suppose that you must delay the scheduled departure time of all major
flights (which carry more than a certain number of passengers) from a certain
airport, at a certain time on a certain date, for whatever reason –say, bad runway
conditions. You’ll have to access all the FLIGHTINSTANCE records where the
FlightInstanceDate and FlightInstanceTime values match the date and time when
planes won’t take off, and belong to flights that depart from a certain airport and
carry more than a certain number of passengers. In those records, you’ll have to
replace the current values of FlightInstanceTime, and maybe FlightInstanceDate,
with the new ones. To do so, you could filter the ‘Work With FlightInstance’ by those
values. For each line (an actual flight) displayed on the grid, you’d have to call the
FlightInstance transaction in Update mode and manually edit the values. Most

91
likely, this will be unacceptable for end users. The other alternative is to use vari-
ables in a web panel (such as ‘Work With FlightInstance’) for users to enter both
the current and new date and time values for those flights, as well as their country,
city and carrying capacity. Finally, an action (button or image) would call a proce-
dure that runs through the FLIGHTINSTANCE records and makes the change.”

“Is it a common procedure?”

“Yes, it’s a new GeneXus object type. Here’s my notebook. It’ll be more visual
if we create this procedure to try it in GeneXus.”

A few seconds later, Diego was ready to create the Procedure object in order
to implement the previous logic. Following is the edit window of the newly created
procedure.

Through the Rules selector, Diego declared the received parameters:

parm( in: &CurrentInstanceDate, in: &CurrentInstanceTime,


in: &CountryId, in: &CityId, in: &NewFlightInstanceDate,
in: &NewFlightInstanceTime, in: &FlightTotalCapacity);

“Wait a second, I got lost. I assume that the For each is a command for
accessing the database by running through a table. But, where do you say that
FLIGHTINSTANCE is the table to be run through? Besides, you’re using attributes
from another table. Shouldn’t you run through FLIGHT first and, for the records
that meet the conditions, make a join with the FLIGHTINSTANCE table?”

92
“It’s not necessary,” Diego replied. “To begin with, you don’t declare the table.
That’s the trick! In the For each command that we wrote,1 we said that for each
record of the table where the attributes mentioned are located (FlightInstanceDate,
FlightInstanceTime, FlightDepartureCountryId, FlightDepartureCityId, and
FlightTotalCapacity), the values of the first four should match those of the variables
received through the parameter. In addition, the FlightTotalCapacity value should
be greater than or equal to the variable that’s received through the parameter. In
this case, the FlightInstanceDate and FlightInstanceTime values should be replaced
with the new ones.”

“I still don’t get it. Those attributes are in different tables. FlightInstanceDate
and FlightInstanceTime are in FLIGHTINSTANCE, but all the others are in FLIGHT…
Shouldn’t you run through…?”

“That’s right,” Diego interrupted her. “But FLIGHT is in the extended table of
FLIGHTINSTANCE. In other words, for each actual flight there’s a FlightNumber
(foreign key) that belongs to only one record of the FLIGHT table, which has one
FlightDepartureCountryId, one FlightDepartureCityId, and one FlightTotalCapacity.
There’s an n to 1 relationship between FLIGHTINSTANCE and FLIGHT. GeneXus
doesn’t need anything else: it’ll run through the FLIGHTINSTANCE table and access
each record’s counterpart in FLIGHT, by making an automatic join to get the
FlightDepartureCountryId, FlightDepartureCityId and FlightTotalCapacity attribute
values. Using this data, it decides whether to keep the record to process it (pro-
vided that the FLIGHTINSTANCE record matches the date and time indicated by the
&CurrentInstanceDate and &CurrentInstanceTime variables). The condition to keep
a record for processing is the And concatenation of all the logical conditions you see
in the For each command’s Where clauses. Since we’ve talked of base tables, we’ll
do it here as well: it’s the table run through by a For each command. Because
GeneXus knows the relationships between tables and the attributes’ location when
making the analysis, it can infer the data access without you naming any table. As
a consequence, you can change those attributes from one table to another, without
losing the procedure’s description.2 ”

1
Take a deep breath, dear reader; we don’t want you to run out of air.
2
As long as the attributes belong to the same extended table; otherwise, GeneXus will give an error
saying that the attributes couldn’t be related.

93
“Why? It looks a bit like magic... I wouldn’t feel safe programming in this way.”

“Believe me, there’s no magic here. Let’s look at the navigation report to
address your doubts –and mine. Before executing a procedure to test it, the first
test is done: it’s the navigation report, which provides information about the things
that are making you nervous. That’s why I never execute without reading this
report. Ok, I’m not going to lie to you. Sometimes I don’t read it and regret it
afterwards. Let’s read together...

Base table

You shall access


this table
through a Join

See? It displays the For each command’s base table, the order that it’ll use to
process the data,3 and the index suggested to follow this order (if it exists). Be-
sides, it shows the navigation filters; that is to say, where it starts and finishes
running through the table. In this case, it’ll run through the entire table.4 Then,
Constraints (filters on the records to run through) are analyzed. Below you can see
that for each FLIGHTINSTANCE record a join is made with the FLIGHT table of its
extended table (to filter by FlightDepartureCountryId, FlightDepartureCityId and

3
The order can be indicated with the Order clause of the For each command. Since it hasn’t been
indicated, there is no database index to optimize the search for records satisfying these conditions.
Thus, GeneXus assumes it’s the primary key of the table to be run through.
4
If there was an index formed by {FlightInstanceDate, FlightInstanceTime, FlightDepartureCountryId,
FlightDepartureCityId, FlightTotalCapacity}, it would use it to optimize the query and avoid running
through the entire table. It would inform this in the Navigation filters of the Navigation report. In
the event that there was an index formed by a subset of those attributes, it would suggest it. (At
any time you can have GeneXus create a user index). We say that it’ll suggest it because this
information is valuable for SQL generators, but actually, the DBMS determines the most appropri-
ate access plan. On the other hand, it is vital for non-SQL generators (RPG, COBOL, VB-Access,
VFP-DBF).

94
FlightTotalCapacity). In addition, the FlightInstanceDate and FlightInstanceTime
attributes of the FLIGHTINSTANCE table will be updated. Be honest, Mary. Tell me
how much longer it would take you to implement this with your current tools. You’d
manually make this join. Really, it’s best to keep talking in a high level. Think about
what would happen to your implementation, which most likely will require you to
name tables, if you moved the FlightTotalCapacity attribute from FLIGHT to
FLIGHTINSTANCE. Here, you don’t need to change anything at all. You just regen-
erate this object for GeneXus to infer the new navigation, and that’s it!”

“I see your point. How do you insert and delete records from the database?”

“Well, the For each command allows you to run through a database table and
access its extended table not only to read but to update attributes. For this reason,
it’s a very important command. It can be used not only in procedures but in every
GeneXus object that supports procedural code (such as transaction and web panel
events). For additions and deletions, two new commands have been created: New
and Delete.”5

“Now that I think about it, the procedure doesn’t control the same as the
FlightInstance transaction: advancing a flight’s departure date and time is not al-
lowed. I remember there was an error rule that prevented it,” Mary said.

“You’re right...” he nodded. Something was obviously on Diego’s mind, and


Mary looked at him expectantly. He fell silent for a few seconds and finally said, “I’ll
have to add this control to the procedure by asking with an If command before
updating. Every time I change the date and/or time of an actual flight, in any
object, I’ll have to redo the same control of the transaction rule, repeating the code
over and over. I may make a mistake or skip it altogether...”

5
Referential integrity is not checked in any case, allowing users to enter records pointing to nonexistent
records, or to delete records pointed by other records, thus orphaning them. Only uniqueness is
checked. These are programmatic controls, as GeneXus enables referential integrity checks at the
DBMS level, where controls will always be made.

95
A sure and easy way:
the “what” of Business Components

“Since we know,” he continued with renewed energy, “that transactions are


one of the most important objects, because that’s where users’ views, business
rules and formulas are gathered, and the uniqueness and referential integrity con-
trols are executed, what would you say about reusing them from any other GeneXus
object?”

“Huh?!” the look on her face made Diego laugh.

“That’s right, reuse them, drawing on all the knowledge they’ve incorporated.
For example, if I had a way of encapsulating all the logic of the FlightInstance
transaction, disregarding the interface… that is, if we could have a buffer or some-
thing, a temporary structure, like, for instance, a composite, structured variable,
where all the data (header and lines) of an actual flight could be loaded… I could
enter it into the database from any object… If the transaction’s logic were really
encapsulated like that, the insertion would only be allowed if all the conditions for
entering that same information through the transaction were met… What I mean
is: if I wanted to insert a flight instance associating a nonexistent flight
(FlightNumber) to it, or tried to add a nonexistent passenger, it would fail and I
wouldn’t be allowed to make the insertion, just as would happen in the transaction.
Or, for example, if I want to add a passenger that actually exists but whose incor-
poration exceeds the flight’s capacity, it won’t allow me to perform that insertion,
just as it wouldn’t allow me to do it through the transaction, as I have an error rule
in the transaction,” Diego explained as he opened the FlightInstance transaction
and showed Mary the Rules section.

You, dear reader, can look this up in the previous chapter. So, it’s possible to
encapsulate the transaction’s logic, retaining the structure, but discarding the form:
it’s called Business Component. It is a data type that GeneXus generates building
on a transaction.6

“And how do you go about encapsulating all that?” Mary asked. “How do you
use it?”

6
Business Components are obtained from transaction objects, but they can be used from any other
GeneXus object to add, delete or modify data in their tables.

96
“With the transaction you want to use in this other, ‘silent’ way, all you have
to do is change the value of its Business Component property to ‘True.’ Once you
save this change, GeneXus will create a new Business Component data type, which
will have the same name as the transaction.”

“But how do you use it?” she asked again, intrigued.

“Through variables based on that data type. Every time you want to update,
add or delete a flight instance, instead of using For each, New, and Delete, you’ll be
able to use all the possibilities provided by the FlightInstance transaction, through
the properties and methods of a variable based on the FlightInstance data type
generated by GeneXus. Let’s change our last procedure to perform an update through
a Business Component,”

Diego went on with his monologue, while Mary waited expectantly, without
speaking. “We need a variable, &FlightInstance, of the data type generated when
we switched the Business Component property to ‘True.’ In it, we will put all the
content of the flight instance that we want to change. This variable will naturally be
structured; it will be the ‘buffer’ where we’ll temporarily have the data of the flight
we want to manipulate at a certain time. The code will look more or less like this …”
he said, replacing the two direct assignments in the object with the four sentences
we see in the image below. “Note how here we only use the For each command to
run through the base table and to filter, but we don’t update directly.

97
“See? The first thing I do here is load from the database the flight instance to
be modified, in the &FlightInstance variable, according to the FlightInstanceId value
corresponding to the record that met the filter conditions in the For each command
(it’s the record of that iteration). Next, I change only the data that we need to
modify, and then I save, using the Save method. To edit a flight through the trans-
action, you’d have placed the identifier in the form’s FlightInstanceId field, and
then you’d have left the field. To do that with the Business Component, we use the
Load method. In the transaction, you’d have changed the values of the
FlightInstanceDate and FlightInstanceTime fields in the form, and then clicked [Con-
firm]. And in this case? You change the values in the variable, and then run the
Save method. What you’ll have as a result is practically the same thing. I mean,
what would happen if in the transaction you changed the flight to an earlier date
and time?”

“The error you programmed as a rule would be triggered, and it wouldn’t let
us save. That is, the change you wanted to introduce in the record wouldn’t be
made. The record would be left as it was.”

“Exactly. And what do you think will happen here, in the procedure?”

“The… same thing?” she asked.

“Right! The same thing! The rule will be triggered, and as its condition will be
met, it won’t allow you to save the change.”

“And how will I know what happened?”

“Well, in the case of the transaction, since it’s an interactive object, there’s no
doubt there. A Business Component, however, is not interactive, so any messages
and errors resulting from the processing (executing the Load and Save methods, or
even the Delete method) must be stored somewhere. GeneXus places them in a
collection (list) of messages associated to the corresponding Business Component
variable, and you can retrieve this list with a method (GetMessages). Then you can
browse this list of messages… But if you only want to know if any errors occurred,
you have the Fail method, which returns a ‘True’ value whenever there’s an error.
So, in our case, you’d write ‘if &FlightInstance.Fail()…’”

“I get it,” Mary said. “And what other errors can occur when you’re manipulat-
ing data with a Business Component?”

98
“The same as when you try to insert through the FlightInstance transac-
tion. That is, referential integrity (if you tried to change the flight, FlightNumber,
which is a foreign key, for one that doesn’t exist), uniqueness (if you wanted to
insert a new flight instance, and you assigned it a FlightInstanceId that already
existed for a different record), data type validations, error rules declared in the
transaction and whose triggering conditions were met…”

“Of course! In this sense, it’s safer to have a procedure using a Business
Component. Besides, that way you know that all the business rules are going to be
triggered without having to repeat them.”

“All of them?” Mary asked. “If you don’t keep the visual interface, what hap-
pens if the transaction has a rule that triggers a call to a web panel, for example?”

“Well, ok, not all of them… GeneXus ignores any rules in the Business Compo-
nent that employ user interfaces. The rule you describe won’t be included.”

“Interesting…” she said.

Where do you want to go with this?


Tempting attractions… in PDF format

If you’ve been paying close attention, you’ve probably realized the same
thing Mary did:

“Among the selectors of the Procedure type object there’s a ‘Layout’ selector.
What’s it for? Can a procedure allow you to make a visual output?” she asked.

“Actually, it can. As it happens, one of the requirements our users have


included in their specifications is that the travel agency’s site should have a
page showing attractions per city, and a link of the type ‘View as PDF.’ To do
that, I created a procedure, which I’ve called AttractionsPerCity. Look,” Diego
said as he opened the object in his notebook and selected Layout.

“I’ll have to tell this procedure that it will have a PDF file as its output. The idea
of the Layout is to declare what I want to have in the output. As a result of the
execution, I want to display for each city, all the attractions it has. The user will

99
obviously have to have Acrobat Reader installed, in order to open from the browser
the PDF file that is generated. To indicate what is to be displayed in the output, and
the format it will have, the Layout contains print areas, which are controls called
printblocks. In color in the figure, you can see where two of these controls start:
City_Block and Attraction_Block. I gave them those names after I added each con-
trol. Inside each printblock you enter the information (attributes, variables, images,
lines, boxes, etc.) that you want to display in that data area, when it’s invoked from
the code. For example, note how in City_Block I’ve included the CityId and CityName
attribute controls, because that’s the information I want to display in the list for each
city.”

“And with that little bit of information GeneXus already knows what to list and
how?”

“Whoa! Mary, hold on. You can’t expect it to do magic! With what we’ve
entered so far, it can’t know how you want to list the information. We still have to
get to the code,” Diego said, raising his eyebrows with a playful look on his face
that made his friend blush.

“Well, you make it sound so great… it wouldn’t surprise me if it could read


your mind.” They smiled at each other.

100
“Can you read my mind?” Diego ventured, moving forward.

“How about you tell me?” Mary returned, staring straight into his eyes.

“Your wish is my command!” After a brief silence, he began again. “I want to


run through two tables: COUNTRYCITY and ATTRACTION. For each COUNTRYCITY
record, I want to go through all the related ATTRACTION records, that is, all the
records corresponding to that country-city. This entails using the two nested For
each commands.”

Mary moved her chair closer to his, took the mouse from his hand without
asking his permission, and, smiling all the while, clicked the Procedure selector.
The window changed, and showed the following code:

Diego continued:

“Note that you don’t need to set the filter by city for the second For each
command: that’s because there’s a direct 1-n relationship between the tables that
are run through, and this is one of the most common cases of nested
For each commands. The base table of the external For each command
is COUNTRYCITY, and the one for the internal For each command is
ATTRACTION (because of the attributes of the printblocks involved), and as GeneXus
knows the relationships between the tables, it implicitly applies the restriction over
the records to be retrieved. But it’s more powerful than that: it also finds indirect 1-
n relationships. For example, if you wanted to list, for each airline, the number of
flight instances.”7

7
Between the AIRLINE and FLIGHTINSTANCE tables there is an indirect 1-n relationship (with the FLIGHT
table as intermediary). GeneXus finds indirect 1-n relationships in many other cases and makes the join.

101
Mary didn’t utter a word. She just looked at the screen. Still smiling, she
right-clicked the procedure Tab and selected ‘View Navigation’ from the context
menu. Diego was looking at her. A new Tab appeared on the screen, with the
following window:

“See what I mean? It’s restricting the search,” he explained to Mary, who just
watched and smiled. “This is indicated by the navigation filters of the ATTRACTION
table in the second For each command. Note the “@.” It’s indicating that it takes
those values from the context. What are the values for @CountryId and @CityId?
The ones from the record of the first For each command it works with in that
iteration. These are intentions that GeneXus does discover.”

Diego went on:

“You can also tell it to send the output to some printer within reach of the
computer running the browser with the application.”

Finally, Mary broke the silence: “Paris looks tempting… Why don’t you come
over to my place for dinner tonight? And you can tell me more about it…”

102
Chapter 6
Winds of Change

Straightening up the house: Categorization

That night, Diego brought the wine. And his notebook. The music playing in the
background created an extremely cozy atmosphere.

“You have to keep your promise,” Mary demanded, smiling, as she filled her
wine glass. “Tell me more.”

“About GeneXus? Well, I don’t know what to tell


you…” he seemed nervous, but immediately got hold
of himself. “Today, for instance, I was categorizing the
objects of the KB. I don’t know if you remember, but
the IDE has a panel in the KnowledgeBase Navigator
container called Category View, which displays a tree
with all the objects that you’ve classified, under their
respective categories. Hold on, I’ll show you,” he put
the notebook on his knees and his wine glass on the
end table near the sofa.

“I’m not sure I see the point…” Mary replied as


she sat down next to him.

“Well,” Diego tried to fill the silence while his note-


book started up, “for example, in my company we usu-
ally have categories to identify the status of the ob-
jects: ‘Operating,’ ‘Under Review,’ ‘Under Construction.’
That way, with a quick look you can see which objects
are ready to be tested, simply by opening the ‘Under
Review’ category. In this case, we divide our universe
of objects into separate categories. In fact, you can

103
even name this criterion for classifying your universe, precisely with a category:
‘Status,’ for example, containing these three subcategories. But, at the same time,
we might want to categorize the same universe according to other criteria. What I
mean to say is: you can include the same object in several different categories. For
example, suppose you also want to organize by system, subsystem, etc. Nothing
prevents your object from being in the category corresponding to a subsystem and
also in the ‘Under Review’ category in ‘Status.’ Or you can categorize objects ac-
cording to whether they will be used in the application’s back-end or front-end.
Categories allow us to organize and view the information in our KB according to our
specific needs.”

“Multi-categorizing…” her eyes were shining intensely. Or at least it seemed


to Diego that they were.

“When you select an object from Folder View, under the properties window,
you have a container called Categories that starts with a small toolbar where you
can both add categories to the object and eliminate categories from it. But, as
always, there’s more than one road leading to Rome…”

“Today you were categorizing… that means you had to go to every object, one
by one, and assign the corresponding category to each, right? Too much work!”

“Yes,” he said, a little embarrassed. “The thing is, categories are pretty new,
and I’m not really comfortable using them yet, even though it was a company
decision to use status categories. Sometimes it’s difficult to change the way you’re
used to doing things. We should have created these categories from the very be-
ginning, and the objects already with the ‘Under Construction’ category, so that we
could move them across categories as their status change. Today I had to straighten
up the house, because the objects in the KB were getting to be too many. But I only
had to do this for the ‘Status’ subcategories, because the ‘To-Do Diego’ category is
dynamic, and maintains itself.”

“How’s that?” Mary reached out for the wine bottle.

“In this case, as I had to straighten things out anyway, I put comments with
the text ‘To-Do Diego’ in some objects that were pending. Then I created a dynamic
category. Dynamic categories have a search condition associated to them. All the
objects resulting from the search, become part of the category. In the search con-
dition, I indicated that it look for objects with the text ‘To-Do Diego,’ and it found all
the things I have to do –quite a few, by the way…”

104
Seek and you shall find…
Another interesting feature you’ll discover in GeneXus Rocha is its capacity to
find “anything” that’s in the KB. This feature is presented in the same way as when
we use search engines on the Internet. Based on complex algorithms, GeneXus
Rocha’s full-text search engine finds what you’re looking for among what could be
tons and tons of words contained in the objects that make up the KB. And like most
search engines, it allows us to use intuitive syntax to limit our searches. In the
following image you can see the “To-Do Diego” search…

The full-text search engine browsed the KB and reported all the places where
the text was found. Note that on the right there’s another search proposed, but in
this case only of properties. For example, if we wanted to locate all the objects with
the Main program property set to “True,” all we’d have to do would be to write
“main_program = True.”

Notice also how from this query we can create the dynamic category with the
same name, “To-Do Diego,” that Diego showed Mary above. To do so, you just have
to [Save as Category]. Maybe that’s what Diego did that day…

105
Foundation, mascara, eye-shadow…
Making up the application

That same afternoon, several hours earlier, Julia was finishing up the docu-
mentation in the KB, when Mike, who was doing the last of the testing remarked:

“I heard from Diego that they want to change the style of the pages. He was
too busy with some objects he had to finish developing, so he passed that matter
on to me. He told me to talk to you about it and ask you for the details.”

“Yeah, I got an email describing more or less how they want it to look, and I
copied the instructions in the Main Document’s Talk; I’ll document it properly later.
They left it up to us to decide on the colors and all the rest. And I had already saved
their logo to the KB some time ago, in the Images node. They want it to be located
at the top of each page.”

“I can do that right now. I just have to open the AppMasterPage master page
created with the KB and used by default by all objects. This centralizes the header
and footer that will appear on all the site pages… then I replace the default ‘Appli-
cation Header’… and it’s all set. To do ev-
erything else they asked for, we should
call Paul, the graphic designer…”

“But Paul doesn’t know anything about GeneXus, and you’re going to let him
open the objects and modify the controls in the forms, changing the color, size, and
everything else?! If I were him, I could never understand…”

Mike laughed: “Julia, look, we should each stick to what we know. I won’t let
him touch our objects. But I need him to configure the design for each control in
the forms. For example, I need him to specify the size, background color, font, etc.,
for the transaction buttons, as well as for the grids and other controls. I’d like to
centralize that so that he won’t have to touch the controls ‘in’ the objects. That’s
what we have the Theme type object for. See, here, under the Themes node in
Folder View, we have one called Modern. It’s the one GeneXus associated by de-
fault to our objects. If I open it, you’ll see that it’s a list, in tree format, of classes
of controls (although not only).”

106
This is where you
configure the design
aspects for this class.

“Each control type has several possible classes. In the Button class there’s a
subclass, BtnDelete, which by default inherits its properties, but which allows you
to change its characteristics. If we now go to any transaction and we edit the form,
in the properties of the [Delete] button we’ll be able to see the ones associated to
this class. You can change it for a differ-
ent one. With this, you completely sepa-
rate the behavior from the design in your
application. And look here, what I’m go-
ing to do now is export1 the Modern
theme from our KB (we could also cre-
ate a new one), send it to Paul so that
he can configure the appearance of the
classes and send it back to me, so that I
can then import it, and voila! Design applied! Paul doesn’t need to have GeneXus,
just the Theme Editor, which is a utility program that only allows you to work with
these objects. It’s a specific tool for the graphic designer. Another option is to do it
from within GeneXus.”

The Master Page and Theme object types are the most important when it comes to
designing the application’s appearance.

1
We hadn’t talked yet about exporting/importing in GeneXus. In this book we will only say that you can
export GeneXus objects and other types of knowledge from a KB, in files with an xpz extension, which
can later be imported into another or the same KB. For that we have an option in the Knowledge
Manager menu.

107
Tell me when and I’ll tell you how you were

Another interesting possibility offered by GeneXus Rocha is that of seeing


how objects in the KB evolve over time. That is, each object will have a history
associated to it, which will record the changes with the date and time on which they
were made and the user who made them. With that, you can monitor an object’s
evolution, starting from that object’s creation.

And what’s more: in the very near future, you’ll be able to know the real
status that the object had in the version you’ve clicked on. In this next image…

…you can see, on the left, the content of the Latest Changes View panel, and, on
the right, the history of the FlightInstance transaction. Note how there were two
changes since the date it was created; therefore there are three version numbers.
You will also be able to compare two versions and see the differences between
them. Powerful, right?

108
What the Oracle says…

Legend has it that certain prophets spoke of the Oracle foretelling that, re-
gardless of the alignment of the stars, a new era would be coming…

The new protagonists of knowledge: Data Providers


GeneXus’ goal: that you declare, declare and declare. When you declare, you
say the what, without worrying about the how. The how varies with time. We often
discover new, better, and more efficient ways of implementing. The what is stable. It’s
the essence. Knowledge that enables automation. Transactions and business compo-
nents used to be, then, the stars of GeneXus: they declared the business logic. They
declared knowledge. In each stage of its evolution, GeneXus found a how. But a new
time is dawning. A new protagonist emerges: Data Provider. For a wide range of cases,
we’ll go from programming procedures, to declaring data providers.

Intelligent components, capable of processing various types of inputs, filter-


ing them, sorting them, and producing some form of desired output (like a different
data structure or a given format).

In every process we can say that we have an input, a transformation, and an


output. In procedures, the focus is on transformation. In Data Providers what’s
important –declared– is the output.

Are you intrigued by this concept? Would you like to see an example that will
give some substance to this description? Since we like suspense, and we like to keep
you on the edge of your seat right to very end, we’re saving a more detailed discussion
on this subject for the annex that comes after this chapter, if you still feel like it...

Masking desires with Data Selectors

We often find ourselves coding the same “situations” (filters and orders for
accessing the database) in different places of our application where we retrieve
data, scattering the same logic (or part of it) through several different places,
wasting considerable time, which in turn negatively affects our productivity. If we
look at the following bits of code…

109
…and compare them, it’s obvious that different results are obtained through
them, although with the same bit of logic: they both want to filter by African
cities (CountryWorldRegion=1), sorting them by name. The first displays just
that in the output (let’s suppose that City_Block contains the city attributes),
and the second displays the attractions of the African cities in the “Safaris”
category. Note the code block they have in common, formed by an order and a
filter. There could be dozens of GeneXus objects where you’d need African cities
ordered by name.

A Data Selector allows you to centralize and reuse navigations, thus avoiding code
duplication.

But it has more advantages. New members of the development staff are often
unaware of the common criteria or filters of an application. For example, suppose
that tourism to Africa is being actively promoted; as it usually happens, someone
who is asked for a list of cities gets one with all cities instead of only the African
ones. Centralizing these criteria greatly shortens the learning curve, allowing staff
to quickly become productive and reducing the number of mistakes.

In the previous example, if we gave these common clauses a name, as if they


were a macro that could later expand… we’d have a Data Selector! A name for a
data search criteria. In our case: AfricanCities.

The above procedures will now be:

110
The Using clause, which says to “use the content” of the AfricanCities Data
Selector, is written to the right of the For each command; and that’s all… If we
change the criteria later on, we do so inside the Data Selector object and it’s
automatically changed everywhere!

The path of processes

People are very good at a lot of things, but in tasks such as searching for a
document among hundreds of others, being on top of when each document is due, and
making sure the work that’s completed is channeled from one place to another accord-
ing to a predefined sequence... hmmm, are we very good at that, do you think?

GXflow, a well-known Artech tool connected with automation of company


processes, by determining task flows, is also integrated into GeneXus Rocha. Why?
Applications have increasingly more process flows, which require Workflow compo-
nents.

Now you will be able to create your own diagrams within GeneXus, greatly
simplifying integration tasks, and connecting activities with KB objects more easily.

In this image we’ve designed a simple


example that shows the process flow for flight
reservations.

The reservation itself, expressed by the


first box in the diagram, is none other than
the start-up of the transaction it represents.

A given condition -such as, for example,


if the data is correct and complete- is then
evaluated. For illustration purposes, let’s say
we have the following conditions:

Print Tickets IF FlightStatus = ‘AUTHORIZED’


Get in contact with Client IF FlightStatus = ‘COR-
RECT PERSONAL INFORMATION’

111
These conditions are expressed through a conditions editor. The idea is that
they be able to express rules, where first the name of the succeeding task is
indicated, followed immediately by a condition that must be met in order to
continue down that path. Simple, practical, and powerful.

If the condition is met, the reservation ticket is printed and sent to the client.
Otherwise, the flow detours to the Get in Contact with Client task, the information
is updated (most probably through the transaction corresponding to clients), and
then the flow goes back to the reservation, restarting the cycle.

Were you already a GXflow user? Would you like to see a summary of the
changes? Straight to the annex, then…

Back and Front End - Intra and Inter Net

In this book, we took the liberty of peeping into some moments of our char-
acters’ lives, and that way we’ve been able to see how some parts of the application
have been implemented. The goal: to see a little bit of everything. But we haven’t
seen the full picture. At times, we, the authors, feel a little ashamed of our voyeur-
ism, and we look away, to later feel tempted again to turn our eyes back to the
story. This is why we’ve seen objects that will be used in the application’s back-end
(for example, Work With objects, as the data for airlines, countries, cities, flights,
passengers, etc., can only be updated by company employees, with permits, through
the Intranet) mixed in with other objects that can be used in the application’s front-
end, that is, on the web site that will be consulted by people around the world via
the Internet.

However, Diego, Mike and Julia have done more work than what we’ve been
able to see. They’ve created the home page for the Intranet, slightly modifying the
home page created by the Work With pattern. They’ve added a login section in the
master page… web panels with various queries and different menus.

In fact, that very afternoon, before his date with Mary, while Paul was given a
theme to modify, Julia contacted users of the Travel Agency, and Mike finished
testing, Diego was carefully examining how the home page of the company’s web
site finally looked:

112
Notice how hotel, car rental and weather information is provided. These are
third-party applications, published as Web Services that can be easily integrated
(consumed) within GeneXus. At this point the reader has all the elements neces-
sary to have an x-ray of the page and guess what might be behind it: a web panel,
web components, master page, theme, images, controls…

However, Diego didn’t use all of that. GXportal, one of GeneXus’ technologies,
enabled our friends to develop the web portal with a minimum of effort. Was it
Diego who developed it? Or was it Julia?

GXportal allows you to design, manage and maintain scalable portals, without hav-
ing to program. Therefore, GXportal users don’t need to have special programming
or design skills. It offers a framework for integrating knowledge, information and
applications through a portal, with the aim of bringing together the different people
involved in the organization and the communities.

113
The End… or the Beginning?

So far we’ve obtained different pieces of a puzzle that you will be putting
together, drawing on what’s most important: your imagination.

With it, you will be discovering the remaining pieces of the puzzle in what will
be a continuous search. An unending search. The puzzle is always nearly… but not
quite finished. That’s where its secret lies: in keeping us permanently in suspense,
searching, thinking, imagining, changing.

“Friends, with faith, with joy, with generosity, with the synergy of this
Community, let’s move forward, and preserve the magic.”
Breogán Gonda, Closing Address, 16th GeneXus International Meeting
September 20, 2006

What do you think happened with our characters? Was the development project
successful? How did that dinner with background music end? Was Mary finally
persuaded to join the Community? Pieces that are still missing, and that each will
find… like the secrets that are still brewing in the Rocha Age……

…Or could it be that this story is only just beginning?

114
Annex
Building the Future

Application development grows increasingly complex with each passing day; GeneXus
has its own weapon to combat such complexity, and that weapon is knowledge-
based development.

GeneXus has always based its work on the idea that you can generate an entire
application by building on knowledge (and, as a by-product, maintain the applica-
tion automatically). GeneXus Rocha reaffirms the full validity of that idea. In this
sense, GeneXus Rocha is not just another version, it is a reformulation of the
product, and it will be the version that captures and uses the most knowledge.
Why? Because one of the key concepts that distinguishes GeneXus Rocha from its
predecessors is the extensibility architecture it was conceived with.

What this means currently is that GeneXus Rocha is not built just by Artech: the
entire GeneXus Community contributes to the building process through its own
extensions.

When we say extensibility, we mean extensibility at all levels, from the capturing of
structured or unstructured knowledge, to participation in the generated applica-
tion.

The GeneXus Community, together with Artech, will be in charge of finding new
mechanisms to capture knowledge, devising automated development methodolo-
gies, and, ultimately, generating future applications.

It will be the Community who benefits the most from extensions (those who par-
ticipate proposing extensions, developing extensions, testing them, criticizing them,
using them…).

115
Extensibility: A Common Denominator
All of Artech’s products are currently being developed with the concept of extensi-
bility in mind.

The GeneXus development environment (IDE), GXpatterns, products such as GXflow,


GXquery, GXplorer, and Ruby generator, as well as every feature developed for
each of these products, all rest on Extensibility as one of their pillars.

Extensions refer to all of these things, and are not limited just to the development
environment.

What must be achieved: that knowledge is captured the “GeneXus Way,” that is,
with a clear, simple and usable way of enabling the abstraction of such knowledge.

Extensibility, Integration and Usability

In developing our new product architectures, we decided that extensibility would


need to have two inseparable allies: Integration and Usability.

Our extensions must be seamlessly integrated into different environments, be they


the development environment, or a batch environment.

Extensibility at the Workflow level, for example, can only be viewed as a real ex-
tension if there is a true Integration of the Workflow in my development process, in
the same environment, and with a high degree of Usability.

In all likelihood only those extensions that incorporate Usability as a key aspect will
be well received by the Community.

An Extensible Environment
One of the most important features in terms of extensibility is that of the GeneXus
development environment itself.

The GeneXus development environment is currently extensible through Modules,


called packages, which provide a particular functionality.

The environment provides a user interface Framework, with services that enable
interactions with menus, toolbars, windows, management of user interface prefer-
ences, etc., and a Universal Data Model to handle concepts such as Knowledge
Base, Model, and Versions, among others.

116
Every new package that is added to the environment defines new concepts, adds
functionality, and enhances the user interface. GeneXus itself is implemented as a
package of this environment, adding the concepts of Transaction, Domain, Attribute,
etc. GXflow adds the concepts of Business Processes; Patterns incorporates gen-
eration mechanisms based on GeneXus; and so on.

Therefore, there’s no difference between what can be performed by a third-party


package and what can be performed, for example, by GXflow, or GeneXus itself.

A package may include the following possibilities, among others:

• Defining new types of objects (for example, WebPanel, Data Provider, Activity
Diagram, etc.)

• Defining new object parts (for example, WebForm, WinForm, Variables, etc.)

• Providing new editors

• Adding menu options

• Adding toolbars

• Defining new properties for the objects or parts

• Subscribing to events

• Creating new services and consuming existing ones

Data Providers: Accessing Knowledge


When designing an application, it is crucial to conceptualize what our business
logic will be, regardless of the architecture we plan to develop. This business
logic applied in knowledge-based development is represented naturally through
rules.

Subsequently, with Transactions (and in particular, with Business Components)


GeneXus provides a way of capturing these rules and effectively generating and
maintaining them, so that they are complied with when required. Business Compo-
nents, therefore, play a major role in the construction of the Business Logic.

However, these rule application and updating components are complemented by


other, essential components: those that in a sense define our application’s informa-

117
tion retrieval and presentation services, thus forming what we could refer to as the
application’s Business Framework.

We’ll call these intelligent components –which are capable of processing various
types of inputs, filtering them, sorting them, and producing some form of desired
output–1 Data Providers. Together with Business Components, they will play the
leading roles in the construction of our applications’ future Business Frameworks.

Declaring our Data Providers

Data Providers are a major step in GeneXus’ evolution, as they are new objects that
will enable the capturing of automatable knowledge in a declarative way.

The great innovation is in the way GeneXus users will be able to express them, so
that we could say that for a great number of cases we will go from programming
Procedures to declaring Data Providers.

Being declarative in whatever you want enables you to obtain a knowledge that
opens the doors to innumerable variations in terms of generating the application’s
definitive code. GeneXus will always tend to declare knowledge instead of pro-
gramming the application, as the latter is simply an automatic step that follows the
former.

If a Data Provider declares that it wants a set of data with certain filters, that same
data can be obtained through several ways, from various sources, with different
technologies. If I have something that is declarative, I won’t have to worry about
these parameters when declaring knowledge: this will simply be a decision that is
adopted later, and possibly automatically.

What is it that I declare?

In every process we can say that we have an input, a transformation, and an


output. In Data Providers what’s important and what’s declared is the output.

As we said, by declaring the output, GeneXus will be able to evolve in such a way
as to obtain that output. When we say output, we’re not thinking solely of cases of
outputs to a certain given format. These are, no doubt, common cases, but they
vary with time.

1
For example, a different data structure or a given format.

118
There are a number of “outputs” that are more important than these, and they are
outputs to, for example, internal components of my Business Framework.

A Data Provider that has an Invoice as input and a set of accounting entries as output
is clearly more important for my Framework than the Data Provider that generates
an RSS with the entries. The latter will surely change over time, as the RSS format
may no longer exist, while the former is pure knowledge of how to convert an invoice
into the corresponding entries. Let’s see this in a specific example.

Use case: entering a sales invoice into accounting records

Let’s suppose we have the following invoice for which we want to obtain a corre-
sponding accounting entry.

Your accounting entry would be as follows:

Before we go into the specific example, we need to make some observations:

Firstly, the transformation is considerably complex, that is, from a two-line invoice
we need to generate a six-movement entry (four movements are fixed, and the
other two vary according to the number of document lines).

119
Secondly, the problem arises in the output, so Data Providers are a natural solution.

And lastly, we’ve declared our intention, and have specified no transformation
process; we simply declare the output.

Entry
{
EntryDate = InvoiceDate
EntryDescription = 'Invoice ' + InvoiceId
Movements
{
Movement
{
AccountId = ObtainAccount.udp('Cash/Bank')
MoveType = 'CR'
MoveAmount = TotalInvoice
}
Movement
{
AccountId = ObtainAccount.udp('Debtors')
MoveType = 'DB'
MoveAmount = TotalInvoice
}
Movement
{
AccountId = ObtainAccount.udp('TAX')
MoveType = 'CR'
MoveAmount = TotalInvoice * 0.20
}
&MoveAmount = 0
Movement
{
AccountId = AccountForProduct.udp(ProductId)
MoveType = 'DB'
&MoveAmountItem = ProductCost.udp(ProductId) * InvoiceLineQuantity
&MoveAmount = &MoveAmount + &MoveAmountItem
MoveAmount = &MoveAmountItem
}
Movement
{
AccountId = ObtainAccount.udp('SaleCost')
MoveType = 'CR'
MoveAmount = &MoveAmount
}
}
}

This declaration is very simple, but that doesn’t make it less powerful in the Data
Providers. Notice that the example uses formulas; you could also use filters, differ-
ent types of outputs, and many other things that make Data Providers simple and
powerful objects, something that is very difficult to achieve simultaneously.

120
The Path of Processes
GXflow, a well-known Artech tool connected with automation of company processes,
by determining task flows, is also integrated into GeneXus Rocha.

Why? Applications have increasingly more process flows, which require Workflow
components.

What is accomplished by this approach?

• Process modeling is part of the KB, which means it adds more high-level
business knowledge in the KB itself.
• When modeling business rules through transactions and other objects, it is
not necessary to know beforehand whether they will be used or not in a
Workflow process.
• When dragging an object to a GeneXus activity diagram you’re guaranteeing
that that object will be invoked by the engine with no additional program-
ming required.
• You can express conditions through an editor that enables you to describe the
transaction rules based on the relevant attributes and data defined for the
process.
• All the cross-reference functionalities are available, as the diagrams are just
another object of the KB.
• The GXflow Prototyper will enable quick diagram execution, so as to incre-
mentally perform the prototyping. That is, as the diagram is formed, the
<F5> key can be used to execute, at which point it will trigger everything
necessary to execute the diagram, from the impact of the process on the
metadata to the generation and compilation of the objects associated to it.
• The GXflow engine and client will be components that are external to the KB,
and thus they will not weigh on the KB building process.

And what about queries?


We will add the capability to express within the Knowledge Base queries that can
be used in any object, whether you want to display the data returned by the query
as a pivot table or a chart, or simply read it through. An interface will be provided
for this, to help create queries in the KB, where users will only have to select the
attributes (data) they wish to retrieve, and they will be presented with the corre-
sponding results.

121
“I have to admit that, at first, the informal tone of the book took me by
surprise. After reading it carefully, I see that the “informal tone" is
another of the many great ideas that the authors have had. In my
opinion, this book is a great contribution to the knowledge of the Rocha
Version and the huge change it represents, so that the GeneXus
Community can prepare for its launch in 2008."

Episode One
Breogán Gonda, Engineer
Artech President
Cecilia Fernández is GeneXus instructor
and has worked in Artech's Training
Department since 2001. She teaches
Diego and Mary run into each other after many years. Long gone are the GeneXus courses in Uruguay and abroad,
days and nights of studying, laughing and talking in the classrooms and writes manuals and creates distance-
hallways of the School of Engineering, when Mary was always so full of learning courses. She attended the School
life and Diego would let himself be carried away by her laughter. Until of Engineering, University of Uruguay, and
the chance meeting shakes the dust off that memory... and Diego happily is currently pursuing a Bachelor of Arts in
finds himself able to help his old friend solve some big problems at work Literature at the School of Humanities and
and get back to being the cheerful, outgoing woman he knew (and Educational Sciences.
loved?) so long ago.

Diego, Mike and Julia have three weeks to develop a web application for
a travel agency, including the application's back-end and front-end.
Mary is going through a difficult time professionally; she's a project
manager who is so overburdened by maintenance chores that it's
affecting her health.

GeneXus is the thread that interweaves the characters' journeys through


these pages. Discovering and showing. Showing and discovering. Over
and over again: the Rocha Version.

Daniel Márquez Lisboa, is a GeneXus


analyst, technical writer and consultant, as
well as a freelance writer, who has
developed large systems in GeneXus and
other languages. He has authored or co-
authored four books, including "GeneXus
Knowledge-based Development," which
wa s p re s e n t e d a t t h e G e n e X us
International Meeting in 2006.

Episode One

You might also like