I initially meant to finish the universal operation and design level status reporting accompanied with techical requirement enforcing. I meant to go for the modularity then afterwards; however as we already start to have multiple demonstrations and as I’ve claimed the 100% true reusability, I simply had to implement sharing and modularity first.
Instead of trying to prioritize different project and demonstrational requirements, adding true sharing and modularity solved these issues for me. Videos to follow within few days, let me present the outcome briefly (available at GitHub partially, full demo coming up also in few days).
When thinking about sharing and modularity, I realized that the originally simple abstractions needed to change into somewhat more complex – as the generators needed to be separated from the input and output content. Adding modularity to the package added also another requirement to be able to run generators in specific order.
Now I didn’t want to ruin the simplicity in the original “just-start-using” idea, where everything about single abstraction is contained under single folder hierarchy. So instead of making all the abstractions shared and modular, I designed a model where abstractions can switch their type and behave a little differently in each mode, but are effectively logically the same. The types are Local, Shared and Modular.
Local (replacing guidance and how-to)
This is the simplest form. The one that current Codeplex demonstrations are all about. Simply using one folder structure, everything in one source code repository.
Local abstractions are transformed within the Visual Studio’s mechanism, at .tt file save or with “Transform All Templates”. Or in other words, are not preprocessed T4 templates.
When creating completely new abstraction(s); they are the simplest done first as local, as the project has no responsibility to others. After the abstraction is at least a bit matured in practice and then made shared, the likelihood of it radically changing is much smaller.
Shared (replacing libraries, shared code and shared frameworks)
This is basically the same as local, except that the input and output are not read and generated alongside the abstraction itself, but in parallel directory structure under “AbstractionContent” project. Source control can thus separate the abstraction itself from its content.
Shared abstraction generators are alike Local; not preprocessed T4 templates.
Sharing abstractions will keep them also auto-updated organization or even open-source community wide. This updating is made in completely safe fashion, as the shared abstractions published from source code repositories have full history. This means that breaking change within the update can be rolled back.
Also because abstractions are logical blocks, the changes mostly revolve around their generators and not break the actual higher level of abstraction where all the design-level work is done.
Finally, as the abstractions and their generators are distributed in fully open source form, for any need (be it bugfix or new feature) the shared abstractions can and should be in-place modified when appropriate. These changes can be pushed back to the shared repositories (made as pull requests) so that the original provider can choose to accept the modification or fix as-is.
Modular (no current universal or even wide-accepted alternative)
Combining modules based on pure design-level information that has no platform dependency simply binds different abstractions together. When done with specific type of “transform” abstractions, the combinations can be formed without any single abstraction causing difficult-to-maintain dependency.
Modular abstractions require preprocessed T4 templates and actual generator-order controlling “build chain”, but for the power they bring, this is fairly acceptable. After all, the actual abstractions are still as simple as before, but their input-output and generation order simply needs to be controlled to allow correct information flow between them.
For simplest example, using abstracted object-oriented class, modular abstractions can contain logic that perform calculations and other logical operations against the design level model.
OrderRow.Price = OrderRow.Product.Price * OrderRow.ItemCount;
or in Java (through the platform-specific generator(s)
OrderRow.setPrice(OrderRow.getProduct().getPrice() * OrderRow.getItemCount());
As long as in the design model has OrderRow (with related Product and ItemCount property) and Product (with Price property), regardless what else is there, the logic above works and compiles as normal.
Accompanying Modular with Universal Logical Operation presents a way to build software from logical blocks, where each block in the entire tree of logical operations can be hand-picked.
But more of that with concrete demonstrations and videos soon.
For those eager to look, the repositories are found (and updated at):
The “abscommon” is required for all the abstractions, “absbuilder” and “absconfig” are required for modular abstractions. The other ones ending with “ABS” and “TRANS” are the actual abstractions; the work is still in process of transforming these. Some old demonstrational repositories are still hanging around; if the name does not start with “abs” or end with “ABS” or “TRANS” it’s some old (and outdated) demonstration.
I’ll provide demonstrational solution soon, but basically all the abstractions are placed under same folder; the same folder is supposed to contain AbstractionContent subfolder as well, that is project-specific content for the abstractions.