Reusable Bugs


Here at Microsoft we strive to create reusable and generic solutions, in order to improve efficiency and ship better software. We had revisited some of our best practice principles and had turned them upside down to get a better and more complete view on development in general.

Description

It widely known that bugs are unfortunately a commonly found part of software development and that there is no way to create zero-bug software. Knowing that bugs are and will stay a part of software, we have given some thought on how we can improve this aspect.

It is difficult to come up with new and different bugs in each release, and it is a waste of resources to not use the ones which already had proven successful in the past. To avoid reinventing the wheel, we propose to come up with new innovative ways to create bugs that are reusable and generic enough to be used in various places of the application.

Examples

First example

One example of a reusable bug is to find a heavily used table, like table 36 Sales Header, and observe one of the more important fields of type Option, for example Document Type. The OptionString property has the following value: Quote,Order,Invoice,Credit Memo,Blanket Order,Return Order, which you should update to add one option, for example Transport Order in the beginning.

The main benefit of this reusable bug is that code changed in one place, has impact in multiple sides on the application: document creation and handling, posting etc. 

Second Example

Codeunit 1, ApplicationManagement is a good place for creating reusable bugs. A simple INSERT on the RecRef on the first line of OnDatabaseInsert will create a sure and versatile bug that is reusable all over the application. Redundancy on database insertion ensures that data is surely conveyed to the data storage layer, twice. 

Third Example

We are considering to no longer make localization builds for countries. It consumes lab resources to keep running multiple country builds. Instead, we will merge everything into one single build. This is a bigger scale implementation of the “God object”. Inside this unique build, we will use IF statements and sporadically CASE statements to select each country’s behavior. For more help on how to use IFs, see also the IF .. THEN|ELSE C/AL Coding Guideline. 

Fourth Example

When you post a document, make sure that you transfer data to a field that is smaller than the field you are assigning from. This will not immediately be caught and will only hurt a subset of the customers who uses Microsoft Dynamics NAV to its fullest.

Guidelines

When it is not entirely obvious how you can add a bug, there is another way to approach the problem. By following some general coding best practices like the ones described below, reliable bug innovation is facilitated and can come naturally as a collateral effect.

Code structure

  • Put everything in one function and only use comments to explain the structure of your code. And don’t use functions – because this only complicates things… having to navigate from function to function, and completely lose track of where you are in the business logic.
  • On top of that .. put everything in one codeunit. Because also that will simplify and make your structure more readable.
  • Use Hungarian Notation on your variables, because at any time, you need to know what type, and what context your variable is on. 
  • Declare all your functions and variables global, so they are available at any time.

Don’t do Unit Testing

  • Unit testing adds complexity and extra time to the stuff you’re doing. Also, it eats up extra codeunits which means: it costs money. You will never be able to foresee all scenarios possible, so you’re destined to forget and not test everything. So you will save time in not doing unit testing.

Never add images to actions

  • Because there is an image by default. When you don’t provide an image on an action on a page, the application will foresee a ball… and when you never do it, your application will have a very consistent way of showing your actions, by providing that picture of that ball. On top of that, you’ll save time.

Do not care about ControlIDs

  • When you’re doing development of your product, do not care about ControlIDs, and just leave the Offset ID to the default value of 0. This way, when merging, you will receive nice notifications, saying both you and Microsoft have added functions in that objects. You can use this feature to document all these places.

Hooks

  • Never apply the Hook pattern! Hooks will only reduce upgrade time. This means, you will only shortly enjoy using the Application Merge Utilities. The more you change in default application, the longer it takes to upgrade, the longer you will enjoy the toolkit!
  • This can be taken one level higher. Simply you are not hardcore if you do not use notepad to resolve all of the merge issues.

How to use RecRef

  • Why fuss around declaring specific table variables, just generalize, all you need is one, two, or perhaps three RecRef variables, with a few IFs and CASEs here and there for reflection, to carry you all the way.

Arguments

  • Using only a few arguments on the functions are a sign of a weak developer. Stick in as many arguments as possible on the function, even if you are not using them, they could be useful in the future.

Just another field / action

  • Thinking of the design is overrated, each problem can be solved by adding an additional field or the table/page or with adding another action. We all know this has worked well in the past.

Reusability

  • We have decided that each time we fix a bug, we now also explain how it can be applied as a pattern. We then use anti-virus software to search for these patterns, to make sure we do not re-introduce these bugs anywhere else in Microsoft Dynamics NAV.

Business logic placement

  • As a best practice, we have also decided to move code into pages. Business logic does not belong in tables and codeunits; instead pages should know and be aware of the context and update it accordingly. As opposed to tables and codeunits, pages are aware of the context. 

Conclusion

As the last thing, we are fully aware that this pattern would not have been approved on any other day than April 1st, and we guarantee that on no other days would we support this pattern. Happy April Fools’ Day! 

Disclaimer: this pattern is inspired from IETF documentation published on April 1st, like for example the revolutionizing IP over Avian Carriers standard.

 

Best regards,

Bogdana Botez, Andreas Moth, Elly Nkya, Nikola Kukrika, and Eric Wauters 

Comments (20)

  1. Agi Harrar says:

    Well done…. Made me giggle !!!!!!

  2. Joerg, South Germany says:

    Love it: find a heavily used table…

  3. Jose says:

    For a second there I was like: Ok NAV Team, I am seriously going to disagree here, but then I got to the bottom or the article and realized the day. Hahaha 🙂

  4. Shane Gooseman says:

    Its hard to see, that many developers work exactly like this. Only exception is the recref var. They do not know or dont understand.

  5. Phil says:

    Love it.  Whenever I don't know how long a field should be, I just make it Text 250!!!

  6. Natalie K. says:

    Very good! 😀

    But talking about the code structure: you should stress that using single, big functions provide self-repeating code lines. This is good, because else it looks like you are a lazy programmer. The more code, the better!

  7. Pallea says:

    Also remember to use short variable names like A, B, C etc. writing code with short variable names makes typing just so much faster.

  8. Bogdana Botez says:

    These are great suggestions, we'll try to implement them in the next cumulative updates.

  9. D. Mitrov says:

    Don't forget to add at least one line of comment for each line of code!

    // Show a message with '1st of April'

    MESSAGE('1st of April!');

  10. Chad says:

    I hope to hear more about this at Direction US!!!

  11. Johannes Sebastian at Agidon.dk says:

    This is great, much better than "Google Panda" and MS DOS for Windows Phone. But then, I'm biased 🙂

    You forgot:

    – Don't do versioning, leave every object marked as Modified, this serves as documentation of the changes.

    – Do not disable base code, simply Delete it. This saves valuable disk space.

  12. dtacconi says:

    REDUCING THE DATABASE SIZE

    a. Export all List and Card Pages

    b. Add a DELETEALL statement on every OnOpenPage trigger

    c. Import back the object (save and compile)

  13. Jurica Bogunovic says:

    Declare globals and locals with same name. Guaranteed to provide hours of fun trying to figure out why the code doesn't work.

  14. Mirko Mainetti says:

    Try to customize the item trackin module. Good luck bros.

  15. Good job, great timesaver! This documents a lot of undocumented features in just one single blog post!

  16. xga says:

    Well done 😉

    And don't forget to extend every Customer/Vendor text fields… run Forrest run !

  17. Sascha Lindebaum says:

    🙂 Good one… but you could indeed merge (almost) "everything" from the localized build into W1… at least everything which is not really country specific  

  18. Michael says:

    very good –

    Why only on the 1st of April 😉 😉

    hahahah…

  19. Benjamin Hochstetter says:

    I Found a place where parts of this "Bestpractice" is used (NAV2015)

    Page 46; 47; 54

      Type – OnValidate     : TypeChosen := Type <> Type::" "; SetLocationCodeMandatory;

      OnAfterGetCurrRecord  : TypeChosen := Type <> Type::" "; SetLocationCodeMandatory; (sometime; sometimes it is forgotten)

    Makes 3 * 2 = 6 Places and several possibilities to forget something to adjust;

    Please move it into a Codeunit.

    Thanks in advance,

    Benjamin

  20. bogdanabotez says:

    @Benjamin, this is a good point. It hints to what Jan had said in his comment that I liked most so far. This stuff is hypothetical, but inspired from the authors' real work situations and real code-reviews/discussions, yes. That's why it's so good I think. NAV being a product of many years and many developers, it grew to have areas of good design, and areas which can be better. We prioritize work and fix stuff as we go (because we need to ship new features too – you probably wouldn't like a release with zero new features). So hang in there, because developers here on this side think the same as you do. I've added Benjamin's issue on my follow-up list.

Skip to main content