Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/05/2012 in all areas

  1. I've never used it, but I've seen rabbit MQ code in Python and LabVIEW as well. RabbitMQ is a message broker, so should be able to bridge the gap. Ton
    3 points
  2. Producer Consumer Loop Example: COM Port Hyperterminal Application
    1 point
  3. I reckon this package would make a great OpenG candidate.
    1 point
  4. If I can add a bit to what Paul said... Any two components that collaborate to achieve some goal are going to be dependent on (coupled to) each other somehow. Some types of coupling are strong; others are weak. (See here for a list of coupling types.) At the very least they have to agree on the shared data schema. What's it look like? How is it formatted? What does it mean? How you solve the problem depends on your goal for that particular component. If a component is application-specific, typedefs are an okay solution. (I generally avoid them though.) Since all the code that uses the typedef will be in memory any time the typedef changes you're pretty safe. If the component is intended for general reuse, you're probably better off passing data using native types--arrays of strings, numbers, etc. Sometimes I don't want the two components (CompA and CompB) to directly depend on each other at all. In those cases I have a few options: Mediator - I create CompC that acts as a go-between for CompA and CompB, controlling the flow of information. It doesn't matter if CompA and CompB use the same data schema; CompC simply translates one schema to the other and passes along the data. CompC block diagrams use CompA and CompB methods, so it is dependent on them. A and B can easily be reused in other apps, but C must take A and B along with it for reuse. Dependency Injection - In this case CompC provides a common interface and I "inject" it into CompA and CompB at runtime. CompC could be a TestData class, providing Set Data, Get Data, and SaveData methods. This makes CompA and CompB dependent on CompC as CompA and CompB block diagrams use CompC methods. C can easily be reused in other applications; A and B must take C with them if they are reused. Which one you use depends on several factors. If A and B have already been created and tested then using a Mediator is the better solution. You don't want to make a habit of rewriting completed code. If you're creating them all from scratch then you can decide what you want your dependency graph to look like and design around it. FWIW, I often implement a TestData class and use it with both a Mediator and/or Dependency Injection, depending on the module that needs the data. In my case the BaseState class holds the shared information and exposes protected static dispatch accessors allowing the child classes to read and write the data. It may or may not be a good solution... I haven't worked with that state machine model enough to decide. Your questions sound like the same questions I was asking not too long ago. I'll make the huge assumption that your designs and way of thinking are similar to where I was at that point. My apologies if my assumption is wrong. When literature refers to cohesion and coupling, they usually refer to it in the context of a specific class. It is certainly important there, but I found that focusing on each class as a separate entity in my applications often resulted in bad code. I ended up trying to make each class do too much.* I believe my code became much clearer and much more flexible when I started concentrating on decoupling modules instead of classes. I typically use project libraries to organize a group of classes into a module that provides some useful functionality. Since none of those classes are going to be reused independently, it's okay for them to be relatively tightly coupled to each other. To limit the incoming dependencies and preserve module decoupling I'll often make all the tightly coupled classes private and provide one or more public classes as the module's interface. *As an example, just yesterday I was tracking down .Net memory leaks in a class I had written to control an RF sniffer. The instrument hardware captures data in a queue and 8 ms "frames" of data (each one a .Net reference) are read one at a time. I need to keep all the capture frames in memory so they can be post processed, but I didn't want .Net references running all over my application. The RfSniffer class' evolution resulted in the class maintaining a history of captured frames, to preserve encapsulation. This class not only provided hardware control (Open, StartCapture, ReadFrame, etc.) but also had to provide data analysis methods. (FindTriggerFrame, GetFrameTimestamp, etc.) The api for the class was a little confusing, but not terribly so. I thought it was a reasonably good design. (This was just last week...) Had I not discovered the .Net reference leak I would have left it as it was. As it turns out, the RfSniffer class wasn't properly releasing all the captured frames in memory when a new capture was started. Furthermore, because of the overall application design there wasn't a good way to introduce a ReleaseFrameReference methods without violating my layering and creating a ripple effect up through the app. The solution I decided on was to refactor the RfSniffer class into two classes**: RfSniffer for instrument control and RfSnifferData to store and perform operations on captured frames. It's obvious to me now the new design is cleaner, easier to use, and more flexible. I hadn't really realized it at the time, but I was struggling with how to implement the requirements into the RfSniffer class. It's easy to chide myself for not realizing the problem and figuring out the solution earlier, especially because I often create TestData classes and I'm familiar with the strategy. In retrospect I was so focused on trying to get the product released (it was supposed to be out the door on Tuesday) I made a series of "quick and easy" changes rather than step back and look at the bigger picture. If my design had been correct from the start I could have avoided the reference leak and released on time. [**I don't always encapsulate modules in libraries. For trivial cases such as this I'll define sub-modules using virtual folders and the project window hierarchy.] Meh... I don't know that any of us are terribly qualified for this. I consider all the LVOOP discussions 'group learning.' The more people contribute--regardless of qualifications--the better we all learn.
    1 point
  5. Yeah, that answers it for the example I listed. I'm always looking for ways to really encapsulate and abstract as much as possible and when I've got 95% of it done, hard-wiring to achieve something similar to what you were describing it seems like I'm compromising all which went before. Maybe I'm hung up a bit too much on abstracting everything. If everything has been abstracted, where do we go from there? I always tend to try to create re-usable code which is reusable without code changes whereas I'd probably most often be better off assuming that minor changes will be neccessary for minor updates. There are exceptions where a truly generic class can be created, but these are rare I think. Thanks Shane
    1 point
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.