Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

Designing Network-Friendly Applications

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.

The Enterprise Network

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.

Workgroup Manager

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.

Details Pane

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.

Adding the VoiceOver Utility

Figure 4: Adding the VoiceOver Utility

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

VoiceOver Added to the Details Pane

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.

Editing the VoiceOver Utility's Properties

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.

Preference Manifest Reflected 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.

Preference Manifest Reflected in the Details Editor

Figure 8: Preference Manifest Reflected in the Details Editor

For More Information

Updated: 2005-10-27