There's any way to delete objects in VB6 without getting errors? - object

I need to simplify a program made in VB6, so I need to delete a lot of objects but don't want to delete one, run, get an error, fix it, run, get another error, a so on for every object.
I don't created the original program, so is very annoying try to think what someone else thought.
Plus, the code is not commented and is very dirty, the objects have the default names, like Label1, Timer12. WTF?
So I can't get a clue about what a timer does until I fully read the code.
Any idea?

Perhaps the original author didn't have much thought, true. But then you're not giving it much thought either by thinking that the best approach will be to delete an object, run and see what happens, and then rinse and repeat until you have a fully working program. Given your approach, by the time you've finished deleting all the objects - you won't have much left to run anyway! (No data, No Problem!).
Look through the code in conjunction with running and debugging the application. This will give you an idea of what it is trying to do (I am under the assumption there's not really much in the way of documentation for this project?)
Time to think of a new plan! Sometimes re-writing from scratch is absolutely necessary rather than attempting to work with legacy code that is clearly hard to maintain and is far from optimum. The downside is that this will take more time, on paper - but perhaps will save time in the long run. This might be the time also to move away from VB6 and in to the .NET era. Rewriting applications can let you do this too!
If a re-write is out of the question (such a shame), then you can't go through willy-nilly deleting objects! The program functions with these objects. So they've got to stay and you need to maintain it.
See (2).
Good luck, God speed.
Or, given your comment
Rename Label1 to something more appropriate. Do a search replace within that file (Not the whole solution) to the new name, then correct any accidental errors and move on.

I would go with the last option of Moo-Juice's answer, but slightly different: I would rename a control by adding an "x" to its name and run the project.
If it runs, then remove the control, if it doesnt run, then rename the control back by removing the "x".
This should not take more than 1 hour for about 250 controls
But first you might do something else: Instead of just deleting the unused controls, you might also want to look at the controls:
If there are so many controls then it might be possible to convert series of controls into a control array: This might clean up the code a lot as well, and give you a better overview of the remaining controls
When you cleaned up the controls have a look at their names, and rename them to something useful.
After that it is time to clean up the code in the same way.
You can download MZ-Tools to help you with that.
It's a must for the lazy coder :)
Also place "Option Explicit" at the top of all code windows. This will make it easier for you to spot errors caused by not (properly) declared variables.
Do this after you have done "Review Source Code" of MZ-Tools though, as that might save you a lot of work :)

Related

Should I delete variables I don't plan on using anymore?

At first, it sounds like a no-brainer, but the more I think about it the more I feel like others' opinions would be helpful. Whenever looking at others' Python code, I never see them delete variables. Is there a reason for this, or is it just them not wanting to. I assume it has to do more with clean code vs. quick code, but I'm not sure that's the case. Plus, to be honest, I don't know for sure the impact deleting variables has on a program (I always just assumed it was good, since the courses I've taken on Python never really mentioned it).
Example of deleting a variable...
j = 'jjjjj'
for i in range(len(j)):
print(j[i], j)
del j
Not the most relatable example but you get the point.
In general, don't worry about deleting variables.
Python has garbage collection, so any objects that you can no longer access (usually because you've left their scope) will automatically be freed from memory, you don't have to worry about this at all.
The case where you might want to use del would be if you want to make it explicity clear that this variable cannot be used anymore by this part of the program.
As mentioned in the comments, this won't even necessarily delete your object.
You can read about the del keyword more here

MS Access writing to Excel over multiple minutes will sometimes throw a false error

I'm someone who solves problems by looking, not asking. So this is new to me. This has been an issue for years, and it crops up with different computers, networks, versions and completely different code. There is a lot here, so, thank you in advance if you are willing to read the whole thing.
Generally speaking, I write MS Access programs that will open Excel and then create multiple worksheets inside of a workbook using data from Access tables and/or Excel sheets. The process can take a couple of minutes to run and occasionally, it will get an error. I could tell you the error message, but it doesn't matter because it will be different depending where the error occurs. When it occurs I simply click debug and click continue and it... continues. If it errors out again (many loops later), it will happen in the exact same spot.
So, what I start with is to make minor changes to the code. In the current program I'm working on, the error happens when I write to a cell and the value is a value directly from a table. I created a variable, copied the value to the variable and then wrote to the cell. The error moved to a completely different part of the program and it became a "paste" error. Generally what fixes it is to put a wait function at the spot where the error occurs. One second is usually good enough. Sometimes it takes a couple of these, but that usually solves it. It only took one delay per loop this time, so it is working. I just hate causing delays in my program. So... Has anyone seen anything like this before, or is it just me. It feels like a timing issue between Access and Excel since the delays are usually helpful. Thanks in advance.
I dug up my last major Access project that interacted with Word (ca. 2016) where I struggled with similar issues. I see many, many Debug.Print statements (some commented, some still active), but unlike what I recalled earlier in my comments, I don't see any "wait" statements anymore! From what I now recall and after re-inspecting the code, most problems were resolved by
implementing robust error handling and best practices for always closing automation objects (and/or releasing the objects if I wanted the instances to persist)
subscribing to and utilizing appropriate automation object events to detect and handle interaction rather than trying to force everything into serialized work-then-wait code. To do this, I placed all automation code in well-structured classes that declared automation objects WithEvents (in VBA of course) and then defined relevant event handlers for actions I was effecting. I now recall finally being able to avoid weird errors and application hangs, etc.
You also may never get a good answer to a question like this, so despite that I am not an absolute expert on Office development, I have had my own experience with frustrating bugs like this and so I'll share my 2 cents. This may not be satisfying, but after experiencing similar behavior using office automation objects, my general understanding is that interaction between OS processes are not deterministic. Especially since VBA generally has no threading or parallelism concerns, it can be strange to deal with objects that behave in unpredictable ways. The time slices given to each process separately is at the mercy of the OS and it will vary greatly with multiple processors/cores, running processes, memory management, etc. Despite the purpose of the automation objects--to control instances of office apps--the API's are not designed well for inter-application processes.
Although it would be great if old automation code would produces more useful errors, perhaps nested exceptions (like in .Net and other modern environments), something that indicates delays and timeouts within callbacks between automation objects, instead you get hodgepodge of various context errors.
My hardware is old, but still ticking. I often get delays, even if only for a second, when switching between apps, etc. Instead of thinking of it as an error, I just perceive it as a slow machine, just wait and continue. It may be useful to consider these type of random errors as similar delays. If a wait call here or there resolves the issue, however annoying, that may just be the best solution... wait and continue.
Every now and then after debugging these types of issues I would actually discover the underlying problem and be able to fix it. At the least I would be able to avoid actual problems with the data, despite errors being raised, just like you describe. But even when I felt that I understood the problem, the answer was still often to do exactly as you have done and just add a short wait.
I do believe now this is a timing issue. After thinking things through, I realized that I could easily (well 3 hours later) separate the database info from the spreadsheet info and then move the updated code that is causing problems into an Excel Macro. I then called that macro from Access. Not only do the errors go away, but it runs about 4 times faster. It's not surprising, I just hadn't thought of that direction before.

When exactly am I required to set objects to nothing in classic asp?

On one hand the advice to always close objects is so common that I would feel foolish to ignore it (e.g. VBScript Out Of Memory Error).
However it would be equally foolish to ignore the wisdom of Eric Lippert, who appears to disagree: http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/when-are-you-required-to-set-objects-to-nothing.aspx
I've worked to fix a number of web apps with OOM errors in classic asp. My first (time consuming) task is always to search the code for unclosed objects, and objects not set to nothing.
But I've never been 100% convinced that this has helped. (That said, I have found it hard to pinpoint exactly what DOES help...)
This post by Eric is talking about standalone VBScript files, not classic ASP written in VBScript. See the comments, then Eric's own comment:
Re: ASP -- excellent point, and one that I had not considered. In ASP it is sometimes very difficult to know where you are and what scope you're in.
So from this I can say that everything he wrote isn't relevant for classic ASP i.e. you should always Set everything to Nothing.
As for memory issues, I think that assigning objects (or arrays) to global scope like Session or Application is the main reason for such problems. That's the first thing I would look for and rewrite to hold only single identifider in Session then use database to manage the data.
Basically by setting a COM object to Nothing, you are forcing its terminator to run deterministically, which gives you the opportunity to handle any errors it may raise.
If you don't do it, you can get into a situation like the following:
Your code raises an error
The error isn't handled in your code and therefore ...
other objects instantiated in your code go out of scope, and their terminators run
one of the terminators raises an error
and the error that is propagated is the one from the terminator going out of scope, masking the original error.
I do remember from the dark and distant past that it was specifically recommended to close ADO objects. I'm not sure if this was because of a bug in ADO objects, or simply for the above reason (which applies more generally to any objects that can raise errors in their terminators).
And this recommendation is often repeated, though often without any credible reason. ("While ASP should automatically close and free up all object instantiations, it is always a good idea to explicitly close and free up object references yourself").
It's worth noting that in the article, he's not saying you should never worry about setting objects to nothing - just that it should not be the default behaviour for every object in every script.
Though I do suspect he's a little too quick to dismiss the "I saw this elsewhere" method of coding behaviour, I'm willing to bet that there is a reason Eric didn't consider that has caused this to be passed along as a hard 'n' fast rule - dealing with junior programmers.
When you start looking more closely at the Dreyfus model of skill acquisition, you see that at the beginning levels of acquiring a new skill, learners need simple to follow recipes. They do not yet have the knowledge or ability to make the judgement calls Eric qualifies the recommendation with later on.
Think back to when you first started programming. Could you readily judge if you were "set[tting an] expensive objects to Nothing when you are done with them if you are done with them well before they go out of scope"? Did you really know which objects were expensive or when they truly went out of scope?
Thus, most entry level programmers are simply told "always set every object to Nothing when you are done with it" because it is within their grasp to understand and follow. Unfortunately, not many programmers take the time to self-educate, learn, and grow into the higher-level Dreyfus stages where you can use the more nuanced situational approach.
And then we come back to my earlier statement - even the best of us started out at that earlier stage, where we reflexively closed all objects because that was the best we were capable of. We left large bodies of code that people look at now, and project our current competence backwards to the earlier work and assume we did that for reasons we don't understand.
I've got to get going, but I hope to expand this a little futher...

Catching resource filename errors at compile time

I'm doing my first iOS App with Monotouch and I'm loading quite a lot of images from my resources directory. Every now and then I get a typo in a filename and the app will then crash on me spewing out some unintelligible error message. (I'll try adding deciphering stack traces to my skill set any day now ...)
I was thinking that there must be a smarter way to handle this. For example one could have a utility script that goes through the resources directory and constructs a list of global constants based on its contents. Each file in the resources gets an entry.
So that MyResources/Icons/HomeIcon.png will be represented by the constant MyResources.Icons.HomeIcon_png. Then one could have something like Inotify (don't know what that would be on Mac) watch the resources directory and regenerate the constants file on every change.
This would of course also give nice autocompletion for resources.
Maybe there's already something like this is already in Monodevelop or online somewhere? Otherwise how would I go about setting it up?
Or maybe there's some other smart way of mitigating the problem?
Your primary problem is typos in resource names are not caught early, and only cause crashes when the app is actually ran.
Your proposed solution of a list of global constants generated based on the available resources is kind of neat, but as far as I know this does not exist yet.
In the mean time, you could manually construct this list of global constants, and create a unit test that verifies all the elements in this list are valid resources (by looping through them automatically, of course - adding a resource to the list should not require a change to the test).
This way you can catch typos earlier (when you run the unit test rather than when you run the app), which is your primary concern. Additionally, if you ever find/write the script you envision, your application code is already prepared.
I filed an enhancement bug on Xamarin bugzilla for you: https://bugzilla.xamarin.com/show_bug.cgi?id=3760
So I spent four precious hours to cook up this little python script that sort of solves my problem. For now it's the best solution to my problem.
http://github.com/oivvio/Monodevelop-Resources-as-Constants

Writing easily modified code

What are some ways in which I can write code that is easily modified?
The one I have learned from experience is that I almost always need to write one to throw away. That way I have developed a sense of the domain knowledge and program structure required before coding the actual application.
The general guidelines are offcourse
High cohesion, low coupling
Dont repeat yourself
Recognize design patterns and implement them
Dont recognize design patterns where they are not existing or necassary
Use a coding standard, stick to it
Comment everyting that should be commented, when in doubt : comment
Use unit tests
Write comments and tests before implementation, that way you know exactly what you want to do
And when it goes wrong : refactor, refactor, refactor. With good tests you can be sure nothing breaks
And oh yeah:
read this : http://www.pragprog.com/the-pragmatic-programmer
Everything (i think) above and more is in it
I think your emphasis on modifiability is more important than readability. It is not hard to make something easy to read, but the real test of how well it is understood comes when someone else (or you) has to modify it in repsonse to changing requirements.
What I try to do is assume that modifications will be necessary, and if it is not really clear how to do them, leave explicit directions in the code for how to do them.
I assume that I may have to do some educating of the reader of the code to get him or her to know how to modify the code properly. This requires energy on my part, and it requires energy on the part of the person reading the code.
So while I admire the idea of literate programming, that can be easily read and understood, sometimes it is more like math, where the only way to do it is for the reader to buckle down, pay close attention, re-read it a few times, and make sure they understand.
Readability helps a lot: If you do something non-obvious, or you are taking a shortcut, comment. Comments are places where you can go back and refactor if you have time later. Use sensible names for everything, makes it easier to understand what is going on.
Continuous revision will let you move from that first draft to a better one without throwing away (too much) work. Any time you rewrite from scratch you may lose lessons learned. As you code, use refactoring tools to eliminate code representing areas of exploration that are no longer needed, and to make obvious things that were obscure. The first one reduces the amount that you need to maintain; the second reduces the effort per square foot. (Sqft makes about as much sense as lines of code, really.)
Modularize appropriately and enforce encapsulation and separation of logic between your modules. You don't want too many dependencies on any one part of the code or that part becomes inherently harder to understand.
Considering using tried and true methods over cutting edge ones. You give up some functionality for predictability.
Finally, if this is code that people will be using before and after modification, you need(ed) to have an appropriate API insulating your code from theirs. Having a strong API lets you change things behind the scenes without needing to alert all your consumers. I think there's a decent article on Coding Horror about this.
Hang Your Code Out to D.R.Y.
I learned this early when assigned the task of changing the appearance of a web-interface. The code was in C, which I hated, and was compiled to a CGI executable. And, worse, it was built on a library that was abandoned—no updates, no support, and too many man-hours put into its use to change it. On top of the framework was a disorderly web of code, consisting of various form and element builders, custom string implementations, and various other arcane things (for a non-C programmer to commit suicide with).
For each change I made there were several, sometimes many, exceptions to the output HTML. Each one of these exceptions required a small change or improvement in the form builder, thanks to the language there's no inheritance and therefore only functions and structs, and instead of putting the hours in the team instead wrote these exceptions frequently.
In my inexperience I was forced to change the output of each exception, rather than consolidate the changes in an improved form builder. But, trawling through 15,000 lines of code for several hours after ineffective changes would induce code-burn, and a fogginess that took a night's sleep to cure.
Always run your code through the DRY-er.
The easiest way to modify a code is NOT to write code. Write pseudo code not just for algo but how your code should be structured if you are unsure.
Designing while writing code never works...for me :-)
Here is my current experience: I'm working (Java) with a kind of database schema that might often change (fields added/removed, data types modified). My strategy is to parse this schema and to generate the code with apache velocity. The BaseClass generated is never modified by the programmer. Else, a MyClass extends BaseClass is created and the logical components of this class (e.g. toString() ! )are implemented using the 'getters' and the 'setters' of the super class.

Resources