Initially, the package split can be thought of in three main areas: the platform, the foundation, and the application. The platform is all the essential AX platform pieces that are not in the kernel but in X++, yet they are essential to the AX platform. Things like the users tables and the form to create and maintain those users. The foundation contains basic features that most of the application code will depend on. Things like the number sequence functionality. Finally, the application itself, which is all the business logic. Although you can think of those big three, the "application suite" as the package is called is slowly being split up further. You'll see packages like "general ledger" and "dimensions" that have been split off from the application suite. In a sense they sit in between the foundation and the application suite, because they are application logic but they are shared between different modules and functionalities.
So what is the use of having these separate packages? In a nutshell, it's all about maintainability and serviceability. As we discussed in the paradigm articles, having code in packages as opposed to a huge monolithic code base allows for faster compiles (since you're only compiling the code for your package / .NET assembly). Whereas AX 2012 and before would either require you to compile the whole application (or, in case you're into bad practices, take the risk of importing an XPO and just compiling forward or something), the new AX decreases the compile and deployment time needed by splitting up the code into packages (even though the compiler is already significantly faster than previous versions thanks to a rewrite). This has clear advantages during development (for example, being able to do continuous integration or gated check-ins, which is very difficult if your build takes 30 minutes or more. But it also has advantages for deployment, and testing. It's clear that a split in smaller packages means smaller and faster compiles and smaller and faster deployments. But considering that you cannot over-layer from one package to another and packages reference each other as .NET assemblies (DLLs), it means you can replace and update packages independently, as long as the API to its functionality doesn't change. Yes, I said API :-)
If you look at a dependency graph of the packages in the new AX, you'll find that the packages at the bottom are more like APIs. An API for number sequences, and API for dimensions, etc. At the top end, you'll have the ultimate consumer of those APIs. The application suite and other packages, providing the end-user functionality of the business logic. If a hotfix is needed on the number sequence functionality, the foundation package can be hotfixed and replaced without requiring a re-compile or re-deployment of the application suite - provided none of its APIs changed (which wouldn't happen for a hotfix of course). It also wouldn't require any code upgrade, assuming there are no over-layering models in the foundation package. And that is the gotcha…
Below a "simplified" view of the standard package hierarchy in AX7. Some packages were left out to show the idea. Since packages "reference" each other like normal .NET assemblies, the references are not transitive and usually the package at a "higher" layer needs to reference some of the lower layer packages as well. But clearly, everything references platform, some reference foundation, and it goes up from there.
So, to avoid over-layering and also keep one's code in a separate package to facilitate quick compiles and easy deployments of custom code, what is a X++ developer to do? That, my friends, is where extensions come into play. To be continued…
- 查询函数：SysQueryRangeUtil 扩展 / Query Functions: SysQueryRangeUtil Extensions
- 改变思维定势-转向扩展 /Moving to Extensions is Changing Your Mindset
- 包和模型 / Beating the Drum on Packages and Models
- 代码扩展 / Accidental Code Extensions
- 安装修补程序 – 准备vs应用 / Installing Hotfixes – Prepare vs Apply
- PSA: AX7 生成 Packages / Model 导出时编译错误 / PSA: AX7 Build Failure on Generate Packages / Model Export