views:

56

answers:

2

I have multiple business entities in VB.NET Windows Forms application. Right now they are instanced on application startup and used when needed. They hold descriptions of business entities and methods for storing and retrieving data. To cut the long story short, they are somewhat heavy objects to construct (they have some internal dictionaries and references to other objects) created and held in one big global variable called "BLogic".

Should I refactor this so that each object is created when needed and released when out of scope? Then every event on UI will probably create a few of this objects.

Should I strive to minimize creation of new objects or to minimize number of static and global objects? Generally I am trying to minimize the scope of every variable but should I treat this business logic objects specially?

A: 

Yes, you should refactor to allocate the objects only when needed, and dispose of them when they are no longer needed. This is always a good design choice unless trumped by specific and measurable performance requirements.

The advantage of deferring allocation until absolutely needed is that in many (most?) cases, the object will never be allocated at all. Procrastination pays! ;> Your app runs leaner and the system as a whole should be less taxed and snappier. Nobody enjoys using a memory hog.

The disadvantage of allocate on demand is that it may introduce delays in user feedback/responsiveness that will be irritating. If you have an object that takes a considerable amount of time to construct or initialize (say, loading data across the network), that would probably not be a great match for allocate on button click if the user expectation is to see results immediately after the button click. If you can bring up UI immediately in response to the button click but have controls on the new form fill themselves in from network data as soon as they can (and indicate that they are loading something), that would be less of an issue. The general UI metric for "considerable amount of time" is usually about half a second max between click and UI response.

dthorpe
+2  A: 

Let's look at the two options you've presented:

Single Global Instances

Pros:

  • Less performance cost in each method because the objects are already created
  • No need to figure out how to pass the data around

Cons:

  • Chance that objects are created but never used. This is a waste of both memory and performance. This could be mitigated by using lazy initialization that will create the object the first time it is used but still keeping a single globally created instance.
  • Multithreading concerns such as ensuring data consistency (potential performance and development costs)

Unique per function instances

Pros:

  • Each function gets it's own copy and does not have to worry about what other functions may be doing at the same time.
  • If the objects are not being constantly created and destroyed, you may have a lower total memory usage for your program.

Cons:

  • Depending on how long it takes to create the object, you could have responsiveness issues in the UI.
  • Depending on how the object is created, you may have to wait for another function to finish creating the object before you can create your copy.

This is not meant to be an exhaustive list, but it does point out the main tradeoffs as I can see them. Obviously, you know more about the situation and which tradeoffs are acceptable. A few judiciously chosen globals can be useful, but like most people I would lean away from having a lot of globals unless they represent something that there can only be one of, like a SerialPort, or something that the entire application should only have one of, like an ApplicationSettings class.

Don't undervalue your time (both now and later when you come back for maintenance) as a cost. Sometimes a "better" solution may actually be worse because it takes too long to implement. Often "good enough" turns out to be, well, good enough.

Gideon Engelberth
and then there are instance pools (i.e. connection pools) where you as a factory for an instance, and depending on the settings you get a fresh one or a pooled one.
Jeroen Pluimers