16 Learning Experiences Stories of Dynamics 365 Finance & Operations Apps Developer for Diwali
Hi everyone, so November is started, and Diwali, the festival of light, is just begun. It's a moment of bliss to put out this article on some of the victory of light over darkness that Microsoft Dynamics 365 Finance & Operations Apps developers/technical consultants may have experienced.
In this article, here are some stories that are shaped learning such as major obstacles to increasing continuous upgrade cost and written code that is not easy to understand, not easy to change by another person (developer) and not in line with best practices.
Please comment to share your experiences as a developer/technical consultant while working on Dynamics 365 Finance & Operations Apps implementation, upgrade or business as usual (BAU)
1. Indicate unfinished code
Lets begin with the most common condition, keeping unfinished code. Often developers put TODO comments in the code to track problems or mark parts of their code for future references. Just a thought, your code shows that your change is WIP. For example, TODO comments indicate unfinished code to me and not to be committed as a release candidate.
if (1 == 1)
{
// TODO: First information is recorded.
info('Hello World, 1.');
}
if (2 == 2)
{
/* TODO: Second information is recorded. */
info('Hello World, 2.');
}
2. Empty finally blocks π
This particular one could be the best learning. In several methods, try/catch/finally statements are written with empty finally blocks though it is an optional clause.
The important aspect of this story is that it shows your code is incomplete. In my opinion, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. It will resolve lots of ambiguity.
try
{
// Your code here.
}
catch (Exception::Error)
{
info("Caught 'Error'.");
}
finally
{
}
3. Empty while loops π¨
Any empty while loop means the body is simply going to execute continuously until the condition for termination of the while is met. It can be a developers nightmare to identify the issue if proper care is not taken.
The learning part of the story is proper care is required to be sure the condition has been properly constructed.
while(without body);
4. Exists and notexists joinsπ―
This one could be a common story to developers. It is when exists and notexists joins are used where fields are specified in the query. In my opinion, this has no meaning, since no table buffer will actually be fetched for exists and notexists joins.
Not including fields for such types of join tables is the best way. The key takeaway from this story, keep your code in line with best practices and readable.
5. Extension classes with Eventhandlers π
Since the new model of Extensibility framework is launched, it replaced customization through overlaying. In my view, any extension class but contain data event handlers is the deviation category of best practice.
Not the correct way to use extension classes and doing this will typically make the handler methods available on any table, since the first parameter of such handlers is of type Common.
Especially when the task to debug or troubleshoot the code and understand the complete call stack that does not belong to you. You just spend hours trying to understand the code.
[ExtensionOf(tableStr(CustTable))]
final class CustTableMy_Extension
{
public void myDefaultCustgroup()
{
this.custgroup = this.getcustgroup ();
}
[DataEventHandler(tableStr(CustTable), DataEventType::Inserting)]
public static void CustTable_onInserting(Common sender, DataEventArgs e)
{
CustTable custTable = sender as CustTable;
custTable.myDefaultCustgroup();
}
}
6. Methods with parameters π
As extensions get larger and you have been told to resolve best practices issues related to methods with parameters not starting with underscores. One of my friends experienced this huge pain to resolve.
In my view, there is no semantic difference. It is a style used to differentiate between method arguments and global variables. Developer can adapt practice to read your code by another person.
It will also help to decorate your method for local variables & method parameters names properly.
7. Parm methods π
Any parm method declared as private can be unpleasant for a developer.I had a debate with one of my friends whether param method should be private or protected & public. In my view, there is no semantic difference. It is a way to differentiate between parm method arguments and global variables.
However, a parameter is not allocated. This occurs sometimes and is a strong indication of an error.
public MyEDT parmMyFunction(MyEDT _myvariable = MyVariable)
{
;
MyVariable = _ myvariable;
return MyVariable;
}
8. Implementation of IDisposable π
This learning is a bit tricky to analyse, this approach is a better way to pass extra information from your code to a pre/post handler someplace downstream. It gets trigger disposal of the object when control passes out of the blocks scope.
My learning says that an exception to this rule is when your method returns IDisposable. In this case using disposes of the object before the caller can make use of it, causing exceptions at runtime. Sometimes it can be a tedious activity to find places where classes that implement IDisposable are not created in using statements and remove them. That was not fun at all.
9. Concatenated string literals
This story is hilarious. Appending one string to the end of another string, enclosed in double quotation marks (" "). As part of the code review process, Ive seen multiple strings concatenated but to be honest, it is inefficient and should be replaced with the complete literal.
10. Calling strfmt statement π
One of my friends share this story with me a couple of days ago while he was debugging the issue. Identifying references of strfmt is called with only a single argument can be a nightmare for a developer. You cannot find updated references with the find references option.
void diwaliFun()
{
str festival ="Diwali";
info(strfmt("Name of the festival : %1"));
}
11. Table buffers presented in the select or join π
This could be a common story of all developers, and it has a huge performance impact. The key lesson learned from this story is to use the field list and join when possible.
while select * from Table1
{
var field1string = Table1.field1 ;
}
12. Abstract classes with no abstract methods π
This is one of my best learning with abstract classes. The developer declares an abstract class without any abstract method and the purpose of declaring a class as abstract is not to instantiate the class. It is useful when you inherit a class from an abstract class and the main purpose of doing is don't implement your logic in child class you can get the parent logic.
13. Complexity of methods π¨
In the past couple of years, one thing I learned during the code review process is methods complexity. This story connects to all developers.
The rule of thumb is to have if statements, for, while, and do/while constructs, switch/case constructs each count as one. If you add these types of constructs more then it leads to unorganized and inefficient code.
14. Nested select statements π©
SQL syntax query is used for data selection and manipulation. This one could be a common story to developers. The Nested select statement can lead to performance issues. Such types of nested select statements can be challenging for a developer to resolve performance issues.
In my view, these cases may or may not be good candidates for joins.
15. Label mismatch π
Any label text not appearing on UI in the correct business terms can lead to a lot of confusion. The part of the story is maintained dedicated label files per language. This can lead to a nightmare for developers to realign the labels.
16. Method documentation π
As code gets larger, there is a risk of readability and understanding of business logic. In my view, developers never forget the code they wrote. Maintaining the documentation means you clear your mind before coding and layout clearly what you need to capture with the code π. The method documentation indicates the quality of code.
It is also useful when another person uses your code and learn implemented logic.
Conclusion
As this article is intended for some of the learning experiences sharing, these are all encouraging experiences for a developer/technical consultant. For many who experienced one of the stories I've mentioned above, there is always an approach or an inhibition method, such as sticking to best practices.
So, have you collected these learning experiences yourself? If not, what other most Dynamics 365 Finance & Operations Apps implementation stages have you experienced as a developer/technical consultant?
Please share in the comments below, and I might share your stories in my next blog! Have a prosperous & healthy Diwali, cheers!
Thank you for Reading - Let's Connect!
Enjoy my blog? For more such awesome blog articles - follow, subscribe and let's connect on LinkedIn , Twitter
Published on:
Learn moreRelated posts
Practical Hints for Technical Management of D365FO Go-Live
In this post, I share practical insights from my experience managing the technical side of Go-Live for D365FO projects, focusing on key activi...
D365FO Integration: Event-Based Exports to External Web Services
How to implement robust, efficient integrations between Dynamics 365 Finance and Operations and external Web Services. This post covers design...
Physical cost inclusion for Weighted Average Valuation in Microsoft Dynamics 365 Finance and Operations: Part-13
What is physical cost in Dynamics 365 F&O? Anything which has been received or shipped but not invoiced is considered as physical cost for...
Product bundles in Microsoft Dynamics 365 Finance and Operations
Product bundle was first introduced in module revenue recognition but as we all know the there is new modules which has been introduced and wi...
D365 Sending Email with Customer Account Statement SSRS report as attachment using X++
D365 Sending Email with Customer Account Statement SSRS report as attachment using X++ custTable _custTable; &...
clicking link on info message X++ to Open form
Message::AddAction() method can be used to embed an action within a message sent to the message bar. This method supports adding a singl...