Object Oriented Programming/Lifetime Management

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Lifetime Management[edit]

Object Lifetime Management is the concept of controlling the number of instances a configured service will have and the duration of the lifetime of those instances. In other words, it allows you to determine how returned instances are cached.

Manual Lifetime Management[edit]

Factories[edit]

In the real world, factories are used to make stuff (e.g. automobiles). In OO programming, factories also make stuff; specifically, OO factories "make" (instantiate) objects.

At least in Java, a constructor is unable to return a reference to an existing object—it MUST return a brand-new object. This can cause two problems—too many object instances, and identical objects that are duplicates—not the exact same object.

Factories are generally implemented as a public static method inside a class that has only private constructors. In this way, only the factory can create instances "Guaranteeing[1]" that all instances of the object have been created by the factory.

The factory most often has an internal "Cache" of objects. Whenever a user asks the factory for a new object, the cache is consulted first and one of the cached objects are returned if it is identical—otherwise a new instance is created, added to the cache and returned.

Factories can also be used to inject user code into an "Unmodifiable" library. It is possible to save and restore a user object that implements some important functions of a library object. The library then uses that factory to get instances of the users object, and doesn't even know that the user has replaced a core component with completely new code.

As an example... Say the library uses Library objects all over the place. The library user can create a class (let's call it User) that extends Library. The user then calls LibraryFactory.set(User.class), and the factory stores it. Inside the library, whenever the library wishes to use a Library object, it calls the LibraryFactory.Factory() function to get a new instance. Without changing any code, the user can now completely change the way the library functions by overriding one or more methods in his User class.

This is used in various places inside the Java SDK to allow you to change how chunks of the SDK works without rewriting any of the code.

  1. In Java, just having private constructors does not truly guarantee that all your objects came from the factory. Serialization and reflection can still create new instances without going through the constructor.

Reference Counting[edit]

Reference counting is a programming technique of storing the number of references, pointers, or handles to a resource, such as an object, a block of memory, disk space, and others.

Garbage Collection[edit]

Garbage collection refers to freeing of heap-allocated memory. The heap memory must be freed eventually. Either the programmers code must explicitly free it, or some automatic system mechanism is required.

The most common mechanism is mark and sweep. This is where the system knows of certain top-level classes (Threads and windows mostly). It follows all the references from these "Known" classes to every class that can be reached and marks each class. When it's done, it "sweeps" (gets rid of) every unmarked class.

Garbage Collection is a huge enabler of Object Oriented development—it completely changes the way you design. With code-based memory management it is necessary to have some way to track an object. If it is created on the stack, it will be deleted when the method exits (so instances passed outside your method will become invalid). If it is created on the heap, some object must delete it manually—so if your method is going to create an object and pass it to two other objects that both retain the object, you have a problem. Who deletes the object? The original method can't because it will have exited before the two objects are finished with it, and the two objects shouldn't know anything about each other.

This type of problem is often solved with "Reference counting" which is another form of garbage collection, but a manual one. It also leads to fewer long-lived, free-roaming classes being created since they have to be tracked.

GC solves problem, that of ownership. If you are programming in a language with Garbage Collection, you may create classes on the fly, pass them off, retain a copy or forget about it... You really can't go wrong. When all instances have been "Forgotten", the class disappears.

The drawback is that GC tends to take a solid chunk of time. This is less true lately as at least Java has threaded GC and the ability to limit the amount of time GC will run. There are actually dozens of tuning and reporting options and the ability to select from multiple GC systems to fit your need.

GC Implementations run from trivial (instance counting) to amazingly complex. The current default Java VM uses a multi-tiered system with different mechanisms for new, middle-aged and old objects. For instance, since almost all new objects tend to die almost instantly, the first section (Eden) is divided in half. When one half becomes full, the currently referenced objects are copied to the other side. The system switches to using the "new" side and completely forgets about the old half. There is no explicit code invoked to delete objects that are already gone.

This means that GC can actually be more efficient than traditional allocation/free since there is no free operation for nearly all objects.

Garbage collection should be considered essential to OO Design.

Persistence[edit]

Persistence is simply the act of having objects that "Stick around" between invocations of your program.

This can be trivial (Just serializing an object out when exiting, serializing it back in when loading) to a full OO-database implementation.

Hibernate is a good program that sits between your application and a database and ensures that your objects are properly persisted.

Serialization[edit]

Serialization is converting an object to a stream of bytes that can then be saved to a file or transmitted over a network.