Yup. Being heavily invested in Duet and RMS, any and all device communication modules I write strictly conform to SNAPI - makes my life incredibly easy when it comes to deployment.
After integrating with two Duet modules this past job, I'm seeing the value in SNAPI. Now only if I had a license for Duet I'd take full advantage of it . . . I am thinking about however using SNAPI in my NetLinx modules just for conformity sake.
Yep, SNAPI works well - sort of designed for it I suppose .
If you switch to rolling your modules in Duet that's where they really shine. You develop all your device communication modules to adhere to SNAPI for talking to NetLinx so that they can be used by anyone rolling code there without issue. Where it gets funky though is when you use OSGi to allow the 'modules' to talk to each other in Duet world. This lets you to do things like build a helper module that ties a display device's power/mute/input state to your signal distribution system (matrix switcher et al) - when there's signal it's on, when there's not its off, when there's a higher quality signal (DVI > CV etc) available use that, or do things like have a group of DSP modules work in unison (the AMX supplied ClearOne_ConvergeGateway implements this) and talk though the one physical device.
How many of you are using SNAPI for NetLinx module standards AND has anyone found any weird anomalies with SNAPI standards? I know the ENV-VST-C is a little odd because is sort of matches SNAPI. Converting my modules over to compliance with SNAPI is high on the list. Just wondering how others are handling it in their modules.
How many of you are using SNAPI for NetLinx module standards AND has anyone found any weird anomalies with SNAPI standards? I know the ENV-VST-C is a little odd because is sort of matches SNAPI. Converting my modules over to compliance with SNAPI is high on the list. Just wondering how others are handling it in their modules.
If you had a device and you knew you would never, ever need more that one would you create a module for comms or just create an include file for this device? If you would create a module is that out of habit, because it would be easier or because it would be better?
Actually, yes, I would. I have several boilerplate modules that I frequently modify with the device-specific code necessary. A simple RS-232 or IP device takes me less than an hour to implement this way, and all my queuing, buffering, debugging, and interface code is already done. I'm sure you have boilerplate includes that do the exact same thing. I simply find it easier to maintain them in module form. Just a personal preference choice.
It is all part of keeping my code as orthogonal as possible. This orthogonality is what makes it possible for me to customize the code for each job without introducing bugs or having to test every aspect of the code with each roll out. It is also the best reason to use modules.
Actually, yes, I would. I have several boilerplate modules that I frequently modify with the device-specific code necessary. A simple RS-232 or IP device takes me less than an hour to implement this way, and all my queuing, buffering, debugging, and interface code is already done. I'm sure you have boilerplate includes that do the exact same thing. I simply find it easier to maintain them in module form. Just a personal preference choice.
Yeah I have templates for my includes/modules too and like most folks I have includes specific to the devices which instatiate the modules for one or as many instances needed. I generally handle my modules in .axs form so for me the only difference is the file extension letters since they're both open source code in my workspace.
I get the lock down aspects, at first I didn't even think of that since I don't really care about such things anymore. I've come to realize I'm not competing against anyone doing AMX so I why should I care who has my code. Also if someone has my code and can make it better, more power to them.
Not that it really matters but modules also multiply the resources the code requires since vars, constants, functions etc are duplicated for every instance where in the include style it's just a matter of creating array to hold values for each device which happens to be what I do anyway when instantiating multiple modules.
Now I just started another modules for an Oppo DVD player and so far I doing it the traditonal method since it is easier because that's how I'm set up to work and I too busy right now to start thinking and trying to re-invent the wheel even if my version turns out to be square. I still think it would be easier to integrate into the main code and decrease the amout of resources the system uses.
How many of you are using SNAPI for NetLinx module standards AND has anyone found any weird anomalies with SNAPI standards? I know the ENV-VST-C is a little odd because is sort of matches SNAPI. Converting my modules over to compliance with SNAPI is high on the list. Just wondering how others are handling it in their modules.
I do not, but then again, I'm not writing my modules in DUET. I use the EMAPI.
I’m on the *modules are good* side of the fence for the same reasons that others have already stated and I have one other benefit to add that hasn’t been mentioned yet which is Token and Variable count.
There was a thread a couple of weeks ago or so where someone was getting close to exceeding the Token and Variable count limit of 100000. The program consisted of a whole bunch of include files and the count was in the 90K plus territory. I never paid much attention to the count so I was concerned that I might be running into the same problem and didn’t know it but when I recompiled some of my larger programs I couldn’t find one that exceeded 16000.
So I ran some tests trying to figure out how the count incremented. I started with a blank program and that gave me a Token and Variable count of 607. I then added a DEFINE_VARIABLE section and one variable and the count went to 609. Every variable I added after that incremented the count +1 and it didn’t matter what the size of the variable was. The larger variable used more memory but the count only went up by one.
Next I added a DEFINE_CONSTANT section and some constants and the count appeared to follow the same pattern as the variables.
I then added a DEFINE_TYPE section with one STRUCT that had one member and the count went up +3 and every additional intrinsic member to that struct incremented the count by 1.
I wanted to see what a DEFINE_FUNCTION would do and found out that an empty stub with no parameters incremented the count by +7.
I then tried on last define: DEFINE_MODULE and found out that DEFINE_MODULE costs nothing. It didn’t matter how many modules I added the Token and Variable count remained the same. The memory obviously increased but not the count.
When you compile a module you’ll see that the module gets its own set of 100000 variable and tokens which makes sense since a module is essentially a program in and of itself.
If you’re looking to create easily scalable systems, modules are a good way to go.
I’m on the *modules are good* side of the fence for the same reasons that others have already stated and I have one other benefit to add that hasn’t been mentioned yet which is Token and Variable count.
There was a thread a couple of weeks ago or so where someone was getting close to exceeding the Token and Variable count limit of 100000. The program consisted of a whole bunch of include files and the count was in the 90K plus territory. I never paid much attention to the count so I was concerned that I might be running into the same problem and didn’t know it but when I recompiled some of my larger programs I couldn’t find one that exceeded 16000.
So I ran some tests trying to figure out how the count incremented. I started with a blank program and that gave me a Token and Variable count of 607. I then added a DEFINE_VARIABLE section and one variable and the count went to 609. Every variable I added after that incremented the count +1 and it didn’t matter what the size of the variable was. The larger variable used more memory but the count only went up by one.
Next I added a DEFINE_CONSTANT section and some constants and the count appeared to follow the same pattern as the variables.
I then added a DEFINE_TYPE section with one STRUCT that had one member and the count went up +3 and every additional intrinsic member to that struct incremented the count by 1.
I wanted to see what a DEFINE_FUNCTION would do and found out that an empty stub with no parameters incremented the count by +7.
I then tried on last define: DEFINE_MODULE and found out that DEFINE_MODULE costs nothing. It didn’t matter how many modules I added the Token and Variable count remained the same. The memory obviously increased but not the count.
When you compile a module you’ll see that the module gets its own set of 100000 variable and tokens which makes sense since a module is essentially a program in and of itself.
If you’re looking to create easily scalable systems, modules are a good way to go.
I would second this. One might derive from my earlier post that I'm anti-module but I'm not. In my case I use them ver extensively. They work like they work and that's it. I do not try to over code them and the number of things they do is very nitty-gritty. Where I find myself getting into hot wate with them is if I get lazy and start to let other program functionality creep into them due to lack of time and/or laziness. If I keep the comm modules 'comm modules' and nothing more, I'm usually very happy with them.
I do not tend to use modules for UI or most other over-arching program stuff. That's where I go to Includes. My includes tend to be copy/paste from other programs and then tweaked. My Main file is nothing more than a bunch of lnclude commands.
I tend to follow a typical C style model and all my code is in modules. I have no code in the Main source file outside of DEFINE_MODULE statements and whatever declarations are needed by them. All my code is in modules and all declarations (constants, devices, types, etc.) in include files. No code in includes outside of some helper functions I use. I also pass as much as possible to modules, like device id's, to promote portability.
I also kind of follow a loose MVC architecture in that I have device modules, UI modules and "master" modules that implement the higher levels of control. By using structures and meta-data I have been able to significantly reduce the amount of code I used to write, which makes flexibility and troubleshooting much easier. Also, I do everything in Events and Functions, my goal is no code in DEFINE_PROGRAM.
I have to say, includes drive me up the wall! This is certainly based on one very large and poor experience, but it has shown me that they can make coding really frustrating, cumbersome and slow to debug with - more than they are a help.
I have been looking after a client who has dozens of systems for a while now and they used to have an inboard programmer from the die-hard include paddock. With no disrespect intended, the code is so fragmented (more than half the trouble to be honest) that debug is a marathon (read: nightmare).
These particular codes have an include for *everything*. Devices, constants, variables, M_E, latches, define_call routines, and program elements like mode selections, source selections, lighting, even a helpful miscellaneous.axi, exit routines, feedback, you name it, it has .axi stuck to the end of it. On average, 25 includes per system.
But sadly the internal convention is not strict. Poor old miscellaneous.axi for instance has a couple of define_calls in it some random feedback just because - actually, I can't imagine why, but it does! Feedback can be found in most of the source.axi's, there are calls declared in the source includes and on and on the saga goes.
Instead of being able to surf through one file to look for a var etc, you have to potentially surf through all 25 includes, then have the presence of mind to remember where it was when you have to come back to it - perhaps even write down where it was if you have a mind as simple as mine.
There is no doubt this is a poorly disciplined code, but the resultant problem is a shocker. I have 'unincluded' plenty of the .axi files from a few of these sites back into a single .axs program simply for redability and ease of debug.
Having everything back in one file also helps NSX. Find now works well. Search and destroy now works well too.
I'm a big fan of includes but I simply use a single include per device. The includes hold code specific to the device and is used to instantiate the modules for that device. If vars have to be declared outside of the individual dev's .axi so they are accessible to .axi's included prior they go into the main under their own code folding header.
I agree over use of .axi's is a pain to follow and debug as you bounce from file to file trying to follow the logic but when you simply use a single include per device it's very simple and clean. I prefer to keep device specific stuff out of my main file and leave that for common/global stuff. The stuff that isn't for a specific device and doesn't make sense to turn into modules.
I have to say, includes drive me up the wall! This is certainly based on one very large and poor experience, but it has shown me that they can make coding really frustrating, cumbersome and slow to debug with - more than they are a help.
I have been looking after a client who has dozens of systems for a while now and they used to have an inboard programmer from the die-hard include paddock. With no disrespect intended, the code is so fragmented (more than half the trouble to be honest) that debug is a marathon (read: nightmare).
These particular codes have an include for *everything*. Devices, constants, variables, M_E, latches, define_call routines, and program elements like mode selections, source selections, lighting, even a helpful miscellaneous.axi, exit routines, feedback, you name it, it has .axi stuck to the end of it. On average, 25 includes per system.
But sadly the internal convention is not strict. Poor old miscellaneous.axi for instance has a couple of define_calls in it some random feedback just because - actually, I can't imagine why, but it does! Feedback can be found in most of the source.axi's, there are calls declared in the source includes and on and on the saga goes.
Instead of being able to surf through one file to look for a var etc, you have to potentially surf through all 25 includes, then have the presence of mind to remember where it was when you have to come back to it - perhaps even write down where it was if you have a mind as simple as mine.
There is no doubt this is a poorly disciplined code, but the resultant problem is a shocker. I have 'unincluded' plenty of the .axi files from a few of these sites back into a single .axs program simply for redability and ease of debug.
Having everything back in one file also helps NSX. Find now works well. Search and destroy now works well too.
Huh, I started exploding my systems into a bunch of includes because I find sifting through multi-thousand line files to be annoying when I'm trying to debug something. However, in my defense, I'm not crazy enough to name one of them miscellaneous.axi. 'Miscellaneous' files can only end badly. Usually, even the creator has no idea what's in one after a month or two. I have no problem creating include files for single events if I can't think of a sensible name for a file with them grouped together.
I typically break my program up into a file for devices, constants, variables, functions, module declarations, and then files for each area of functionality like volume controls, presentation, or lighting. I also have module interface include files that contain constants and functions that are useful for accessing the module (for example, my ConvergePro module has constants for all of the input and output channel groups in the header file, and a lot of the commands to the module are wrapped in functions). By putting the module interface in functions and constants, auto-complete and the syntax highlighting drastically cut down debugging time lost to stupid typos in the main program.
The only variables, constants, and functions that aren't in the appropriate file are device related ones, which are in the devices.axi, and the module specific ones in my module interface files. This isn't as bad as it sounds however, as anything in a module interface file is prefixed with the device it's controlling (for example, a function starting ConvergePro_ is going to be in the ConvergePro interface file). The main file is just a long list of #includes.
The only real problem I've run into with this approach is that the netlinx compiler isn't the best at telling you which file an error is actually in. Which isn't surprising, considering how often it's right about what line the error is on in the first place.
I'm a big fan of includes but I simply use a single include per device. The includes hold code specific to the device and is used to instantiate the modules for that device. If vars have to be declared outside of the individual dev's .axi so they are accessible to .axi's included prior they go into the main under their own code folding header.
I agree over use of .axi's is a pain to follow and debug as you bounce from file to file trying to follow the logic but when you simply use a single include per device it's very simple and clean. I prefer to keep device specific stuff out of my main file and leave that for common/global stuff. The stuff that isn't for a specific device and doesn't make sense to turn into modules.
Why put this in an include instead of a module though? Traditionally, includes (or header files) are for declarations, definitions, type_defs, etc.
How many of you are using SNAPI for NetLinx module standards AND has anyone found any weird anomalies with SNAPI standards? I know the ENV-VST-C is a little odd because is sort of matches SNAPI. Converting my modules over to compliance with SNAPI is high on the list. Just wondering how others are handling it in their modules.
I don't use SNAPI, mainly because I didn't know it existed when I started writing modules, and by the time I found out about it, the effort to go back and convert from the API I built didn't seem worth it. 'specially since I don't have Duet.
I'm also a huge fan of includes. Since modules won't allow structures to be passed, I started realizing the value of includes. I have never been a fan of modules and virtual devices and all that. Makes no sense to me.
The one thing that I insist on in my programs is leaving ALL devices, include and module file declarations in the main source file. Having files and devices declared all over the place would cause for frustrations and headaches.
I'm a big fan of includes but I simply use a single include per device. The includes hold code specific to the device and is used to instantiate the modules for that device. If vars have to be declared outside of the individual dev's .axi so they are accessible to .axi's included prior they go into the main under their own code folding header.
I agree over use of .axi's is a pain to follow and debug as you bounce from file to file trying to follow the logic but when you simply use a single include per device it's very simple and clean. I prefer to keep device specific stuff out of my main file and leave that for common/global stuff. The stuff that isn't for a specific device and doesn't make sense to turn into modules.
I agree there is definitely a place for includes and whilst the one project spoken of has irritated me to distraction, I can say that I have indeed used includes a fair bit myself in the past.
rfletcher: Huh, I started exploding my systems into a bunch of includes because I find sifting through multi-thousand line files to be annoying when I'm trying to debug something. However, in my defense, I'm not crazy enough to name one of them miscellaneous.axi. 'Miscellaneous' files can only end badly. Usually, even the creator has no idea what's in one after a month or two. I have no problem creating include files for single events if I can't think of a sensible name for a file with them grouped together.
I personally have no issue of hitting search and ending up on line 6000. it's a nano-second blip compared to opening a file and having to do the same thing then going back to the main code.
I totally agree about the concept of placing all relevant device code in the include - thereby making finding stuff very easy - compared to the unfortunate method I inherited on 'that' job. But that is kinda a module anyway isn't it?! ;-)
As for the topic of to module or not to module, I certainly am a module person. The downside of a pre-fabed module is you can't change it or fix it. I for one was caught a while back trying to use a module I didn't write for something as simple as an amplifier. It had major issues with coms, and I ended up writing it myself.
The upside is the way instancing can simplify everything so much. If you have a system with a small cart load of identical plasmas for example and one is not responding correctly, it just about has to be device related not code as the others theoretically should misbehave too if it is a code problem. If you have to create a unique include for projectors 1-6 - isn't there a bit of risk to correctly name everything and not accidentally leave vp1_cool when it should be vp2_cool etc ?
As I say, I use them both in the right places, but I will build a module for a dev in preference to making an include for the dev.
Includes and modules have their place and they should both be used when the time is right.
I have a project I am working on right now that has 8 masters, all talking M2M, in each main file I have all the ip devs defined, and the virtuals that only that system accesses (logs, io, ftp, etc) and then an include that all systems point to that has all the virtual from every system that every other system accesses. (~500 virtuals) That way any changes happens in 1 spot if I change dev number. As far as modules, we have 12 dell 48 port managed switches that we control and monitor, I wrote 1 modules, 1 Combiner file, and I am done for as many switches as I need, and all the magic happens in the module in its own execution space, trying to do that and copy the parsing, queue, lexicon, and response, and feedback 12 times would kill me.
I define all vars and out of module feedback inside these. for example, _Lights.axi contains the lutron init values, keypad addresses, and the define module statement. if I ever need to troubleshoot lighting, I know right where to go.
I also in the main file make a comment as to when a file was added, and if it has an order of precedent. I only include files in main with 2 exceptions, my lighting.axi does include a lutron specific file for keypad parsing, and I keep the naming convention, but double prefix it to let me know its included in an include __lutronKP.axi
Anyway, I have trolled this post for a week or 3 and I wanted to chime in, modules have their place, when used by people that dont know how to properly treat them, discussion like this come up. Its OOP people, its not that hard.
Comments
If you switch to rolling your modules in Duet that's where they really shine. You develop all your device communication modules to adhere to SNAPI for talking to NetLinx so that they can be used by anyone rolling code there without issue. Where it gets funky though is when you use OSGi to allow the 'modules' to talk to each other in Duet world. This lets you to do things like build a helper module that ties a display device's power/mute/input state to your signal distribution system (matrix switcher et al) - when there's signal it's on, when there's not its off, when there's a higher quality signal (DVI > CV etc) available use that, or do things like have a group of DSP modules work in unison (the AMX supplied ClearOne_ConvergeGateway implements this) and talk though the one physical device.
I'd have to say my modules are pretty SNAPI.
Paul
Actually, yes, I would. I have several boilerplate modules that I frequently modify with the device-specific code necessary. A simple RS-232 or IP device takes me less than an hour to implement this way, and all my queuing, buffering, debugging, and interface code is already done. I'm sure you have boilerplate includes that do the exact same thing. I simply find it easier to maintain them in module form. Just a personal preference choice.
It is all part of keeping my code as orthogonal as possible. This orthogonality is what makes it possible for me to customize the code for each job without introducing bugs or having to test every aspect of the code with each roll out. It is also the best reason to use modules.
I get the lock down aspects, at first I didn't even think of that since I don't really care about such things anymore. I've come to realize I'm not competing against anyone doing AMX so I why should I care who has my code. Also if someone has my code and can make it better, more power to them.
Not that it really matters but modules also multiply the resources the code requires since vars, constants, functions etc are duplicated for every instance where in the include style it's just a matter of creating array to hold values for each device which happens to be what I do anyway when instantiating multiple modules.
Now I just started another modules for an Oppo DVD player and so far I doing it the traditonal method since it is easier because that's how I'm set up to work and I too busy right now to start thinking and trying to re-invent the wheel even if my version turns out to be square. I still think it would be easier to integrate into the main code and decrease the amout of resources the system uses.
I’m on the *modules are good* side of the fence for the same reasons that others have already stated and I have one other benefit to add that hasn’t been mentioned yet which is Token and Variable count.
There was a thread a couple of weeks ago or so where someone was getting close to exceeding the Token and Variable count limit of 100000. The program consisted of a whole bunch of include files and the count was in the 90K plus territory. I never paid much attention to the count so I was concerned that I might be running into the same problem and didn’t know it but when I recompiled some of my larger programs I couldn’t find one that exceeded 16000.
So I ran some tests trying to figure out how the count incremented. I started with a blank program and that gave me a Token and Variable count of 607. I then added a DEFINE_VARIABLE section and one variable and the count went to 609. Every variable I added after that incremented the count +1 and it didn’t matter what the size of the variable was. The larger variable used more memory but the count only went up by one.
Next I added a DEFINE_CONSTANT section and some constants and the count appeared to follow the same pattern as the variables.
I then added a DEFINE_TYPE section with one STRUCT that had one member and the count went up +3 and every additional intrinsic member to that struct incremented the count by 1.
I wanted to see what a DEFINE_FUNCTION would do and found out that an empty stub with no parameters incremented the count by +7.
I then tried on last define: DEFINE_MODULE and found out that DEFINE_MODULE costs nothing. It didn’t matter how many modules I added the Token and Variable count remained the same. The memory obviously increased but not the count.
When you compile a module you’ll see that the module gets its own set of 100000 variable and tokens which makes sense since a module is essentially a program in and of itself.
If you’re looking to create easily scalable systems, modules are a good way to go.
I would second this. One might derive from my earlier post that I'm anti-module but I'm not. In my case I use them ver extensively. They work like they work and that's it. I do not try to over code them and the number of things they do is very nitty-gritty. Where I find myself getting into hot wate with them is if I get lazy and start to let other program functionality creep into them due to lack of time and/or laziness. If I keep the comm modules 'comm modules' and nothing more, I'm usually very happy with them.
I do not tend to use modules for UI or most other over-arching program stuff. That's where I go to Includes. My includes tend to be copy/paste from other programs and then tweaked. My Main file is nothing more than a bunch of lnclude commands.
I also kind of follow a loose MVC architecture in that I have device modules, UI modules and "master" modules that implement the higher levels of control. By using structures and meta-data I have been able to significantly reduce the amount of code I used to write, which makes flexibility and troubleshooting much easier. Also, I do everything in Events and Functions, my goal is no code in DEFINE_PROGRAM.
I have to say, includes drive me up the wall! This is certainly based on one very large and poor experience, but it has shown me that they can make coding really frustrating, cumbersome and slow to debug with - more than they are a help.
I have been looking after a client who has dozens of systems for a while now and they used to have an inboard programmer from the die-hard include paddock. With no disrespect intended, the code is so fragmented (more than half the trouble to be honest) that debug is a marathon (read: nightmare).
These particular codes have an include for *everything*. Devices, constants, variables, M_E, latches, define_call routines, and program elements like mode selections, source selections, lighting, even a helpful miscellaneous.axi, exit routines, feedback, you name it, it has .axi stuck to the end of it. On average, 25 includes per system.
But sadly the internal convention is not strict. Poor old miscellaneous.axi for instance has a couple of define_calls in it some random feedback just because - actually, I can't imagine why, but it does! Feedback can be found in most of the source.axi's, there are calls declared in the source includes and on and on the saga goes.
Instead of being able to surf through one file to look for a var etc, you have to potentially surf through all 25 includes, then have the presence of mind to remember where it was when you have to come back to it - perhaps even write down where it was if you have a mind as simple as mine.
There is no doubt this is a poorly disciplined code, but the resultant problem is a shocker. I have 'unincluded' plenty of the .axi files from a few of these sites back into a single .axs program simply for redability and ease of debug.
Having everything back in one file also helps NSX. Find now works well. Search and destroy now works well too.
I agree over use of .axi's is a pain to follow and debug as you bounce from file to file trying to follow the logic but when you simply use a single include per device it's very simple and clean. I prefer to keep device specific stuff out of my main file and leave that for common/global stuff. The stuff that isn't for a specific device and doesn't make sense to turn into modules.
Huh, I started exploding my systems into a bunch of includes because I find sifting through multi-thousand line files to be annoying when I'm trying to debug something. However, in my defense, I'm not crazy enough to name one of them miscellaneous.axi. 'Miscellaneous' files can only end badly. Usually, even the creator has no idea what's in one after a month or two. I have no problem creating include files for single events if I can't think of a sensible name for a file with them grouped together.
I typically break my program up into a file for devices, constants, variables, functions, module declarations, and then files for each area of functionality like volume controls, presentation, or lighting. I also have module interface include files that contain constants and functions that are useful for accessing the module (for example, my ConvergePro module has constants for all of the input and output channel groups in the header file, and a lot of the commands to the module are wrapped in functions). By putting the module interface in functions and constants, auto-complete and the syntax highlighting drastically cut down debugging time lost to stupid typos in the main program.
The only variables, constants, and functions that aren't in the appropriate file are device related ones, which are in the devices.axi, and the module specific ones in my module interface files. This isn't as bad as it sounds however, as anything in a module interface file is prefixed with the device it's controlling (for example, a function starting ConvergePro_ is going to be in the ConvergePro interface file). The main file is just a long list of #includes.
The only real problem I've run into with this approach is that the netlinx compiler isn't the best at telling you which file an error is actually in. Which isn't surprising, considering how often it's right about what line the error is on in the first place.
Why put this in an include instead of a module though? Traditionally, includes (or header files) are for declarations, definitions, type_defs, etc.
I don't use SNAPI, mainly because I didn't know it existed when I started writing modules, and by the time I found out about it, the effort to go back and convert from the API I built didn't seem worth it. 'specially since I don't have Duet.
The one thing that I insist on in my programs is leaving ALL devices, include and module file declarations in the main source file. Having files and devices declared all over the place would cause for frustrations and headaches.
I personally have no issue of hitting search and ending up on line 6000. it's a nano-second blip compared to opening a file and having to do the same thing then going back to the main code.
I totally agree about the concept of placing all relevant device code in the include - thereby making finding stuff very easy - compared to the unfortunate method I inherited on 'that' job. But that is kinda a module anyway isn't it?! ;-)
As for the topic of to module or not to module, I certainly am a module person. The downside of a pre-fabed module is you can't change it or fix it. I for one was caught a while back trying to use a module I didn't write for something as simple as an amplifier. It had major issues with coms, and I ended up writing it myself.
The upside is the way instancing can simplify everything so much. If you have a system with a small cart load of identical plasmas for example and one is not responding correctly, it just about has to be device related not code as the others theoretically should misbehave too if it is a code problem. If you have to create a unique include for projectors 1-6 - isn't there a bit of risk to correctly name everything and not accidentally leave vp1_cool when it should be vp2_cool etc ?
As I say, I use them both in the right places, but I will build a module for a dev in preference to making an include for the dev.
I have a project I am working on right now that has 8 masters, all talking M2M, in each main file I have all the ip devs defined, and the virtuals that only that system accesses (logs, io, ftp, etc) and then an include that all systems point to that has all the virtual from every system that every other system accesses. (~500 virtuals) That way any changes happens in 1 spot if I change dev number. As far as modules, we have 12 dell 48 port managed switches that we control and monitor, I wrote 1 modules, 1 Combiner file, and I am done for as many switches as I need, and all the magic happens in the module in its own execution space, trying to do that and copy the parsing, queue, lexicon, and response, and feedback 12 times would kill me.
I define all vars and out of module feedback inside these. for example, _Lights.axi contains the lutron init values, keypad addresses, and the define module statement. if I ever need to troubleshoot lighting, I know right where to go.
I also in the main file make a comment as to when a file was added, and if it has an order of precedent. I only include files in main with 2 exceptions, my lighting.axi does include a lutron specific file for keypad parsing, and I keep the naming convention, but double prefix it to let me know its included in an include __lutronKP.axi
Anyway, I have trolled this post for a week or 3 and I wanted to chime in, modules have their place, when used by people that dont know how to properly treat them, discussion like this come up. Its OOP people, its not that hard.
Jim