I have read many books on successful projects, project management, development life cycles, quality code, etc. One of the pit falls I have discovered with many (if not all) of these books is that they mostly focus on team development. Most stress the need for quality assurance people, at least 2 developers, project leads, etc. Unfortunately, this is not always realistic and can seem overwhelming when a single developer is faced with large projects.
I have been the only programmer at my employer for about 3 years now. I am fortunate that my boss is an ex-programmer and has a good eye for architectural details and big pictures. However, all of the architecture, design, development, debugging, testing and refining work falls to me. I do not have a staff to assist with the development, QA or testing so for just about every aspect of development my company needs, I'm on my own. Many of the projects I have worked on have been very small and accomplished in just a couple of weeks, but others have spanned 3 years and are continuing.
To combat this problem I have been endeavoring to train myself on the best practices and solutions to my problem. Many of the concepts outlined in the various books can be easily applied to one-man-shows(embeddesoft:独脚戏), but others cannot. As a result I have searched for alternate solutions to the various problems I have encountered. Most if not all of the solutions I have come up with are not original and many of you will already know what I know and much more. I decided to write this article in the hopes that it would help some other developers AND that I could obtain feedback from the CP audience on best practices and techniques for success.
I have broken this article into 2 primary sections. The first deals with my observations and techniques regarding the non-technical aspects of my job. The second deals with the technical aspects.
Before I begin I just want to say that I am no expert and the contents of this article are my observations and techniques. You may have better techniques or think that mine are terrible. I would love to hear from you. I am interested in improving my abilities and skills and I am not egotistical about my views in this regard. So, if you have a comment, positive or negative, please leave me feedback and explain what you think. In fact, if there seems to be consensus on better ways of doing things then I will probably update this article to include those better techniques.
As stated before, I have divided this article into two sections. Before I get into the details I am going to list the various bullet points here.
NON TECHNICAL | |||
1 | Set personal goals | ||
2 | Read, Read, Read | ||
3 | Come out of the closet | ||
4 | Meetings are not all bad, just mostly bad | ||
5 | After hours is off limits | ||
6 | Set reasonable expectations | ||
7 | I'm not a programmer, I'm an architect | ||
TECHNICAL | |||
1 | Plan, then code | ||
2 | The right tool for the right job | ||
3 | Fix bugs early | ||
4 | Develop good coding habits | ||
5 | Know thy enemy | ||
6 | Documentation is your friend | ||
7 | Form over function | ||
This has been the single most important activity I have undertaken. Setting and then working towards my goals has helped me to find direction in my career as well as keeping me focused on the job. Some of my goals are short term and can be achieved in under a month. Others are more long term and may require more than a year to achieve. I write these goals in a word document and review them often. Some of the goals I have set for myself are listed below.
Read at least 1 programming book each month.
Read at least 1 non programming books each month.
Learn at least 1 new language this year.
Take the final test for my MCSD this year.
Develop and release at least one shareware application this year.
Write at least 1 article for CP every 3 months.
Write up the documentation framework for the XXX framework this month.
Increase my salary 25% within 2 years.
etc.
My goals are intended to improve my skills as a programmer and developer, but also to improve my viability when seeking a new job. One of the things I have learned about goals is that any real goal must have a deadline attached to it. You will notice that each of the goals I listed is singular in nature and has a set deadline. The deadline is very important because it guides me and helps me manage my time better. By knowing what I want to achieve and having a deadline for that achievement I am not setting myself up for failure, I am creating a healthy environment in which to build my career.
I don't always meet my goals but when I don't I review them to understand why I did not meet them. Sometimes the reasons are beyond my control and I simply readjust the goal to a more reasonable one. Sometimes, however, the reason I did not meet my goal is because it was too ambitious to be met. If this is the case I want to fully understand what part of the goal is too ambitious. If the deadline is the problem, then I simply adjust the deadline. If the problem is that the goal itself was over-my-head then I create new goals which are the steps I need to take to achieve the original goal.
Setting goals for myself has not been easy. I have had to force myself to follow my own goals and I often find that I drift from the goals for all kinds of reasons. The most important aspect of goals is not to set myself up for failure. My goals are often challenging to achieve and require that I sacrifice some other aspect of my life. Limiting my other sacrifices to things I can live without is the key to success.
Most successful software developers I have spoken with here on CP and elsewhere would agree with this statement I think. Keeping up-to-date and learning new languages, etc is extremely important to long term success. No matter how good I am there is always someone better. This is OK, especially when those who are better than me write books or articles and I can learn from them.
In my early years of programming I did not read many books at all. I tried to spend all of my time writing code and learning by reading other peoples code. This worked up to a point, but failed miserably as soon as I was faced with a problem that was beyond anything I had already written or seen written. It took me a while to learn that reading was just as important as the coding itself.
My next mistake was to focus only on reading programming/coding books. This was better than not reading at all but still didn't help me solve some of the more complicated problems. What was needed was for me to begin reading more general technical books. Books on design patterns, fuzzy logic, AI, etc. Most of these books don't contain much (if any) source code at all. What these books did was to broaden my exposure and help me to find better solutions to problems.
Reading coding as well as more broad technical books has made quite a difference in my abilities. However, even this broader scope still leaves some gaps in my abilities. I have learned that even more mundane topics such as User interface design, usability, databases, etc are necessary as well. With a complete range of technical books and articles I have been able to broaden my horizons and greatly increase my ability as well as my ability to get a job. Currently I read books on project management, team growing, design patterns, C++, AI, UI design, usability, writing solid code, and the list goes on.
One other area of reading that I have not begun to dive into yet is non-technical, non-programming books. Books on sales and marketing, branding, etc. I see the potential for these books to help me in marketing and selling my shareware products as well as helping me to understand the needs and requirements of the sales and marketing people I must work with.
Reading does not have to be books. It can be magazine articles, MSDN, CP or any other source of knowledge you can find. At my previous employer I had a budget for books and freely purchased books as often as I liked. My current employer does not have such a budget so my book buying has been greatly limited. I have been learning to leverage the free and less expensive resources available from the internet and magazines.
When I first began my career as a programmer I enjoyed the endless hours of coding and would often not come out of my office except for lunch and bathroom breaks. (embeddesoft::这就是为什么我说自由程序员往往会成为技术牛人) For me, this was a bad habit. It lead to various problems, not the least of which was a disconnect with the rest of the office. Now you may be thinking "what does this have to do with programming?". Well, for me it had a lot to do with programming. First, it made me appear reclusive and stand-offish (which was basically true.) Second, it prevented me from stepping back from the computer and trying to grasp the problem out of the context of code. The first issue made it more difficult for end-users and my peers to discuss issues with me. Also, it gave the impression to my peers and end-users that I though of myself as an "elite". (embeddesoft::不易于和人沟通和相处,也是阻碍他成为软件管理人员的原因之一。虽然美其名为“精英”,却一辈子在做软件“苦力”)This was not true, but lead to many interpersonal problems which had a direct impact on the quality of the applications and modules I delivered. The second issue related to this was just as severe. Failing to step away from the computer and think of the problem instead of the solution is dangerous. Often by stepping away from the computer and working on the problem a better solution can be achieved.
The typical business office is filled with people of various skills and with various job descriptions. Even if the programs you are developing are not targeting the type of people in your office, a lot can be learned by observing how other people interact with their computers, and if you are targeting your office staff this issue is even more important. Ultimately, most software developed is not targeted at just the one who wrote it. By staying alert and interacting with end-users you can gain valuable insight into how software is used by the "Rest of the world".
If you work out of your house or in an office by yourself, this still applies. It just requires a little more travel on your part.
I dread meetings. I don't like attending them and I don't like having to be involved when I have to attend. However, my approach to meetings has changed quite a bit in the past few years. I used to attend them with the intention of not saying a word and slipping out of them at the earliest possible moment. I have learned that not all meetings are bad. Some are even useful. The key question that I ask myself when attending a meeting is "What can I gain from this meeting to improve my skills?". That is the only question I need to ask because if I improve my skills it will have a positive impact on the project I am working on as well. Now you may be wondering what kind of skills you can improve from a meeting. The skills I have identified that meetings can hone are 1) my ability to quickly disseminate technical information to non-technical people, 2) better understand how other people think and 3) better organize the information I receive at meetings.
Meetings that have no direction and seem to just "blow in the wind" are the worst of all. I hate them. As far as I can tell there is no benefit whatsoever to my presence and it just annoys me to no end. The meetings that I can tolerate have a defined agenda and a set time limit (one hour is still too much for most, though.) If a meeting does not have a defined agenda I will usually back out of it with whatever excuse I can come up with. If it is set for a long period of time I want to know that that time is well spent and is not going to cover too much ground.
Some of the warning signs that a meeting is useless are:
No agenda. This is a dead giveaway. If the person calling the meeting can't tell you exactly what its about, take a pillow.
Too long. Either this meeting is covering way to many topics or there are going to be some long-winded people there.
Too many people.
The wrong people.
Not all meetings can be avoided, unfortunately. Even some useless ones must be attended to keep a job, keep the boss happy or keep a client happy.
On the few occasions where I have had to be the presenter for a meeting I have tried to follow some simple guidelines based on the negative issues I listed above.
Create an outline for whatever it is I am going to be discussing.
If my audience is non-technical, run though the outline with my wife (she is non technical).
Set a time limit.
Only invite the people that I really need to be there.
I have worked quite a few late nights and many times have worked though one day and into the next. However when I look back at those occasions and try to understand why I did it I usually come to the conclusion that it was unnecessary. Had I done a better job of planning or taken a more pragmatic approach to a problem the extra time could have been avoided. This problem is especially thorny if you are not being paid by the hour. There have been a few occasions where I can't see any other way around it, but an honest inspection of the details has shown me that the truth in most situations is that the late night was my fault. The three most common reasons for this have been 1) failing to set reasonable expectations, 2) gold-plating and 3) failing to adequately test.
Part of the problem with after hours work is that it cuts into my family time. Another aspect, however, is that it leads to bad habits. At one point, I found myself saying to myself (and others) that I would have a particular feature/component/whatever finished by Monday morning. This is a dead giveaway for a problem. How can anything be ready in the morning unless you plan to work on it at night?
Another problem I have discovered with after hours work is that I tend to produce poorer quality code after hours. This is probably because I don't like having to do it and partially because I am rushed to complete something.
This insight leads to several practical changes in the way I work.
When I tell people when something will be available it is never in the morning and rarely Monday.
When I make schedules and plans I base those plans on the work day and do not consider weekends and after hours.
I force myself to manage my time better. I watch how long my lunches are and how long I spend checking email and surfing the web.
I develop in the morning and test in the afternoon. Knowing this I do not plan to accomplish 8 hours of coding. Instead I get 4-5 hours of coding and 3-4 hours of testing and debugging.
I value my personal time and although I don't mind working hard and (when necessary) long hours, I try to stay within a reasonable limit regarding time at work.
Most people I have worked with have been fairly reasonable. Most of the major problems I have encountered with people not being pleased with my work have revolved around me not setting their expectations correctly. This can be as simple as setting a deadline too early or as involved as showing a beta version of a product without explaining what it is first.
In one situation I ran into, I needed to show a beta version of a product I was working on to the client. I proceeded to sit down at a computer and show off the applications features and what it could do. I was confident that the program wouldn't blow up, and it didn't. Once I had finished the presentation I realized that the client was not pleased at all even though I felt that the demo had went well. The client was upset because I did not show them the features they cared about. Not only that, but they felt that the time that had been spent so far was wasted because the features they wanted to see weren't implemented. This lead to a great deal of confusion and problems. In all reality, the client did not need to see the software at all. What the client wanted to know was that I understood their problem well and could solve it for them. Showing the software to them at the early stage was a mistake because it shattered their expectations and reset their future expectations much lower than they should have been.
In another situation my boss needed to know when I could have something working. I told him that it would take me a couple of weeks to set it up and get it running. My understanding was that he just needed a working model, not a finished product. 2 weeks passed by and I delivered the whatever it was and to my dismay he was not pleased because it was incomplete. The error handling had not been fully coded, the UI needed some tweaking and it was somewhat slow. Now he was stuck because he needed to make a presentation to a client and the product wasn't where he wanted it to be. The problem here wasn't that he gave me insufficient directions, the problem was that I gave him unreasonable expectations. First, I should have been specific about what I could get done in 2 weeks. Second, I should have asked questions as to what he needed it for, etc. If I had said 3 weeks, he would simply have set the appointment with the client for 3 weeks out instead of 2 and there wouldn't had been a problem. Even if 2 weeks had been a firm timeframe, I would have been able to tell him what was going to be lacking in the 2 week version. Instead I ended up working a couple of late nights to sharpen it up.
The moral of this story is that people want to be told reality as they see it, not as I see it. The reality was that in both situations I failed to set the expectations of my user (client/boss) and as a result paid a price in respect and time. I had the power and opportunity to set proper expectations and instead ran headlong into a bad situation unnecessarily.
Nowadays, anyone can pickup HTML, VBScript, etc without too much technical skills. The title "programmer" does not have the respect that it merits. As a result I have tried to acquire a name for myself as an engineer or architect. I want the people I work with to think of me as more than a coder. In addition, I would rather put "Senior Software Architect" on my resume instead of "Programmer". By establishing this title with the people I work with now I will have no problem telling my future employers what my title was.
Another aspect of this is that I am not technical support. I don't want to be known as the "computer guy" who everyone comes to when their computers won't boot. It distracts me from my job and detours me from my goals. By establishing an expectation among the people I work with I have managed to avoid this issue almost entirely.
Many of the projects I work on are short term projects which must be completed in under a month. In my early years this would have lead to an instant desire to jump in and start coding the solution. This type of effort has frequently back-fired on me. Either the resulting solution is not right or the code is littered with bugs. Either way a serious problem in the end.
Most books preach the need for phased development involving requirements analysis, architectural design and detailed design prior to any real code being done. This is fine and good when you have a team of developers working on a long project, but for short term projects especially when I'm by myself, this can seem like a lot of unnecessary labor. The reality is that this phased development still applies and is even more important when I'm working alone. One part of the early design that I feel is omitted from many of the books is vision.
Vision
For some reason most books do not cover this, but I feel it is at least as important as any other aspect of the design. When I say vision, I am talking about what does the person/people asking for the product intend to do with it and how do they envision it working. Do they plan to send it out to customers as a shrink-wrapped program? Is it going to be shown to clients/customers? Do they see it as an excel spreadsheet, access database or something entirely custom? A task bar item? A plug in for some other product?
Knowing what the vision for a product is greatly simplifies the requirements analysis and later phases of development. Having a complete understanding of the vision empowers me to talk with the people involved at a higher level and with more confidence. It also empowers me to do a better job of making decisions on my own in regards to the project.
Requirements Analysis
Often the project seems so simple that there is no need for this phase. The reality in these situations is this is where a requirements analysis can make the biggest (percentage-wise) difference in the time it takes to complete the project. Often the project specification is done by a non-technical person (sales or marketing, etc). They typically omit important details which without asking I would never know about. Simply writing up the requirements in an HTML document and reviewing it with the appropriate people will usually flush out the missing details.
Having a good working relationship with the important people is extremely important at this point. The ability to communicate in non-technical terms pays off every time. Sometimes the missing details can be as simple as "I want it to print landscape by default". These kinds of things are easy to deal with and would probably not impact the overall design or implementation at all. Other times, it can be "I want all edit boxes to be spell checked automatically like the other apps." This may not be an issue either, but is usually a bigger issue and needs to be understood early.
This exact situation has happened to me. I have an application which took several months to develop and has rich-edit style edit controls throughout the application to allow for text formatting. Another project came up which was just a 1-3 week type project and the users were expecting it to work the same way. The requirements provided to me did not detail this and at first it did not cross my mind since the type of application was simple. Had I not stopped and asked for more details this would have been a big problem.
Architectural Design
On small projects this phase usually takes less than 1 day but is also very important. Building on a proper architecture makes actual implementation much easier and usually results in a more flexible product in the end. Typically I use a white board in my office to lay out the architecture and work out any problems. My boss is very good at this and usually helps me quite a bit, fortunately.
Typically I don't document the architectural design that I end up with. This has proven to be a mistake for me. Many times I have had to explain various aspects of projects I developed some time ago. Usually I don't need to know the details of how the code is written, the architecture is all I need to know to answer most questions. This is definitely an area I need to work on in the future.
I could write page after page on how to do this phase, but there are many books out there that provide excellent detail on this phase of development.
Detailed Design
OK. OK. I admit I have never done a detailed design of anything. Even for the multi-year projects I have worked on I have not done this. Would it have helped? I doubt it.
I consider myself a C++ programmer. However, C++ is not always the right tool for every job. I firmly believe that as a developer part of my responsibility is to decide what tool to use to solve each problem. C++ is not always a good solution for a web application. Nor is it wise to use it when a simple excel spreadsheet would suffice. Choosing an appropriate tool to finish a project and maintain it is an important decision. As an example, a couple of years ago I needed a tool to update some tables in a database that gets used quite often. I could have written a C++ app to do this, but I chose to create a simple MS Access database with some link tables, a coupe queries and 3-4 forms. This solution has served me well up until this time.
Sometimes languages are like religions. Some C++ developers are so zealous about it that they will use C++ to solve every problem they come to. Granted, C++ is extremely flexible and powerful and in the right hands can do just about anything. However, sometimes it just isn't the best too. ASP and VBScript is often a better solution for a simple web app than writing a complete ISAPI extension. It just depends on the needs of the given application.
Another aspect of this is 3rd party libraries and open-source code. At one time I wanted to implement everything myself. This has come back to bite me more times than I care to remember. I have learned to scour the web for open-source solutions to many of my problems. Also, I try and stray abreast of the available libraries and toolkits that exist so that I can (when needed) ask for the money to buy them. Using other people's code is a great thing. It can greatly reduce total development time AND many times someone else has done a much better job that I could do myself. The moral of this is not to get caught up in the "all-mine" approach. Leverage other people's work and libraries as much as possible.
Yet another aspect of this is the development environment itself. I use a pretty plane-jane version of MS Visual C++. I have tried Visual Assist and WndTabs and although I liked both of them I found that their overall impact on my productivity was not very much. This is not to say that your work habits won't benefit more from these than I did (BTW They are both great products.). My point is that you should try various configurations and available tools to improve your environment for your needs. If Visual Assist helps you, use it.
I can't stress this enough. From my own experience I can state unequivocally that leaving bugs in code thinking I will fix them later is the worst habit I have ever had. I have had to force myself to rethink how I work to avoid this. This habit creates bad problems later in the project. Either they never get fixed, they get forgotten and customers find them, they screw up the schedule or they introduce problems into the architecture which result in me pigeon-holing a solution instead of fixing them correctly.
This has been a difficult habit for me to break. Sometimes I think that a bug can wait because the next feature on my list is more important than the one where the bug exists. This may be true, but is not an excuse. Failing to fix the bug will only result in a cascading list of bugs which will just cause more and more problems.
A corollary to this is that testing is very important at every stage of development. In the early stages of development I typically spend 3-5 hours of pure coding with no compiles or debugging in-between. Then I spend the rest of the day testing the code I have implemented. (This may not be a text-book method, but it works for me.) Sometimes I must spend an hour or so developing a test-bed in which to test the component I have worked on, but this has been well worth the effort.
One habit I have discovered that helps to limit the number of bugs I create is to comment the code where a bug has been found and fixed even if it is found on the first day of development. This helps me to remember what I did and what to avoid the next time I have to modify a section of code. Another habit which has helped to reduce the number of bugs is not to rely on the compiler to identify problems for me. Just because code compiles does not mean it works. I try and avoid compiling my code every 5 minutes and instead do a compile only a few times a day. Instead I use the compiler as a window into my code. I use level 4 warnings which can identify certain problems very early in the process.
Good coding habits are very important to the quality of the code produced as well as to the quality of the final product which uses the code. Nothing earth shattering here, just learned behavior. Some of the most important habits I have learned are:
I'm sure there are hundreds of other rules I could write up but that could take whole books. The bottom line for me is that there is no one to review my code or help me when problems arise. If I can eliminate the most common problems I can spend more of my time working on the more serious problems.
We are all familiar with the phrase "keep your friends close, any your enemies closer". I have learned that this applies to software development as well. For me I have two enemies in regards to my work. The first is procrastination and the second is gold plating.
In my earlier career I procrastinated on pieces of my code which were new territory for me because I was afraid of failure. Now I procrastinate on the pieces of my code which are mundane and boring. The results are the same, unfortunately. I end up working longer hours than I should because of my own failures. I continue to struggle with this enemy but knowing that it is a problem is at least a start.
The other enemy to my work has been gold plating. I know. I know. We all want to work with the latest technology, explore some new technique, use some whatever we found in a CUJ article last week. Sometimes this is a good thing and can result in better code or a better end product. Often, however, the gold plating has no positive impact on the end product as far as the user is concerned. I have learned to limit the gold plating that I undertake to the very end of projects and to my side projects. This has paid off immensely in my opinion. By limiting the gold plating until the end of a project I limit the chance that I will go over the schedule or be forced to leave a bad implementation intact.
Whatever your enemies are, you should be aware of them and combat them at every turn.
I can't tell you how many times I have been asked the same question by 2 or 3 different people. I hate it. One of the areas I am currently working on is learning to document not just my code but the user interface and the questions/answer sessions I have with users. I firmly believe that this documentation will reduce my workload by limiting the number of Q+A sessions I have with users on the same repeating questions.
At this point I am not concerned with finding the best documentation product or tools. I am mainly interested in getting the documentation started and developing the habit of maintaining it. I have chosen to use a simple HTML based documentation library (no special tools) and setup a simple web site organized by project and use MS Index server to allow simple searches. I feel that this will allow me to easily move to a more sophisticated solution later.
I don't have a budget for this so it's one of those personal projects that I take on. In the future I am going to be adding documentation time to my time/schedule estimates and making it clear that this is part of my process.
I am not advocating pretty UI's with lousy functionality here. What I am advocating is that the UI is important to the overall projects success and is an important aspect of where I want my career to go. The UI is the part of the product that a customer/user sees. They typically don't care about whether I used a quick sort or a bubble sort for a particular feature. Again, I am not advocating using poor techniques to solve problems. There are many simple steps that you can take to improve the user experience and prevent problems later.
Some simple things I have observed:
Some other suggestions I would make to the stand alone programmers are
Find and use a source control product. Use it consistently. (MS SourceSafe is better than nothing.)
Leverage CodeProject for all its worth. There are literally thousands of wonderful articles and code snippets here.
Stay focused on your personal goals.
Get in the habit of documenting your thoughts and ideas. You never know when one of them will pay off.
Subscribe to as many magazines and journals as you can (not just technical ones). Many tech journals have free subscriptions available.
Keep up-to-date on the progress technologies are making even if you don't like them. (Ie. Java, MS, whatever.)
Being a stand-along programmer can be a daunting task and sometimes be overwhelming. Learning to leverage the experience for your personal goals will make it much much easier. Lack of code reviews and technical help can lead in two directions. Either you will get lazy and allow you skills to lapse or you will become more serious about improving your skills and ultimately making yourself more sellable if/when you search for another job or seek a raise.