Page 2 of 3 FirstFirst 123 LastLast
Results 41 to 80 of 85

Thread: GOSUB - Is it really bad?

  1. #41
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    Re: GOSUB - Is it really bad?

    I'm sure there are times when it may make sense to use a gosub though I am not sure there is ever truly a need for it. I suspect that the only reason it is there is for backward compatibility. In older forms of Basic I used them extensively and was quite happy when I started using a version that did not need them.

  2. #42
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,990

    Re: GOSUB - Is it really bad?

    I'm sure it's just there for backwards compatibility, as it is never essential. Even the folks who use it say that it makes more sense to them, or seems more reasonable for one case, or is more efficient for a specific case. So, if it were eliminated, code could still be written, the problem could still be solved, it would just be solved in a different fashion.
    My usual boring signature: Nothing

  3. #43
    Lively Member
    Join Date
    Jun 2016
    Posts
    109

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by Elroy View Post
    However, Tubus, when you say, "In the end, it boils down to: you cannot really hide complexity, you can only shift it around to different places", I suspect you may have a battle on your hands with that one.
    ... well, sometimes yes, you have a point with this one

  4. #44
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by tubus View Post
    In the end, it boils down to: you cannot really hide complexity, you can only shift it around to different places.
    Yes, and there is some misunderstanding what *is* complexity actually.

    From human point of view a long function is complex, a god-like class is complex and you reduce complexity by dividing functions/classes to become more manageable chunks. This usually requires writing more lines of code, which is counter-intuitive -- write more code, for something to become less complex.

    "When a solution is too complex, then you usually need *more* classes"
    -- Paulo Coelho

    cheers,
    </wqw>
    p.s. Trusting quotes on the internet. . .

  5. #45
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    @wqweto: That's a good point. For the coding I need to do, I frequently write very long procedures. IMHO, there's always some degree of judgment as to when I need to make another procedure. And, to some degree, it's a matter of personal taste. It's one of those things that's not terribly easy to nail down.

    As an example of how it can be a matter of personal taste, I've recently taken a project by The Trick (whom I consider to be, without question, one of the most brilliant programmers on these forums) and reworked it for my own purposes. Here's a certain procedure I started with:

    Code:
    
    Public Sub InitializeScene( _
               ByVal hwnd As Long)
    
        InitDevice hwnd
        InitLight
        InitCamera
        InitGrid
        InitSelectionBox
        InitTransformGizmo
    
        mlBackColor = RGB(&H30, &H3F, &H3F) ' // R B are swapped
    
    End Sub
    
    Each one of those Init... procedures was called only once. I'm just learning Dx9, and I found myself jumping around a lot trying to get my head around all those concepts. Therefore, with some additions for my own purposes, my incarnation of that same procedure looks like the following:

    Code:
    
    
    Friend Sub InitializeScene(ByVal hWnd As Long, Optional lBackBufferWidth As Long = 1920&, _
                                                   Optional lBackBufferHeight As Long = 1080&, _
                                                   Optional lBackColor As Long = &H0&)
        ' This gets everything needed for Direct3D up and running.
        ' There are several pre-determined and initial settings made below.
        '
        Dim uPP         As D3DPRESENT_PARAMETERS
        Dim uLight      As D3DLIGHT9
        '
        ' Some initial settings.
        mhWnd = hWnd
        mlBackBufferWidth = lBackBufferWidth                    ' This is the TOTAL width of the BackBuffer, and not just the Viewport setting.
        mlBackBufferHeight = lBackBufferHeight                  ' This is the TOTAL height of the BackBuffer, and not just the Viewport setting.
        mlBackColor = lBackColor                                ' BackColor of the entire scene.
        muInitialCameraPos = DxVec(-6!, 4!, -6!)                ' Initial camera position.  -6, 6, 4 in lab coordinates.
        '
        ' Initialize our mesh collection.  This ONLY contains things that will move with the grid.
        ' The grid and the camera's target mesh are NOT included.
        Set mcollMeshs = New Collection
        '
        ' Get Direct3D up and running.
        Set moD3Dx = Direct3DCreate9()
        '
        ' Initialize Direct3D device.
        With uPP
            .BackBufferCount = 1
            .Windowed = 1
            .SwapEffect = D3DSWAPEFFECT_DISCARD                     ' After swapping (.Present), discard old BackBuffers.  Discard is fastest.
            .EnableAutoDepthStencil = 1
            .AutoDepthStencilFormat = D3DFMT_D16
            '
            .PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE   ' This is necessary to keep the .Present method from slowing things down.
            '
            .BackBufferCount = 1
            .BackBufferFormat = D3DFMT_A8R8G8B8                     ' D3DFMT_X8R8G8B8, Let's use alpha (and not X).
            '
            .BackBufferWidth = mlBackBufferWidth                    ' This needs to be the maximum of the ScaleWidth of mhWnd.
            .BackBufferHeight = mlBackBufferHeight                  ' This needs to be the maximum of the ScaleHeight of mhWnd.
        End With
        Set moD3Device = moD3Dx.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mhWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, uPP)
        '
        ' Enable Z_buffer (depth buffer).
        ' A Z-Buffer, also known as a depth buffer, is simply a large buffer that keeps track of the distance
        ' from the camera of every pixel on the screen. Whenever a pixel is drawn, it takes the closest pixel to the camera and
        ' draws that on the back buffer. At the same time, it stores the depth value into the same spot in the z-buffer,
        ' so that the next time something is drawn, Direct3D can see how close each pixel is, and which objects should be drawn and which should not.
        ' For more, see:  https://msdn.microsoft.com/en-us/library/windows/desktop/bb219616(v=vs.85).aspx
        moD3Device.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE     ' This just turns it on.
        '
        ' Now we can set the BackBuffer's used area (i.e., the internal ViewPort).  It may change if user resizes the hWnd.
        SetViewportSize
        '
        ' And now for some lighting.
        With uLight
            .Type = D3DLIGHT_POINT
            .Position = DxVec(0!, 50!, 0!)
            .Attenuation0 = 1!
            .Range = 100000!
            .Diffuse = DxColorWhite
            .Specular = DxColor(0.05!, 0.05!, 0.05!)
            .Ambient = DxColor(0.8!, 0.8!, 0.8!)
        End With
        With moD3Device
            .SetLight 0&, uLight
            .LightEnable 0&, 1&                           ' Arguments: Light index (we could have multiple), Enabled.
            .SetRenderState D3DRS_LIGHTING, 1             ' This turns on lighting.  TRUE to enable Direct3D lighting, or FALSE to disable it.
        End With
        '
        ' Get the grid going.
        Set moGridMesh = New clsDxMesh
        With moGridMesh
            .CreateGrid moD3Device, 8&
            .Position = DxVecZero
            .DiffuseColor = vbWhite
            .Name = "TheWorldGrid"
        End With
        '
        ' A mesh that represents the camera target.
        ' The camera object really doesn't care about this mesh.
        Set moCameraTargetMesh = New clsDxMesh
        With moCameraTargetMesh
            '.Position = DxVecFromLabXYZ(0, 1, 0)        ' Just for testing, it's always set when the scene is rendered.
            .CreateSphere moD3Device, 32&, 0.1!         ' Just a nice sphere in case we wish to show it.
            .DiffuseColor = &HFF8080
            .AmbientColor = &HFF8080
            .Name = "TheCameraTarget"
        End With
        '
        ' Three meshes that show the lab's orientation.
        Set moLabXMesh = New clsDxMesh: Set moLabYMesh = New clsDxMesh: Set moLabZMesh = New clsDxMesh
        With moLabXMesh
            .CreateRod moD3Device, 32&, 0.25!, 0.01!
            .Orientation = DxQuatFromLabEulerXYZ(0!, nPI / 2!, 0!)
            .DiffuseColor = vbRed
            .AmbientColor = vbRed
            .Name = "TheLabAxisX"
        End With
        With moLabYMesh
            .CreateRod moD3Device, 32&, 0.25!, 0.01!
            .Orientation = DxQuatFromLabEulerXYZ(-nPI / 2!, 0!, 0!)
            .DiffuseColor = vbGreen
            .AmbientColor = vbGreen
            .Name = "TheLabAxisY"
        End With
        With moLabZMesh
            .CreateRod moD3Device, 32&, 0.25!, 0.01!
            .DiffuseColor = vbBlue
            .AmbientColor = vbBlue
            .Name = "TheLabAxisZ"
        End With
        '
        ' Get the camera up and running, and set initial position/properties.
        Set moCamera = New clsDxCamera
        moCamera.Fov = nPI / 4!
        '
        '               ( keep X=Z for 45°)
        '               camera position     target     up direction
        moCamera.LookAt muInitialCameraPos, DxVecZero, DxVec(0!, 1!, 0!)
    End Sub
    
    
    All of those original calls are gone, and just strung together, with comments, into one much longer procedure. (They're also a bit rearranged, but that doesn't really change anything.) It just helped me to learn this stuff to see the code just drop down through it all.

    I think this is one case where Tubus is correct. To paraphrase him, "we can sometimes move complexity around, but we're not necessarily making it simpler."

    And, for the other side of the coin, let me return to that form code for my spine protocol. As stated earlier, that thing has about 70 non-event procedures in it. It's chocked full of stuff like ...

    Code:
    
    Private Sub LoadSrs30(udt As Srs30ScoresType, rs As DAO.Recordset)
        ' The rs must be open and sitting on the record before this is called.
        ' Used by both the encounter and the comparison.
        '
        udt.bFound = True
        udt.FunctionMean = DoubleVal(rs![FunctionMean])
        udt.PainMean = DoubleVal(rs![PainMean])
        udt.SelfImageMean = DoubleVal(rs![SelfImageMean])
        udt.MentalMean = DoubleVal(rs![MentalMean])
        udt.SubtotalMean = DoubleVal(rs![SubtotalMean])
        udt.SatisfactionMean = DoubleVal(rs![SatisfactionMean])
        udt.TotalMean = DoubleVal(rs![TotalMean])
    End Sub
    
    
    ... which is called from two other procedures. Or ...

    Code:
    
    Private Function bVectorHasData(v As VectorType) As Boolean
        bVectorHasData = (v.X <> 0) Or (v.Y <> 0) Or (v.Z <> 0)
    End Function
    
    
    ... which is called all over the place. Or ...

    Code:
    
    Private Function ButterTheAngles(C3dPoint() As C3dPointFrameDataType)
        Dim Buf() As Double
        Dim i As Long
        '
        ReDim Buf(LBound(C3dPoint) To UBound(C3dPoint))
        '
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            Buf(i) = CDbl(C3dPoint(i).X)
        Next i
        oButter.Filter Buf()
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            C3dPoint(i).X = CSng(Buf(i))
        Next i
        '
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            Buf(i) = CDbl(C3dPoint(i).Y)
        Next i
        oButter.Filter Buf()
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            C3dPoint(i).Y = CSng(Buf(i))
        Next i
        '
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            Buf(i) = CDbl(C3dPoint(i).Z)
        Next i
        oButter.Filter Buf()
        For i = LBound(C3dPoint) To UBound(C3dPoint)
            C3dPoint(i).Z = CSng(Buf(i))
        Next i
        '
    End Function
    
    
    ... which is also called multiple times.

    To try and write any of those in-line, rather than make separate procedures, to my eyes, would clearly be making things more complex. In fact, that ButterTheAngles (a Butterworth low pass filter) procedure could possibly be further simplified by overlaying those C3DPoint UDTs with a 2D array, making XYZ an array. But array overlaying introduces a certain complexity in itself, so I doubt I'll be reworking it.

    So, it's clearly a matter of taste, to some degree. However, I sometimes just listen to my gut. When it's getting nervous, I start thinking that it's telling me to take a step back and "simplify" this thing, breaking it up into smaller, more manageable pieces. And then, other times, if I'm clicking along with some procedure, putting in appropriate comments, I think it's all fine, with no need to break up anything.

    Best Regards,
    Elroy

    EDIT1: Actually, after staring at that Butterworth procedure, I probably do need to work on that some more. All my C3dPoint data is Single precision, but my Butterworth filter expects Double precision. You can see me jumping through hoops to accommodate that. I should probably write a Single precision Butterworth filter, which wouldn't take that much.
    Last edited by Elroy; May 15th, 2018 at 07:05 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #46
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by Elroy View Post
    To paraphrase him, "we can sometimes move complexity around, but we're not necessarily making it simpler."
    That's what I'm trying to debunk. If complexity can only be shuffled then all refactoring efforts are defeated beforehand.

    My mantra is: If a system is complex, add more classes! Because it is fairly easy to reduce complexity at the expense of lines of code.

    At the same time it is very hard to reduce complexity while reducing lines of code and reducing asymptotic execution time (the Big O notation). You'll need mostly super-star devs to do this.

    cheers,
    </wqw>

  7. #47
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    Hi wqweto,

    I definitely think we're on the same page.

    However, I must say that I've backed off of Class modules to a large degree since it became crystal clear to me that shuttling code into them doesn't reduce the code memory footprint of an executable (unless we take the extra step of actually creating an ActiveX DLL out of those class modules). However, having said that, my primary project certainly has its share of Class modules:

    Name:  Classes.png
Views: 437
Size:  29.0 KB

    And it's probably going to soon get three more when I weave in my DX9 work (unless I decide to make that an ActiveX or possibly a separate stand-alone program).

    IDK, on a large project like mine, managing complexity is a perpetual task, and I'm not sure a one-size-fits-all approach works all that well. I use just about all the tools at my disposal to manage complexity and to keep things organized. And it's not easy.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #48
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: GOSUB - Is it really bad?

    Personalty, I like GOTO. For Gosub in vb6 haven't used, but if i have to do then there is no reason why not. In my M2000 Interpreter I implement GOTO, GOSUB, ON GOTO, ON GOSUB, with numbers and labels(with : at the end). The reason to use these commands is to get flow control on same scope of variables. Lets skip the use of them in M2000, and see what happen in Vb6.

    Visual Basic 6, pass anything by reference or we have to state ByVal otherwise. Why ? Because in final assembly code there is smaller code to use a location in stack frame. This meas that cpu cache has more space for code. So instead of retrieving an address for "same" scope variable, we get it from stack. If we have to use it for less than two or three times then the pushing to stack maybe worse, but it happens to use a variable more than two or three times, so indirect reading, can be faster than direct (less statements in cpu cache, so more "pages" need to be read, in slow speed). A local variable stored to stack, so if we use it in a routine called by a Gosub, we get no new stack frame, and if we are lucky, our code run from cache, so we get maximum performance. But we may have another problem, if we overkill the conditional jumps. Jump prediction in cpu load with a wise way the cache. Gosub and Goto are unconditional "jumps", where a jump here means a change to program counter, or PC in CPU. A call to a function is a Gosub for cpu with some care to stack frame for parameters and local variables. So why in VB code, we get a statement that a Gosub is slower than a function call in compiled code?. The only reason is that in function we have the return value, as a state for our program in specific line of code, that is inside CPU. Using Gosub, we have all state in variables. So the call is the same fast, and maybe faster for Gosub, but we get a penalty for not passing results from cpu registers, but make results in local variables, unless compiler is so good and use registers as local variables.

    Look at cpu history for the first 16bit cpu, from Texas. The TMS9900 processor supposed to be the affordable 16bit cpu. This cpu utilize a WorkSpace Pointer register, which is the same idea of using local variables in stack, but for registers. So at the end this cpu luck true registers, and need cycle of read/write memory, and that was a bad idea. When this processor need to push registers, just push the WorlSpace Pointer and get an uninitialized memory for registers, so need to initialize it again. In a multi-thread scenario switching task using just a push of a pointer can be very good. So why Texas sold TI 99/4A sold as a micro without mult-tasking, at least in Basic ? (this was my first computer, not owned, when I learn Basic). In same decade other 8 bit cpu was faster. The famous 6502, was faster from the original 6800, and uses first page (256 bytes) as registers too. And for the finale of this reply, eventually cpu got more registers, then got one level of cache ram, then a second, and then a third, with predictions, speculations, out of order executions, two or more execution pipelines. All this stuff never stand to calling method, but to balance cpu internal to external time for moving bits.

    As for the spaghetti code, i have to say that in the other side, the extreme hiding of "under the hood" code is not good. We didn't know exactly what happen in some parameter combinations, or after a series of call in an object, when we don't breakpoint the code inside object. We can do this only at the stages which programmer leave to us. As an example, I make a Text Editor (based on ideas from others here in this forum), and because I made the user control and all of the events, we get a flicker free "note pad". Just check Notepad at resize, to see the flickering. Why Microsoft use this bad "UI control" inside NotePad? This is not a use of spaghetti code, but a use of objects, when object are stay as is, without improvements. "If something is bad but can be sold then is a product to make profit". I expect more from Microsoft. From my stand as programmer, spaghetti code or not, using of Gosub or not, is not a matter of choice, I can use everything to achieve my scope, and this is not so big as those scopes of a big company. What matters is the final work to be useful, to not disturb the user experience, and to give a felt of stability.

  9. #49
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by Elroy View Post
    However, I must say that I've backed off of Class modules to a large degree since it became crystal clear to me that shuttling code into them doesn't reduce the code memory footprint of an executable . . .
    I mean classes in the C++/Java sense of the word i.e. in VB6 terms that would be modules. The idea is to separate *concerns* into different modules.

    Anyway, I'm staring here at a 1000+ modules project group at ~800 kLOC but the complexity of the project is not very high IMO. And I'm planing on adding more modules to reduce it further :-))

    cheers,
    </wqw>

  10. #50
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    I actually ran into a VB6 limit a couple of years back. I'm not sure if it was Intellisense identifier space or an absolute module limit, but I hit a hard limit. That's when I got truly serious about making ActiveX DLLs a fundamental part of my primary project. It was just an absolute necessity to keep going.

    I'm all with you though on keeping complexity down (and organization up). That should be one of the primary goals of a programmer, regardless of their purposes. And it's a skill we should be constantly honing. (Maybe that's why I attempted to strongly suggest to Tubus that he reconsider his use of Goto's.)

    Also, I think it's safe to say that accomplishing that simplicity/organization will be different for different projects.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  11. #51
    Hyperactive Member
    Join Date
    Mar 2018
    Posts
    460

    Re: GOSUB - Is it really bad?

    DoEvents() is pure evil. It only has a few legitimate uses but seems to show up everywhere.

  12. #52
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: GOSUB - Is it really bad?

    I didn't even bring up the misuse of Static.

  13. #53
    Hyperactive Member
    Join Date
    Mar 2018
    Posts
    460

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by dilettante View Post
    I didn't even bring up the misuse of Static.
    I'd like to hear that rant

  14. #54
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: GOSUB - Is it really bad?

    Not much to it. Usually what happens is that people use Static and then complain that they can't clear the value back to zero from outside. Or else they don't understand what a Static is and get tripped up because it doesn't get reallocated each call. Or better yet they'll have Static objects and then wonder why their program won't terminate.

    If you know what you're doing there is no problem.

  15. #55
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: GOSUB - Is it really bad?

    "Complexity" is a tough topic and learning to manage it is what separates experts from novices.

    Every time you separate functionality into multiple files, you increase complexity. This is as far as the novice gets: they hear "increase complexity" and decide "more files are hard". That's how you end up with an 80,000 line Form1.vb that's impossible to decipher.

    The expert understands the goal is to create less complexity than is removed. For very small projects, adopting a very formal Separation of Concerns approach is foolish and you devote more code to infrastructure than work. For very large projects, tools like Design Patterns help us express the things we're doing in ways other experts expect and that decreased cognitive load pays for the extra layers of indirection that are introduced. In a small project, you very rarely end up using extensibility patterns and they are wasted time. In a large project, it's guaranteed you'll need them.

    But "complexity" isn't the only tension in software engineering. Sometimes "performance" is the concern. There's a famous, long, heated argument between Linus Torvalds and another developer over the use of a goto within some Linux kernel code. Torvalds (correctly) argued that since this particular bit of code executes millions of times per second and the goto results in fewer cycles per execution, the "loss of clarity" in using the goto is paid for by the millions of cycles saved per second.

    So I can't condemn GoSub in any language, but I can ask the developer why it was used. And I think if you see one you should ask why it was used. If there's an answer, and it makes sense, leave it. If there's not an answer, but the code is functioning properly, leave it until you need to change that code. If there's not an answer, but removing it makes the code harder to follow or maintain, leave it.

    The worst thing you can do is follow dogma. Don't do things "because the internet says they are bad". Do them because, "I read an article with convincing benchmark evidence that this approach yields impressive performance returns in exactly this scenario."
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  16. #56
    Member
    Join Date
    Oct 2014
    Posts
    42

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by wqweto View Post
    Yes, and there is some misunderstanding what *is* complexity actually.

    From human point of view a long function is complex, a god-like class is complex and you reduce complexity by dividing functions/classes to become more manageable chunks. This usually requires writing more lines of code, which is counter-intuitive -- write more code, for something to become less complex.

    "When a solution is too complex, then you usually need *more* classes"
    -- Paulo Coelho

    cheers,
    </wqw>
    p.s. Trusting quotes on the internet. . .
    This rings very true for me.
    I like things to be very simple

    A trivial example:

    Code:
    'I much prefer
    
    dim s as string
    s = somefunction(a, b, c)
    
    dim d as integer
    d= someotherfunction(s)
    
    dim e as boolean
    e = yetsomeotherfunction(d)
    
    'rather than
    
    e = yetsomeotherfunction(someotherfunction(somefunction(a, b, c)))
    There's much less thinking involved to understand what's going on.
    BTW I know you as wqw on stackoverflow and I've found myself using a lot of your answers from there.

  17. #57
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: GOSUB - Is it really bad?

    Why all the hate for doEvents or API equiv? If for example you are not at event level and using sockets there is little else to do to get your winsock message actually processed other than wait for your stuff to finish and then have vb return to the main message loop. Remember it is actually pumping messages for you all the time when it is idle with probably PeekMessage, TranslateMessage & DispatchMessage calls.

    Mostly what doEvents does anyway I think

  18. #58
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by vbcommander View Post
    Why all the hate for doEvents
    Because all too often it's reached for by those who do not understand the ramifications as a solution to the wrong problem and then don't understand why other things then start to go pear-shaped. That's why.
    It's the same thing with gosub, oern, and several other things inherent in BASIC/VB ... there's a few constructs that people latch onto because it was easy and allowed things to "just work" without realizing it was the wrong answer to the problem. And as a result, they get themselves deeper into hot water over it and make things worse.
    IF you KNOW what you're doing, IF you UNDERSTAND the implications of what you're doing, AND you're willing to deal with the consequences, AND you understand what is happening and why, then there isn't a problem. It isn't that there's hate for it... it's that there's a healthy dose of pessimistic caution. I think it's safe to say that ideally we'd like to try to avoid those situations when we can, and look for a "better way." But there are times when we can't, but again, it's a near last-resort situation. I haven't written DoEvents, with the exception of in posts here in the forums, in over 20 years... so that just goes to show the "necessity" of DoEvents.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  19. #59
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    vbcommander, This is a bit of a bait for you to realize something. But, what's the API equivalent to DoEvents?
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  20. #60
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    Ok, I'll outline the problem with DoEvents. Let's say you're sitting on a form that's something like the following:

    Name:  O2.jpg
Views: 332
Size:  53.3 KB

    Now, there are a few different buttons on that form that make take a few seconds to execute. (Most actually won't, but let's say they will.) I know that the "Copy CSV" and "Export Report" buttons can take a few seconds. Now, let's say that we scatter DoEvents within the code that's under those buttons. What's the harm, right?

    On that form above, there's really no need to disable any buttons. In other words, they are all always enabled.

    Ok, what does DoEvents do? It's similar to calling a procedure that could possibly be unintentionally recursive. It pauses our code at whatever line it was on, specifically that DoEvents line, and goes and checks the event queue to see if any other events are sitting there waiting to fire. If they are, it fires them. And don't forget, our thread is still paused at our DoEvents line of code. It goes off and runs the code for those other events, and, when done, it returns to our "paused" DoEvents line and then completes our execution (possibly pausing again on the next DoEvents to go off and execute some other event code in our program).

    So, with that "Export Report" button, since it takes a few seconds, the user could bounce on that button, recursively executing its code several times before the first time finished. Or, the user could bounce between several buttons, getting code from several sections simultaneously (or somewhat simultaneously, with internal DoEvents lines paused) running.

    Hopefully, you can see that this could rather quickly just become a huge mess, causing our program to crash or possibly garble data. At the very least, it makes the code under those buttons exceedingly difficult to debug, with users not being able to accurately tell you what they did before running into some problem.

    In other words, in a situation like that form above, when the user executes some code by clicking a button, that code should run to completion before the user is allowed to do anything else. And that's precisely what will happen if there are no DoEvents in the underlying code.

    I hope that helps. I think we are all rather universally in agreement on the evils of DoEvents. There's only one very specific example where I use it. And that's where it takes a loop to get some long process done, and you want to give the user the option to "Cancel" before it completes. And, in this situation, you should make sure that a "Cancel" button is the only option available to the user while the long loop is running.

    Best Regards,
    Elroy

    EDIT1: And I'll go ahead and answer my "bait". I assume you're talking about the "Sleep" API call. People get confused but Sleep does something quite different from DoEvents. Personally, I've got no problems with Sleep, if you really feel that you need it for something. All it's going to do is slow down your program.

    When you call Sleep, the event queue of your program is not checked. Other waiting events are not allowed to fire. Your program simply pauses at the Sleep statement, returning control to Windows until the Sleep time has expired.

    Now let's also realize something else. And this is at a level beyond our program. When we are executing a VB6 program, and let's say we're also in some long running loop. We do not have exclusive control of the CPU. For one, all modern CPUs are multi-core (think multi-thread, but that's not quite right either). However, even if we're on a single-core CPU, a VB6 program still doesn't have complete control of the CPU in a long running loop. Since the beginning of Windows, it's been a true multi-tasking OS. What that means is that it'll "swap out" the CPU's program pointer and give timeslices to other running programs and services, even if our VB6 program is attempting to be a CPU hog. Therefore, unless we specifically need pauses (and I can think of a few good reasons we might), there's typically no need for Sleep either. But again, it doesn't have the deleterious effects that DoEvents has.

    EDIT2: Also, DoEvents should never be used as a replacement for refresh. If we need to refresh something, then figure out how to do it with the appropriate .Refresh method. Worst case, figure out how to call an API invalidate call.
    Last edited by Elroy; May 18th, 2018 at 07:29 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  21. #61
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: GOSUB - Is it really bad?

    DoEvents is a bit more nefarious than Elroy indicated because it doesn't just look at the application event queue... in fact, that's not what it even checks... it checks the SYSTEM event queue... so it's looking for messages from EVERYTHING in the system. And that's where the danger begins because the #1 time people use DoEvents is when they are doing something intense that freezes their screen since UI updates are a minor priority... so they use DoEvents to allow UI updates to be processed, not realizing what it's really doing.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  22. #62
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GOSUB - Is it really bad?

    as I wrote before, DoEvents is needed in certain situations, like in a neverending loop but if you create a application that dont use loops in that way, but instead timers, buttons etc, then doevents can mess things up.
    and use the API as I also mentioned:

    Code:
    If GetQueueStatus(QS_ALL) Then DoEvents
    Code:
    Const QS_KEY = &H1&
    Const QS_MOUSEMOVE = &H2&
    Const QS_MOUSEBUTTON = &H4&
    Const QS_SENDMESSAGE = &H40&
    Const QS_POSTMESSAGE = &H8&
    Const QS_TIMER = &H10&
    Const QS_PAINT = &H20&
    Const QS_HOTKEY = &H80&
    Const QS_ALL = (QS_MOUSEMOVE Or QS_MOUSEBUTTON Or QS_KEY Or QS_SENDMESSAGE Or QS_PAINT Or QS_TIMER Or QS_POSTMESSAGE Or QS_HOTKEY)

  23. #63
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,900

    Re: GOSUB - Is it really bad?

    That's what I'm trying to debunk. If complexity can only be shuffled then all refactoring efforts are defeated beforehand.

    My mantra is: If a system is complex, add more classes! Because it is fairly easy to reduce complexity at the expense of lines of code.
    Those two sentences are in direct conflict with each other. I agree with the second completely but the first is, IMO, wrong.

    There is certainly a complexity minimum threshold for any system that no amount of refactoring will get us below. But that doesn't mean we should stop refactoring when that threshold is reached. Instead refactoring becomes about shifting the complexity away from the consumer. When I want a price for my order it's far easier for me to say:-
    Code:
    Price = myOrder.Price
    than it is to say:-
    Code:
    Price = 0
    For Each OrderLine in myOrder.OrderLines
       Price = Price + OrderLine.Product.Price * OrderLine.qty
       Price = Price - OrderLine.discount
    Next OrderLine
    Price = Price + 1.125 'Sales Tax

    In the first case the complexity is not removed, merely shuffled out of sight.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  24. #64
    Hyperactive Member
    Join Date
    Mar 2018
    Posts
    460

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by techgnome View Post
    so they use DoEvents to allow UI updates to be processed, not realizing what it's really doing.
    You are both right about the side effects but this is the main reason why it is evil. Devs around here get one warning about DoEvents.

  25. #65
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    @FunkyDexter: In your sample refactoring you are not attacking complexity in any way, just shuffling snippets intact. Do you end up with more lines? Not significantly.

    Split calulcation into two separate functions: AddRowTotal and ApplyDiscount and now you start dealing w/ complexity. Naming here is obviously very hard and my function names are daft, but you get my point.

    cheers,
    </wqw>

  26. #66
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by DllHell View Post
    You are both right about the side effects but this is the main reason why it is evil. Devs around here get one warning about DoEvents.
    Maybe it's a matter of semantics, but I disagree... doEvents itself isn't evil... no more than a pentagram is evil, but it's the use of DoEvents that tends to be evil... just like using a pentagram to raise the dead. That's the bad juju.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  27. #67
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by techgnome View Post
    Maybe it's a matter of semantics, but I disagree... doEvents itself isn't evil... no more than a pentagram is evil, but it's the use of DoEvents that tends to be evil... just like using a pentagram to raise the dead. That's the bad juju.
    Yes, DoEvents in a comment block is pretty harmless for instance. . . lol

    cheers,
    </wqw>

  28. #68
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GOSUB - Is it really bad?

    just because you don't know how to use it, doesnt mean its bad or evil. DoEvents is there for a reason and we need it.
    the same with "end", it can be quite evil, but it can be useful and even necessary in some cases (i always use it).
    so stop with this nonsense.

  29. #69
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    Oh wow, End. Now there's one I'll say should never be used for any reason other than possible testing and debugging. I'll go out on a limb and say that it should never be used in production code.

    Y'all Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  30. #70
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GOSUB - Is it really bad?

    if you "scared" of use it, sure do something else, but that doesnt mean its wrong to use.

    i would say that end "should" be used in almost all projects.
    of course theres a "termination" procedures, where we stop hooks, unloads, set nothing etc, but at the very end the use of "end" could actually help cleaning the memory if for some unknown reason a API/3rd party Dll didn't unload properly.
    sure you can be a pro, knowing exactly what you are doing, unloading your "own" program nicely. but can you be sure that this is the case for all the dll you are using (if any)? or if the OS, or updates changes something and creates a problem when unloading APIs? no "end" for me its quite useful and i want it there, the same with DoEvents.
    Last edited by baka; May 19th, 2018 at 11:37 AM.

  31. #71
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: GOSUB - Is it really bad?

    "Since the beginning of Windows, it's been a true multi-tasking OS. What that means is that it'll "swap out" the CPU's program pointer and give timeslices to other running programs and services, even if our VB6 program is attempting to be a CPU hog"

    Actually not quite true or perhaps you are too young to remember. Windows was originally a "cooperative multi-tasking" O/S before I think 3.51 where it was actually required for you to give up the CPU. Proper preemptive scheduling only came later.

  32. #72
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by Elroy View Post
    vbcommander, This is a bit of a bait for you to realize something. But, what's the API equivalent to DoEvents?
    Forgive me if this posts 2wice. It did not seem to work the first time.

    I would guess doEvents calls PeekMessage,TranslateMessage and DispatchMessage. It may also call Sleep(0).

    And I perhaps mistakenly assumed that everybody knows not to pump messages while already in an event. This leads to madness.

  33. #73
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by techgnome View Post
    DoEvents is a bit more nefarious than Elroy indicated because it doesn't just look at the application event queue... in fact, that's not what it even checks... it checks the SYSTEM event queue... so it's looking for messages from EVERYTHING in the system. And that's where the danger begins because the #1 time people use DoEvents is when they are doing something intense that freezes their screen since UI updates are a minor priority... so they use DoEvents to allow UI updates to be processed, not realizing what it's really doing.

    -tg
    Actually I believe it checks the message queue FOR THAT THREAD. Yes it does process everything it finds which is why Mattew Curlands methods of pumping Com synchronization messages is useful for multi threading.

    According to his book DoEvents

    1) Clears all pending keystrokes from the sendKeys function
    2) Clears the thread message queue using PeekMessage and its friends
    3) Calls sleep(0) (so it does call this) to give up quantum.

  34. #74
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by vbcommander View Post
    Actually I believe it checks the message queue FOR THAT THREAD.
    How do you PeekMessage for another thread at all?

    Btw, Curland's list is not *all* DoEvents does. There is some custom msg handling for keyboard navigation and/or windowless controls (hidden VBFocus) that is out of scope of this discussion.

    Curland's msg pump for cross-thread calls is very much obsolete since Windows 2000 when CoWaitForMultipleHandles API was introduced -- it reliably waits for hThread/whatever to get signalled while spinning COM cross-thread messages.

    Curland's msg pump for cross-thread calls was not very reliable even before that, I remember non-stop getting ERR_RPC_S_CALLPENDING and family errors while in CoGetInterfaceAndReleaseStream call.

    cheers,
    </wqw>

  35. #75
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,900

    Re: GOSUB - Is it really bad?

    @FunkyDexter: In your sample refactoring you are not attacking complexity in any way, just shuffling snippets intact. Do you end up with more lines? Not significantly.
    That's exactly my point. In a price calculation with a fixed algorithm you cannot reduce complexity, but that doesn't mean that refactoring is pointless. By "shuffling" (or abstracting) the complexity away into functions, classes etc. you can reduce complexity at the point it's consumed.
    Last edited by FunkyDexter; May 21st, 2018 at 07:48 AM.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  36. #76
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by FunkyDexter View Post
    you can reduce complexity at the point it's consumed.
    That's very significant conclusion IMO

    Interfacing has a great part in increasing/reducing complexity, as far as good interfaces' mental models are much easier to comprehend and use.

    cheers,
    </wqw>

  37. #77
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,871

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by FunkyDexter View Post
    you can reduce complexity at the point it's consumed.
    I'll second that motion. It's always a judgment call, and there's sometimes a trade-off between hiding complexity and creating obscurity (but not always, if our functions and arguments are well named and commented).

    I must admit that I've followed the rule that "we should push complexity down into the deepest recesses of our code as we possibly can" for many years. This might mean creating general purpose BAS modules, creating general purpose CLS modules, creating spun off ActiveX modules, creating a UDT to keep our data together, or just creating a set of functions that sit at the bottom of some complex FRM module. For any reasonably complex project, there will be levels of how far this complexity is pushed down, depending on the generality or specifics of the actual complexity.

    IMHO, the creation of this organization is very close to the definition of reducing complexity.

    Y'all Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  38. #78
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,900

    Re: GOSUB - Is it really bad?

    there's sometimes a trade-off between hiding complexity and creating obscurity
    There shouldn't be... but, yeah, there often is. In fact, if you're finding yourself thinking "I wonder how this method calculates the price/drives the car/quacks the duck", that's a pretty strong smell that things aren't as they should be. You should have enough trust to just look at the signature and say "yeah, go and quack my duck for me". But we often have to work with other people's smelly code and it can sometimes be difficult to trust that quacking a duck is all that function's going to do .

    we should push complexity down into the deepest recesses of our code as we possibly can
    I mostly agree but would like to add a nuance: Complexity should be consumed at the lowest possible level but should be configured at the highest possible. I.e. we should use inversion of control to pass objects down into the darkest recesses of our hierarchy where they can be consumed, but we should decide which classes of objects to pass down right at the top, in a factory, and then pass them down using dependency injection.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  39. #79
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: GOSUB - Is it really bad?

    Quote Originally Posted by FunkyDexter View Post
    In a price calculation with a fixed algorithm you cannot reduce complexity, but that doesn't mean that refactoring is pointless.
    By "shuffling" (or abstracting) the complexity away into functions, classes etc. you can reduce complexity at the point it's consumed.
    "Complexity" can be seen in quite a lot of things when developing a solution -
    and it is "happening" in quite different areas of any larger project, and those areas are sometimes "opposites"
    (meaning, when you decrease complexity in one, you will increase complexity in another).

    E.g. - even when we assume that the "DRY"-requirement was met to a certain "sufficient degree",
    the structure and organizing of your projects functions still remains "discussable" under different "aspects of complexity", as e.g.:

    - deployment complexity and versioning (single Script?, Script with include-dependencies?, single Exe? or Exe with Dll-dependencies?)
    - code-organization (Module-breakups, Class-structures, Class-Hierarchy-depth, organization and depth of Helper-Binaries)
    - Context- and State-Handling, as well as Argument-passing (also generic Param-Types, or Userdefined-Types - depending on performance)
    - Data-placement and Data-Volume (Client only?, Server only?, or "mixed"?, Online/Offline-modes?, Change-frequencies and Caching?)
    - maintainability + the extent of Error-Transport and Handling/Logging (Isolation- and Level-depth of your includes or Bin-references?)
    - teamsize (single dev, small team, large team)
    - used language and/or platform

    So there is no real "one size fits all" pattern, which can be applied (depending on the size and kind of your project).

    Of course there's a certain "optimum" which can be found (over all aspects listed above) - but only for a given project
    which "stands still"... well, most of them don't do you that favour - and therefore refactoring (in one, or all of the above
    listed aspects) is a constant companion in real-life-projects.

    Olaf

  40. #80
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,900

    Re: GOSUB - Is it really bad?

    and therefore refactoring ... is a constant companion in real-life-projects
    +1 to that

    So there is no real "one size fits all" pattern, which can be applied
    ...and to that.

    It chimes with what I was saying about configuring things at the highest (not sure I like the word highest here - "most visible" might be better) possible level. This gives us the best chance of reconfiguring our system's behaviour with a minimum possible impact. Of course, there'll always be some impact but we can aim to keep it to a minimum.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width