Some of you have probably heard one or more of my talks, or read the annotations I made in the Design Guidelines. If you have then you already know that I don't always agree with every suggested guideline. Especially not in every context. It's probably fair to say that one of the greatest areas of disagreement has to do with the handling of value types and the prevelance of properties vs. fields in the framework.
Generally, my feeling is that properties are highly overrated and fields terribly under-utilized. Did I mention that not everyone agrees with this position? 🙂
So suffice to say that the guidelines are still good guidelines but of course they are only that, and so you should know when it might be a good time to consider disregarding some of them. Today I wanted to write a motivational example for you that shows the kind of situation that might call for an approach that is more "old-school" if you like.
To try to make it more real, I've cooked it up in terms of some graphics library primitives that might happen in a real graphics library that was dealing with objects made up of 4 side polygons (quads) with some basic texturing. Naturally this example isn't complete but hopefully there is enough there that you could imagine what the other primitives might look like.
Below is the code written in the style that I would suggest, following are some key questions which are intended to suggest the origin of my thinking on some of the more important points.
// typical 3d coordinate
public double x;
public double y;
public double z;
// handy math methods
// projected cooridinates in the text space
public double u;
public double v;
// handy math methods
// useful for normals etc.
public double dx;
public double dy;
public double dz;
// handy vector math methods
// a single vertex, with location, and normal
public Point3d location;
public Point2d uvmap;
public Vector3d normal;
// manipulation methods
// vertex indices within a mesh
public int corner1;
public int corner2;
public int corner3;
public int corner4;
// at last a reference type
private Vertex vertices;
private Quad quads;
private TextureMap texture; // defined elsewhere
// assorted methods that accept arrays of vertices and quads
// and insert them into the structure and things like that
Question #1: Point3d is a struct, not a class. Why?
Question #2: Point3d.x is a field, not a property. Why?
Question #3: Vertex is a struct, not a class. Why? Same reason as #1?
Question #4: Vertex.location is a field, not a property. Why? Same reason as #2?
Question #5: Quad has no methods. Why?
Question #6: MeshSection is a class with private members. Why?
Question #7: Why do I suggest that MeshSection methods accept arrays of Vertices, Quads, and the like rather than singletons?
Question #8: No mention is made of synchronization here at all, is that just an oversight?
Question #9: How useful is the "foreach" construct likely to be when working with arrays of vertices or quads etc?
Question #10: How many rules did I break? 🙂
Of course Brad and Krzysztof (the principle authors of the guidelines) both understand that the guidelines need to be broken sometimes. Sometimes we disagree when the bar for breaking them has been reached but I think that's actually a good thing because that kind of tension makes for good professional growth for everyone and better discourse for our customers.
Whenever you decide to go off the recommended path it's still good to be familiar with the guidelines in the area because they can give you some valuable information about what the consequences might be so that you can make an informed decision. Like in this parctiular case you might learn about some serialization issues you'll have to deal with since properties were not chosen.
Try to answer yourself before you peek at the comments, there's good thoughts down there. 🙂
Update: I posted my solution here.