
For most home users, networking means a dial-up or
DSL account. For a growing number of users, however, the network is
often an enterprise environment like the one shown in Figure 1.

Figure 1: The Enterprise Network
An enterprise environment deployed on Mac OS X v10.4 Tiger Server can include
network accounts, network home directories, managed accounts, laptops
with mobile accounts, managed systems, and roaming users who connect
using wireless networks.
In an enterprise environment, IT administrators create network users,
each of which can be managed individually. For ease of management, IT
administrators often create one or more workgroups, each of which allows
a set of network users to be managed collectively. In addition, IT administrators
can apply management controls to specific systems.
Part of your responsibility as an application developer is to ensure
that your application performs optimally in every network environment.
In this article, you'll learn how to think about your application as a
network client, we'll offer some best practices to follow, and we'll explain some solutions that Tiger
Server provides to make your application perform well on a network.
Enterprise Network Considerations
Users of your application who work in an enterprise network environment
expect your application to provide good performance and predictable
behavior wherever they use their Macs. IT administrators expect your
application to avoid consuming network resources unnecessarily. As an
application developer, you should consider the following:
Network home directories vs. local home directory
Network home directories are different from local home directories
in that everything is going over the wire. The UNIX-based Mac OS X treats
a network home directory just the same as a home directory, the only
difference being that one starts from /Network and the other from /Users.
To ensure optimal application performance and avoid unnecessary network
utilization, be careful to differentiate between the local drive and
the home directory, and to allocate data intelligently to the appropriate
storage location.
Managed vs. unmanaged users and systems
Developers need to take into account the fact that users, or the systems
they are using, might be subject to management constraints of various
kinds:
- Getting DNS settings or Open Directory settings from a DHCP binding.
- System management, for example, using Apple Remote Desktop to install
packages on systems.
- Client management using Managed Preferences, in which user and workgroup
preferences in the network environment are set through Workgroup Manager.
Network vs. mobile vs. local accounts
Developers need to pay attention to the nature of the network environment, for example:
- Does the user have a network account in which network credentials are
coming from a directory system?
- Does the user have a local account?
- Or, is this a mobile user whose account is a hybrid of network and local
accounts?
A mobile account caches network credentials. Authentication
information comes from the network as in a network account. Mobile users
who are disconnected from the network cannot change their credentials.
Best Practices
Let's consider two different sets of best practices, one for file system
access and the other for preferences.
Best Practices for File System Access
Observe these best practices to accommodate users whose home directories
are on network volumes:
Optimize for performance
To optimize for performance, minimize disk access. If you hit the disk
all the time, you're going to incur network traffic for every user who's
using a network volume. The less you access the disk for any application
data inside your bundle looking at plists and whatnot, the better. The
tools available to you for optimization are Shark, fs_usage, and sc_usage.
The ADC website has performance tools for system-level
optimization and for file-system optimization along with information
on how to use these tools to tune your application for performance.
Use system disk for temporary files and caches
If you have to create local files, consider whether you want to create
those files in the user's home directory or on the local system. There
are utilities in the operating system to provide you the path to the
right places. Use FSFindFolder and kOnSystemDisk to find location information
for system-related directories, and to find temporary folders or chewable
items that reside on the local system.
~/Library/Caches
If you're optimizing your application's performance so that it doesn't
access the network unnecessarily, be wary of supposedly local caches
that are in fact using the network. You might want to use local data
for local system disk caching as opposed to user directory data.
Security concerns
There are some security concerns regarding the use of local files.
If you do create local and temporary files, make sure they're not accessible
by other users or other applications. Testing is the best way to find
out how your application is behaving. Try out the different scenarios
that your typical user would most likely encounter, not just a local
system or a local hard drive. You should also test your application
running from a network volume, from a locked volume, and from a locked
system where the user does not have access to the local disk because
that disk may be locked for administrator access only.
Best Practices for Preferences
With respect to preferences management on Mac OS X, the rule of thumb
is to use CFPreferencesCopyAppValue because this will always get you
the right paths to the preferences. Because of the way management is
applied, your application might not know where its preferences are coming
from. They could be locked for the system, they could be locked for
the user, or could be locked for the work group that the user is part
of.
CFPreferencesCopyAppValue is guaranteed to return the right preferences
and whether the application is running in a managed or unmanaged state.
NSUserDefaults objectForKey is the corresponding class in Cocoa.
Avoid CFPreferencesCopyValue() unless specifically required
Do not use CFPreferencesCopyValue() unless you explicitly need some
information from a particular domain. If you want to find the global
preferences for a specific setting, you would use CFPreferencesCopyValue(),
but not as the standard preferences code. Under most circumstances,
you should use CFPreferencesCopyAppValue() instead.
If your application supports preferences, make sure that any preferences
that you have reflect the management state in the user interface. You
can find whether preferences are locked by calling CFPreferencesAppValueIsForced()
or using NSUserDefaults objectIsForcedForKey. Preferences that are forced
are not under the user's control but are instead imposed on the user
by the network administrators. In such cases, you'll want your application's
GUI controls to provide visual cues to let the user know which preferences
are locked.
Inherit user interface from Cocoa classes
If your application inherits its user interface through Cocoa classes,
use NSUserDefaultController to find out whether the key that is associated
with your GUI element is locked.
Some Reasons Why Applications Behave Badly
There are many reasons why applications behave badly. Here are the
ones that show up most often in enterprise network environments.
Excessive file system access
For example, if you have an application that uses fonts and wants to
copy them to the local system, it not a good idea to copy them to the
user's home directory because that could be a network volume. Instead
of sending all these bits over the wire, design your application so
that the fonts reside on the local disk.
Use library application support for storing any files that make sense
to store for the system rather than for an individual user, because
the user home directory users may be on the network disk.
Creating network shared resources
Mac OS X makes it easy for users to share resources. In some settings,
such as schools, universities, and businesses, this ease of sharing
resources - music and music, for example - can be problematic. So if
your application permits sharing of resources from a local system, you
should provide a preference that allows network administrators to disable
that functionality if necessary.
Portable Home Directories
Panther users had mobile accounts, which were local copies of the users'
network accounts. Tiger Server introduced mobile accounts with portable home
directories - a local copy of the network account with a local copy
of the user's home directory. Portable home directories allow workgroup
settings and other management settings to remain in effect on the local
system even when it's not connected to the network. Users who have administrator
privileges can create a portable home directory themselves by going
through system preferences accounts and making local accounts, or by
the network administrator using Workgroup Manager.
An important consideration for application developers is that the home
directory path on the mobile computer is not /Network/Servers but rather
/Users/user, so if any applications write a path into their settings
files, that path would no longer be valid on the on the mobile computer.
So if you write anything that's relevant to the user's home directory,
make it relative to the ~ path for the user and instead of using hard-coded
paths.
Preference Manifests
Another important new development in Tiger Server is the preference manifest.
Preference Manifests allows developers to declare how their application
preferences are used in terms of custom defaults or enabling/disabling
functionality. Having a preference manifest allows a system administrator
or network administrator to manage the deployment of the application
quickly and easily through Workgroup Manager, using the Details Editor.
Notice that the Workgroup Manager has an Overview pane (shown in Figure
2) and a new Details pane.

Figure 2: Workgroup Manager
By clicking Details, you display the Details pane, which as you can
see in Figure 3, currently contains settings for the dock and for Managed
Preferences. Let's suppose we're in setting in which we want to disable
the VoiceOver utility. The VoiceOver utility includes a built-in preference
manifest, so this is easy to do.

Figure 3: Details Pane
First, click the Add... button on the Details pane. Locate VoiceOver Utility
under Applications and click Add, as shown in Figure 4.

Figure 4: Adding the VoiceOver Utility
VoiceOver now appears as an entry in the Workgroup Manager Details
pane, as shown in Figure 5.

Figure 5: VoiceOver Added to the Details Pane
Select VoiceOver in the Details pane and click Edit to change its preferences,
as shown in Figure 6.

Figure 6: Editing the VoiceOver Utility's Properties
Notice that the preference for disabling VoiceOver is shown under the
Always heading in the preceding figure. To move it under a different
heading, you can simply cut the preference and paste it where you want
it. The three options function as follows:
- Once: Applies the preference setting the next time the user logs
in. The preference is editable on the user's system and Workgroup
Manager does not attempt to set the preference again if the user elects
to change it.
- Often: Applies the preference each time the user logs in. The preference
is editable on the user's system but the user's changes to the preference
setting persist only for the duration of the user session.
- Always: Applies the preferences and does not permit the user to
change them. (Also knows as forcing the preference setting.)
Behind the scenes, the preference manifest for VoiceOver, com.apple.screenreaderd.manifest,
is a localizable bundle inside the application bundle. Listing 1
shows what the VoiceOver preference manifest looks like.
Listing 1: VoiceOver Utiltiy Preference Manifest
<plist version="1.0">
<dict>
<key>pfm_title</key>
<string>VoiceOver</string>
<key>pfm_domain</key>
<string>com.apple.screenreaderd</string>
Notice that the preference manifest is a property list (plist).
The first item in the plist is a key for pfm_title, where pfm stands
for Preference Manifest. The application to be managed is specified
as VoiceOver. The pfm_title key provides the name that will be shown
in Workgroup Manager's Preference Manifest Editor as the name for the
application's preferences as a whole.
Next there is the key for pfm_domain. This key ties the preference
manifest to the VoiceOver utility. The pfm_domain key specifies the
application domain for this preference manifest file, in this case com.apple.screenreaderd.
This is the name of the application's bundle ID, which is specified
in the application's info.plist and is the name that the application
uses to retrieve preferences through the CPPreferences or NSUserDefaults
API calls.
Figure 7 shows what this would look like in the Workgroup Manager UI.

Figure 7: Preference Manifest Reflected in the Workgroup Manager UI
In addition, there are subkeys for every controllable element in the
application, as shown in Listing 2.
Listing 2: Subkeys in the Preference Manifest
<key>pfm_subkeys</key>
<array>
<dict>
<key>pfm_title</key>
<string>Disable VoiceOver</string>
<key>pfm_description</key>
<string>Set to TRUE to disable VoiceOver</string>
<key>pfm_name</key>
<string>SCRStartupDisabled</string>
<key>pfm_type</key>
<string>boolean</string>
The contents of the preference manifest are organized as an array of
dictionaries. Each element in the array corresponds to one controllable
entry (element) in the application's preferences. So these are under
the preference manifest's pfm_subkeys key in the plist.
The first subkey is for disabling VoiceOver. It's under pfm_title and
the string provided is "Disable VoiceOver." The description of what
it does is "Set to TRUE to disable VoiceOver." Now, how does the VoiceOver
application know what to do? The pfm_name key points to a function internal
to the VoiceOver application, namely, SCRStartupDisabled. The value
of that key, specified by pfm_type, is Boolean. Figure 8 shows
what the user sees in the details editor.

Figure 8: Preference Manifest Reflected in the Details Editor
For More Information
Updated: 2005-10-27
|