Common Pitfalls every developer should know when developing with the Agile Platform

Common Pitfalls every developer should know when developing with the Agile Platform

  
During my ramp up time at OutSystems, like other developers, I made some mistakes that cost me some time. Some of these mistakes are common to all OutSystems newbies. If you haven't suffered from them yet, you'll bump into one of these sooner or later, and I hope this post can help you avoiding it.

This is just my personal experience, but I’d really like to see all the community contributing to this list so that it becomes a resource to new developers. If you have more pitfalls that you think can be useful, feel free to share!

 
Pitfall: Circular references
Imagine that you have these two eSpaces: DataToTextActions and DataToText. One is the eSpace where you have the Web Pages and the other one has some actions you want to use. It happens, in this scenario, that you also want to use one action from the DataToTextAcctions in the DataToText eSpace. You end up with what you see in figure 1: a circular reference. That is, eSpace DataToTextActions references eSpace DataToText, and eSpace DataToText references eSpace DataToTextActions.


Figure 1
Why is it a problem?  You now added a new action in the DataToTextActions eSpace, and published it. You got to DataToText, update the references and start using this new actions, integrate it in your logic, end your work and publish DataToText. The references of the DataToTextActions will become outdated and you end up with a never ending story! This can lead to a bunch of problems like broken references and more.
 
 

Figure 2
How should I do it? To prevent this situation, always try to follow the 4 layer architecture Structure. Creating different levels of layers will prevent many of these issues. Is not that the 4LA advocates that each layer is an eSpace, but prevents that, in the future, if you need to split up one eSpace in multiple, you don’t bump into this problem.
Either way, if you get into this chase your tail kind of problem, you can add your eSpaces to a solution and publish it. This is the one way to publish two eSpaces with cyclic references and don’t end up with outdated references. Remember though that you should always avoid having cyclic references.
 
 
Pitfall: Assign list expression to query
Imagine that you are creating a list of people and when you test it the LastName expression appears whit an equal result in all rows of the list and you don’t know why. In this case, check to where you have the expression assigned. When you create a new list/show record or list record be careful where you assign your expressions, because different references will return different results. Particularly, you should try to avoid assigning an expression to the query output if you are in the context of a List or Show record


Figure 3
Why is it a problem?   If you assign the list to the query the value returned will be the current row value of the query, which is always the last one, so it will be the same in all rows since the list don’t  iterate on the query.
Example: Imagine that you’re building a list of people and you have a cell with an expression to show the last name of the person. If you assign that expression to the query's “LastName” field and the “LastName” field of your query is “Catarino”, than “Catarino” will be showed in every row of the list.


Figure 4
 
How should I do it? : The expression should always be assigned to the widget (new list/show record or list record) and not directly assigned to the query in preparation.
In order to have the correct behavior, you must assign the expression to the list record widget. This way, the widget will loop through the query's result and list the correct name of each person.

 
Pitfall: Binary loaded in Preparation
In this case we are doing a list of people for a recruitment application and, in our list, we have an option to download the person’s Curriculum Vitae. Normally we load on the preparation’s query all the entities that we need in the list, but in this case, since the CV entity contains Binary Data, we shouldn’t load it on this query. When you create a list make sure that you never load information that you don’t need to build that list. Keep in mind though that, if your query takes some attributes that you never use, the Agile Platform will not load them. The query will only retrieve those attributes that you actually use in your screes (if the query is in the preparation).


Figure 5

Why is it a problem?  If you load data that you don’t need, the access time to the Database will be higher which will increase the response time of the application. This can be especially relevant when dealing with binary data like the CV binary in our case, which will take a long time to load. Loading the binary data in the preparation can increase to a great extent the loading time of the page and overflow the view state.


Figure 6
How should I do it? : In our case the solution is to create a new action to download the CV binary and call that action from the download button/link. This way you grant that you improve the performance of your page and use the data only when you really need it.


Pitfall: Assign Empty Record Lists to Clean
We have now a record list and we need to clean it to store new values. When we work with records and we need to clean a record we usually use the method of assigning an empty record to clean another. This method is very practical and works well for records, but for record lists it doesn’t work you can see another example here.


Figure 7
Why is it a problem? When we assign an empty record list to another record list it will only point the reference but the data will not be erased. This means that if you assign new records to that list you will just append records to the old list and you are not creating a new one.
 

Figure 8
How should I do it? :  In order to erase the record list you will need to use the ListClear action. Just need to get the ListClear action from System references, drag it to your flow and set the RecordList value. 
Awesome post Hugo!

You forgot when we switch the IF condition connectors! =)
Hello Hugo,

Nice post, only one comment related to the list clear action.

Somewhere in my memories it says that the list clear only clears the list attributes. When you have an RL attribute in that RL that attributeRL will not be cleared and it will keep the values it had. So you can only use the list clear action in case the RL doesn't have an attribute which is also a RL.

As I said, this is something that pops my mind, knowing I had some problems with that in the past. Don't know for shure if this still is a problem.

Kind regards,
Evert
Another tip is if you are using action adding (+) lots of strings together.  This can really slow down performance.  If this is the case you should be using a string buffer.
Hi,

A common error I find in the code of people new to the platform is not using the DB engine as they should, example:
Improve your SQL!

That If is completely useless, do it inside the query! Believe it or not I do find this error more often then I'd like to...

Another one is related to deleting records in bulk... this one really makes me boil and, also, appears from time to time.
The scenario on the left is obviously the wrong one...
Learn your SQL

Good post by the way! ;)

Cheers,
Hermínio Mira
Herminio -

We have a policy of "no advanced queries unless there is no other choice", because we've found that maintaining a large application gets very bad when there is advanced queries being used. For us, in that second example, the version on the left would be the correct way to do it (though we also do not delete anything in bulk... and we typically only hard delete a very few, inconsequential items at all).

J.Ja

Herminio,

I'll also agree with Justin. Here we like to avoid the advanced queries. For performance issues we indeed use some delete actions for bulks but the general is to use the 'default' OS action. Maintaining large applications is better with simple queries then advanced.

Kind regards,
Evert


Hi,

Of course I agree with both of you regarding advanced queries.

The main ideia behind my post was that "people should improve the SQL / use the DB engine better" before using lots of OS actions to go around it. It was not meant to be "go ahead and use advanced queries for everything"! :)

Cheers,
Hermínio Mira
Hi Herminio,

In fact you're recommendation about using the AdvancedQueries (now SQL Widget) to delete large amounts of data is the "correct one". This is the same best practice (and also to do massive updates) we present to our customers.

If you have no corporate restrictions about using the approach then you should, because there's no comparison when you think about the performance of both approaches.

Cheers,

There is an Application in the Forge called "Discovery" that allows you to identify applications that have circular references.  It also lets you organize your environment into the 4-layer architecture.  Its a great tool to help identify possible issues. 

Thanks for the article!