-
Jul 12th, 2017, 08:54 AM
#1
Thread Starter
Addicted Member
Should I use a Class instead of a Function
I am still learning VB.Net and been reading up on various topics.
I have the following code. The code represents an Analog Type that is used in a PLC program. (The code creates the PLC objects that are imported into the PLC program.) The VB code "auto generates" the code for the PLC so that the user does not have to do it manually. There are also Drive types, etc.
One parameter, the Device Number, is passed to the function. The function then calculated the addresses of the various elements and builds the string as required by the PLC.
I have written the code as a Function. Would it be better to write it as a Class and then reference the attributes?
Code:
#Region "ANL01m - Analog Input"
'~~> ANL01m Global Var
Public Function DUT_ANL(strDeviceNumber As String, strChannel As String) As String
Dim strDUTValue As String = ""
Dim intDevicenumber As Int16 = CType(strDeviceNumber, Int16)
Dim strCommandAddr As String = CType(0 + (2 * intDevicenumber), String)
Dim strAlarmAddr As String = CType(1 + (2 * intDevicenumber), String)
Dim strStatusAddr As String = CType(1000 + (2 * intDevicenumber), String)
Dim strBusInputAddr As String = CType(2000 + (2 * intDevicenumber), String)
Dim strInterlocksAddr As String = CType(3000 + (2 * intDevicenumber), String)
Dim strFirstUpAddr As String = CType(4000 + (2 * intDevicenumber), String)
Dim strAuxilaryAddr As String = CType(5000 + (2 * intDevicenumber), String)
Dim strAnalog_InAddr As String = CType(6000 + (2 * intDevicenumber), String)
Dim strDelay_HLAddr As String = CType(7000 + (2 * intDevicenumber), String)
Dim strDelay_HHLLAddr As String = CType(7001 + (2 * intDevicenumber), String)
Dim strNo_ErrorsAddr As String = CType(8000 + (2 * intDevicenumber), String)
Dim strLLow_LimitAddr As String = CType(9000 + (2 * intDevicenumber), String)
Dim strLow_LimitAddr As String = CType(10000 + (2 * intDevicenumber), String)
Dim strPV_ValueAddr As String = CType(11000 + (2 * intDevicenumber), String)
Dim strHHigh_LimitAddr As String = CType(12000 + (2 * intDevicenumber), String)
Dim strHigh_LimitAddr As String = CType(13000 + (2 * intDevicenumber), String)
Dim strHysteresis_ValueAddr As String = CType(14000 + (2 * intDevicenumber), String)
Dim strReal_ValueAddr As String = CType(15000 + (2 * intDevicenumber), String)
'Command Word
Dim strCommand = "Command: R" & strCommandAddr
Dim strBypass_Req = "Bypass_Req: R" & strCommandAddr & ".0"
Dim strCommand_9 = "Command_9: R" & strCommandAddr & ".1"
Dim strReset_Req = "Reset_Req: R" & strCommandAddr & ".2"
Dim strCommand_B = "Command_B: R" & strCommandAddr & ".3"
Dim strCommand_C = "Command_C: R" & strCommandAddr & ".4"
Dim strCommand_D = "Command_D: R" & strCommandAddr & ".5"
Dim strCommand_E = "Command_E: R" & strCommandAddr & ".6"
Dim strCommand_F = "Command_F: R" & strCommandAddr & ".7"
Dim strCommand_0 = "Command_0: R" & strCommandAddr & ".8"
Dim strCommand_1 = "Command_1: R" & strCommandAddr & ".9"
Dim strCommand_2 = "Command_2: R" & strCommandAddr & ".A"
Dim strCommand_3 = "Command_3: R" & strCommandAddr & ".B"
Dim strCommand_4 = "Command_4: R" & strCommandAddr & ".C"
Dim strCommand_5 = "Command_5: R" & strCommandAddr & ".D"
Dim strActive_Req = "Active_Req: R" & strCommandAddr & ".E"
Dim strSimulate_Req = "Simulate_Req: R" & strCommandAddr & ".F"
Dim strCommandWordString As String = strCommand & vbLf &
strBypass_Req & vbLf &
strCommand_9 & vbLf &
strReset_Req & vbLf &
strCommand_B & vbLf &
strCommand_C & vbLf &
strCommand_D & vbLf &
strCommand_E & vbLf &
strCommand_F & vbLf &
strCommand_0 & vbLf &
strCommand_1 & vbLf &
strCommand_2 & vbLf &
strCommand_3 & vbLf &
strCommand_4 & vbLf &
strCommand_5 & vbLf &
strActive_Req & vbLf &
strSimulate_Req
'Alarm Word
Dim strAlarm = "Alarm: R" & strAlarmAddr
Dim strAlarm_8 = "Alarm_8: R" & strAlarmAddr & ".0"
Dim strAlarm_9 = "Alarm_9: R" & strAlarmAddr & ".1"
Dim strAlarm_A = "Alarm_A: R" & strAlarmAddr & ".2"
Dim strAlarm_B = "Alarm_B: R" & strAlarmAddr & ".3"
Dim strAlarm_C = "Alarm_C: R" & strAlarmAddr & ".4"
Dim strBus_FU = "Bus_FU: R" & strAlarmAddr & ".5"
Dim strAlarm_E = "Alarm_E: R" & strAlarmAddr & ".6"
Dim strAlarm_F = "Alarm_F: R" & strAlarmAddr & ".7"
Dim strAlarm_0 = "Alarm_0: R" & strAlarmAddr & ".8"
Dim strAlarm_1 = "Alarm_1: R" & strAlarmAddr & ".9"
Dim strAlarm_2 = "Alarm_2: R" & strAlarmAddr & ".A"
Dim strAlarm_3 = "Alarm_3: R" & strAlarmAddr & ".B"
Dim strInst_FU = "Inst_FU: R" & strAlarmAddr & ".C"
Dim strAlarm_5 = "Alarm_5: R" & strAlarmAddr & ".D"
Dim strAlarm_6 = "Alarm_6: R" & strAlarmAddr & ".E"
Dim strAlarm_7 = "Alarm_7: R" & strAlarmAddr & ".F"
Dim strAlarmWordString As String = strAlarm & vbLf &
strAlarm_8 & vbLf &
strAlarm_9 & vbLf &
strAlarm_A & vbLf &
strAlarm_B & vbLf &
strAlarm_C & vbLf &
strBus_FU & vbLf &
strAlarm_E & vbLf &
strAlarm_F & vbLf &
strAlarm_0 & vbLf &
strAlarm_1 & vbLf &
strAlarm_2 & vbLf &
strAlarm_3 & vbLf &
strInst_FU & vbLf &
strAlarm_5 & vbLf &
strAlarm_6 & vbLf &
strAlarm_7
'Status Word
Dim strStatus = "Status: R" & strStatusAddr
Dim strStatus_18 = "Status_18: R" & strStatusAddr & ".0"
Dim strStatus_19 = "Status_19: R" & strStatusAddr & ".1"
Dim strBus_Healthy = "Bus_Healthy: R" & strStatusAddr & ".2"
Dim strStatus_1B = "Status_1B: R" & strStatusAddr & ".3"
Dim strStatus_1C = "Status_1C: R" & strStatusAddr & ".4"
Dim strStatus_1D = "Status_1D: R" & strStatusAddr & ".5"
Dim strStatus_1E = "Status_1E: R" & strStatusAddr & ".6"
Dim strStatus_1F = "Status_1F: R" & strStatusAddr & ".7"
Dim strStatus_10 = "Status_10: R" & strStatusAddr & ".8"
Dim strStatus_11 = "Status_11: R" & strStatusAddr & ".9"
Dim strStatus_12 = "Status_12: R" & strStatusAddr & ".A"
Dim strStatus_13 = "Status_13: R" & strStatusAddr & ".B"
Dim strStatus_14 = "Status_14: R" & strStatusAddr & ".C"
Dim strStatus_15 = "Status_15: R" & strStatusAddr & ".D"
Dim strStatus_16 = "Status_16: R" & strStatusAddr & ".E"
Dim strStatus_17 = "Status_17: R" & strStatusAddr & ".F"
Dim strStatus_08 = "Status_08: R" & CStr(CSng(strStatusAddr) + 1) & ".0"
Dim strStatus_09 = "Status_09: R" & CStr(CSng(strStatusAddr) + 1) & ".1"
Dim strStatus_0A = "Status_0A: R" & CStr(CSng(strStatusAddr) + 1) & ".2"
Dim strInst_FU_Activate = "Inst_FU_Activate: R" & CStr(CSng(strStatusAddr) + 1) & ".3"
Dim strStatus_0C = "Status_0C: R" & CStr(CSng(strStatusAddr) + 1) & ".4"
Dim strBypass = "Bypass: R" & CStr(CSng(strStatusAddr) + 1) & ".5"
Dim strSimulate = "Simulate: R" & CStr(CSng(strStatusAddr) + 1) & ".6"
Dim strStatus_0F = "Status_0F: R" & CStr(CSng(strStatusAddr) + 1) & ".7"
Dim strLLow_State = "LLow_State: R" & CStr(CSng(strStatusAddr) + 1) & ".8"
Dim strLow_State = "Low_State: R" & CStr(CSng(strStatusAddr) + 1) & ".9"
Dim strHigh_State = "High_State: R" & CStr(CSng(strStatusAddr) + 1) & ".A"
Dim strHHigh_State = "HHigh_State: R" & CStr(CSng(strStatusAddr) + 1) & ".B"
Dim strUnder_Range_Fault = "Under_Range_Fault: R" & CStr(CSng(strStatusAddr) + 1) & ".C"
Dim strOver_Range_Fault = "Over_Range_Fault: R" & CStr(CSng(strStatusAddr) + 1) & ".D"
Dim strInstrument_Error = "Instrument_Error: R" & CStr(CSng(strStatusAddr) + 1) & ".E"
Dim strStatus_07 = "Status_07: R" & CStr(CSng(strStatusAddr) + 1) & ".F"
Dim strStatusWordString As String = strStatus & vbLf &
strStatus_18 & vbLf &
strStatus_19 & vbLf &
strBus_Healthy & vbLf &
strStatus_1B & vbLf &
strStatus_1C & vbLf &
strStatus_1D & vbLf &
strStatus_1E & vbLf &
strStatus_1F & vbLf &
strStatus_10 & vbLf &
strStatus_11 & vbLf &
strStatus_12 & vbLf &
strStatus_13 & vbLf &
strStatus_14 & vbLf &
strStatus_15 & vbLf &
strStatus_16 & vbLf &
strStatus_17 & vbLf &
strStatus_08 & vbLf &
strStatus_09 & vbLf &
strStatus_0A & vbLf &
strInst_FU_Activate & vbLf &
strStatus_0C & vbLf &
strBypass & vbLf &
strSimulate & vbLf &
strStatus_0F & vbLf &
strLLow_State & vbLf &
strLow_State & vbLf &
strHigh_State & vbLf &
strHHigh_State & vbLf &
strUnder_Range_Fault & vbLf &
strOver_Range_Fault & vbLf &
strInstrument_Error & vbLf &
strStatus_07
Dim strBusInput = "BusInput: R" & strBusInputAddr
Dim strInterlocks = "Interlocks: R" & strInterlocksAddr
Dim strFirstUp = "FirstUp: R" & strFirstUpAddr
strDUTValue = strCommandWordString & vbLf & strAlarmWordString & vbLf & strStatusWordString & vbLf & strBusInput & vbLf &
strInterlocks & vbLf & strFirstUp & vbLf & strAuxilaryWordString & vbLf &
strAnalog_In & vbLf & strDelay_HL & vbLf & strDelay_HHLL & vbLf & strNo_Errors & vbLf &
strLLow_Limit & vbLf & strLow_Limit & vbLf & strPV_Value & vbLf & strHHigh_Limit & vbLf &
strHigh_Limit & vbLf & strHysteresis_Value & vbLf & strReal_Value
Return strDUTValue
End Function
#End Region
All advice appreciated.
Last edited by Slabs1960; Jul 12th, 2017 at 08:57 AM.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 09:56 AM
#2
Re: Should I use a Class instead of a Function
You have a function that takes two arguments and returns a string. That's pretty compact, regardless of what is happening in the body of the function. What advantage do you feel a class would provide?
Much of the length of the code is driven by the way you organized it, which I'd say is pretty reasonable. For example, you have a block of string variables that you create, then you put them all together. You could have avoided creating those string variables, but only at the cost of making a really long and complicated string even longer.
One thing you probably should look into for this is the StringBuilder class. Anytime you concatenate a string onto a different string, what happens is that a new string is created and both of the originals are copied to the new string, then the originals are abandoned. This is inefficient, but it only matters if you have LOTS of concatenation. I remember people (possibly including me) times how many concatenations were enough to justify switching to a StringBuilder, but I don't remember what the number was. You're over that number, no matter what it was. What the StringBuilder gives you is a resizable string, so you don't pay the cost of the copying every time you concatenate. You call Append or AppendLine, both of which are worth a look, in your case. AppendLine 'might' do what you are doing in lines such as the one where you fill strCommandWordString. It might not do that, either, since you are adding just a line feed, and AppendLine might add CRLF rather than just LF, so it might not work. Even without that, you could just call Append with the variable, then append with the LF. This would cut the number of lines of code down by a fair amount, and you wouldn't have to create all those local variables.
My usual boring signature: Nothing
-
Jul 12th, 2017, 10:47 AM
#3
Re: Should I use a Class instead of a Function
I don't think it's as important to ask, "Should I use a class or a function here?" as it is to realize you did something important: you recognized this is a very complicated chunk of code and you'd like to simplify it.
I'm going to compliment you up-front: you have properly represented this problem as "the final string is made of several smaller strings that, in turn, consist of even smaller strings." You've carefully made each calculation its own individual variable, and you build them all in a "bottom-up" fashion. This is the way a professional thinks, and it makes it really easy to decompose the problem further and try to yield some simplification.
"Less complex" won't mean "fewer lines", and rarely does. In this case, if we're going to make a class for doing this, "less complex" takes the form of being able to use new names describing what we're doing as opposed to how it's done. You're building a ton of strings and gluing them together in a specific order, there's no way to make that "simple". But there are ways to make it look a little more methodical.
It's big enough I don't think I can write an entire class to help out, but here's the kind of thing I mean.
It doesn't compile as-is, I think towards the bottom variables like 'strAnalog_In' were meant to reference 'strAnalog_InAddr'? I'm going to go on that assumption. What I see in that first big chunk of variables is a repeated calculation:
Code:
0 + (2 * intDevicenumber)
1 + (2 * intDevicenumber)
...
So that's the first 'optimization' I'd make, you want to form a formatted string based on that calculation, this is a good way to subdivide into a function:
Code:
Function GetAddress(ByVal offset As Integer, ByVal deviceNumber As Int16) As String
Dim address As Integer = offset + (2 * deviceNumber)
Return address.ToString()
End Function
That simplifies the lines slightly:
Code:
Dim commandAddress As String = GetAddress(0, deviceNumber)
Dim alarmAddress As String = GetAddress(1, deviceNumber)
...
Let's look at the next "chunk", the code that builds 'strCommandWordString". (By the way, don't you think that variable name's wordy? The 'str' stands for "String", which is also at the end. I'd have just called it 'commandWord' instead of "stringCommandWordString".)
Each bit is built from formatting a command, the variable 'strCommandAddress', and an optional number. Helper methods for this could make it a little cleaner. Here's the helper methods I'd use:
Code:
Private Sub AppendCommandTo(ByVal builder As StringBuilder, ByVal prefix As String, ByVal suffix As String)
builder.AppendFormat("{0}{1}{2}{3}", prefix, commandAddress, suffix, vbLf)
End Sub
With that in place:
Code:
Dim commandWordBuilder As New StringBuilder()
AppendCommandTo(commandWordBuilder, "Command: R", "")
AppendCommandTo(commandWordBuilder, "Bypass_Req: R", ".0")
AppendCommandTo(commandWordBuilder, "Command_9: R", ".0")
...
Dim commandWord As String = builder.ToString()
The Alarm and Status words are built in very similar fashions. One thing I want to call out, take a look at this:
Code:
Cstr(CSng(strStatusAddr))
'strStatusAddr' is a String. This code says, "Convert the String to a Single, then convert the Single to a String". Is there a good reason for doing that? It seems silly, and if there's some reason there might be a better way to make it clear.
You could certainly move all this code into another class, but I think the best first step is making helper methods so your code more properly explains what it is doing rather than how. The final string could be built up more compactly with a loop over an array:
Code:
Dim resultComponents() As String = { commandWord, alarmWord, statusWord, busInput, ..., real_value }
Dim resultBuilder As New StringBuilder()
For Each component In resultComponents
resultBuilder.AppendFormat("{0}{1}", component, vbLf)
Next
Return resultBuilder.ToString()
This makes it easier to reorder/tweak the string without making errors.
So I wouldn't say any of this is making the code "less complicated", but it does make it "easier to change".
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jul 12th, 2017, 12:01 PM
#4
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Thanks Sitten Spynne , Shaggy Hiker for the great replies and compliments .
'strStatusAddr' is a String. This code says, "Convert the String to a Single, then convert the Single to a String". Is there a good reason for doing that? It seems silly, and if there's some reason there might be a better way to make it clear.
The reason for this that the "Device Number" comes in as a string. So in order to do the calculation I need to convert to a integer. The result has to be a string, it is converted back to a string. Not sure if there is a simpler way to do this.
Let's look at the next "chunk", the code that builds 'strCommandWordString". (By the way, don't you think that variable name's wordy? The 'str' stands for "String", which is also at the end. I'd have just called it 'commandWord' instead of "stringCommandWordString".)
I missed that. You are correct and I will fix it.
What the StringBuilder gives you is a resizable string, so you don't pay the cost of the copying every time you concatenate
The string structure will never change (the PLC expects it this format). That said, I will definitely look into the "StringBuilder" class. The concatenation at the end of each word bothered me from the beginning.
I like my code to be simple and easily readable (there will be others maintaining it, later)
The reason I asked the question is, that I have been reading up on classes and wondered if this is an ideal case to use a class. I do not need to change it. Part of the learning process.
Last edited by Slabs1960; Jul 12th, 2017 at 12:19 PM.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 12:15 PM
#5
Re: Should I use a Class instead of a Function
Oh! I didn't see the "+ 1" in that spot. Easy to miss when so much is going on. But there's a better way to go about it.
In about a dozen places, you need to get statusAddr as an Integer rather than a String. I'd be real careful about just using Single here, that's a floating-point number so if you really want an Integer you're inviting disaster if you don't convert to Integer. So here's what I'd do.
'statusAddress' is calculated as a String up top, based on a calculation. You also use 'statusAddress + 1' on about a dozen different occasions. So I'd make a new variable up-top:
Code:
Dim statusAddress = GetAddress(1000, deviceNumber)
Dim statusAddressPlusOne = GetAddress(1001, deviceNumber)
Then just use that in all the cases where you want an offset.
There's some other approaches. Maybe you should just leave all of those addresses as Integers. All of the string formatting calls are fine with converting integers to Strings:
Code:
Dim statusAddress As Integer = 1000
Dim builder As New StringBuilder()
builder.AppendFormat("{0}{1}{2}", "Command:", statusAddress + 1, ".1")
Console.WriteLine(builder.ToString)
' Command:1001.1
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jul 12th, 2017, 12:24 PM
#6
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Oh! I didn't see the "+ 1" in that spot. Easy to miss when so much is going on. But there's a better way to go about it
There is always ONE exception to mess up a simple pattern
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 01:17 PM
#7
Re: Should I use a Class instead of a Function
i would do this completely different. it seems the message header you generate always has the same format. i would have a template for that and search/replace keywords such as ***strCommandAddr*** and ***strAlarmAddr***.
i think this will make the code much much more readable and maintainable.
-
Jul 12th, 2017, 01:46 PM
#8
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Originally Posted by digitalShaman
i would do this completely different. it seems the message header you generate always has the same format. i would have a template for that and search/replace keywords such as ***strCommandAddr*** and ***strAlarmAddr***.
i think this will make the code much much more readable and maintainable.
The format will always be the same. But I do not understand what you are saying. Please explain.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 01:59 PM
#9
Re: Should I use a Class instead of a Function
do you use 2015+? if so you can use interpolated strings:
Code:
Dim intDevicenumber As Int16 = CType(strDeviceNumber, Int16)
Dim strCommandAddr As String = CType(0 + (2 * intDevicenumber), String)
Dim strAlarmAddr As String = CType(1 + (2 * intDevicenumber), String)
Dim sHeader As String =
$"Command: R{strCommandAddr}
Bypass_Req: R{strCommandAddr}.0
Command_9: R{strCommandAddr}.1
Reset_Req: R{strCommandAddr}.2
Command_B: R{strCommandAddr}.3
Command_C: R{strCommandAddr}.4
Command_D: R{strCommandAddr}.5
Command_E: R{strCommandAddr}.6
Command_F: R{strCommandAddr}.7
Command_0: R{strCommandAddr}.8
Command_1: R{strCommandAddr}.9
Command_2: R{strCommandAddr}.A
Command_3: R{strCommandAddr}.B
Command_4: R{strCommandAddr}.C
Command_5: R{strCommandAddr}.D
Active_Req: R{strCommandAddr}.E
Simulate_Req: R{strCommandAddr}.F
Alarm: R{strAlarmAddr}
Alarm_8: R{strAlarmAddr}.0
Alarm_9: R{strAlarmAddr}.1
Alarm_A: R{strAlarmAddr}.2
Alarm_B: R{strAlarmAddr}.3
Alarm_C: R{strAlarmAddr}.4
Bus_FU: R{strAlarmAddr}.5
Alarm_E: R{strAlarmAddr}.6
Alarm_F: R{strAlarmAddr}.7
Alarm_0: R{strAlarmAddr}.8
Alarm_1: R{strAlarmAddr}.9
Alarm_2: R{strAlarmAddr}.A
Alarm_3: R{strAlarmAddr}.B
Inst_FU: R{strAlarmAddr}.C
Alarm_5: R{strAlarmAddr}.D
Alarm_6: R{strAlarmAddr}.E
Alarm_7: R{strAlarmAddr}.F
Status: R1002
Status_18: R1002.0
Status_19: R1002.1
Bus_Healthy: R1002.2
Status_1B: R1002.3
Status_1C: R1002.4
Status_1D: R1002.5
Status_1E: R1002.6
Status_1F: R1002.7
Status_10: R1002.8
Status_11: R1002.9
Status_12: R1002.A
Status_13: R1002.B
Status_14: R1002.C
Status_15: R1002.D
Status_16: R1002.E
Status_17: R1002.F
Status_08: R1003.0
Status_09: R1003.1
Status_0A: R1003.2
Inst_FU_Activate: R1003.3
Status_0C: R1003.4
Bypass: R1003.5
Simulate: R1003.6
Status_0F: R1003.7
LLow_State: R1003.8
Low_State: R1003.9
High_State: R1003.A
HHigh_State: R1003.B
Under_Range_Fault: R1003.C
Over_Range_Fault: R1003.D
Instrument_Error: R1003.E
Status_07: R1003.F
BusInput: R2002
Interlocks: R3002
FirstUp: R4002"
return sHeader & vblf & strAuxilaryWordString & vbLf &
strAnalog_In & vbLf & strDelay_HL & vbLf & strDelay_HHLL & vbLf & strNo_Errors & vbLf &
strLLow_Limit & vbLf & strLow_Limit & vbLf & strPV_Value & vbLf & strHHigh_Limit & vbLf &
strHigh_Limit & vbLf & strHysteresis_Value & vbLf & strReal_Value
if you cant use interpolated strings then loop over the template and do serach replace "{strCommandAddr}"->strCommandAddr.tostring etc.
you have to add the other vars to the template yourself, i am just showing how i'd go about it.
maybe the same is true for the rest of the message? does it really take to send all that stuff everytime?
-
Jul 12th, 2017, 02:03 PM
#10
Re: Should I use a Class instead of a Function
and in regards to the class/function question: it is clearly a function. the question is: is it a method of a class? private/public? is there maybe a class PLC? you see?
-
Jul 12th, 2017, 02:08 PM
#11
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Using VS2017. Forgot to add it to the post.
I think I get the idea. Will give it a try.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 02:11 PM
#12
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
maybe the same is true for the rest of the message? does it really take to send all that stuff everytime?
This is a device type. Depending on the size of the Process Plant, there could be 50 to 60 of them, identical except for a unique TagName and Device number. To add them to the PLC by manually could take a day or so. Doing it this way, few seconds.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 02:33 PM
#13
Re: Should I use a Class instead of a Function
The trouble with that approach is:
How do you guarantee it's using an LF as the line separator instead of the more standard CRLF?
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jul 12th, 2017, 02:50 PM
#14
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
CRLF does not work. Has to a LF only
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 02:59 PM
#15
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Originally Posted by digitalShaman
and in regards to the class/function question: it is clearly a function. the question is: is it a method of a class? private/public? is there maybe a class PLC? you see?
This is a good question. I am not an expert, but from my reading the same questions passed through my mind.
The only way to answer that one is for me to submit a post explaining what my whole project is all about. That will be a long one, but might be worth the while. There is a whole lot of processes involved. The bottom line is that I can automate 80% of the PLC & Scada software development using VB. This saves 3 to 6 weeks of manual engineering time, with the associated finger problems.
When I get a gap I may just do that.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 12th, 2017, 04:40 PM
#16
Re: Should I use a Class instead of a Function
If it is possible, you might try sending with a CRLF rather than an LF. It will either work or fail. If it works, then that would be a good thing, because CRLF is MUCH more common than just the LF.
My usual boring signature: Nothing
-
Jul 13th, 2017, 01:15 AM
#17
Re: Should I use a Class instead of a Function
Originally Posted by Sitten Spynne
The trouble with that approach is:
How do you guarantee it's using an LF as the line separator instead of the more standard CRLF?
thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...
if there is no consitency then one could still explicitly add the LFs to the template. or replace CRLFs to LFs afterwards etc. many ways. the Point that i wanted to make is that instead of that concats the code gets much more readable using a template.
The only way to answer that one is for me to submit a post explaining what my whole project is all about. That will be a long one, but might be worth the while. There is a whole lot of processes involved.
yes, maybe you should do this. it could help you getting Input how others would design the code.
This saves 3 to 6 weeks of manual engineering time, with the associated finger problems.
this sounds archaic
-
Jul 13th, 2017, 12:16 PM
#18
Thread Starter
Addicted Member
Re: Should I use a Class instead of a Function
Originally Posted by digitalShaman
thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...
if there is no consitency then one could still explicitly add the LFs to the template. or replace CRLFs to LFs afterwards etc. many ways. the Point that i wanted to make is that instead of that concats the code gets much more readable using a template.
yes, maybe you should do this. it could help you getting Input how others would design the code.
this sounds archaic
This is PLC's (Programmable Logic Controllers by Siemens, Schneider Electric, Mitsubishi & Allen Bradley) we talking about. Some of these are form based. Uugh.
I can fix what stupid does, but, I cannot fix stupid
-
Jul 13th, 2017, 02:06 PM
#19
Re: Should I use a Class instead of a Function
thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...
ahh, after project reopen: "The line endings in the following file are inconsistent do you want to normalize?"
i remember i was running the function, dumping the result into a file, open with text editor and copy pasted into the project. that makes sense. but actually a bad idea as at some point in time someone will normalize the lineendings and break the code without even knowing. a timebomb good that vs warns about this.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|