With all the good and bad that goes with it, I focus a lot on the design of the applications and application components I work on. This, in part, stems from my appreciation for both the art and science of software development, which is a topic I've been meaning to post about for some time. Since I put a strong emphasis on architecture and design and I'm usually supporting other people's projects, I tend see a lot of different design approaches. Most of these approaches have been centered around the database, which I think is inappropriate for most systems. What I mean by this is that the developers start with a relational database structure and design their domain objects and business services around that. This is typically done by developers who either don't have a lot of design experience or have a strong background in database development. While I admit that every approach has its pros and cons and every project has its priorities, I typically try to focus developers on the application first, whether or not a data store already exists. I've seen bad data structures drive the application's design too many times. I actually discussed this with a coworker a few days ago and we both agreed that most applications should focus on the domain model and core business services during design rather than developing them from a pre-existing data model. Jeremy Miller talks about this in a recent post, Don't Let the Database Dictate your Object Model . I'm glad to see others professing this practice because I think it's very important and not enough people take it into consideration. All too often, database-driven application designs force unnecessary constraints on the system, limiting innovation, growth, and extensibility.
Standards are very important; especially in team environments. One thing that's been getting to me the past few months is what seems to be a lack of standards when it comes managing Visual SourceSafe (VSS) and Team Foundation Server (TFS) repositories. Since most of my version control experience is with Subversion, I want to bounce back to the fact that data in the repositories is managed very simply. You have three (or four) top-level directories that represent the major version controlled entities: branches, tags, and trunk. The term "tag" may not be familiar to some, so let me just say that tags and labels are the same thing -- an ear-marked version of the repository in a significant state. "Trunk" is another term that some may not be familiar with, but it is essentially the main line of code you're working with. I love the fact that Subversion introduces you to these right off the bat because it almost forces you to learn and abide by good version control practices. You don't have this in the VSS/TFS world. For those who caught on to the optional fourth directory with Subversion, that would be shelves. "What? Subversion doesn't support shelving!" you say? Not true. A shelf is simply a branch in the Subversion world . (Shameless plug: Woohoo! I'm the first result when searching for shelving in Subversion.)
As I mentioned, digging into VSS and TFS for the first time, you don't really see these same principles. It's too bad, because that can cause chaos in the field. Well, maybe the word "chaos" is too strong of a word; but you'll be hard-pressed to find two implementations that work the same exact way. Putting some thought into it, I guess the best thing I can come up with is having an application directory with branch directories sitting alongside it. For instance, if my application is called MyApp, I would have MyApp, MyApp-1.0, MyApp-2.0, and MyApp-2.1. These map to the main and release branches, respectively. Not rocket science, I know, but I just haven't seen a common practice. If anyone has one, I'd love to hear about it. If I have more than one releasable project within my repository, then I'd include all project-related branches within a parent directory called MyApp, or something similar. Then, other releasable projects could sit alongside this one. Again, pretty simple.
Beyond this structure, which will probably change over the coming months, I also have something else of mild interest. Time and time again, I need to explain version control concepts to developers who haven't dealt with configuration management before. Not that I mind, but I recently created an image to visualize this for a project I'm on. I figured I'd share this for others to take advantage of. Looking at it, it's fairly easy to explain how the release cycle works and when/where branching and merging comes into play.
Note that this isn't specific to any type of repository, so whether you use VSS, TFS, Svn, or any other version control solution, it should apply to you just fine. The dark blue line represents the main branch (or trunk). At some point, a code freeze is identified, which is when the codebase is branched for the release. Testing is performed and bug fixes are applied to the release branch while, at the same time, changes are also made to the main branch for the follow-on release. Once the release branch is considered stable, a tag/label is applied (identified by the red star-burst), the release is deployed, and the changes applied to the branch are merged (identified by the orange line) back to the main branch (or trunk). Over time, while development on the main branch is moving along, there will inevitably be bugs in the production system. Let's just say your next major/minor release isn't for another 6 months. In that case, you'll probably want to do a point release to push out a bug fix or two (ok, 10 or 20 ). In this case, developers will pull the latest (aka head) from the specific release branch and apply necessary fixes. This is again tested, tagged/labeled, and re-deployed. To get these changes back into the main branch, the release branch is again merged to the main branch. This process will continue for the life of the project.
Honestly, it's all pretty simple; but as they say, "a picture is worth a thousand words."
Processes exist for a reason. I think we all know that. Nobody can acurately say that processes are bad. They can be taken too far, tho, which is why agile processes have grown so rapidly in the software development arena. Personally, I think a lot of that has to do with trying to get away without documentation, but that's a different issue. Honestly, agile processes don't have anything to do with the level of effort put into documentation. Anyway, all of that's besides the point. I read a post, If Not Agile, Then What , by Rockford Lhotka a while back and I've been meaning to remark on it. Over the years, I've put a lot into defining and working to better development processes. This came from being in a process-heavy organization. At the same time, I've always appreciated the fact that the processes in place were more than I thought necessary. There are certain architecturally significant steps I believe are important for any development project, but the level at which they should be achieved can vary a great deal.
Rockford talks about how nobody follows any process 100% and no process was built to be 100% followed. Well, those aren't his words, but it's the basic jist of it. One thing I've always wanted to do was create something like a step-by-step process for defining your own development process. Basically, you'd input your criteria and out would pop a suggested process, documented from front to back. You could, of course, pick and choose what you actually used; but the core concept is that the practices -- along with their pros and cons -- would be given to you so you can make an informed decision. That's one thing you have to be able to do as a consultant: allow your customers to make thier own decisions. If you want to bury yourself, I'll hand you the shovel; but not before telling you what I believe could happen, what to look out for, and what your options are going to be if my foresights have come to pass. Defining and following a development process is a weak point in most organizations. Sure, people might deliver, but is there enough documentation? Beyond that, how much is enough? There's no single answer for these questions and the thousand others that would typically follow. This, of course, is why I've always wanted to formulate the process generator I mentioned. I don't know if I ever will, but it will always be in the back of my mind.
If you're interested in software engineering processes, I suggest you give Rockford's post a read. I'm always interested in people's opinions regarding engineering processes because it helps me take in different viewpoints and better understand the necessary flexibility for any process to survive across multiple projects, which is almost a must-have for a development organization. The more processes in one organization, the more wasted time and money that goes into managing these processes. I don't think most developers realize the importance of a well-defined process because they haven't been exposed to larger system development teams and organizations where project scheduling and documentation isn't something that can be debated without risking project success.
I read an article, Extreme ASP.NET , in the October edition of MSDN magazine that talked about control adapters, a new feature in .NET 2.0. I've heard of control adapters and I knew about the browser capabilities, but I never put the two together like this. Actually, I have to admit that I didn't know much at all about the way the stuff worked, I just knew vague tidbits about them. After reading this article, tho, I'm amped! I can't wait to dig into control adapters!
I'm a big (read: very big) fan of applying standards to your development work. Because of this, I try to use XHTML and CSS wherever possible. The problem is that most developers in the .NET world don't care. Rightfully so, developers are more interested in getting features implemented. I completely understand that and can't argue it -- heck, that's what we get paid to do. But, I can't help but get aggravated when I open a .NET project in Firefox, for instance, and it goes haywire. This is probably more common than you think, too. I admit that IE does add some great features; however, standardization shouldn't be an optional thing. If Microsoft believes so heavily in the added features, then push for them in the W3C. Actually, I can't say too many bad things about Microsoft's lack of applying standards because there has been a huge improvement over the last year or two. I am proud to say that, as a company, we are making great strides in the right direction. Believe it or not, everything's not all about the money... but it does put food on our tables. Anyway, back to control adapters...
One great control adapter implementation is the CSS Control Adapters , which was recently released. In a nutshell, control adapters allow you to give a control a completely new look and feel. This set of control adapters resolves non-standard coding practices built into the existing set of ASP.NET controls by providing a standards-based implementation. I love it! I still need to play with it, but I'm merely excited to have the capability.
Having been in a consulting role for some years, now, coding standards have become very important to me. I'm not going to weigh in on what coding standards I think are most important, but I do have plans to get a document up sometime. Beyond that, Jeremy Miller posted his thoughts on coding standards a few weeks ago. I have to say that I really like the basis of his ideas. To sum it up, creating a 100-page document covering every aspect of software development may be the best way to document all the standards that probably should be applied to any given project; however, we all know developers won't read it and/or remember the standards therein. The best you could hope for with this approach is that developers and code reviewers together cover the foundation of those standards. Even this is a long-shot, in my opinion. Jeremy likes the "by the team, for the team" approach, where coding standards grow over time and are truly (or, at least closer to) a shared vision of what standards are appropriate. I like the comradery and team buy-in this method would generate, but I don't think it really gets to the heart of the problem. For instance, what happens when, after a year, a project now has a 15-page coding standards doc and a new developer joins the team? Well, this would be almost the same as handing an existing doc to a team and telling them to work with them -- that new developer will most likely not go thru the entire document. The problem isn't really solved with this approach.
Personally, I like the idea of grabbing existing standards and changing those as you see fit. There are reasons people put these things together. Again, this doesn't resolve the problem at hand: developers don't want to read standards docs. What's the solution, then? Well, having a document might be a good idea to solidify the standards in their entirety. I don't think we can get away from that. The real problem is getting people to abide by a document that sits in an arbitrary directory and has no real effect on whether or not the software functions as needed. This is a maintainability and extensibility issue, in most cases, which is an afterthought for most projects... unfortunately. What we really need is automation. We need a tool that will tell developers when the code doesn't abide by standards.
The first tool that comes to mind is the built-in code analysis feature of Visual Studio (or the stand-alone FxCop application ). Anyone can write rules for this that will be used to analyze code and point out problems. While I like what the tool offers, this is a lot more explicit than I'd like it to be. I want something that the developer doesn't have a choice with. I want to say, "HEY! Look at this! You're not supposed to do this!" In my opinion, this is the best way we have to-date to ensure standards are abided by. Think about it. When using Word and you get a squiggly saying you spelled your last name wrong -- that happens all the time for me -- do you tell Word to ignore the error or add the word to the dictionary? Or, do you just leave the squiggly on the page? More often than not, you'll find that people don't want to see the squiggly because it's saying that they're wrong -- or, might be wrong, in this case. I admit, when it comes to my last name, I've grown to ignore the squiggly, but in code, that's a different story. No developer will want to have squigglies all over the place if someone else is going to look at it. Sure, maybe a small handful would be ok, but nothing extreme. Either way, this is better than not applying any standards between developers.
The next potential solution I found was something new (to me): Code Style Enforcer , by Joel Fjorden . Now, this is what I'm talking about! The tool does exactly what I want: it tells the developer what's wrong. The only problem I have with it is that it doesn't cover nearly enough of what would be in a typical standards document. All it covers is implicit vs. explicit implementation of interfaces and abstract classes, naming, and what visibility settings should be available. This isn't nearly enough. Also, I have a problem with the way some of the naming standards work. For instance, you typically don't want a method name with an underscore (_); however, the standard control event handler is in the form of <control>_<event>(). Obviously, this is a direct conflict. So, the only way you can avoid a warning on these event handlers is to change the rule to accept an underscore. I don't like that because I don't want underscores to be in other methods. I do have to admit that this is better than nothing, tho.
I need to do some more looking to see if there are any other VS add-ins out there. If not, I may work on 3 things, which I think would bring the best level of coverage. First, I'd create code analysis rules for all the coding standards. This way, a team could bring them into their project and select the ones they do and don't want to apply. Second, and probably more useful on a broader range, would be to create an implicit code analysis execution for the current page. The only problem with this is that code analysis typically runs on compiled code. I'll have to look into that to see if there's a way around it. Probably not. Lastly, I'd like to have something that could auto-generate a standards document based on the approved code analysis warnings. This would be helpful for new developers and process/documentation enthusiasts. I honestly think this 3-parter would be very valuable; but before I commit to anything, I'll have to do some looking to see what else is out there.
Sijin Joseph wrote about his experiences with abstraction/generalization (in the form of interfaces) a few weeks back. I have to say that this is a very common problem developers face when they hear about best practices. All too often, people will hear about how good something is and they'll almost blindly apply it everywhere. Then, when they run into problems with their overuse of the practice, the deem it as useless and go on a crusade against it. This is obviously an extreme case and I'm not saying that's what Sijin has done. I'm merely stating that this is a common problem that we must all be aware of so we don't fall victim to it.
Whenever you hear about a new best practice (or, new to you, at least), you really need to take a judiscious approach to applying it. Definitely give it a try on something small, if you have that luxury. The problem there is that we don't always have something small to try it out on; and, when we do, you may not see the full benefit of the practice in a small environment. This is why software architecture isn't for all developers. Some of the best software architects have no development background. I'm not going to get into that, tho. Knowing how and when to apply best practices, such as abstraction, is something you have to grow into. Honestly, I know I'm not completely there. I tend to over-design throw-away projects because I enjoy the art in my creation (one day, I'll post my thoughts on the art and science in software development). Before you can really determine when to and when not to apply a given practice, tho, you have to have the vision to see its benefit and the experience to know when that benefit will help.
As for my opinions on when to generalize classes into interfaces and/or abstract classes, I typically take a few approaches. First and foremost, I look at the solution and determine whether it needs to be build with extensibility in mind. If I'm creating something that needs a plugable environment, it's a given. Honestly, there are probably a handful of obvious situations like this one, so I'll skip those. Outside of those, I'd take a 1-2-3 approach. When you create the first class, take about 5 seconds to think about extensibility. Is it necessary? Think about the overhead of creating that extra layer. It's not always as simple as an interface. Ok, it's never that simple. You have to know how to deal with the interface at every point in which it will be used. This may be insignificant or a huge effort. There's no telling because it's completely contextual. The second time you create a similar object, you should take at least 30-60 seconds to think about it. How similar are the two objects and are they related? Hmm... As you can imagine, you'll need to have a lot more of an understanding at this point to know and understand the ins and outs of the application to be sure that an abstraction wouldn't break something. For larger systems, this is sometimes impossible, which is why I can't completely back the write first, design later methodology. The third time you create a similar object, you really need to look at everything and ask yourself how much repetition you're doing. Chances are, by this time, you've duplicated some logic. If you ever get to this point, it's pretty much a gimme that you need to generalize something.
Honestly, there are a bunch of factors in this discussion and there's no way for me to cover all aspects here. These are the main situations I've run into, tho, so hopefully you'll find some solice in them. I have.
Well, "fun" might be stretching it, but it's interesting, at least. As I've mentioned before
, I'm doing a lot of work with code analysis problems. Because a lot of these things are so repetitive, I've started thinking about how regular expressions might be able to help speed up my work. I've been fairly happy with the results, but the real answer is that there needs to be more refactoring support around code analysis. I'm interested in this, but doubt that I'll have enough time to dedicate to pulling a complete add-in together. If anyone else is interested in it, let me know. For the time being, I've decided to keep track of the regex for fixing code analysis warnings
I'm coming up with. In part because it might be useful if/when I decide to create an add-in, but mostly because I just want to keep track of it. As usual, I welcome any comments or suggestions for these. Anything that might make a developer's life easier.
I just started working on a project that needs a lot of clean-up work done. It's one of those systems that's grown over the years and nobody has ever really gone thru and cleaned out the closets. To give you an idea, running the latest standalone copy of FxCop on the assemblies in the web app produce 12,020 messages.
When I first loaded the project in Visual Studio 2005, I tried to run the built-in code analysis feature, but didn't know where to find it. Eventually, I found out that code analysis is only available on a project-by-project basis. This means I'd have to run it on each project independantly. There's no way I was going to do that! Eventually, I found out about a macro created by Daniel Fisher that would enable code analysis for all projects (I am hoping to release this as a VS add-in in the future). Executing this and re-running code analysis is what I needed. That gave me 9320 warning messages. Of these, I noticed 50 were not code analysis messages (i.e. updated libraries, deprecated methods, and several other typical compilation warnings). Having this list was just what I wanted... well, almost. I ultimately plan on getting these items imported into Team Foundation Server as development tasks, so I needed to save this list to a file. Of course, when you run code analysis on a project, an XML file is created. Great, right? Not quite. Each project created its own XML file, so I had to dig thru the unorganized directory structure to find all of the files (actually, I just seached for all XML files with "codeanalysis" in the name). After looking at these files, tho, I noticed that they only accounted for 6932 messages -- assuming I was reading them correctly -- which, as far as I'm concerned, is a far cry from the original list.
I dug around trying to find a way to save the error list to a file to no avail. The best I could find was to simply select all of the items, copy them, and paste them in some editor to manipulate. If I have time, I will see about creating the ability to export this list to XML in that VS add-in I mentioned. For the meantime, tho, I needed another way to get the list.
I ultimately resigned myself to the standalone version of FxCop, Visual Studio's code analysis predecessor. The latest version , 1.35, was released in June 2006, 8 months after Visual Studio. This, of course, led me to see if there was a way to update Visual Studio's built-in code analysis capabilities. Unfortunately, there isn't . So, I decided to just keep it simple and stick with FxCop 1.35.
I plan on keeping my eyes open for a resolution to this issue. The best I can see for now, tho, is that we'll have to wait for the next release of Visual Studio, which I'm hoping will be available in very early 2007.