Home AMX User Forum AMX General Discussion

Modules, what good are they?

I was thinking the other while driving that modules aren't really necssarry and might actually cause more problems then they fix.

As far as reusing code for multiple devices by instantiating multiple instances of the code that's easily accomplished using arrays and to me the idea of a module really only makes sense for systems that can run multiple threads at the same time. Since Netlinx is a single thread system you can accomplish the same thing with arrays or structures so that your code can control multiple devices of the same type and just simply track your TPs and what they should be controlling. You have to do that anyway to determine which instance of a module to talk to.

It seems passing stuff to the module, not having persistence, unable to reference other code unless passed in as a paremeter are reasons not to use modules. It often feels like I'm doing things twice, once in the module and then again in the main (.axi) when it could be done just once. Basically instead of a module you can create a manufacturer specific function for your com and not use modules at all.

I'm beginning to think the logic of using modules really makes no sense since we can accomplish the same things with structures, arrays, function and keep our code organized by simply using includes file which we most already do.
«1

Comments

  • HedbergHedberg Posts: 671
    Modules give you the ability to control the source code. That seems to me to be the only advantage.
  • viningvining Posts: 4,368
    Ah yes, there is that.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    I was thinking the other while driving

    First of all, you shouldn't do that or you'll get in an accident.
    vining wrote: »
    As far as reusing code for multiple devices by instantiating multiple instances of the code that's easily accomplished using arrays and to me the idea of a module really only makes sense for systems that can run multiple threads at the same time.

    You can control any number of UIs and any number of devices from one module. There is no need to instantiate one per device. The entire program is a module, so without modules, nothing would work.

    You don't need multiple threads to run modules so I don't see the relevance there. Unless you have multiple cores or CPUs, its not true multithreading. You should be grateful for this. Multithreaded applications bring with them all sorts of nasty problems. For robotic control, a single threaded system is much superior in my opinion.

    vining wrote: »
    It seems passing stuff to the module, not having persistence, unable to reference other code unless passed in as a paremeter are reasons not to use modules. It often feels like I'm doing things twice, once in the module and then again in the main (.axi) when it could be done just once. Basically instead of a module you can create a manufacturer specific function for your com and not use modules at all.

    Its funny that the reasons you state to not use modules are precisely the nice features of modules. A module encapsulates functionality, and this reduces complexity, a tenet of good software engineering. I don't want the module code to interact with any other part of the program other than the things I pass into it. I like this guarantee. Modules shouldn't be able to use persistent memory since the module itself isn't persistent. You can write to a file from a module so you can safely store long term data if need be.

    .I don't understand what you mean about doing things twice. Sounds like you might be doing something wrong there. Using modules allows a write once and reuse paradigm.
    vining wrote: »
    I'm beginning to think the logic of using modules really makes no sense since we can accomplish the same things with structures, arrays, function and keep our code organized by simply using includes file which we most already do.

    Ugh. I use a few includes to organize functionality, but I prefer to let the modules do most of the work. The last shop I worked at used includes all the time and I hated it. Since all the variable names have global scope, you end up coming up with stupid names just so they don't confiict with other variables with similar function. For instance, the names that I give the real and virtual devices in the module that are passed in are dvDevice and vdvDevice. Its the same in every module, so I never have to think about naming schemes and simplifies module creation since I can copy an existing module and the only things that I need to change are the commands, parsing and a few other things. Everything else stays the same. You can't do that with includes. If Netlinx didn't have modules I would seriously consider getting out of this line of work.
    Paul
  • ericmedleyericmedley Posts: 4,177
    ...another golden opportunity for a plug for my idea of the SUPER_INCLUDE...
  • viningvining Posts: 4,368
    a_riot42 wrote: »
    First of all, you shouldn't do that or you'll get in an accident.
    That's part of my problem, I think when I shouldn't and don't think when I should.
    You can control any number of UIs and any number of devices from one module. There is no need to instantiate one per device. The entire program is a module, so without modules, nothing would work.
    Most folks reason for using module is to "re-use" by instaniating the module for multiple devices of the same type. I'm just saying that's a pointless reason since that can easily be done using arrays and structures and instantiating instance of code for each UI is beyond un-necesaary.
    You don't need multiple threads to run modules so I don't see the relevance there. Unless you have multiple cores or CPUs, its not true multithreading. You should be grateful for this. Multithreaded applications bring with them all sorts of nasty problems. For robotic control, a single threaded system is much superior in my opinion.
    My thinking here was if you had multi thread capability then instantiating modules would be necessary so that multiple instances of the code can run at the same time. Since we're single threaded we can't run code simultaneously so instances don't really make sense except for some reasons you discuss below.
    Its funny that the reasons you state to not use modules are precisely the nice features of modules. A module encapsulates functionality, and this reduces complexity, a tenet of good software engineering. I don't want the module code to interact with any other part of the program other than the things I pass into it. I like this guarantee. Modules shouldn't be able to use persistent memory since the module itself isn't persistent. You can write to a file from a module so you can safely store long term data if need be.
    This is true but do these benefits out weigh the drawbacks of using modules? I think the encapsulated functionality aspect is more of a pain than a benefit and if we're creasteing modules for the sole mis-guided purpose of "re-using" code then I thinks it's a waste. If you want to create modules for the purposes you descibe that's one thing but that's now why most folks have been creating modules.
    .I don't understand what you mean about doing things twice. Sounds like you might be doing something wrong there. Using modules allows a write once and reuse paradigm.
    Let's say you have a comm module you have to create data_events, channel_events, level_events, maybe button_events just to pass information back and forth between the main and the module. You process information in the module and then re-process it in the main. You could just do this in the main and be done with it. If you want the same type devices from different manufacturers to be plug and play then just use includes or functions.
    Ugh. I use a few includes to organize functionality, but I prefer to let the modules do most of the work. The last shop I worked at used includes all the time and I hated it. Since all the variable names have global scope, you end up coming up with stupid names just so they don't confiict with other variables with similar function. For instance, the names that I give the real and virtual devices in the module that are passed in are dvDevice and vdvDevice. Its the same in every module, so I never have to think about naming schemes and simplifies module creation since I can copy an existing module and the only things that I need to change are the commands, parsing and a few other things. Everything else stays the same. You can't do that with includes. If Netlinx didn't have modules I would seriously consider getting out of this line of work.
    Paul
    Most modules/code can be written with very few global vars so that's not such a big deal but if that's the reason you write modules that's fine. Yes you can use generic names for values in modules but you still have to create the devs, vdevs and array in the main that are passed in. So that's kind of doing things twice too.

    If you want code isolated from the main that's fine, if you want control of the source code that's fine also but if the reason for creating modules is to "re-use" code for multiples of the same device then that's not a legitimate reason since you can run as many devices you want from code that's structure to do so with out modules. Then you don't have to deal with the negative aspects of using modules and IMHO the negatives do out weight the positives most of the time.
  • annuelloannuello Posts: 294
    I like modules for the following reasons:
    1) I can provide my module to anyone, without providing them source code.
    2) When I assist them with implementing my module I am guaranteed that they haven't modified the source/behavior, since they don't have the code. This makes it easier for me to support them.
    3) When debugging a room it can be tempting to chop-n-change a variety of code just to get the room working. By "locking away" code that is tried and tested, you reduce the risk of modifying code which was behaving fine, allowing you to focus on the actual cause.
    4) Including a .tko in your project rather than the .axs reduces compile time, since the .tko does not need compiling, only linking.

    Yes, lack of persistence is a minor pain but it makes sense. However, if I don't want to expose the code in my module, how will an implementer know what variable needs to be set? Configuring the module through send_commands makes a lot more sense. Besides, persistent variables are only stored as long as the timekeeper battery lasts. Once it goes flat you'll lose your persistent values on reboot, and wish you had loaded your variables from file instead.

    Roger McLean
    Swinburne University
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    Let's say you have a comm module you have to create data_events, channel_events, level_events, maybe button_events just to pass information back and forth between the main and the module.

    I don't understand. For instance, if you use the AMX iPort module, you have a comm module and a UI module. You instantiate both and are finished writing code. Same with the Kaleidescape module. What events are you writing in these cases?
    vining wrote: »
    but you still have to create the devs, vdevs and array in the main that are passed in. So that's kind of doing things twice too.

    Devs, vdevs are only ever defined once, no matter whether you use modules or not. The fact that you say they are done twice makes me wonder if you are using modules incorrectly or in a unorthodox manner leading to problems.
    vining wrote: »
    If you want code isolated from the main that's fine, if you want control of the source code that's fine also but if the reason for creating modules is to "re-use" code for multiples of the same device then that's not a legitimate reason since you can run as many devices you want from code that's structure to do so with out modules. Then you don't have to deal with the negative aspects of using modules and IMHO the negatives do out weight the positives most of the time.

    The whole point of software engineering principles is to determine the best way to do something, given an unlimited choice. You can write the same program in an infinite number of ways. Are all these ways going to be equally efficient, maintainable, modifiable, readable, etc? No. Just because you can do something doesn't mean its good practice to do so. Limiting scope is a valuable software engineering pinciple and modules allow for this. Just because there are built in limitations to AMX modules, like not being able to pass structures to them, or having only commands, strings, and events to communicate with them rather than being able to use tradtional OO syntax like dvBluray.play(), doesn't negate the principle behind using them, at least to me.
    Paul
  • viningvining Posts: 4,368
    a_riot42 wrote: »
    I don't understand. For instance, if you use the AMX iPort module, you have a comm module and a UI module. You instantiate both and are finished writing code. Same with the Kaleidescape module. What events are you writing in these cases?
    I'm talking about modules you write yourself and the iPort module I re-wrote so I didn't have an instance of the UI mod and TP port for each UI used, that's just a dumb way to write a module.
    Devs, vdevs are only ever defined once, no matter whether you use modules or not. The fact that you say they are done twice makes me wonder if you are using modules incorrectly or in a unorthodox manner leading to problems.
    Well they are defined multiple times if you have multiple master and if there's a need to do so but that's another story. I didn't say define twice I said create twice which is a sense you do becuase you create a generic name for the parameters passed in. So you referring to the same dev, vdev, or whatever else you pass in with different names which you don't have to do if left in your main. Sure if you're writing modules it's easier to do with a template using generic names but when it comes time to debug what a PITA to figure what instance of the var or constant to debug with. Files names don't match most of the time and even when they're correct and you have multiple instances it's a PITA to figure out the instance to look at. Is it in normal order or reverse order? I swear sometimes it changes.
    The whole point of software engineering principles is to determine the best way to do something, given an unlimited choice. You can write the same program in an infinite number of ways. Are all these ways going to be equally efficient, maintainable, modifiable, readable, etc? No. Just because you can do something doesn't mean its good practice to do so. Limiting scope is a valuable software engineering pinciple and modules allow for this. Just because there are built in limitations to AMX modules, like not being able to pass structures to them, or having only commands, strings, and events to communicate with them rather than being able to use tradtional OO syntax like dvBluray.play(), doesn't negate the principle behind using them, at least to me.
    Paul
    I agree completely! Just cuz you can write a module doesn't mean you should. :) Everything you spoke of can be done with out modules. I can see writing modules for reasons annuello mentioned which are also some of the same reasons you mentioned but as far being better style I don't buy it and to gt back to original point which is if the reason you're writng modules is to "re-use" code which you agree isn't necessary for connecting to multiple devices or TPs then the only reason for modules are basically because we were brain washed into thinking we needed to or for some of the reason annuello mentiond which is really just for locking the code.

    I've been writng module to "re-use" the code for multiple instance of devices and for me it would be easier and cleaner not too but I just thought it made sense because that's what's been said over the years. I don't care about locking code anymore and I like includes and if done right it's just as clean as using modules. I found with modules I spend more time marshalling data in and out or sending levels, channels, command & strings. If I keep it simple I can create stack structure or var and pass them to the function that need them and have those functions accessible through the code.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    I've been writng module to "re-use" the code for multiple instance of devices and for me it would be easier and cleaner not too but I just thought it made sense because that's what's been said over the years. I don't care about locking code anymore and I like includes and if done right it's just as clean as using modules. I found with modules I spend more time marshalling data in and out or sending levels, channels, command & strings. If I keep it simple I can create stack structure or var and pass them to the function that need them and have those functions accessible through the code.

    In that case I would strongly suggest you don't use modules.
    Paul
  • Jorde_VJorde_V Posts: 393
    vining wrote: »
    I'm talking about modules you write yourself and the iPort module I re-wrote so I didn't have an instance of the UI mod and TP port for each UI used, that's just a dumb way to write a module.

    I would advise you to look in to design patterns such as MVC (Model-View-Controller) or a simplification of that practice. see http://www.leepoint.net/notes-java/GUI/structure/ui-model-communication.html for a short explanation. Perhaps wikipedia will help as well: http://en.wikipedia.org/wiki/Model-view-controller
    vining wrote: »
    Well they are defined multiple times if you have multiple master and if there's a need to do so but that's another story. I didn't say define twice I said create twice which is a sense you do becuase you create a generic name for the parameters passed in. So you referring to the same dev, vdev, or whatever else you pass in with different names which you don't have to do if left in your main. Sure if you're writing modules it's easier to do with a template using generic names but when it comes time to debug what a PITA to figure what instance of the var or constant to debug with. Files names don't match most of the time and even when they're correct and you have multiple instances it's a PITA to figure out the instance to look at. Is it in normal order or reverse order? I swear sometimes it changes.

    Are you doing weird things in your modules or something? Because I never run in to the issues you're describing and I make modules for every device I encounter. I build a small framework on which I plug-in these modules. I do everything that's purely device-related in the modules themselves and handle system-wide commands etc in the framework. So in case of a kaleidescape system I pass around the framework (using the extra port on the touchpanel for that deivce) which is more of a blessing really, I don't want to dig in to the kaleidescape module.

    Granted I don't use modules written by AMX/manufacturers unless I really need to (like with kaleidescape).
    vining wrote: »
    I agree completely! Just cuz you can write a module doesn't mean you should. :) Everything you spoke of can be done with out modules. I can see writing modules for reasons annuello mentioned which are also some of the same reasons you mentioned but as far being better style I don't buy it and to gt back to original point which is if the reason you're writng modules is to "re-use" code which you agree isn't necessary for connecting to multiple devices or TPs then the only reason for modules are basically because we were brain washed into thinking we needed to or for some of the reason annuello mentiond which is really just for locking the code.

    Or you can approach it like I do and build a framework on which you can plug-in your modules. Another thing with modules is that you can debug purely on that code and don't have to touch code you previously tested as running and bug-less.
    vining wrote: »
    I've been writng module to "re-use" the code for multiple instance of devices and for me it would be easier and cleaner not too but I just thought it made sense because that's what's been said over the years. I don't care about locking code anymore and I like includes and if done right it's just as clean as using modules. I found with modules I spend more time marshalling data in and out or sending levels, channels, command & strings. If I keep it simple I can create stack structure or var and pass them to the function that need them and have those functions accessible through the code.

    You should read a book or two on software engineering, at first I thought it would be a pain in the arse as well. But as it turns out it has saved me a lot of time. It's not something you see returned on just one project, you see it on all of them. Because you know your framework is running correctly and if a certain device is messing up you know it's either in the module of that device or in the device itself.

    Books I suggest:
    http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
    http://www.amazon.com/exec/obidos/ASIN/0201633612/ref=nosim/cboard-20

    And my favorite:
    http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?s=books&ie=UTF8&qid=1301906967&sr=1-1
  • viningvining Posts: 4,368
    Ok, other that the ability to lock your code what is the difference between using a function or an include as opposed to a module? Is this not enough seperation? The premise for my argument is that modules in terms of AMX are intended to "re-use" code and while you can use modules to do this you can just as easily control any of of devices you want with out them by changing the structure of your code, using more arrays and structures which for the most part you have to do anyway even if using modules.

    The only time modules would be required to controll multiple devices is if it were possible to run multiple threads. Since netlinx can't spawn or fork a child processes (excuse the terminology) then the only real purpose of modules is ultimate isolation which allows you to define names with out regard to the names already being used and it can also be locked. Whether you see modules as being better than includes or functions that may be inpart due to languages that actully need module instances that can run simultaneously and the guys making the rules, writing the books are using these languages.
  • DHawthorneDHawthorne Posts: 4,584
    It's not simply being able to re-use the code, it's the instancing. If you have six identical projectors in a system, you can have ONE module running six instances, without having to worry about variable uniqueness.

    As for the need to marshal data in and out of a module ... I've never had much of a need for that since I handle all that internal to the module. I think it comes down to a way of thinking. To my mind, a module is the nearest thing to a fully encapsulated object that the NetLinx language allows. So, I really work as hard as I can to do just that ... encapsulate it. It should be a plug-in with the minimal amount of hooks to make it run and to allow the rest of the program to know what it's doing. Granted, NetLinx doesn't go far enough with that, but I rarely have the need to send anything more to the module than the device number, a virtual interface, and some variables holding the UI devices and channels. Everything else stays inside as much as possible.
  • viningvining Posts: 4,368
    DHawthorne wrote: »
    It's not simply being able to re-use the code, it's the instancing. If you have six identical projectors in a system, you can have ONE module running six instances, without having to worry about variable uniqueness.
    That's why we have arrays. An index position per device, per rx buffer. We have to use arrays as it is to determine which instance to send to so to me there's not much difference. If you're tracking to send to a module you can just as easily send to the device. Same for the data being retuned. You still have to track the return to decide what to do with the data by using arrays. You just need a local or created buffer for each device, create an array of these buffers and route to the appropriate storage array. Not much difference than what we have to do with the data coming from modules.

    You can have one include file running six idenctical rojectors too, it's not really any different.
  • DHawthorneDHawthorne Posts: 4,584
    I suppose it's my OOP background. The idea of replicating module functions in an include file just makes me shudder with horror. Personally, I find it much easier to manage modules than to try to keep track of all that, but that's me.
  • viningvining Posts: 4,368
    DHawthorne wrote: »
    I suppose it's my OOP background. The idea of replicating module functions in an include file just makes me shudder with horror. Personally, I find it much easier to manage modules than to try to keep track of all that, but that's me.
    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?
  • BrallenBrallen Posts: 25
    I agree with vining. I'd rather just create an include file that accomplishes the same thing but, in my opinion, is easier to work with.
  • ericmedleyericmedley Posts: 4,177
    I use both modules and includes..(full disclosure)

    Here's a good scenario that I run into all the time that an include seems to work best (if they'd make the super_inlcude)

    Situation:
    I quite often find myself programming installations that have the following things.

    TVs, Whole House Audio systems and a plethora of sources.

    Quite often our designers will do things like use the whole house audio system to pump TV audio to a room that has a big TV but no speakers for all the sources they want. Visa-Vera, they might put a TV in a room and feed the whole house media player to that TV so the owner can listen to music on their TV.

    So, I have a routine to handle general house audio stuff that works with any touchcpanel, keypad, remote, etc... I also have a routine that handles TVs from any TP, keypad, remote, etc... I also have a routine for each source and its control.

    So, let's say part of my routine is an "All House Off' button for whole house audio. However, If the current audio zone is being used for TV audio, then don't turn it off.

    or, let say you don't want other users in the house to be able to set up a party scene on the whole-house audio if someone's watching TV...

    The idea is there are states and variables that need to go back and forth from one routine to another. This is doable in modules but is a bit clunky.

    If I always have a global variable called House_Audio_Zone_source[32] that tracks the source selected, then I can use that variable at any time to track the status of the HA system easily. Not to mention, I can make it persistent so it stays true after reboots.

    So, the reusable code in this example is the global variable. In essence it's functioning like a module in that it can be used again and again all over the program. But, the difference is that I don't have to do a lot of hook handling in my main code to cause changes in state to traverse the entire program.

    The advantage of a module is that you can declare variables within the module that stay there and work every time. The disadvantage of the Include is that where you declare your variables gets a bit sticky. For any of use who've tried using the above mentioned method, we know that the order in which or include statements occur and where they are placed can be a bit of a juggling act.

    That's what my idea for the super_include comes from. It's just something to tell the compiler, "Look, I know you don't see this variable declared yet, but hold on, you'll see it once you pass through all the includes..."
  • a_riot42a_riot42 Posts: 1,624
    ericmedley wrote: »
    For any of use who've tried using the above mentioned method, we know that the order in which or include statements occur and where they are placed can be a bit of a juggling act.

    Ugh. Order shouldn't matter in a program. I had to redo so much of a predecessors code because he relied on order/timing so much that if you changed the order or timing of something, then a variable wouldn't be set in time, so a device wouldn't turn on, etc and includes are part and parcel of this for the reason you mention. It was a total nightmare. Sure it mostly worked on small systems, most of the time, but on large systems, if you wanted to do anything interesting, forget it.

    The way I do thngs now, order/timing doesn't matter, turn on any source from any TP in any zone at any time, and it will work. Since Netlinx is single threaded you can always be sure of the order of execution unless you are dealing with waits, or non-blocking I/O. Since I use modules rather than includes, I never have to worry about any interaction between global variables or the timing of when some variable gets read or written to. It cuts way down on gnarly, hard to reproduce, hard to solve timing/order type bugs.
    Paul
  • PhreaKPhreaK Posts: 966
    When I'm doing stuff on the NetLinx side I'm another module/include co-user. Each have their advantages and disadvantages - most of which have already been covered.

    Working to a 'real world' framework is awesome, unfortunately though as NetLinx is half way between a scripting language and an OOP language this isn't always possible. You can however do a lot of funky things with a combination of effective use of structures and adhering to some non compiler enforced rules. For example, if you've got a nice little neat include for a device prefix all the function names with something relevant to that device (that way when NS auto fills for you it makes things a little easier) and prefix all 'private' functions with and underscore or similar. If you (and anyone else you are developing with) can adhere to a single ruleset things stay a lot more structured and maintainable.

    The absolute major advantage of modules, for me at least, which seems to have been left out of the conversation so far is abstraction. You have the ability to define a set API for handling all communication with that module. As long as it remains the same (or at least doesn't remove anything) you can completely change anything happening inside to improve performance, add functionality, or remove bugs then push this out to *anywhere* using that module without breaking things. Make the change in one place and instantly improve/fix everywhere it is used.
  • ericmedleyericmedley Posts: 4,177
    a_riot42 wrote: »
    Ugh. Order shouldn't matter in a program. I had to redo so much of a predecessors code because he relied on order/timing so much that if you changed the order or timing of something, then a variable wouldn't be set in time, so a device wouldn't turn on, etc and includes are part and parcel of this for the reason you mention. It was a total nightmare. Sure it mostly worked on small systems, most of the time, but on large systems, if you wanted to do anything interesting, forget it.

    The way I do thngs now, order/timing doesn't matter, turn on any source from any TP in any zone at any time, and it will work. Since Netlinx is single threaded you can always be sure of the order of execution unless you are dealing with waits, or non-blocking I/O. Since I use modules rather than includes, I never have to worry about any interaction between global variables or the timing of when some variable gets read or written to. It cuts way down on gnarly, hard to reproduce, hard to solve timing/order type bugs.
    Paul

    I wasn't referring to program order. H I was referring to what order the includes are declared. Using my same example I may have an Whole House Audio include that uses a global variable from the TV include to determine if an Tv using the Whole House Audio for Tv Sound. And visa versatile: a global variable from the WHA include sed in the TV include.

    If I put the WHA include before the TV include I'll get a 'undefined variable' error for the variable From the TV include

    What I'm referring to is a 'module-like' include. I never have to modify a line of code either. I have a WHA include for Précis, Élan s12, etc that can be interchanges without a problem.
  • the8thstthe8thst Posts: 470
    ericmedley wrote: »
    I wasn't referring to program order. H I was referring to what order the includes are declared. Using my same example I may have an Whole House Audio include that uses a global variable from the TV include to determine if an Tv using the Whole House Audio for Tv Sound. And visa versatile: a global variable from the WHA include sed in the TV include.

    If I put the WHA include before the TV include I'll get a 'undefined variable' error for the variable From the TV include

    What I'm referring to is a 'module-like' include. I never have to modify a line of code either. I have a WHA include for Précis, Élan s12, etc that can be interchanges without a problem.

    What you are asking for should not be a difficult compiler change to implement. You are asking for the AMX engineers to add 1 additional pass at the scanner/parser level of the compiler. The first pass would collect and store constants,variables,calls, and functions of all includes. Then the second pass processes everything else.
  • viningvining Posts: 4,368
    the8thst wrote: »
    What you are asking for should not be a difficult compiler change to implement. You are asking for the AMX engineers to add 1 additional pass at the scanner/parser level of the compiler. The first pass would collect and store constants,variables,calls, and functions of all includes. Then the second pass processes everything else.
    Yes, but it's been on the request list for at least 5 years so it must be more complicated than it appears. Unless they just don't care. :)
  • the8thstthe8thst Posts: 470
    vining wrote: »
    Yes, but it's been on the request list for at least 5 years so it must be more complicated than it appears. Unless they just don't care. :)

    I have long since given up on trying to understand how AMX decides to allocate their engineering departments brain power. Don't ask me to explore that road again.
  • jjamesjjames Posts: 2,908
    Or perhaps it's as simple as AMX's stance is probably that include files are not modules and shouldn't be treated like them?

    I think this argument of "why not use an include file?" is kind of silly to be honest. If you look at everything as a nail, you'll use a hammer all the time. Just read what the documentation says on the subject:
    INCLUDE
    The keyword allows you to include programming instructions from an external file and have those instructions inserted at any point in the program.

    Syntax:
    INCLUDE '<filename>'

    * The parameter filename can be any valid (long) filename.
    * If the file extension is omitted, "AXI" is assumed.
    * The contents of the file can be thought of as being copied to the location of the INCLUDE statement.
    * An INCLUDE statement can appear anywhere in a program.
    NetLinx Modules (Advanced Programmers)
    The ability to reuse code is a desirable goal in software development; however, code reuse takes careful planning and organization. NetLinx provides tools such as functions and modules to promote reusability. Modules are NetLinx sub-programs designed to be "plugged into" a main program.

    The main difference I see between the two are that one is meant to be integrated *with* your program, while the other is meant to be it's own *separate* program (in a sense.) And yes, NetLinx is single threaded, so you do have to be careful how you define them as explained in the help file.

    When using modules, always keep the order of usage in mind. The modules must be placed (in the program code) in the order in which you want them to occur.

    My point is: how you use them is up to you. A hockey stick was meant to be used with a puck on ice not a ball on grass but kids get enjoyment out of it either way.
  • jimbrasjimbras Posts: 7
    I know that this is a little late to the game, but I use the poop out of modules for both device interfacing and UI functionality. I find that modules have helped us to stay more organized and be able to pass source code between programmers internally with almost no effort. For each module or category of a system (i.e. lighting, HVAC or shade control), I build an include file that defines module specific variables/parameters, defines the module itself, and standardizes any light program interfacing (channel/level/data events etc.). The include gets a few instructions in the comments as to programming intent so everyone is on the same page and I can remember what I was doing when I use them. The include method has increased our productivity greatly. When you need a standard set of programming that you use all the time, there it is. All it takes is writing a simple #INCLUDE statement. It is super easy to version up only a section of your code with some tweaks without having to dig or worry about harming other parts of the code.

    Besides productivity and being able to "put away" whole sections of code that doesn't need to be touched anymore, I have created a module template that I use to build all of our comm modules with. It already has queuing and input/output processes built. No need to change the variable names because it is encapsulated in the module package. This makes troubleshooting comm modules easier because they all work the same way.

    Persistence inside the module can be simply handled by passing a persistent variable in to the module and using the parameter name on the inside. I know this doesn't sound ideal at first, but sometime AMX doesn't provide all of the tools you might need to make things perfect. (Timeline arrays would probably change my life)

    I have included a couple of examples of how I apply it if you are interested. The Include example has been changed to .axs due to file type limitations.
  • a_riot42a_riot42 Posts: 1,624
    jimbras wrote: »
    I have included a couple of examples of how I apply it if you are interested. The Include example has been changed to .axs due to file type limitations.

    Interesting. I don't use the define_program like you do. If you end up with lots of modules does this slow things down at all? I would think that with chatty devices like Kaleidescape players, lighting, security, etc, it might but perhaps you haven't found this.
    Paul
  • jimbrasjimbras Posts: 7
    I developed the define_program thing after many different revisions of trying to get the processors to run faster with up to 50 touch panels and multiple iPods and KScapes. What I found is that I could go old school AXCESS style and use mainline to my advantage to do looping dynamic UI feedback. Because mainline is last priority in the processor thread AND there are no looping keywords (i.e. FOR), it runs at it's own pace and keeps the processor priority loose for processes that need more power right away.

    This has to be combined with multi-processor usage. The include format that I have also helps me to quickly and easily move a whole category of programming off to another processor without causing major amounts of work trying to untangle it from the main code. For example, I like to run the KScape module on a local processor that is just providing ports somewhere in the system. It is Ethernet typically so who cares where it is located. This moves all but the touch panel command and channel data from the passing through the main processor.
  • viningvining Posts: 4,368
    jimbras wrote: »
    I know that this is a little late to the game, but I use the poop out of modules for both device interfacing and UI functionality. I find that modules have helped us to stay more organized and be able to pass source code between programmers internally with almost no effort. For each module or category of a system (i.e. lighting, HVAC or shade control), I build an include file that defines module specific variables/parameters, defines the module itself, and standardizes any light program interfacing (channel/level/data events etc.). The include gets a few instructions in the comments as to programming intent so everyone is on the same page and I can remember what I was doing when I use them. The include method has increased our productivity greatly. When you need a standard set of programming that you use all the time, there it is. All it takes is writing a simple #INCLUDE statement. It is super easy to version up only a section of your code with some tweaks without having to dig or worry about harming other parts of the code.

    Besides productivity and being able to "put away" whole sections of code that doesn't need to be touched anymore, I have created a module template that I use to build all of our comm modules with. It already has queuing and input/output processes built. No need to change the variable names because it is encapsulated in the module package. This makes troubleshooting comm modules easier because they all work the same way.

    Persistence inside the module can be simply handled by passing a persistent variable in to the module and using the parameter name on the inside. I know this doesn't sound ideal at first, but sometime AMX doesn't provide all of the tools you might need to make things perfect. (Timeline arrays would probably change my life)

    I have included a couple of examples of how I apply it if you are interested. The Include example has been changed to .axs due to file type limitations.

    I always make my comm modules support IP and 232 since now a days it's just so easy to add a $100 serial server when you have a long distance ot simpluy run out of 232 ports. I actually wrote one recently that would do IR too, the TriFecta.

    When I made my AutoPatch module I made the single module actually manage up to 3 18x18, 3 dev ports, 3 com buffers so Icould seemlessly control up to 54 zones although I limited myself to 18 sources which have to cascade from one AP to the others with Y's. If you select zones 2, 24, 30 & 50 to switch to XM radio the module will build the string and route to the appropriate Devs.

    I like modules I just don't see them as being as essential for coding in AMX as most of you folks. Maybe that's cuz I ain't been properly skooled. That said I don't know if I can get out of the habit of writing them but I sort wish I had module to write now that would normally require instances so I could try it with out actually using modules. A non module, module (include). :confused: I did recently take code that required 6 instances of one of my modules and made a simple include that handled everything even more elegantly than instantiating the modules did. I guess different strokes for different folks applies here. I've always been somewhat abnormal anyway. :)
  • jimbrasjimbras Posts: 7
    I guess that's what draws us to do this work. You get to build your better mouse trap and if it works, no one really cares how you did it.
  • PhreaK wrote: »
    The absolute major advantage of modules, for me at least, which seems to have been left out of the conversation so far is abstraction. You have the ability to define a set API for handling all communication with that module. As long as it remains the same (or at least doesn't remove anything) you can completely change anything happening inside to improve performance, add functionality, or remove bugs then push this out to *anywhere* using that module without breaking things. Make the change in one place and instantly improve/fix everywhere it is used.


    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.
Sign In or Register to comment.