LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Reusable Code in LV.


@billko wrote:

@crossrulz

I design even the little engineering tools I make with scalability and re-usability in mind


This in my opinion is more important than the tools you use.  Using VIPM (or NIPM) doesn't mean you have a good reuse library.  Just like check all the boxes, when it comes to what makes a good system.  If you aren't actively thinking about reuse, the stuff in your library is likely crap.  This is why mining old projects for reuse nuggets usually doesn't pan out.  The original developer might not have been thinking about the interactivity between code modules, or the alternate ways their code could be used in the future.  Most developers just have a goal in mind and can't spend extra time polishing something that they expect will only ever be used once.  It certainly is a balance though.  You need to have a good reuse mindset, but also don't spend multiple days on making something reusable, causing the project to get behind.

Message 11 of 27
(1,898 Views)

 

classic.

Message 12 of 27
(1,869 Views)

@crossrulz wrote:

@LV_COder wrote:

Is using an ancestor class data or method in child class also be an example of reusing code?


It is different in some senses, but this form of reuse is a major reason OOP became popular in any language.


<OOP_Zealot_Mode_On>

Using ancestor data in child abuses encapsulation. Using anything from parent as a child requires this child to "know" the parent, hence creates high coupling between the two. Changing anything in parent might break the child. This becomes major problem if you have multiple childs and they all expect something else from the parent (I have only one so far, but I know this from others as a fact). If you like SOLID terms, you're violating the Dependency Inversion principle by depending on concrete - the parent implementation of the function, rather than abstraction - for example some external component by delegating to it.

So yes, this is a reuse of code, but not necessarily good reuse of code from the object-oriented point of view.

</OOP_Zealot_Mode_Off>

Yeah, I too love the ramblings about the principles! 😄 But in fact I have seen, wrote (and re-wrote, obviously) a lot of code where removing any calls from child to parent vastly improved the code maintability and quality.

 

0 Kudos
Message 13 of 27
(1,863 Views)

@PiDi wrote:

@crossrulz wrote:

@LV_COder wrote:

Is using an ancestor class data or method in child class also be an example of reusing code?


It is different in some senses, but this form of reuse is a major reason OOP became popular in any language.


<OOP_Zealot_Mode_On>

Using ancestor data in child abuses encapsulation. Using anything from parent as a child requires this child to "know" the parent, hence creates high coupling between the two. Changing anything in parent might break the child. This becomes major problem if you have multiple childs and they all expect something else from the parent (I have only one so far, but I know this from others as a fact). If you like SOLID terms, you're violating the Dependency Inversion principle by depending on concrete - the parent implementation of the function, rather than abstraction - for example some external component by delegating to it.

So yes, this is a reuse of code, but not necessarily good reuse of code from the object-oriented point of view.

</OOP_Zealot_Mode_Off>

Yeah, I too love the ramblings about the principles! 😄 But in fact I have seen, wrote (and re-wrote, obviously) a lot of code where removing any calls from child to parent vastly improved the code maintability and quality.

 


Sorry, I disagree.

 

An accessor for a parent defines a contract regarding what that accessor should do.  If the parent changes something, then not only the child needs to be aware of that change, so does every piece of code which uses a parent.  This is a change that cannot be encapsulated away. Of course a child needs to "know" the parent, otherwise it can't know what it needs to override and so on.  The question is what it should know about the parent.

 

If a parent simply provides public or protected access to "inner" data which is NOT part of it's behavioural contract (and is thus subject to change due to details of implementation), then the parent has leaky encapsulation.  Using the accessor in this moment is not the problem, the existence of the accessor is.  The culprit is the parent, not the child.

Message 14 of 27
(1,861 Views)

@Intaris wrote:

Sorry, I disagree.

 

An accessor for a parent defines a contract regarding what that accessor should do.  If the parent changes something, then not only the child needs to be aware of that change, so does every piece of code which uses a parent.  This is a change that cannot be encapsulated away. Of course a child needs to "know" the parent, otherwise it can't know what it needs to override and so on.  The question is what it should know about the parent.

 

If a parent simply provides public or protected access to "inner" data which is NOT part of it's behavioural contract (and is thus subject to change due to details of implementation), then the parent has leaky encapsulation.  Using the accessor in this moment is not the problem, the existence of the accessor is.  The culprit is the parent, not the child.


You've broken the problem into two aspects:

1. What if the child uses accessor/method that is a part of parent contract?

2. What if the child uses accessor/method that is not a part of conciously designed parent contract, but got there "accidentally" and broke encapsulation?

I think we agree that the latter is bad. It is the culprit of the parent, so we remove this accessor, so the child is now broken and we need to fix it by using some other ways to get to this data/function. And we rewrite the child so it does not have this dependency to the parent, and now we conform to the rules I wrote about. Hence we wouldn't have any problem if we'd not have child-to-parent dependency in the first place.

 

Now, for the first point: yes, the child may use any method that is a part of parent contract, just as any other object. The question is: if this happens, may it be an indicator that this method should actually belong to other class? See the example below. 

 

parent_child.png

A typical example of children using parent I've seen in our LabVIEW world is some kind of HAL where parents ("abstract" hardware, like PowerSupply) hold connection to the hardware and children (specific hardware driver implementations, like ACME9000PowerSupply) keep asking the parent for that connection. This obviously breaks when the connection type required in new child is different (i.e. we have VISA, we need some kind of DLL handler) and can be easily avoided by not introducing this dependency in the first place.

By the way, about the accessors and children using parent data: are you sure you want access to that data? Shouldnt you just tell the parent what to do?

 

Message 15 of 27
(1,842 Views)

By the way, about the accessors and children using parent data: are you sure you want access to that data? Shouldnt you just tell the parent what to do?

 

Using an accessor to access data, you ARE asking the parent to do something, to get the value represented by part of the public (or protected) interface of that class definition.  The accessor is a member of the parent class.  What the parent does to pass back a value is up to the parent, there is no direct data access across inheritance boundaries possible in LabVIEW.  I understand the idea of falling into the assumption that accessors are plain old get and set placeholders for private parent data fields, but that is not automatically the case at all.  Accessors can do whatever you want them to.  The classic "empty accessor" is not automatic. There are certainly cases where accessors for parents being used in children are perfectly valid (and part of a required intended functionality).

 

I would not say that in this case the child is abusing encapsulation (which is the phrase I orginally had a problem with).  It is simply using encapsulation as the parent has provided it.  The parent is not applying the concepts properly.  A child cannot differentiate between "use" and "abuse" since encapsulation provides no insight into the intentions of the parent, only the available methods.  To paraphrase Yoda: "Use or use not. There is no abuse."

 

The idea as to whether the classes are correctly organised, I believe that is a separate topic entirely.

Message 16 of 27
(1,834 Views)

Hooovahh wrote: "Most developers just have a goal in mind and can't spend extra time polishing something that they expect will only ever be used once.  It certainly is a balance though.  You need to have a good reuse mindset, but also don't spend multiple days on making something reusable, causing the project to get behind."

 

Whenever I was assigned to maintain a piece of code I didn't write, I felt compelled to go refactor it so that it was up to my standards (mostly for readability). After reading this post my mindset has changed a bit. I still try to be thoughtful when creating new functions, but for a quick fix on a code that has been doing what the customer wants, I just make the fix and don't (i.e. try not to) think about leaving the code "ugly".

Message 17 of 27
(1,774 Views)

@Gregory..., but for a quick fix on a code that has been doing what the customer wants, I just make the fix and don't (i.e. try not to) think about leaving the code "ugly".

I have gone as far as putting a decoration around the code I changed with a comment of;

 

"This is only part I did!"

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 18 of 27
(1,759 Views)

@Ben wrote:

@Gregory..., but for a quick fix on a code that has been doing what the customer wants, I just make the fix and don't (i.e. try not to) think about leaving the code "ugly".

I have gone as far as putting a decoration around the code I changed with a comment of;

 

"This is only part I did!"

 

Ben


I have code in my reuse with comments attributing it to a forum post with notes about the correction for NaN cases.

 

Bug me someday and i'll dig it up.  You'll recognize the author.  (He has more posts than you do)


"Should be" isn't "Is" -Jay
0 Kudos
Message 19 of 27
(1,753 Views)

@Gregory wrote:

 

After reading this post my mindset has changed a bit. I still try to be thoughtful when creating new functions, but for a quick fix on a code that has been doing what the customer wants, I just make the fix and don't (i.e. try not to) think about leaving the code "ugly".


I've read that article a few times and it makes some very good points.  The problem for me is starting over and writing from scratch has been so successful to me in the past.  There are a few projects where multiple developers work on a project for over a year, then they get promoted, or leave the company.  I was then brought in to clean it up.  I re-wrote it starting on a Monday and testing was running on the system that Friday logging data and doing everything their system was doing but much better.  The software didn't crash, logs were more detailed in a TDMS and PDF rather than a text file, configuration was manageable and wasn't hard coded, test could be adjusted or skipped, manual controls were added, etc.  This is something I've done multiple times and while there are usually some nuggets of usefulness in the old stuff, I've usually just asked the engineer what they actually want it to do and make it do that.  Maybe this is more of testament about LabVIEW and how quickly it can get something going, or maybe it is a testament about how poor the previous developers were.

Message 20 of 27
(1,670 Views)