show all comments

programming

To self access - or not

June 30, 2006 15:00:20 EDT

One topic that generates a lot of heat is the question, "Should one use self accessors?". First, for clarity, self accessors are accessors used to access private instance variables. My opinion is that they should be avoided and one should not automatically use self accessors. There are situations where self accessors should be used but that should be determined as the code evolves.

Let's look at the reasons people use self accessors and what I think.

1. Using an accessor instead of a direct reference provides consistency with the message sending paradigm.

This only works if one does not use method temporary variables or refer to message arguments, to me this is rather weak. Additionally, when one uses a direct reference it is clear from the code that state is being read or changed. If the code uses a setter or getter a user reading the code, who is unfamiliar with the code, cannot be 100%25 sure that nothing else is being done by the accessor and must also read the accessor. Trying to maintain consistency with the message sending paradigm is a lot less important than readability.

2. Object state variables can also be considered attributes and using accessors maintains consistency with the concept that attributes are represented by methods.

I agree with this and is what I consider to be the strongest argument for using self accessors. When I am creating a new design I frequently write my code using self accessors, but later change them to use direct references. This is because, other than working, I consider readability to be the most important goal of the code. Additionally, I have seen too much code where other objects improperly used the accessors, resulting in brittle code that needed to be reworked. This tends to be more of a problem with novice smalltalk programmers who have not yet rid themselves of their procedural thinking.

3. Using accessors allows one to more readily reuse a design and specialize in a subclass.

While there is some truth to this, what frequently also occurs, is the subclass changes are sufficiently different that the method names no longer are a good representation of what the methods are doing. Also frequently, the programmer has designed the class with re-usability in mind, but has no actual use cases. This results is a class that is immature with respect to re-usability and is less readable than its actual use would dictate. Using self accessors in an abstract class is something that should be arrived at through design evolution.

4. Forcing state access through a couple of methods makes debugging easier.

This is because of a lack of good tools. The proper solution here is to get, or create, good tools instead of making your code compensate. In the current version of VisualWorks if you want to trace state access or interrupt execution, there are browser menu commands that allow the user to place probes on all instance variable accesses.

general

Re: Breakpoints and Probes in VisualWorks

March 23, 2006 09:53:13 EST

Spotted in Runar Jordahl - Smallwalk

Just discovered... "ThisProbe" is a variable you can use in the code snippet. This simplifies the code for a probe that removes itself to:

I would not recommend doing this. Adding or removing a probe changes the method bytecodes. If you change the bytecodes while you are executing a method you could crash your image. The debugger takes great pains to fix up a context if you add/remove a probe in an active context.

general

Preventing and recovering from Notifier hell

March 22, 2006 11:02:43 EST

Notifier hell is when you have a bug that generates a continuous stream of notifiers and if you don't act quickly your image will die.

Cause:

In almost every case Notifier hell is caused by a bug that is encountered as a result of a #displayOn: message send or a bounds calculation. When the bug is hit a notifier pops up and the presence of the overlapping notifier causes another #displayOn: to be sent to your app.

Prevention:

In the VW settings tool under Debugger, enable "Use event faithful debugging". When an exception occurs you will get only one notifier for that Window Manager. The downside for this setting is that all windows associated with the window manager will be frozen, no updates or events will be processed. For some bugs you may want to disable this setting.

Recovery:

In the event you did not enable "Use event faithful debugging", you can use the following procedure to gain control of your image and clean out the notifiers. However, you must first load the "ProcMonitor Window Close" package from the Open Repository. This adds the "Close Windows" command to the process monitor.

  • Hit ctrl-\. This will open the Process Monitor and pause all user processes.
  • Select the Windows tab.
  • Select all the exception windows.
  • If the Process Monitor keeps scrolling to the top then stop the sampling process.
  • From the popup menu select "Close Windows"
  • Start the sampling process.
  • All the windows you selected should be closed.
  • Select the "VisualWorks Team" window, i.e. the launcher.
  • Select the "Proceed" menu command from the menu. This will unfreeze the launcher.
  • From the Launcher open settings and under the Debugger settings enable "Use event faithful debugging" and accept.
  • In the Process Monitor File menu, select "Proceed All Paused"

At this point you may get another exception, but only one.

general

Slow running computer

November 30, 2005 09:16:22 EST

I got a new desktop computer around the beginning of this year. After a few months I noticed that occasionally an application would run rather slow. It took me a few months to realize that this was happening as I was not yet accustomed to XP. Eventually, I noticed that there was some dependence on what I did when I first started up, and if it was too frequent, I could reboot and possibly not encounter it for the remainder of the day.

Because, I could not find a pattern with enough consistency and restarting the app or rebooting fixed it, I tolerated the situation. Furthermore, my virus scanner and spyware scanner never reported any intrusion and defragging did not improve it. But, it slowly began to happen more frequently so I got RootKitRevealer but it did not report anything either, argh!

Recently it began to occur more frequently and it was becoming harder to get rid of. I tried a few more things to find out what was happening but nothing turned up. At this point it appears that isolating it will get real difficult so I figured I better first make sure there is no memory problem, comparatively speaking this is much easier to do. So I started looking for memory tests. My processor board is an Intel board and it came with a CD containing various utilities so I looked at it and decided to load the desktop monitor. To my surprise I found that the processor temperature was reported to be -190 C, rather weird. So, I rebooted and looked at the BIOS settings. One of the BIOS pages was a hardware monitor and it showed the temperature being 270 F, much too high, but it also seem to change too much between reboots. Anyway I decided to check out my processor board and noticed a lot of dust on the fan intake, but I did not think it was enough to severely restrict airflow. After cleaning and rebooting I still saw weird temperature readings.

I then went to the Intel support site and after a bit of looking around I downloaded the most recent BIOS update. Finally! After updating my BIOS the processor temperatures looked like they should. In the release notes I found that one of the updates corrected improper temperature readings.

Best of all, the problem with slow applications is now gone!

VW MultiProc UI

Thread-safety and the MulitProc UI

November 07, 2005 13:00:00 EST

Thread-safety and the MultiProc UI

The MultiProc UI introduced in VW 7 provides the developer with additional flexibility in creating his application. However, this flexibility also presents a new potential problem, namely thread-safety. This article will provide the developer with techniques to address the thread-safety issues with the MultiProc UI.

What is thread-safety?

When multiple processes interact with a common resource and at least one process updates the resource, the potential exists for a process to “read” the resource when it is an inconsistent state, or if there are multiple updaters, then the resource may end up in a permanent inconsistent state.

The techniques employed to ensure thread-safety usually involve some form of serialization, i.e. use of semaphores, or simply restricting resource access to just one process. The problem with serialization is that there may be several points that need to be serialized and if one is missed then you can still have a problem. Additionally, serialization also introduces the possibility of deadlock if multiple resources are involved.

Because of its simplicity, I prefer to restrict resource access to just one process. This is not always possible but this is what I use when I begin my design. By restricting access to just one process I mean that only one process should have a reference to the resource at any given moment in time, the reference can be passed between processes.

What does this mean in the context of the MultiProc UI?

Basically, I consider all the windows and the local objects reachable from a window to be restricted to the window manager process. This means the application model and all the supporting domain objects. Additionally, this includes the window display surface. While this may seem rather restrictive there is a good reason for this.

Consider a domain object that is being displayed by a window and this domain object is being updated by a background process. Typically, when a domain object is updated it sends a changed message to its dependents which eventually results in the display being updated to reflect the new value. But, what happens if the user is doing something in the window related to the field that is being updated? Additionally, when the display is updated it usually does an invalidate, this may cause the field to be redisplayed immediately, by the background process, or it may post an event to the window manager event queue. If the widget is directed to perform the invalidate immediately, the window manager may process events in the background process. This is undesirable because now you can have the window manager process processing some events while another process processes other events for the same window, resulting in strange a display.

A common issue for an application that communicates with a server is performing the communication in a manner that does not block the UI while waiting for a response from the server. Usually, this involves performing the communication in a background process and then updating a domain object. However, as previously stated, updating the domain object should be done by the ui process and not the communication process. One way to do this is to use #uiEventFor:

obj := sever getMyFeature.
[myDomainObj someFeature: obj] uiEventFor: myWindow.

If you find that you need to share a domain object between applications using different window managers, then you should wrap your dependents so the wrapper ensures that the proper window manager process does the update. For example, if you can subclass AspectAdaptor, add a “window” instance variable, and create a new update method as follows;

update: anAspect with: parameter from: sender
	"Propagate change if the sender is the receiver's subject and anAspect is the receiver's aspect."

		(sender == subject and: [anAspect == self forAspect])
		ifTrue: [[dependents update: #value with: parameter from: self] uiEventFor: window]
		ifFalse: [[sender == subjectChannel ifTrue: [self changedSubject]] uiEventFor: window]

Summary

Begin your design using the following two guidelines.

  1. Restrict all your application windows to just one common window manager.
  2. When using background processes, make sure your domain models are updated by the window manager process instead of the background process.

Use multiple window managers and access controls such as semaphores only when the first two rules are inadequate for your system.

Tools

Method Defactoring tool

October 31, 2005 15:47:30 EST

One of my pet peeves about smalltalk is that it can be a pain to read highly factored code. You end up chasing through several small methods to figure out what is going on. Once I mentioned on the VWNC mailing list that it would be nice if someone would write a defactoring browser. I think it was John Brant who responded by saying I should use the method inliner. However, the method inliner recompiles the method, which I don't want to happen.

So, recently I created a defactoring tool. It reuses the method inliner but does not recompile the method. If you are interested in using it you can find it here.

probes

Probe Libraries - Again

October 12, 2005 10:17:39 EDT

In a previous article I provided an example of how a developer could create his own special probe library. Well, Boris inquired as to why the library was file based instead of stored in the image using pragmas. The answer was that PDP predates pragmas and an image hosted library had not been created.

Well, now there is an image hosted probe library available here.

probes

Simulating Exceptions with probes

September 28, 2005 19:16:53 EDT

The other day I was asked if there is a way for a probe to generate an exception but make it appear that it was raised from the context that contains the probe and not the probe context. This is quite easy to do.

If we look at GenericException class>>raiseSignal we see;

   ^self new
      searchFrom: thisContext sender;
      originator: thisContext sender homeReceiver;
      raiseSignal.

If we generate the exception from the probe conditional expression then the expression becomes;

   SomeException new
      searchFrom: DOITCONTEXT;
      originator: self;
      raiseSignal.
   ^false

You have to remember that in the probe expression 18self' is bound to the receiver of the method in which the probe resides.