Announcement

Collapse
No announcement yet.

Substrings from Offsets in a string

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    George,
    I'm not sure how your main string is parsed but this might give you another alternative especially if there are MANY calls to your subs.

    James

    Code:
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    'SED_PBCC
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    #COMPILE EXE
    #DIM ALL
    '==============================================================================
    SUB TestIt(S3 AS STRING )
        PRINT "TestIt -> "; S3 
    END SUB
    
    '==============================================================================
    FUNCTION PBMAIN () AS LONG
        LOCAL S1,S2 AS STRING
        LOCAL WhereIsIt() AS DWORD
        LOCAL idx,dwIdx,i AS LONG
        LOCAL bPtr1,bPtr2 AS BYTE PTR
        
        LOCAL dwPtr AS DWORD PTR
        DIM WhereIsIt(100)
        
        
        
        S1 = "One,Two,Three,Four,Five"
        S2 = STRING$(1000,0)
        bPtr1 = STRPTR(S1)
        dwPtr = STRPTR(S2)
        bPtr2 = dwPtr + 4
        
        WhereIsIt(0) = bPtr2
        
        DO      
            IF @bPtr1 = 44 OR @bPtr1 = 0 THEN
                @dwPtr = idx            
                dwPtr = bPtr2            
                bPtr2 = dwPtr+4
                idx = 0
                INCR dwIdx
                WhereIsIt(dwIdx) = bPtr2                        
                IF @bPtr1 = 0 THEN
                    EXIT LOOP
                END IF    
                INCR bPtr1
                ITERATE
            END IF
            @bPtr2 = @bPtr1
            INCR bPtr1
            INCR bPtr2
            
            INCR idx 
        LOOP
    
        FOR i = 0 TO 4
            TestIt BYVAL VARPTR(WhereIsIt(i))
        NEXT i
        WAITKEY$
    END FUNCTION

    Comment


    • #42
      Originally posted by Bob Zale View Post
      How soon they forget... {smile}

      [/B]The ASCIIZ method method above will use two (2) temp strings and three (3) copy operations of the text.

      Best of luck,

      Bob Zale
      PowerBASIC Inc.
      Bob what documentation did I forget?
      The following compiles fine
      Code:
      FUNCTION PBMAIN () AS LONG
      
          LOCAL t AS ASCIIZ *100000
          LOCAL s AS STRING
          s = SPACE$(1000)
          t = MID$(s, 100,100) + CHR$(0)
      END FUNCTION
      so I would need to decompile to determine that there was a surprising number of temp strings used in the middle, in which case Micheals code surely would be faster.
      The requirement for printing the text to a graphic to be an OLE string must be a PB implementation. TextOutA requires a pointer to a buffer and the number of characters not a pointer to an OLE string.
      If speed is the issue in this application then by using Windows API functions there isn't even any need to extract the substring, merley pass a pointer to the first character and the number of characters (obviously with the other paramaters such as Hdc etc after having set the text format)
      John

      Comment


      • #43
        Originally posted by Bob Zale View Post
        Hi George--

        "Cloning my SUBs and altering the passed parameter from STRING to FIELD works perfectly, so obviously FIELDed variables act just like normal strings (which is what they're supposed to)."

        That is not a correct inference. At some point, this will fail. Dramatically.

        Bob Zale
        PowerBASIC Inc.
        OK Bob, I'll bow to the expert, but GRAPHIC PRINT seems to have no problem handling the passed FIELD variable as input. So far ... )

        I have the new code plugged into my main app now, and I almost hate to say this after all the work various people here have done, but I tried swapping from using FIELD, which seemingly worked OK, to the original method of using MID$ and frankly I can detect no external speed difference. Maybe PB's string handling is just too efficient.

        I guess growing up in the programming of 40 years ago, where we'd code critical routines with the hardware timing manual open, I can't get used to the incredible speed of todays systems and I'm always fretting over the 'cost' of various routines.

        For those who experimented with routines etc. many thanks, I learned even more. I'm also not imune to programming challenges, so I know why you did it.

        I'll heed Bob Zales warning, but I wish I understood better what he means by 'fail, disastously'.

        Thanks again to all of you.
        George

        Comment


        • #44
          Saying these are all correct. Which is the best?

          Code:
          'TestCopyMemory.bas
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "win32api.inc"
          FUNCTION PBMAIN () AS LONG
             LOCAL pTo       AS BYTE PTR
             LOCAL pFrom     AS BYTE PTR
             LOCAL sTo       AS STRING
             LOCAL sFrom     AS STRING
             LOCAL x         AS LONG
             LOCAL Length    AS LONG
           
             FOR x = 1 TO 5
               sFrom  =  "123"  'init value
               Length = LEN(sFrom)
               sTo    =   STRING$(9,"-")    'init value
               pFrom  = 0
               pTo    = 0
               ON x GOSUB Test1,test2,test3,test4,test5  'don't see this every day
               ? sTo
             NEXT
             WAITKEY$
          EXIT FUNCTION
          Test1:
             pFrom   =       STRPTR(sFrom)              'Method 1  CopyMemory
             pTo     =       STRPTR(sTo)
             CopyMemory      pTo, pFrom, Length
          RETURN
          Test2:
             MID$(sTo,1)    = MID$(sFrom,1,Length)      'Method 2  MID$
          RETURN
          Test3:
             pFrom = STRPTR(sFrom)
             sTo = PEEK$(pFrom, Length)                 'Method 3  PEEK$ (wrong)
          RETURN
          Test4:
             pFrom   =       STRPTR(sFrom)              'Method 4  POKE$/PEEK$
             pTo     =       STRPTR(sTo)                
             POKE$ pTo, PEEK$(pFrom, Length)
          RETURN
          Test5:
             LSET ABS sTo = sFrom                       'Method 5  Don't pad
          RETURN
          END FUNCTION
          Last edited by Mike Doty; 9 Apr 2008, 01:19 PM. Reason: All values were not init, STRPTR needed.

          Comment


          • #45
            Which is best?

            Depends on what "best" means.

            Which in turn, depends on context.

            Which in turn means, "ALL OPTIMIZATION IS APPLICATION-SPECIFIC"

            In your case, since the substring you need must be passed to a GRAPHICS statement which requires a dynamic string as a parameter, at some point that dynamic string must be created, period.

            You can create it with your code with MID$() or PEEK$(). OR, you can let the compiler create it in the background as required from a working buffer. Six of one, half of dozen the other.
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #46
              Actually, this is George's posting.
              I think going with the compiler instead of the API is better because in
              the future if the compiler is updated the code is updated with it.
              To eliminate temp strings the best is?

              Comment


              • #47
                Well, you don't have to Thank me for this George, because as you say, programming challenges get our blood flowing. So I couldn't resist trying this what with all the talk and grief with temp string creation and so forth.
                Here's my technique with no new memory allocations, and no movement of bytes from the original 'given' string to some other location. Should this not be even more efficient than Mid$()?

                From your original post you said you had a big string composed of sub strings, and for each substring you had a length and offset.

                So in fnWndProc_OnPaint(...) below I build up a main string like this...

                Twenty five
                Twenty fiveFifty
                Twenty fiveFiftySeventy five
                Twenty fiveFiftySeventy fiveOne hundred etc

                I had code already to create the strings from integers. I just ran 25 to 500 through a loop concatenating all the way. During the concatenation in the loop I saved the lengths and offsets.

                Now, in the creation of the strings piles of memory thrashing and temp strings would have been involved - but you said in your program that that was a given or input.

                In the DrawText() output I just printed each string through its offset address and lengths. Unless DrawText() creates tmp strings in its processing, none were used by me.

                Try this..
                (it only took an hour)
                Code:
                #Compile Exe
                #Include "Win32api.inc"
                
                Type WndEventArgs
                  wParam               As Long
                  lParam               As Long
                  hWnd                 As Dword
                  hInst                As Dword
                End Type
                
                
                Function OneDigit$ (strNum As String)
                  Select Case strNum
                    Case "0"
                      OneDigit$ = "zero"
                    Case "1"
                      OneDigit$ = "one"
                    Case "2"
                      OneDigit$ = "two"
                    Case "3"
                      OneDigit$ = "three"
                    Case "4"
                      OneDigit$ = "four"
                    Case "5"
                      OneDigit$ = "five"
                    Case "6"
                      OneDigit$ = "six"
                    Case "7"
                      OneDigit$ = "seven"
                    Case "8"
                      OneDigit$ = "eight"
                    Case "9"
                      OneDigit$ = "nine"
                  End Select
                End Function
                
                
                Function TwoDigits$ (strNum As String)
                  If Left$(strNum, 1) = "1" Then
                     Select Case Right$(strNum, 1)
                       Case "0"
                         TwoDigits$ = "ten"
                       Case "1"
                         TwoDigits$ = "eleven"
                       Case "2"
                         TwoDigits$ = "twelve"
                       Case "3"
                         TwoDigits$ = "thirteen"
                       Case "4"
                         TwoDigits$ = "fourteen"
                       Case "5"
                         TwoDigits$ = "fifteen"
                       Case "6"
                         TwoDigits$ = "sixteen"
                       Case "7"
                         TwoDigits$ = "seventeen"
                       Case "8"
                         TwoDigits$ = "eighteen"
                       Case "9"
                         TwoDigits$ = "nineteen"
                     End Select
                  Else
                     Select Case Left$(strNum, 1)
                       Case "0"
                         TwoDigits$=OneDigit$(Right$(strNum, 1))
                       Case "2"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "twenty "
                         Else
                            TwoDigits$ = "twenty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "3"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "thirty "
                         Else
                            TwoDigits$ = "thirty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "4"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "fourty "
                         Else
                            TwoDigits$ = "fourty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "5"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "fifty "
                         Else
                            TwoDigits$ = "fifty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "6"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "sixty "
                         Else
                            TwoDigits$ = "sixty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "7"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "seventy "
                         Else
                            TwoDigits$ = "seventy " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "8"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "eighty "
                         Else
                            TwoDigits$ = "eighty " + OneDigit$(Right$(strNum, 1))
                         End If
                       Case "9"
                         If Right$(strNum, 1) = "0" Then
                            TwoDigits$ = "ninety "
                         Else
                            TwoDigits$ = "ninety " + OneDigit$(Right$(strNum, 1))
                         End If
                     End Select
                  End If
                End Function
                
                
                Function ThreeDigits$ (strNum As String)
                  Local strFirst As String
                
                  Select Case Left$(strNum, 1)
                    Case "1"
                      strFirst="one hundred"
                    Case "2"
                      strFirst="two hundred"
                    Case "3"
                      strFirst="three hundred"
                    Case "4"
                      strFirst="four hundred"
                    Case "5"
                      strFirst="five hundred"
                    Case "6"
                      strFirst="six hundred"
                    Case "7"
                      strFirst="seven hundred"
                    Case "8"
                      strFirst="eight hundred"
                    Case "9"
                      strFirst="nine hundred"
                  End Select
                  If Right$(strNum,2)="00" Then
                     ThreeDigits$=strFirst
                  Else
                     ThreeDigits$=strFirst & " and " & TwoDigits(Right$(strNum,2))
                  End If
                End Function
                
                
                Function GetAlphaNumber(iNum As Long) As String
                  Local strCulls As String, strNumberCulls As String, strTmp As String
                  Local iLenStrCulls As Integer
                
                  strCulls = Str$(iNum)
                  iLenStrCulls = Len(strCulls)
                  Select Case iLenStrCulls
                    Case 2
                      strTmp = OneDigit$(Right$(strCulls, 1))
                    Case 3
                      strTmp = TwoDigits$(Right$(strCulls, 2))
                    Case 4
                      strTmp = ThreeDigits$(Right$(strCulls, 3))
                  End Select
                  Mid$(strTmp, 1, 1) = UCase$(Mid$(strTmp, 1, 1))
                
                  GetAlphaNumber = strTmp
                End Function
                
                
                Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                  Local lpCreateStruct As CREATESTRUCT Ptr
                
                  lpCreateStruct=Wea.lParam   'Can use GetModuleHandle() here instead, or, use Global (Hate Globals!)
                  [email protected]
                
                  fnWndProc_OnCreate=0
                End Function
                                 
                
                Function fnWndProc_OnPaint(Wea As WndEventArgs) As Long
                  Local lpPaint As PAINTSTRUCT
                  Local strMain,strTmp As String
                  Local iLen(),iOffset() As Long
                  Register i As Long
                  Local hDC As Long
                  Local rc As RECT
                  
                  Redim iLen(20),iOffset(20) As Long
                  For i=0 To 19
                    strTmp=GetAlphaNumber((i+1)*25)      'For i=0 strTmp will hold "Twenty five"
                    strMain=strMain+strTmp               'Keep concatenating each number converted to a string together
                    iLen(i)=Len(strTmp)                  'end to end.  Store Len(i) of each string
                    If i Then
                       iOffset(i)=iOffset(i-1)+iLen(i-1)
                    End If
                  Next i
                  hDC=BeginPaint(Wea.hWnd,lpPaint)
                  Call SetBkMode(hDC,%TRANSPARENT)
                  rc.nLeft=0 : rc.nRight=500
                  For i=0 To 19
                    rc.nBottom=rc.nTop+20
                    Call DrawText(hDC,Byval (Strptr(strMain)+iOffset(i)),iLen(i),rc,%DT_SINGLELINE)
                    rc.nTop=rc.nTop+20
                  Next i
                  Call EndPaint(Wea.hWnd,lpPaint)
                  Erase iLen,iOffset
                
                  fnWndProc_OnPaint=0
                End Function
                
                
                Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                  Call PostQuitMessage(0)
                  fnWndProc_OnDestroy=0
                End Function
                
                
                Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                  Static Wea As WndEventArgs
                
                  Select Case As Long wMsg
                    Case %WM_CREATE
                      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                      fnWndProc=fnWndProc_OnCreate(Wea)
                      Exit Function
                    Case %WM_PAINT
                      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                      fnWndProc=fnWndProc_OnPaint(Wea)
                      Exit Function
                    Case %WM_DESTROY
                      Call PostQuitMessage(0)
                      fnWndProc=fnWndProc_OnDestroy(Wea)
                      Exit Function
                  End Select
                
                  fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                End Function
                
                Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                  Local winclass As WndClassEx
                  Local szAppName As Asciiz*16
                  Local Msg As tagMsg
                  Local hWnd As Dword
                
                  szAppName="StrangeStuff"
                  winclass.cbSize=SizeOf(winclass)
                  winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                  winclass.lpfnWndProc=CodePtr(fnWndProc)
                  winclass.cbClsExtra=0
                  winclass.cbWndExtra=0
                  winclass.hInstance=hIns
                  winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                  winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                  winclass.hbrBackground=%COLOR_BTNFACE+1
                  winclass.lpszMenuName=%NULL
                  winclass.lpszClassName=VarPtr(szAppName)
                  Call RegisterClassEx(winclass)
                  hWnd=CreateWindow(szAppName,"StrangeStuff",%WS_OVERLAPPEDWINDOW,200,100,525,500,0,0,hIns,ByVal 0)
                  Call ShowWindow(hWnd,iShow)
                  While GetMessage(Msg,%NULL,0,0)
                    TranslateMessage Msg
                    DispatchMessage Msg
                  Wend
                
                  Function=msg.wParam
                End Function
                Fred
                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                Comment


                • #48
                  Is is possible that the design itself - using "one big string" and requiring substrings - could be changed to use an array() of the substrings? That would end the debate for sure.
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #49
                    Originally posted by Fred Harris View Post
                    Should this not be even more efficient than Mid$()?
                    Unless DrawText() creates tmp strings in its processing, none were used by me.
                    Fred you are correct, DrawText() does not use OLE Strings, just a buffer and a number of characters, depending on the use it can be slightly slower than TextOut (which PB actually uses) as it does formatting ie expanding tabs, justification etc inside a given rectangle.
                    Mike Doty
                    I think going with the compiler instead of the API is better because in
                    the future if the compiler is updated the code is updated with it.
                    To eliminate temp strings the best is?
                    Actually Mike no, it is the other way around DrawText and TextOut are both API functions, upgrades to the compiler don't change API functions, changes to the OS do that, however one would expect the compiler to upgrade to match changes in the OS. As M$ has a pretty good policy on backward compatability the compiler has lots of time to catch up, ie in PB the very limited assembler instruction set (yes I know thats a hardware example not OS). Simple answer to your question, use the API.
                    John

                    Comment


                    • #50
                      Mike--

                      You're very perceptive, and I think you have the best approach.

                      Best regards,

                      Bob Zale
                      PowerBASIC Inc.

                      Comment


                      • #51
                        George--

                        The truth is, if you just continue to take a reasonable approach to a problem, PowerBASIC will give you extraordinarily good performance. There's very little need to ever try to "trick" the compiler -- that usually backfires. Just take the obvious approach and I'll think you'll be very pleased with the results.

                        There's very little need to ever worry about an extra temp variable or two. PowerBASIC optimizes most out anyway... but even if there were ten or twenty per iteration, that would still only amount to a fraction of the time it takes to draw that text pixel-by-pixel on a graphical screen.

                        And remember, a STRING and a FIELD are two entirely different animals -- one's 4 bytes long, the other is 16. Though you can assign one to the other at any time, they cannot be "substituted" arbitrarily at the binary level.

                        Anyway, please ask questions! We'll try to help!

                        Bob Zale
                        PowerBASIC Inc.

                        Comment


                        • #52
                          Originally posted by Bob Zale View Post
                          George--

                          The truth is, if you just continue to take a reasonable approach to a problem, PowerBASIC will give you extraordinarily good performance. There's very little need to ever try to "trick" the compiler -- that usually backfires. Just take the obvious approach and I'll think you'll be very pleased with the results.

                          There's very little need to ever worry about an extra temp variable or two. PowerBASIC optimizes most out anyway... but even if there were ten or twenty per iteration, that would still only amount to a fraction of the time it takes to draw that text pixel-by-pixel on a graphical screen.

                          And remember, a STRING and a FIELD are two entirely different animals -- one's 4 bytes long, the other is 16. Though you can assign one to the other at any time, they cannot be "substituted" arbitrarily at the binary level.

                          Anyway, please ask questions! We'll try to help!

                          Bob Zale
                          PowerBASIC Inc.
                          Thanks Bob, as I said, it seems this is mostly paranoia on my part, based on an ingrained disbelief of todays computer speeds. Obviously from now on I should just go ahead and try something and ask for help when itdoesn't perform well enough, rather than anticipating problems that might not even be there.

                          Michael: Yes, maybe data restructuring might be in order, but when adding functions to an App, the tendency is to leave working code alone. In this case it would be major tinkering. And yes, I'm well aware of spaghetti code and its problems, but for me this is. a hobby.

                          George

                          Comment


                          • #53
                            > the tendency is to leave working code alone. ...major tinkering.

                            I've seen that enough myself.

                            I remember once I had to modify some code (COBOL), which had obviously been updated mulitple times. The program was 1400 lines, many of which were IF.. ELSE.. ELSE.. ELSE... which were testing the same things over an over, and because COBOL does not have an "ELSEIF", the indenting made the code really hard to read...e.g.

                            Code:
                              IF  condition 
                                  dosomething
                              ELSE
                                IF condition
                                    dosomething
                                ELSE
                                    IF condition
                                       dosomething
                                    ELSE
                                        IF condition
                                           dosomething
                                        ELSE
                                         ...
                            So, starting with those 1400 lines of code, I added the client's changes and restructed the program to clean out all the duplicate code ..... new size was 360 lines. Just a bit easier to read and follow - AND maintain going forward. But it was quite an effort.

                            I believe all software has a finite 'maintainable life' measured in "changes." You reach a point where it is easier (read: less expensive) to just start over than it would be to insert additional changes AND know you haven't broken something else along the way.
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #54
                              Here Herrre MCM :beerglass: :beerglass:

                              I have one now that adding functionality, is playing HAVOC with what "Just works", and thinking "Leave functionality out, till I do a re-write" to add it in

                              "Scope-Creep" may kill the programmer, but being able to read your own code, learn from it, and adapt it to the concepts that "Creep" in, is what makes the programmer stronger.

                              Engineer's Motto: If it aint broke take it apart and fix it

                              "If at 1st you don't succeed... call it version 1.0"

                              "Half of Programming is coding"....."The other 90% is DEBUGGING"

                              "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                              Comment


                              • #55
                                Works for me Cliff! If it doesn't kill you it'll make you stronger!
                                Fred
                                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                Comment


                                • #56
                                  I really believe this "maintenance life" thing, and when that life is up you are better off just starting over, designing the applications to cleanly support all the features originally wanted, plus those which have been added since then, plus those you want to add now... AND allow for the possibility of still more modifications in the future.

                                  Too bad today's "managers" don't see this... and therefore refuse to budget resources (programming time) for these rewrites. Just another sign of how short-sighted many businesses are, thinking only of the current quarter's profits, unable to recognize that the object of the business is to have profits for many, many quarters into the future.
                                  Michael Mattias
                                  Tal Systems (retired)
                                  Port Washington WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #57
                                    One of the biggest reasons for these rewrites is hard-coded screens.
                                    My screens are now html so applications may not have to be re-coded.
                                    Screen management/dialogs should not be hard-coded in my opinion.

                                    Hard-coding values in a program can be eliminated by thinking to the
                                    future and loading values at startup. The key is a skeleton/template
                                    that you follow when starting new projects. I mentioned this years
                                    ago and got flamed. Boy, we are certainly getting off subject.


                                    How long is an idea?
                                    Last edited by Mike Doty; 11 Apr 2008, 08:38 AM. Reason: Added my favorite quote

                                    Comment


                                    • #58
                                      >can be eliminated by thinking ..

                                      Thinking solves a lot of problems.

                                      But only when you think about it.
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #59
                                        Originally posted by Michael Mattias View Post
                                        > I believe all software has a finite 'maintainable life' measured in "changes." You reach a point where it is easier (read: less expensive) to just start over than it would be to insert additional changes AND know you haven't broken something else along the way.
                                        Very true, when I was assigned maintenance on a program I'd never seen before, I was faced with this. If the change was much more than trivial, I usually opted for a major cleanup or total rewrite. I'd been burned WAY too many times before debugging someone else's bugs.
                                        Never told the boss, I'm also a firm believer in "forgiveness is easier than permission".
                                        George

                                        Comment


                                        • #60
                                          You know one sure sign a program has been changed "too many" times?

                                          A number of large IF ... ELSEIF...ELSEIF...ELSEIF blocks appearing multiple times.

                                          If you were going to have to support that many options to start with, surely you would have used either a SELECT CASE [ or EVALUATE in COBOL] block and/or arrays [tables in COBOL]

                                          That's where I got most of my savings when I reduced the program above. Not to mention, adding a few new items to a table is a heck of a lot easier than extending IF..ELSEIF in mutiple locations within the code.
                                          Michael Mattias
                                          Tal Systems (retired)
                                          Port Washington WI USA
                                          [email protected]
                                          http://www.talsystems.com

                                          Comment

                                          Working...
                                          X