# Generating Code Metrics and Estimating Costs with Xcode

### Costs by Putnam

One of the earliest cost metrics is the Putnam cost model. This metric first appeared in 1978 in a seminal paper written by Lawrence Putnam. It assumes that project growth follows a Rayleigh distribution curve. The commercial package SLIM is based primarily on the Putnam model.

Figure 3 shows the three empirical equations of the Putnam cost model.

Figure 3.

Equation A computes the total effort Etot needed to complete the project. It expresses the effort in terms of person time, which may be in months or years. The constant Ktech is the technology index. It rates the project's dependence on current technology. The constant Kprod is the productivity index. It rates the productive quality of the team in terms of SLOC per unit time. The variable SLOC is, of course, the project size in effective lines of code. And the variable tproj is the desired time-to-market for the project. It uses the same person time units as Etot.

Equation B defines actual development (coding, design, etc.) as 39% of the total project effort. Equation C defines overall project difficulty as a ratio of development effort and time-to-market. Do not confuse this with Halstead difficulty, which measures code complexity.

Listing Two shows the Xcode utility script implementing the Putnam model. It begins with the path to the active project file (line 67). It uses that path to locate the enclosing project directory (lines 69-71). By definition, a project directory is the one with an xcodeproj bundle as one of its items. Checking for that bundle is handled by the utility routine isProject() (lines 52-62).

Listing Two

#!/usr/bin/python
# -*- coding: utf-8 -*-
# import the following module
import os, sys
import string

# Count the number of effective source lines
def getELOC(aPth):
# open an input stream
tInp = open(aPth, 'r')

# create the parse buffer
try:
finally:
tInp.close()

# start parsing the buffer
tLOC = 0
tBgn = False
for tLin in tBuf:
# filter out whitespaces
tTst = tLin.strip()
tLen = len(tTst)
if (tLen > 0):
tMrk = tTst.find("//", 0)
if (tMrk != 0):
tMrk = tTst.find("/*", 0)
tMrk = tMrk + tTst.find("*/", 0)
if (tMrk <= 0):
# filter out import statements
tMrk = tTst.find("#import", 0)
if (tMrk != 0):
if (tBgn):
# check for a closing token
tMrk = tTst.find("*/", 0)
tBgn = (tMrk == -1)
else:
# check for an opening token
tMrk = tTst.find("/*", 0)
tBgn = (tMrk >= 0)
if (not tBgn):
tLOC += 1

# return the count results
return (tLOC)

# Is this the main project directory?
def isProject(aPth):
# get a list of files
tLst = os.listdir(aPth)

# parse the list
tChk = False
for tNom in tLst:
tChk = tChk or (tNom.find(".xcodeproj") > 0)

# return the check result
return (tChk)

# MAIN SCRIPT BODY
# locate the project directory
tPrj = '%%%{PBXFilePath}%%%'
tChk = False
while not(tChk):
tPrj = os.path.dirname(tPrj)
tChk = isProject(tPrj)

# parse the project directory
tSrc = []
for tRef, tDir, tLst in os.walk(tPrj):
# parse the project files
for tNom in tLst:
tExt = string.split(tNom, ".")
if (len(tExt) > 1):
tExt = tExt[1]
tChk = (tExt == "m") or (tExt == "h")
if (tChk):
tPth = os.path.join(tRef, tNom)
tSrc.append(tPth)

# calculate the project size
tSiz = 0
for tPth in tSrc:
tSiz += getELOC(tPth)

# calculate the project costs
# -- PUTNAM:factor:productivity-index
kPI = 500

# -- PUTNAM:factor:technology-constant
kTech = 0.39

# -- PUTNAM:time:maximum-project
tTmax = 0.25

# --- PUTNAM:project:effort:total
tEtot = kTech * (tSiz ** 3.0)
tEtot = tEtot / ((kPI ** 3) * (tTmax ** 4))
print "Estimated total effort: %.3f" % tEtot

# --- PUTNAM:project:effort:development
tEdev = 0.3945 * tEtot
print "Estimated development effort: %.3f" % tEdev

# -- PUTNAM:project:difficulty
tDiff = tEdev / (tTmax ** 2)
print "Estimated project difficulty: %.3f" % tDiff

With project directory in hand, the script then parses all the files in that directory. It looks for files with a '.m' or '.h' suffix and adds them to the array buffer tSrc (lines 75-85). Then it counts the lines in each of the file (lines 88-90) using the method getELOC(). That method (lines 8-48) opens each file and counts only those lines it deemed effective. The resulting count is returned to the main script, which adds them to the variable tSiz.

Finally, the script computes the project's effort and difficulty. And it prints the results for the user to view (lines 103-113).

Calibrating the Putnam model involves choosing the right values to its two constants. For instance, consider the constant Ktech. Its possible values range from 0.1 to 1.0. A high Ktech value means the project is tech sensitive. It can be difficult and costly to adapt the project to a similar but incompatible technology. This is true of drivers that works only with certain hardware, or of video codecs that work exclusively with Apple QuickTime.

Conversely, a low Ktech value means the project is tech agnostic. Adapting it may require only minor rewrites and a rebuild. Some might need just a change of libraries or plug-ins. Low Ktech are typical of many open-source projects. For new projects with unknown dependencies, a value of 0.55 is a good starting point for Ktech.

As for Kprod, its possible values can range from 500 to 28000. Choosing the right value depends on the nature of the project and its team. For instance, a value of 500 means the team is performing below par. This could be due to poor work conditions, low morale, unrealistic demands, or ill-defined goals. It may be due to too many new hires, with their lack of practical experience. It may even be due to a start-up environment, with its uncertain future.

Next, a Kprod value of 2000 is typical of embedded or real-time projects. These projects have to contend with restricted and specific hardware resources. Code work is often exacting and terse, fine-tuned for a narrow range of tasks. Stringent testing is mandatory to ensure near transparent operation.

A Kprod value of 10000 is associated with telecom and system projects. They need to be flexible with hardware changes. Some scale well, showing improved performance and capacity with increases in hardware resources. Some use drivers to support new hardware. Some use discrete code libraries to factor out certain features.

Finally, Kprod values near 28000 are typical of commercial projects. These have high usability standards. They must anticipate every possible action a user might make. They must tolerate faults and guard against unexpected freezes or crashes. Some have to be hardware-agnostic, able to support a wide range of installed hardware. Others have to be system-agnostic, able to run on different host systems.

### More Insights

 To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.

# First C Compiler Now on Github

The earliest known C compiler by the legendary Dennis Ritchie has been published on the repository.

# HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

# Building Bare Metal ARM Systems with GNU

All you need to know to get up and running... and programming on ARM

# Amazon's Vogels Challenges IT: Rethink App Dev

Amazon Web Services CTO says promised land of cloud computing requires a new generation of applications that follow different principles.

# How to Select a PaaS Partner

Eventually, the vast majority of Web applications will run on a platform-as-a-service, or PaaS, vendor's infrastructure. To help sort out the options, we sent out a matrix with more than 70 decision points to a variety of PaaS providers.

More "Best of the Web" >>