The extensibility story

The extensibility story

This is the story of one of the major steps towards creating a cloud-based ERP system: How we changed X++ from being a customizable language to an extensible language. This lifted the product I’m most passionate about into the modern age. I know many others share this passion and are curious about how this happened. I’m frequently asked questions about this, which inspired me to write the story. If you are curious, this story is for you.?The story is told from my point of view, an engineer in the SCM team.?For full visibility other key players should tell their story too.

To respect privacy, I’ve excluded names in this story, unless the individual already is a public Microsoft figure, for example a Blogger. Would you like your name included, just reach out to me.

What success can look like

It is January. 2019. We are in a packed conference room in Bellevue, WA. About 100 people gathered for the yearly ISV Summit. I’m on stage giving an update on Extensibility: What’s new, what have we accomplished since last, and announce break-out sessions later in the day. The usual deal. About 5 minutes into the talk a gentleman from the audience interrupted me. He wanted to thank me and my team for having solved the problem, and I’m greeted with a spontaneous applause. I’m happy my team is standing in the back of the room to hear this unexpected appraisal. I was unsure how to react, if I remember correctly, I completed the rest of my presentation quickly.??

Later in the day, we hosted two break-out sessions on extensibility: Bring your issues, and we will guide you.?No one showed up. Apparently, there were no more issues or significant concerns. We had made it. A 3-year journey was over. Standing alone in the meeting room, a sense of fulfillment and accomplishment rushed through me.

Where it started

Let’s rewind time to 2016. Dynamics AX7.0 was just released. It was a massive effort to bring the on-premises AX2012 R3 to a cloud hosted environment. But that is a story for another day. ?I’m having my very first week of DRI duty. It is a week of 24-7 support for all FnO customers. If something is wrong for any SCM customer, I need to solve it. Day or night.?It is easily the worst week of my life. Perhaps I’m just privileged. During the week I had several calls during the night. Stumbling out of bed, connected my laptop, and started to troubleshoot whatever the problem was. It was often a fruitless exercise. Sometimes it was a problem we already fixed in a later version – but the customer was stuck on a previous version for whatever reason. Sometimes it was a problem caused by a customization, or at least so it seemed.?In reality each customer had their own version of the system, with their own source code and implementation. Anything could be edited. As a supporter that was a nightmare – we didn’t even have access to the source code.?Despite lack of sleep, it was clear that improvements of the situation were needed.

Around the same time James Philips wrote an internal memo, introducing the “OneVersion” vision. “Every customer on the latest release, always” by April 2019. ??While I do love challenges, this one seemed outrageous. How is that even possible and still keep the rich ecosystem of solutions? We have a unicorn of a product. How can that be protected??

I can only imagine what the engineers thought when JFK gave his “Man on the moon before the end of the decade” speech. I think I went through similar motions for several months, two voices in my head having an argument. One saying: “This is so amazing” and one saying: “This will never happen”.

Luckily James and his leadership team recognized the challenges and freed up capacity to tackle this problem head on. I was included from the SCM side. We started by identifying the problems to solve.

My mind map

To get every customer on the latest solution, we must be able to upgrade them seamlessly and automatically. This meant no human intervention, which excluded merging of source code. To avoid merging, we had to prevent customers and partners from editing Microsoft source code, aka intrusive customization.??However, that is only half the problem. If each version is not backwards compatible, then customers cannot upgrade anyway, and we failed. For Microsoft, this would add significant constraints to what we could do going forward.

A landscape of the problem space unfolded and is captured in this mind map. It slowly expanded on the journey.

No alt text provided for this image

We started slowly to refactor code proactively, mostly around base enums where CAR (Customization Analysis Reports) told us there were many overlayerings. Meanwhile we prepared an official announcement of our plans to seal the application – first a soft seal and then a hard seal. Ultimately preventing customers, partners and ISVs from changing Microsoft X++ code.

The 2017 ISV Summit and Technical Conference

In January 2017 we shared our intentions externally for the first time. Most reacted with a can-do attitude understanding and appreciating the direction the product was moving. This became the main topic for ISV summit – dawn to dusk breakout sessions discussing implications and concerns. Parallel tracks and overflow rooms where required to accommodate the demand.

Lots of concerns were raised and we were busy taking notes. One statement that stuck with me was: “This is impossible, as we need custom inventory dimensions”. I must admit that at the time I shared the sentiment. Our na?ve answer to this was to add custom inventory dimensions on demand. Another concern was select statements in X++. They are compiled and not extensible – that would need a solution too.

The mountain ahead of us was taken shape, and the list of problems we had to solve kept growing.

At the following Technical Conference the official public announcement went out, and I started blogging about the situation, proving guidance and solutions to specific problems and describing new platform capabilities as they became available.?This made me the public face of this change, and I received mails from near and far from partners in the ecosystem. The change would make the system less flexible, and the passion about protecting the product and maintaining a flourishing ecosystem is one I share. In many aspects this product is a unicorn: Broad powerful functionality and extreme flexibility. These are rare in cloud solutions that are typically narrow and one-size-fits all. The feedback from partners were quite polar. Some being overly supportive, looking forward to the greener days with continuous updates. Some questioning the direction, fearing a world without a flexible ERP flagship product. ?In my team we valued each of these opportunities for engagements, and everyone got a reply. They enabled us to make decisions that would preserve the unicorn in the cloud.

Extensibility requests

The X++ code base needed significant rework, and we needed lock-step execution with partners to succeed.?To facilitate the communication Vanya Kashperuk set up a VSO instance to receive Extensibility requests from invited partners. This allowed us to learn where the Microsoft code was too rigid and didn’t allow partner solutions to integrate.

We started producing lists of what we refactored in each half yearly release. They were long.?At some point I sent them through a word cloud generator. Here are some of the results:

No alt text provided for this image

Chain of command

As an engineer caring deeply about code hygiene this project was dream coming true. Having a team chartered to refactor code is amazing. Typically, such activities need to be slipstreamed with business deliverables. Much to my despair I didn't like the refactoring we were doing.

At this point most of our extension points were provided via events. Solving an extension request involved introducing a delegate and raising the event. Introducing extra code, that wasn't tested. We spent hours debating and code reviewing this glue-code. It cluttered the code base, and for each we debated the values of only targeting the precise ask, or if being generic (at the risk of opening too much.) Knowing the pile of work ahead of us, we were going too slow and created a monster in the process.

One Thursday evening I used my lifeline and gave Peter Villadsen a call. We talked through the situation, and an idea started to form. Later same day Peter sent out the following mail. This is how Chain of Command started:

No alt text provided for this image

What started like an idea quickly became tangible. Peter and his team performed magic, and within a month a prototype was available. I’m fully confident that when I at some point look back at my career, then this invention will shine the brightest.?Considering that 60 years after object-oriented programming was invented, a new addition was introduced. Sure, it has some similarities with aspect-oriented programming – but also a lot of differences.?

In the following months this feature grew on all of us. It gracefully solved a series of problems we didn’t even consider originally, including how extensions can handle transactions, pass additional parameters downstream, and it merged nicely into the ExtensionOf classes that already existed and provided the ability for a stateful extension. All while not changing the API expose surface that we had to maintain for backwards compatibility. We knew we were on to something right. A term was coined for extending this way: "Wrapping". It belongs in the vocabulary right next to "overriding".

In SCM we had added our last event. Now extension requests were implemented using extract method refactoring – which resulted in Clean code. Many extension requests could now be rejected, as the capability came for free as protected and public methods supported chain of command automatically. Velocity picked up.

Inventory Dimensions

We were thrown a lifeline by an MVP partner. They proposed an ingenious approach to solving the inventory dimension problem. My team accepted the idea on the spot, and we started the long journey of refactoring the application to support the idea: Create 10 generic dimensions and allow them to be purposed at deployment time. Sharp focus was on execution, as we wanted to present the solution at the next ISV Summit. Over 800 methods got refactored. And the result was as good as we could have hoped for.?Previously, introducing a new inventory dimension for a partner would take 3-6 months.??At the ISV summit another MVP confirm doing the same in less than a 1 week with the new model, and without changing a single line of Microsoft’s X++ code. We even provided a sample implementation, introducing a new product dimension: “Flavor”.

Documentation

From the extensibility requests it became clear that we needed a better way of documenting the various solutions to the many different problems. So far, the only external facing documentation was on blogs. Internally we had a OneNote that was a gold mine. It didn’t really scale, we found ourselves spending lots of time giving similar replies as guidance to extensibility requests.?We needed official documentation.?This started another critical deliverable. Create a landing page documenting the extensibility knowledge for partners to extend our code as well as write extensible code themselves. Once it went online, we realized the vacuum in the market this filled. The number of daily page views was staggering. New contents got added on a weekly basis and today over 50 topics are covered – enough material for a book.

The 2018 ISV Summit

The atmosphere was changed, I believe chain of command did the trick. The generic inventory dimensions helped too. Many other application areas had been significantly redesigned to support extensibility, including price discounts and warehouse mobile flows.??

I left the summit with a feeling that we could succeed with this plan, and perhaps even on time. At this point we just needed to focus and keep up with the steady inflow of extensibility requests.

A few months later we released version 8.0, kicking off a new era for X++ customizations.

SysDa

One problem that still needed solving was the X++ select statements. Peter Villadsen provided the key to the solution. X++ select statements are compiled into a document object model. Suppose we exposed that to X++ - then we would have a rich API for creating select statement, and it would have full feature and performance parity. The data access framework, aka SysDA, was born, and a pile of parked extensibility requests could be solved.

X++ the most extensible language on the planet

No alt text provided for this image

A lot can be said about creating, owning, and maintaining a language. The cost is huge, for a small language like X++ investments are sparse. X++ will always trail behind mainstream languages like C# when it comes to tooling, performance, robustness, conciseness, and many other desirable aspects.?However, the freedom to innovate can be priceless, and in this short period of time X++ leaped forward. I will not hesitate to call X++ the most extensible language on the planet.

Getting to version 10.0

The ecosystem of ISV, partners and customer has always been a core strength of Dynamics for Finance and Operations. With the platform in place to support extensible solutions, we needed to enable partners and ISVs to migrate their solution.

Extensibility requests could now be logged via LCS. And we entered a race mode.?We wanted to enable as many solutions as possible to be overlayer free by April 2019 – the date from the memo.

We were tracking throughput, inflow, outflow and burndown. A race against time, each refactoring improving the code base and enabling a new scenario for customers.

To accelerate progress further, we invited a few ISVs with highly intrusive solutions to join us at the Microsoft campus in Lyngby and be part of our daily scrum teams for a period of about one month each. This allowed us to work closely together to find and implement the required refactoring to support their code bases.??Lots of learning and experiences were shared and new friendships were formed.

Don’t break anyone

While churning code, we were thinking about how to avoid breaking APIs and there-by solutions that had migrated.??Our first mantra was “Don’t break anything”.?The key was a compatibility checker. A small tool that would verify each pull request against a baseline, and if it detected breaking changes the merge would fail.

The compatibility checker tool was later released so partners and ISVs can provide the same guarantee to consumers depending on their assemblies.

Our analysis revealed that 90% of all methods were exposed, and thus couldn’t be changed under this model. This would severely hamper our ability to innovate. To counter act this, we introduced Internal and Protected internal. This enabled us to introduce new code while maintaining the freedom to refactor. At least until the first extensibility requests arrived. (Joris de Gruyter and team have recently been tightening up a few loose ends.)

No alt text provided for this image

Another analysis revealed that of all the exposed APIs less than 15% were referenced externally. In other words, we could change the majority without breaking anyone, if just we knew what was referenced externally.?A new idea was born.

No alt text provided for this image

We started including cross-reference information in the deployable packages. When a deployable package was uploaded to AppSource, a pipeline would aggregate the information, and feed it directly to CodeLens in Visual Studio, for each Microsoft engineer to see.

Here is an example. The method “futureValue()” has no known external (or internal) use, whereas “getCompany()” does.

No alt text provided for this image

This information enabled us to create a process for making changes to a subset of public and protected method. Each going through a governance approval process requiring proper justification and risk assessment.

Release Validation Program (RVP)

Being binary compatible is a good foundation. It ensures that binary references will resolve correctly on a live system when Microsoft assemblies are being updated as part of an upgrade cycle.

But why not aspire higher? Most changes are for a reason. Even fixing a product defect is about replacing one system behavior with another. With new releases being pushed out, businesses could have a logical dependency on the previous behavior.?To enable customers to detect such situations early we introduced the RVP program, where recorded tests will be executed on customer’s data and binaries, to detect impactful changes early on. ??I can recommend joining the program.

One version

This brings us to March 2019 and near the end of this story. Version 10.0 is ready for release. The release frequency will be increased from twice per year to 8 releases per year, we call them monthly updates.???

The Extensibility team is gathered in a restaurant in Bellevue. The food is excellent. The mood is high, and the company is even better. We are talking about the journey, for hours without end. We know that when we leave the restaurant, it will be the last time we are all together.

Today

As I’m writing this text late in 2021, we are having feature complete of version 10.0.25 this week.?We have released 25 versions publicly. 8 releases every year. All binary compatible. All allowing customers to upgrade seamlessly.?Each of our customers benefit from being on one of the latest releases always.??Sure, there have been a few misses over the years. Each a problem, but all something that we could solved timely, and each offering an opportunity for further learning and improvement. Now customers get the benefits of being on a proven and tested version, with all the latest product improvements.

Over 10,000 extensibility requests have been logged since we started. Thank you! We have answered each of them. The distribution across application areas is: SCM: 56%, GFM: 20%, SI, Retail and AXL <10 %. ??I’m humbled being part of the team that moved this mountain.

Supporting customers is much easier now. I’m indeed DRI today – no calls so far, and should my attention be needed, I know the customer will be running the same source code as all other customers. I’m prepared.

??

Michael Fruergaard Pontoppidan

December 2021


PS. Please share your story too.


Manish Moothedath

Digital Architect, Microsoft platform & Business applications (Dynamics 365, Power Platform, Azure)

9 个月

Truly amazing!!

回复
Vladimir Pavlovskiy

Microsoft Dynamics 365 Software developer

3 年

I have a question about SysDA , you said that select statements are fixed and you were looking for a solution how to make them more dynamic and extensible, on the other hand we already had query::delete_recordset, query::update_recordset and query::insert_recordset, which are three methods and good alternative for SysDA. From my understanding these Query methods are much easier to use. For example you can create a method which returns a query and then delete everything calling query static method: Query query = MyISVClass::myMethodReturnsQuery(); query::delete_recordset(query); Anyone can later extend MyISVClass::myMethodReturnsQuery and add more login to the query, same goes with query::update_recordset and query::insert_recordset. This makes them dynamic and not fixed. I have seen query::insert_recordset long before SysDA were introduced(in 2012 already). And from my understanding SysDA and query methods serve save purpose. But of course query methods cannot give you select statement to go through the records. Like with SysDA using next()

回复
Muhammad Shoaib

Dynamics 365 CE, CRM, F&O /Power Platform Specialist - Ex Microsoft

3 年

Truly Amazing Journey, I love extensibility of X++

回复
Ben Yu

Head of Engineering - Customer Experience

3 年

What a great story to tell, congrats Michael Pontoppidan and Peter Villadsen to accomplish this "impossible" mission. I also remember the Base Camp days Morten Jensen mentioned.

Einar Hagalín Láruson (Lobbi)

D365 & Power Platform SWAT Commander | Evangelist, Founder & Leader of the Power Platform UG Iceland | Speaker | Lover of the Community

3 年

This evolution is one of the greatest and most successful since the beginning of the ERP days. Great work guys

要查看或添加评论,请登录

Michael Pontoppidan的更多文章

  • My favorite 2024 X++ Improvements

    My favorite 2024 X++ Improvements

    Every year brings new improvements to X++ developers, and 2024 is no exception. On behalf of all X++ developers: Thank…

    13 条评论
  • Warehouse Inventory Transactions - what are you waiting for?

    Warehouse Inventory Transactions - what are you waiting for?

    The single largest performance optimization for D365 SCM Warehouse Management during my time in D365 Supply Chain…

    12 条评论
  • WMA protocol improvements

    WMA protocol improvements

    If you like the technical bits of what happens under the hood, then this article is for you. If not; all you need to…

    7 条评论
  • Do you listen to yourself?

    Do you listen to yourself?

    I'm invincible, I can do anything, my body is a perpetual machine, my mind is a fortress. Sounds familiar? To me it…

    3 条评论
  • Extensibility - Fact Check

    Extensibility - Fact Check

    Introduction Recently, I participated in a longer online conversation with a group of skilled Dynamics partners. The…

    12 条评论
  • X++ Exceptions and Transactions

    X++ Exceptions and Transactions

    Have you ever wondered why the heck transaction scopes in X++ are tied to exceptions? Technically they are two…

    5 条评论
  • A truly extensible warehouse

    A truly extensible warehouse

    One size never fits all - selecting a warehouse solution that can be modeled to your needs and grow with you for years…

    2 条评论
  • How do you balance learning wishes and business needs?

    How do you balance learning wishes and business needs?

    I'm preparing for a manager symposium, where I'm to answer a couple of questions as part of a panel discussion on…

    6 条评论
  • Unleash your warehouse telemetry super-powers today!

    Unleash your warehouse telemetry super-powers today!

    Today is the day. Your can now experience the same insight as I recently wrote about in Warehouse Management -…

    13 条评论
  • Warehouse Location Directives in 10.0.31

    Warehouse Location Directives in 10.0.31

    If you don't know what location directives are - just move on in your feed. If on the other hand, you ever configured a…

    24 条评论

社区洞察

其他会员也浏览了