Wednesday, February 4, 2009

Are Properties really a bad idea?

Read more about this article at my web site.

Like many experienced programmers over the years, I have been exposed to hundreds of different programming styles,


read long philosophical threads about programming methodologies new and old and have been fortunate enough to work with some really expert programmers.




For the most part, I have enjoyed the dialogue and somewhere along the way have learned to let go of of the small stuff,


that is unless of course the small stuff which I would otherwise overlook in the right context, is at risk of becoming


detrimental in the wrong context.




I can remember when I was learning to sail I kept calling those things that hung off the side of the boat bumpers


when in fact I should have been calling them fenders. My instructor immediately corrected me and said "its ok, that really


used to bother me but I've learned to let that one go." What he had learned through unfortunate experience, was that students


needed to understand immediately how to tie fenders on correctly well before the vessel reached the the slip so as not to


damage hull, less important to him was what we called them at the moment of impact. Besides, I would learn the correct


terminology with more practice soon enough.




So back to the subject at hand, properties. Properties are one of the small things I've learned to let go of over the years,


because there is just so much widespread confusion over them that they have become ubiquitous. It would require a huge


investment of resources and time to get emotionally tied to their "proper" use one way or the other, unless, as I mentioned


earlier, I feel they are endangering the codebase.




If you search for the effective use of properties, you'll find literally thousands of conflicting statements about why properties exist,


when to favor properties over member variables and even whether they are evil and should be exercised from all properly


object oriented code completely. Yet in object oriented programming classes, we're told that people have certain properties


like a name or sex or origin, and we should immediately start adding them to the person base class (another thing I'm learning to


let go of..) so that whatever extends that person class will pick up those common properties. OK fair enough, this is exactly how I learned about properties too.




So are properties really a bad idea?


My thesis is that as long as we don't violate some important design principals, properties are absolutely fine under most


circumstances. What are properties exactly? Well, if you wiki property, you'll find that a property is defined as a kind of hybrid


sort of class member somewhere between a data member and a method. In the spirit of keeping it simple, I have highlighted some rules about properties and how to use them without causing too much damage.




Maintainability:


Do the properties you are about to add offer more or less maintainability? In other words, are you writing a class to DoSomething() or are you writing a class that requires the dependant class to get all the information from you and then doSomething(). Good object oriented classes DoSomething(), not the other way around. It is generally acceptable to return an object or interface using property accessors. For instance, if our person class, is used by our personnel system, we expect the personnel system to ask the person for their address and to have the person return the address to the personnel system, what we don't want is to have the personnel system ask the person for the street, city, state, and zip code and then have the personnel system build the address, that would be counterintuitive.




Object Oriented or Procedural Programming:


Are you really writing OO code if you have properties everywhere? Consider for instance that procedural programming relies on local knowledge of objects to perform tasks while OO programming is based on use cases and conversations. Do getters and setters come up during conversations? I will reference the experts Kent Beck and Ward Cunningham for more detailed information but I encourage you to think about the classes you need, and the responsibilities they must perform as well as how they will collaborate. Beck and Cunningham developed some really good practices using CRC cards to model “conversations between classes”.




Encapsulation:


While properties offer better encapsulation than fields do, you shouldn't necessarily start blindly replacing fields with properties in every case. The more accessors you create, the more dependency you create and the more at risk you are to exposing implementation details of your class. Consider your DoSomething() methods, do they take reference or value parameters. Also consider the use of internal and private properties carefully, do you really need them?



State:


Getters and setters which "report" get or "change" set the state of some private member variable shouldn't change the state of the object itself, or any other unrelated object for that matter. Remember when I said that a property is somewhere between a method and a field or member? This is one of the potential hazards of treating your properties as methods. Code in getters or setters which change the state of the object itself will cause unbelievable headaches from adopters. Properties should be reliable, if you call any property repeatedly, you should be able to depend on the value returned from the getter.




Performance:


Impact on performance is another potential pitfall of treating your properties as methods. Performing lengthy or costly operations in getter or setter methods could significantly impact performance. Having for instance a large custom collection or web control object which is dynamically built or retrieved in your getter or setter methods could slow performance as objects are added and increase performance as objects are removed. This can lead to lots of head scratching from adopters, not to mention the loss of hours of productivity troubleshooting mysterious performance issues, which appear and disappear for no reason.




So should you use accessors or not? In my experience, when you start working for large corporations, refactoring decisions sometimes become more about ROI than style and quality is re-defined as the number lines of code over defects or the number of unit tests over uncovered blocks rather than the elegance of design or the implementation of industry best practices. Style and elegance often gives way to brute force. Human beings are certainty freaks, and we have to balance planning and risk with our "drop dead" delivery deadlines. There is never enough time up front but then again, nothing lives forever anyway right? To sum it up, if you are going to use accessors you need understand what they are for and for goodness sakes use them properly because, just to tie the metaphors together, a damaged hull is expensive to fix and if the hole is big enough you may never fully trust the vessel again.




Beck, K. & Cunningham, W. (1989) A laboratory for teaching Object-Oriented Thinking. Apple computer whitepaper, http://c2.com/doc/oopsla89/paper.html#references



Wagner, B. (2008) Choose between Methods and Properties. Visual Studio Magazine p.40 http://visualstudiomagazine.com/columns/article.aspx?editorialsid=2719


Haloub, A. (2003) Why getter and setter methods are evil. http://www.JavaWorld.com





Software Configuration Management Principals

Software Configuration Management Principals

SCM: Software Configuration Management serves as a mechanism for communication, change management and reproducibility.

Team Project: A TFS Team Project is a collection of artifacts used by a team to track a related set of work. You must create at least one Team Project before you can begin working in TFS.



In order to make decisions about how to best organize your projects in Team Foundation Server (TFS), it is important to understand that TFS best practices were developed around the concept of a "Team Project".

Scalability of Team Projects: Scalability is limited by the complexity work item types. MSF for Agile Development have been shown to support 500 team projects per server while MSF for CMMI Process Improvement have been shown to support 250 team projects per server.

Common strategies used to structure team projects

Team Project Per-Application (Most Common – Supports both large and small applications as well as multiple release and parallel development).

• Create one team project for each application being developed.

• Releases are manifested in TFS as source branches or as different nodes in the iteration class hierarchy.

Team Project Per-Release (Works well for large teams working on long-term projects).

• Every major application release starts a new team project.

Team Project Per-Team (Provides central control and monitoring of the activities of software development teams).

• Projects aligned with team boundaries in the organization.

• Cluster together applications developed by the same team.

Isolation Mechanisms in VSTF

Branch: An isolation level mechanism that allows one or more people to work on a set of files in isolation. A branch of a file is a revision of the file that uses the trunk versions as a starting point and evolves independently. Branches are labeled with a minor version number that corresponds to the major version number in the trunk. Typically, most of the work happens in the trunk or main branch, which is branched at every release. Small amount of work might still happen in the release branches, which is typically merged back into the main branch.

Note: Branching is the only isolation mechanism that provides collaboration and version changes among a group of developers.

Workspace: Allow individual developers to work in isolation from others. This is where the developer keeps all the artifacts needed to accomplish a task. Workspaces are normally associated with versions of the artifacts. Workspaces include any item that appears in the Source Control Explorer. Typically the following are stored in the source control:

• Source Code

• Test Code

• Library Files (.cs)

• Library Files for 3rd party or shared libraries (.dll)

• Scripts

Workspaces are associated with one or more code-lines.

Shelve set: When a file is changed in the work space, the source control marks it as being edited by the person who edited the file. However, this change is not reflected into the source control unless the file is checked in. There are scenarios where the user wants to save all the changes made to the workspace, but not check them into the source control. For example, the developer might want to send the changes to their peer/manager for a code review. For this purpose, the changes made can be saved as a shelveset, stored in the source control. The shelvesets are not incorporated into the source tree, but can be retrieved on demand and its contents can be viewed.

Typical Branching Strategies in VSTF

Branch Strategies begin by thinking about where isolation is needed that provides version control and the ability for multiple people to collaborate. Compose the isolation scenarios below to form your overall branching strategy.

1. Release Isolation – If you need to work on multiple releases in parallel you may want to isolate them in their own branch.

a. Note: the term “release” does not refer to a new version of the product; it may refer to releasing to a test team from a dedicated branch so issues can be fixed independently from development continuing on the development branch.

2. Feature Isolation – Isolating functionality that is experimental or risky enough to merit its own branch. Developers can collaborate on a feature without exposing the application to instability.

3. Team Isolation - Sub-teams work in isolation from each other, providing the ability to collaborate without breaking changes that other teams are working on.

4. Integration Isolation – Staging area for merges. Merges are often destabilizing, and maintain a branch where active development does not occur is often beneficial.

Branching Consideration

Over-branching is an easy mistake. Weigh the benefits of isolation against the costs so you can make appropriate decisions about the amount of process overhead you’re willing to incur in your environment.

1. Merging – Moving changes between branches. Changes can easily get merged incorrectly resulting in a destabilized environment. This is one reason for creating a staging area for merges. (above)

2. Latency – It takes time to move changes between branches. A Typical merge operation involves stabilizing the source branch, executing merge, conflict resolution then stabilization of the target branch. On large projects, scenarios taking days, weeks or even months are not uncommon.

Structuring your Branching Hierarchy

Structuring your branching hierarchy is important because merging along the hierarchy is easier than merging across the hierarchy.


1. Merging along the branch hierarchy - TFS tracks information about the relationship between branches in order to allow 3-way merges.

2. Merging across the branch hierarchy - If the information is not present, TFS doesn’t know about modifications made in the different branches. Without this information TFS assumes changes have been made in both branches, resulting in manual merges that are otherwise unnecessary. The first time you merge across hierarchy, the relationship is established and future merges are much simpler.

Note: Cross hierarchy merging is not supported through the GUI even after the relationship is established. Cross hierarchy merges can only be done via command line (tf.exe).

Choose a hierarchy that provides the appropriate isolation strategy while still supporting your merge hierarchy.

Branching concerns: A company’s branching model should match the business model. A company that wants frequent product releases may have complex branching structures and need time-intensive merges. Another company may have many customers using independent releases and few branches.

Labels in TFS: Labels in TFS are powerful in that they can contain versions of files from different points in time.



The canonical example is:


1. You label a build
2. You find bugs
3. You change only a few files.
The label represents a collection of points in time and not a single point in time.

Individual versions of files can be assigned labels, and all files with the same label forms a release group. Unlike VSS, TFS source control repository does not support linking to an item from multiple places in the source folder structure, nor does it allow an item to be "pinned" (allow different references to the same file from different directories to point to different versions in a way that cannot be further edited). - Wikipedia

Geographically located TFS structures: TFS Proxy server provides an experience for remote a user that is comparable to that of on-site users. Factoring geography into your decision is not necessary.


Common SCM Definitions

You can find a list of SCM Common Definitions here

References

Branching and Merging Primer

Team Foundation Branching Guidance

Whitepaper

Microsoft (2007)

V1 TSP VSTF Process Guidance

Book

Berczuk, S. & Appleton, B. (2002)

Software Configuration Management Patterns: Effective Teamwork, Practical Integration.

Boston: Addions-Wesley

External Links


Branching Structures at Microsoft

The Terminology of Branching

A Branching and Merging Primer

Branch Structure in Developer Division at Microsoft

Software Configuration Management with Visual Studio Team System

The purpose of this document is to provide a model for implementing Software Configuration Management in line with the business model and scalable enough to gain broad acceptance among development team members.

Goals

Define SCM concepts and principals within the context of Team Foundation Server to enable better communication and decision making.
Define a common methodology for implementing SCM based upon industry best practices and the development team scenarios.
Guidance and Policies

Software Configuration Management (SCM)

SCM Guidance

SCM Policies and Naming Conventions (Coming Soon...)

Sarbanes-Oxley (SOX) Compliance (Coming Soon...)

SCM Common Definitions

SCM Principals and Best Practices