07-01-2026 10:37 AM
Hey guys,
I have now been working for several years with Actor Framework and I have created multiple Frameworks for larger applications using a packed lib version of AF. The main goals are modularity, reusability and maintainability. The frameworks are heavily using multiple PPLs like driver and service libs that we can share among the team. The application uses a big amount of actors that each have their own tasks.
In order to provide among other things shared debugging, logging and error handling code I have always used inheritance with base classes that provide this code.
I know that composition is the path to choose here, but I really struggle how I can implement this correctly using AF. This is in my opinion especially tricky if I want to outsource actor related tasks like launching nested actors to compositional classes that can e.g. be plugged into an interface slot of some actor. I see that there is the possibility to outsource each module into a separate actor, but when looking at a large scale app with 30 Actors running, each then having 10 subactors, this would increase the amount actors quite a lot.
Now I found some solutions but they look really bad, cause quite some heavy effort and are mostly requiring some knowledge for the application developer to know how to setup the code.
I tried to find best practices in the web, but failed completely. So I was hoping maybe you can give me a hint to those resources. I am not looking for beginner tutorials as I basically know what the fuss is all about. I would rather like to see code that is suited for large scale applications and the things around like how to make structure actors in ppls so that they fit the open-closed principle quite well.
Thanks in advance!
07-01-2026 11:02 AM
(Mainly commenting so I'm subscribed to the thread, but I can offer some advice.)
The Actor tree itself already has "composition" sort of built into it. Nested actors aren't inherited, so that doesn't count against you there.
Could you give some specific examples where you're inheriting now, but would like to composite?
Since the AF is already a framework, you'll need to add a level somewhere to implement your modularity. Two obvious ways are 1- use the Decorator pattern, which doesn't affect your AF itself but requires some boilerplate code, or 2- add an intermediate level at the top of your tree that all of your Actors inherit from.
That intermediary level will contain all of your composition stuff.
Also, one thing I continually struggle with is trying to make too many things into Actors. I get into that mindset and reflexively create Actors instead of Objects. If your module doesn't need an asynchronous message handling loop, don't give it one. Just make it a regular Object. For debugging stuff, a normal by-ref Object can be shared and used by lots of separate processes.
07-01-2026 12:31 PM
You see this because native AF itself mixes different responsibilities into a single class. You still can adapt behaviour but it ends in more wordy/ugly code than necessary. This is why I tend to encourage you not to change your current style since it reads like a reasonable tradeoff.
07-02-2026 02:47 AM
I agree with this too.
Ok composition is better than inheritance when it comes to coupling but I find it more cumbersome to deal with it in LabVIEW, especially when not using "by ref" classes.
You need to use In Place Element Structures (IPES), but then you don't have the actor class wire inside of it. Also it takes more effort to use an IPES than UBN / BBN, but you end up copying the class member when using it which is less efficient since it's a "by value" class...
In a text based programming language its way easier since you can just call the member with the dot notation (eg: self.logger.log("hello")).
For things as generic as debugging, logging and error handling I think inheritance is the way to go since most of your actors will end up using it anyway.
With composition, you'll end up with code duplication and boilerplate. This can be mitigated with VI scripting / template but it has it's limits.
For the record, I developed an AF / PPL based application template for my team using the following inheritance tree:
- LabVIEW Object
- Actor Framework
- Abstract Process (logging, actor naming, async wait, generic message)
- MGI Panel Actor (window, subpanel)
- Abstract Screen (user mgt, translation, theme, FP control map, generic user event message, ...)
(In the futur I plan to merge MGI Panel Actor and Abstract Screen since I never create a direct child actor of MGI Actor. And both are UI related. It'll simplify the inheritance tree quite a bit.)
In my application, my actors inherit either from Abstract Process or Abstract Screen and then use composition for everything else.
This is my opinion after a few years using AF and PPL, but I haven't tried a lot of architectures and I would be glad to change my mind about it.
07-02-2026 04:23 AM - edited 07-02-2026 04:29 AM
@BertMcMahan:
Ok I see I need to spend more time in clarifying my chaotic thoughts 😅
I tried to create two diagrams that should demonstrate my thoughts, I hope they help.
The first one shows a quick sketch and excerpt of the inheritance based hierarchy on the left and the way I would love to solve it on the right hand side. I would use interfaces as some kind of flexible slots which I then compose using some builders. But everytime I try, I stumble over the questions on the right.
This diagram shows the current structure vs. how I was thinking to create the composition but also what questions arose
The diagram below shows the task that made me think about the whole thing. I have an AF based library where an actor is launched and I wanted to launch it as a part of the framework in a clean way. I tried different things but somehow it was all very ugly. I have the code for this shared lib and I am able to modify it, but as it is already in use in different Frameworks I would like to prevent this lib having a dependency to the Framework lib.
I think the decorator pattern would somehow be the right one here if I would not have the possibility to change the code. But as I have the possibility to change it I thought the composition based approach would be the better one...
I began to think about this when trying to integrate a shared lib in a clean way
My problem is also that I feel it is very hard for me to translate best practice design patterns from text based languages to LabVIEW. Some are quite easy but some offer a big amount of possibilities and I always feel like forgetting something that I begin to realize after hours of refactoring.
So thanks for the feedback already.
07-02-2026 04:29 AM - edited 07-02-2026 04:30 AM
@thomas-allibe
Ok thanks for the insight. This seems to be very reasonable. Did you also experience higher IDE loading and editing times when using your AF/PPL structure? This is also something I struggle with. An idea was to somehow prevent LabVIEW to always scan all Dynamic dispatch members by using interfaces and components. But then I am coming again to my questions as shown in my diagrams above.
07-02-2026 06:58 AM - edited 07-02-2026 07:00 AM
@Jenso wrote:
@thomas-allibe
Ok thanks for the insight. This seems to be very reasonable. Did you also experience higher IDE loading and editing times when using your AF/PPL structure? This is also something I struggle with. An idea was to somehow prevent LabVIEW to always scan all Dynamic dispatch members by using interfaces and components. But then I am coming again to my questions as shown in my diagrams above.
Yes, and I wish I knew it sooner that LabVIEW slows down quite a lot when a lot of classes are involved.
The most effective solution is simply to make less actor messages. I made two changes to my application to achieve this:
Also, this helps a little Slow Editor Performance with Large LabVIEW Projects Containing Many Classes - NI.
07-02-2026 07:17 AM
OK thanks for that. I also did quite some research after falling into that trap. Clearing mutation history is also something I stumbled upon, but the amount of classes still seems to be the major part.
I wrote a little tool helping me deleting mutation history for all classes in the current project (see attachment). Hope this helps somebody if in need.