Thursday, October 31, 2019

Pushing, Dragging or Pulling an Industry Forward

Quite a few years ago, in my previous job when I was an MVP still, I did an online webinar for the AXUG called "Putting Software Engineering back in Dynamics AX" (in 2014). Admittedly it was somewhat of a rant / soap box type of talk. I guess "food for thought" would be a more optimistic characterization. I did try to inject some humor into the otherwise ranty slides by adding some graphics. At the time we were building out our X++ development team and we were heavily vested in TFS and automation, and I was very keen on sharing our lightbulb moments and those "why did we only start doing this now" revelations.

Fast forward 5 years to a new generation of technology and a shift to cloud. In fairness, many more people are engaged in some of these topics now because the product finally has features out of the box to do builds, use source control without tons of headaches and setup, etc. But contrary to the advice on one of the original slides from 2014 that said "Bring software engineering into AX, not the opposite" - it sort of feels that is exactly what has happened. People projecting their AX processes onto some software engineering processes. Sometimes ending up with procedures and technology for the sake of it, and not actually solving any problems at all and sometimes even creating more problems. But, they can say they ticked another checkbox on the list. I have stories of customers with messed up code in production, because someone setup branching because they were told that's a good thing to have. Yet nobody knew what that meant or how to use it. So code was being checked into branches left and right, merged in whichever direction. Chaos. A perfect example of implementing something without having a good reason or understanding to do so. On the flipside, we have customers calling us up because they "redeployed" their dev VM, and want to know how they can get a clean copy of their code from production back into their VM. Now, part of that is legacy thinking and not understanding the technology change. But honestly that was never a good thing in older versions either.

Anyway, that brings us to my topic du jour. As you may or may not have heard and read, we're working on elevating the developers tools further. We'll become more standard Visual Studio, standard Azure DevOps. This is all great news as it will allow X++ developers to use more of the existing tools out there that can be used for any standardized .NET languages or tools. The problem is not that we'll be forcing people to use advanced tools they don't know how to use. They can still choose to not use source control or build automation. I'm more worried about the people using all these new tools and not understanding them. What if in the future we start supporting Git? Will our support team be overwhelmed with people stuck on branching, merging, PRs, rebasing and all the great but complex features of decentralized source control? We've never dealt with situations where we "support" the technology (i.e. the tools are compatible) but we won't support the user of that technology (sorry your production code got messed up, go get some training on Git branching and good luck to you on recovering your production environment). In the history of our product, we've never drawn a big line between technical compatibility but not supporting the usage of it. But we will have to. How about other areas, like PowerBI, PowerApps, etc.? Yes they are supported and will be integrated further, but will Dynamics 365 support answer your usage questions?

I've had frank discussions with developers (that I personally know), where I basically tell them "the fact you're asking me these questions tells me you shouldn't be doing this". But that's not an attitude we can broadly apply to our customer base.

So I ask YOU, dear audience. Where and how can we draw a line of supportability?

Friday, October 11, 2019

Debugging woes with symbols: bug or feature?

I've struggled with this myself for a while during the betas of "AX7". Sometimes, symbols aren't loaded for your code and your breakpoints aren't hit. It's clear that the Dynamics 365 option "Only load symbols for your solution" has something to do with it, but still there's strange behavior. It took me a few years at Microsoft for someone to explain the exact logic there. Since I've been sitting on this knowledge for a while and I've recently ran into some customer calls where debugging trouble was brought up, I realized it's overdue for me to share this knowledge.

Summary: it's in fact a feature, not a bug. But I would like to see this behavior changed assuming we don't introduce performance regressions.

There's a piece of compiler background information that is not well understood which is actually at the root of this problem. We all know there are two ways to compile your code: from the Dynamics 365 "Full build" menu, or from the project. The project build, if you right-click on your project, has two options: build and rebuild. Now, the "rebuild" feature does NOT do the same thing as the full build menu - and that is the crux of the issue here. Both build and rebuild from the project only compile the objects in your project. Rebuild will force a build of everything in your project but not the whole package it belongs to. To do this, our Visual Studio tools and the compiler make good use of netmodules for .NET assemblies. Think of a netmodule as a sub-assembly of an assembly, I guess.

Now, the point is this. The "load symbols only for your solution" option only loads the symbols of the binaries for the objects in your project - aka the netmodules. So when you do a full build from the Dynamics 365 menu, you actually HAVE NO symbols only for the objects in your project (only the full binary of the package). And as a result after doing a full build and debugging with the "symbols for solution only" option turned on, your breakpoints will NOT be hit due to the symbols not having loaded.

I think we should change this option to work more like "load symbols for the packages containing your solution's objects" or something to that effect. We'll have to see if that affects the performance for large packages in a significant way, since it will now load all the symbols for that package. That is ultimately why this feature was introduced (see? it's a feature!). Worst case we may need a new option so you can use the old behavior or the more inclusive behavior...

I'd love to hear your thoughts on this, here or on Twitter @JorisdG.