Refuctoring: Winning the Respect of Your Peers

In "No, Be a Jerk", Justin talks about the importance of giving honest criticism of other developer's code. I agree that providing constructive feedback is important. My designs and code improves when there is discussion about how and why a component was written in a particular way. Talking about a problem and giving feedback is a great way to create innovative and elegant methods for solving problems through code. Uninvited refactoring is far more risky.
Just because you are working in someone's code does not mean that you have the right, the wisdom nor the back-story to make sweeping changes that may come with refactoring. A wise way to refactor is to talk to the responsible developer first and verify that your changes will improve the code base, meet schedule requirements and be an appropriate use of your time.
Let's say your have to make a bug fix for a NullPointerException in another developer's code and you see an inefficient sorting algorithm outside of the code affected by your bug fix. You could make the bug fix and refactor the code all in one commit. It seems like a good idea.
There are plenty of reasons not to make any changes beyond your bug fix. First, the code you want to refactor probably works and introducing changes takes that proven code and throws it back into doubt. Just because the refactored code works from JUnit does not mean that it will work from the UI or any other client. Refactoring can add new bugs to previously working code and lengthen the development schedule.
Second, the original code may not be as efficient as it could be, but then again it may not matter. There is a code that marginal or even major performance improvements are irrelevant. A common example is a sorting routine that gets called once in awhile and runs for only a couple of seconds. Shaving even 50% off that time may be interesting but not important since the routine doesn't get called often enough to make a big difference.
Third, the code may have been written that way to solve another specific problem. There are times when a somewhat slow algorithm is necessary because you don't have enough other resources to make it perform better. For example, you may have a memory constraint that doesn't allow you to use a higher performance algorithm. Refactoring this code without the constraint may cause a regression.
Finally, changing code out from under the owning developer may make him pretty annoyed. Small changes may be fine, however sweeping changes without consultation sends a deeply disrespectful message. You still have to work with the developer and maybe face him everyday.
Many of these beliefs come from previous jobs where people went in to working code and refactored. The best case was that the developer didn’t care that his work was redone. The typical case was that the owning developer was pretty ticked off and went to his friends and complained about the situation. The worst case, and one that happens a lot, is that working code gets refuctored with new hidden bugs and delays the delivery date.
I’ve been involved in a fair amount of team scheduling and oversight of late. The simple fact is that there are features to deliver and milestones to hit. Working code is generally considered to be good enough until a real problem comes along. This sounds like a cop-out, but the reality is that suboptimal code does not become a problem until the application is no longer within the constraints in the requirements specification or a customer complains. At that point it gets on the schedule and then it can be fixed in a thorough and thoughtful way.
Don’t get me wrong, I agree that most projects have some amount of bad code and there has to be a way to communicate that fact and fix it. Bad code is not restricted to poorly performing code either. I’ve seen plenty of functions that were pages long that needed to be broken up. Code with cut-and-pasted functions being repeated across classes with a common derivation are incredible candidates for refactoring. The issue is making sure that you are able to communicate a set of changes to the responsible developer and give him the opportunity to defend his choices.
It's great to suggest changes and to volunteer to do them yourself. It's good to be honest and to try to improve other developer's code in a constructive way. The important part is to talk to that developer before making major changes in order to understand why code was written in a particular way. It saves time, teaches and shows respect for your colleague's efforts.

Features and the Wolf

“The Boy Who Cried Wolf” is a classic tale of what happens when a person lies too much. Another classic tale in the technology space is “We have a big demo next week and we need to demo this new feature.” The new feature is always the thing that will clinch the deal and so development works late nights and weekends to churn out something that can be shown. How many times can it be said that a new feature will clinch a sale before people ask the question about the validity of the old features. If the old features were so critical too then why is it that customers don’t see them as compelling enough? How long before engineers and managers simply groan at the cry of wolf?
The notion that one feature can close a sale alone appears silly at first blush. How can a single feature be so critical to closing a sale? Small software companies can sometimes have as little as five or six customers, each worth several hundred thousand over a million dollars in annual revenue. These kinds of software companies often have a hybrid product and services business model where there is a core product and customization or consulting being added to the offering. This model is not very unusual and you’ll find them everywhere. Some of them work on outsourcing product development for companies that need software to supplement existing products, like text book publishers.
The small number of customers and the need for consulting or customization services requires that you are more attentive to the way the customer works from day to day. First, you have a small number of customers that are each worth a lot of money. Losing one means losing a lot of revenue. Lost revenue sometimes means little more than a leaner year or losing a couple employees. Clearly, its better to have a happy customer.
Second, keeping focused on the day to day work of a customer means that you have to keep the product focused on the customer and less on what you want. Every shop has a few pet features that seem like they will expand the customer base. These pet features are important. It’s also important to keep the customer happy and build the features they are looking for. The balancing act is to keep the product moving forward while satisfying the needs of the current customer base. That’s not as easy as it sounds if the customer is worth a lot of money, they can bully you around, especially if there are competitors.
This is where the sometimes frantic meetings of “we need this feature for a demo next week” come into play. You may be trying to expand your existing business with a customer or just solidify your position in a space that has competitors. The need for getting a feature into the product that really improves the relationship with the customer can be terribly valuable and is something to always explore.
Developers don’t always like these features and there is plenty of reason not to. Ad hoc features almost always sound easy to implement, it could seem like you just need to add a button here and a tree control there and suddenly you have a new way of organizing content in your CMS. The developer sits there and promptly reminds you that you have to build the back-end to support the new structure, tie it into security, test it across three browsers, make bug fixes and test other components to be sure there are no side effects. Once the education of what is involved sinks in you find yourself with the too common problem that the demo is a week away and the feature solves a huge problem for the customer but it’ll take two or three weeks to implement. Clearly, you are going to rally the engineers together and get it done by working nights and weekends.
This wolf cry is pretty common and people groan into action. They dutifully work until the feature is implemented, tested and done. The problem is that some companies have a steady flow of ad hoc features and meet heavy competition. They cry wolf every month and it takes a toll on engineering. So what is a developer or a manager to do?
Let’s start with the manager. The goal is to complete the feature on-time and meet quality expectations. You can cancel a weekend and vacations and deal with upset developers. There is a risk though in wolf-crying companies and that’s if the cry is made every couple of weeks. Canceling a weekend or a vacation on a team of singles may be tolerated with only mild grumbling.
People with families don’t always have the luxury of being able to cancel weekend activities or vacations. They may not even be able to work very late on a regular basis. They are also usually the most experienced developers on the team as they are often a bit older and in the industry longer. Keeping these people away from their families too long usually results in their families wanting the developer to find a new job somewhere more family friendly.
Some managers may argue that this is the life that developers signed-up for. That these developers are just being wimps and their families should know better. Family support is widely believed to be a critical factor in entrepreneurial activities. You can start a successful business alone too, but if you are married and your spouse is mad that you are always gone then you are pretty much doomed to divorce, quitting or going through some very troubling years. Developers solve problems and so pressure from work and at home will lead the developer to resolve the issue by finding a new job which eliminates the pressure at home and at work, and maybe gets a raise too. Sure, a manager can say the developer was just not cut out for the field, but then again, the developer is happy and the manager has to hire someone and is upset that the developer left. Who got the better deal in that scenario?
Other managers understand that software development is a marathon with sprints. The on-going features have to be developed and released while the ad hoc features have to be slipped in and released faster. Ways of accomplishing this are varied. One way is to divide development into two teams where the first team acts as customization services while a core team pushes the product forward. Larger companies with bigger development teams can do this as they have the staff and money. There may be very little weekend work because the staffing level is correct for the amount of customization.
A second method that works for smaller companies is to rotate developers into the ad hoc features. The goal being that a developer should not have to be actively implementing consecutive ad hoc feature cycles. This is not to preclude designs and reviews, just the hands-on work of implementation and debugging. The idea is to keep developers feeling important, which they are, and to alleviate the constant pressure of having to perform at peak levels for months on end.
Some managers also believe that the entire team should be present during crunches. The idea is that if two or more people have to work the weekend then everyone should be in the office too. This is usually an unwise idea as it can quickly breed animosity toward managers and the teammates that actually need to work the weekend. There is a belief that developers and engineers crave justice a little more than other occupations. It may be viewed as fair to have people behind on their tasks come into work on a weekend, provided that the schedule is actually reasonable. However, bringing in everyone is immediately unfair to the people that are hitting their milestones. Better to bring in the people that need to be there and no one else.
Developers, on the other hand, handle these sprints in a number of different ways. Some come in at the crack of dawn and others work into the late night to avoid the loss of a weekend or a vacation. Some login from home after having dinner with the family. Others show up on the weekend dutifully because they need to. How many days, nights and weekends they do this is a function of family and benefits.
There is cost for everything. You could put a dollar amount on every hour of the day and use that as a reference for the value of that hour and compare that to what you earn. Money lets you “buy back” time by getting laundry, cleaning and lawn services to free up more of weekend time. Of course, not everyone can afford to buy services, they are stuck with work gobbling up personal time and no way to adjust the way their limited free time is used. It can quickly become the case that the free time is more valuable than the work time. That the money brought in by working becomes so offset by the lack of free time that the developer leaves. Constant sprinting, or constant development crunches, almost push developers out the door.
Some developers stick with it though. They have hope that things will get better. They also may like the team a lot and want to see their friends. Some have also come to realize that certain kinds of companies are sprinting all the time and the developer enjoys it. A similar group of developers that believe that their stock options will make it all worth while too.
Yet another group of “stick with it” developers are more fatalistic. They believe that all companies are miserable and they work there because no place is any better. They will not move on even if the company mandates them to work 12 hours a day seven days a week. They are the same guys that say a sunny day is too bright, that a great meal wasn’t worth the money, that a ten minute drive from home to work is a “commute”, that puppies are born to die, etc.
There is a very self-destructive kind of developer that may choose to try to get back at the company by promising to work the weekend but then chooses not to do it. You’ve probably worked with one of these developers. They have the attitude of “screw the company, I’m not paid for this.” They may have this attitude about working late, doing testing or doing anything that is marginally outside of their job. They feel like the company is sticking it to them every day of the week.
They may say that they are going to work on the weekend but they don’t do anything and then brag to their friends about it. The problem is that people are waiting on the developer’s work and his catchup time may lead to having to work the following weekend. Their attitude puts development at risk as well as risking valuable customers. This can create a great deal of tension.
The “screw’em” attitude is a very odd one too. If the company is so bad then these people should be the first to move on. However, you’ve probably worked with a few that have been there for years on end. They say they hate the job but they actually need someone else to leave before they have the courage to do it themselves.
Finally, there is you. You have the common sense to try to balance work and personal life and to find solutions when they are in conflict. Most managers are good people and will work with you to figure out a schedule that works. That is where the small company shines: they are often more flexible with how people schedule their days.
I was talking to a VP of Engineering one day about balancing personal and work life. He had some interesting comments about how one’s salary eventually grows to a point where the company is really buying more personal time. That once you hit the top 1% for your area’s salary that you are now being paid beyond the usual work week. He also told an interesting personal story. He said that he worked at a startup as a VP of Engineering which required tremendous hours, entire weekends and late nights every day kind of affair. Monetarily the job worked out as the company succeeded and had an excellent exit. Personally it was a disaster as his wife left him. He got married again but felt his first marriage was a tragedy that he could have avoided by shifting his values.
Sometimes the cry of wolf is just a lie too. I worked for a company that decided totest the team by creating a fictitious emergency opportunity that required an entirely new product based on a common core within two months. It was supposed to prove that the professional services group really was whining about the core product. However, it turned out that the core team could not accomplish the task because the professional services team was correct, the core product was not designed for rapid customization. The test was only known to 3 managers. The effect was that the team struggled for nothing and that was found out at the end of the project. Many of the developers quit or transferred out of core within a year. While core was no longer packed with old guard developers, it was also without any experienced in developing that code anymore. The lie was demoralizing and the company suffered.
Crying wolf every month clearly has some very negative aspects and working in one of those companies is challenging. The first challenge is understanding that these cries are often genuine and are meaningful. The second challenge is to ensure that work and family life stay balanced. The third challenge is to never lie about the importance of a feature to a customer. Balancing these sounds like a difficult job and it is, you may have to work a weekend or two to figure out the answers though.

Being a Developer During a Recession

There is a growing fear that we are going into another recession if we aren't already there. The mortgage finance issues, the massive losses that came to the hedge funds, many consecutive bad trading days, rumors of Yahoo about to layoff folks and so on. The picture we are given is one that things are relatively bleak and that soon we will be homeless, jobless, the wife or girlfriend is ditching us and the dog is looking like he's ready to go on the road and run with the pack.
The more immediate fear, for us developers, is being laid off because the company isn’t doing well for one reason or another. It is reasonable to be scared but it is unreasonable to do nothing. Now is the time to start planning for a lay-off and hopefully it will never come for you. But I can assure you that some people reading this right now have been laid off in the past and it will probably happen to you too at some point. It isn't the worst thing that can happen to you but you really don't want to experience it without some kind of parachute.
First, layoffs are common. In the late 80's and early 90's Digital Equipment Corporation (DEC) and Wang went through massive rounds of layoffs and saturated the market with developers. It was difficult to get a gig during that period because of such tremendous competition. Of course, many of the laid off guys founded new companies and hired old friends.
Second, most people remember the "Dot-com" bust that hit its peak some time during 2001- 2002 and 2003 was the start of the recovery. We should also remember that it was preceded by the mobile phone and telco bust that happened a year or two earlier. The network hardware companies also took a beating as Dot-com companies stopped buying. A lot of people were out of work but there were still jobs to be had.
You'll hear a lot of stuff about how to avoid being laid off over the next few months. Some will say that you need to work really hard and work on truly critical code. Work so hard on critical items that the company can't afford to lay you off. You'll hear things like "keep your head down and just do what you are told" and "avoid arguing at all costs." Don't take time off, don't say no, don't be too senior, don't be paid too well, don't be too junior, don't be average, don't stick out and be sure to stick out and get noticed for your work.
The truth: layoffs are fickle. You can be laid off for a number of reasons completely out of your control, that of your manager and her manager. There is no such thing as a person who cannot be laid off. You see C-level executives get ousted for just having a bad quarter or they fell out of favor with investors. Are these people any less critical than even the best developer or architect? If they can go, then so can you. The company, its investors and directors believe that they cannot succeed unless they make cuts and they can make cuts for unusual reasons regardless of how it will impact the company. They believe that another employee will learn the work and pick up the slack, even if the product comes out later. It's true too, someone will learn the code and go from there.
With that, let's talk about what to do before a layoff. I'm not a financial or credit adviser so take what I'm about to say as my opinion alone. You should contact an investment or financial adviser if you have any personal questions.
Saving some money every paycheck is critical. That money is incredibly valuable later on down the line if you get laid off. The cushion it provides is incredibly valuable, especially when you see your unemployment insurance check. Some experts say that you need to have at least one year's worth of salary saved. This is obviously difficult, but every penny counts.
Homeowners are especially vulnerable. In some states unemployment insurance may max out at only $1600 a month depending on your annual income. Is your monthly mortgage payment more or less than that amount? How about your monthly living expenses: food, utilities, medical insurance and car related costs (gas, state taxes, insurance)? Can the unemployment insurance cover all that? No? Then you need savings and you need to start today.
One thing homeowners can do is refinance to a lower interest rate, but you usually need to be working to be eligible. It may be worth your while to refinance and save the difference from your old payment and your new one.
The day you get laid off is terrible. It truly sucks. They hand you lots of paperwork and try to get you to sign everything. They can often withhold severance packages until you agree not to sue them later. Some companies don't give severance except to executives who negotiated it in their employment agreement. Other companies give as much as 6 months pay. It varies but it is not required. They can't withhold COBRA- your health insurance plan. Most of the paperwork is pretty standard, of course, talk to a lawyer and be sure that you are comfortable signing away some rights.
The next thing you have to do is call the state and get your unemployment insurance going. Most states require employers to put money into a pool as a part of their payrole taxes. The state then pays the money back to laid off staff at whatever the state's rate is. Don't worry so much about how much money your company paid into the fund, that doesn't impact your payments. However, the company's unemployment insurance rate often goes up for every layoff. It takes time for the state to process your unemployment request as they have to get in touch with the employer and verify the circumstances of your unemployment. Being laid off and being fired are completely different in many states and it affects what your unemployment insurance rate will be.
 Some states let you do the unemployment insurance registration over the phone while others require you go into an office. You may feel like a failure in some way, but you are not. Layoffs are supposed to be about the financial failure of the company, not your ability to perform. If you were a poor performer they could have fired you or forced you to quit. You are going to that office to get what taxes paid for. It is owed to you.
The drive home after being laid off is terrible too. You may have a wife and kids to tell and that's a hard thing to face. You may be single and you have to figure out how you are going to tell your parents and friends. Its really depressing.
Now you are laid off and you have to sit at home. You may have to make some cuts, like go out to dinner and lunch less, buy less beer or buy cheaper beer, buy less expensive clothes, go to the movies less or rent fewer movies. The trend is clear: buy less if you can.
The first week of unemployment is hard because you may miss your friends from work. It can be painful because one day you are having lunch with friends and then the next you are not allowed to see them at the office anymore. You have been evicted from people that are important to you and a routine you live by. Sure, you can still catch-up with them and have lunches and such, but it isn't the same. Even the strong and reclusive people become depressed by these circumstances.
Looking for a new job is your new job. It can be difficult for a number of reasons. First, being pushed out of a job can leave you bitter and that shows up in an interview. You have probably interviewed people that seemed angry and didn't hire them.
Second, layoffs at the height of a recession can leave you with few job options. I checked for jobs through Hot Jobs during the Dot-com bust and saw very few postings and sometimes no postings in the Boston area. Do a search today and you'll find hundreds of Java developer positions in the same area.
Recruiters can be supremely helpful when they are being employed by companies. They may be in a drought during a recession too though. Next are the online ads. I often wonder the value of ads on HotJobs and Dice whether the companies are showing off or are really hiring. Craigslist.com seems to have ads from employers actively hiring. Of course, your professional network is gold and you really should tell people about your situation. They may get know of a company that's hiring and get you in front of someone.
I've painted a bleak picture so far and now I'm going to talk about some of the joys of being out of work. Yes, being unemployed and scraping by can be a wonderful life-changing thing that may bring you a lot of happiness. And provided you can weather the financial drought, could be the best thing that ever happened to you.
Bear in mind that you are a developer. You have all the skills to write your own application from scratch. You can start your own company. You can work for yourself and now is a good time to start. Your skills will stay sharp and you can explore areas of application development that were not available to you in the past. You can learn things outside of your old job too, like learning sales, marketing and finance. It can be an incredibly valuable learning experience.
You don't have to start your own company though. Consider working on an OSS project fixing bugs and working your way up to being a mainline contributer. The minimal goal is to ensure you don't lose your valuable development skills.
There are lots of fun things you can do on the cheap too. You can go out for a walk, a long walk, every day. Reading is something you have plenty of time for. And of course, you can code for several hours a day on things you are interested in. You can also spend some time blogging (aka writing skills), cooking and gardening. You could probably paint your house too. You can go on long drives and hikes.
One obstacle to overcome is the notion that you must get hired at your old salary, old title or even get a promotion. It happens, but many developers will tell the tales of how employers snapped up highly skilled laid off folks on the cheap.
I talked to a manager at a defense research company during the beginning of the Dot-com crash who was excited by the layoffs happening in the area. She was looking forward to hiring a couple of new people at lower salaries. I lost interest immediately because I currently had a job and a front line manager probably shouldn't be so excited by how labor costs were coming down thanks to the misfortune of others. Moreover, they shouldn't gleefully take advantage of the laid off when there is actually no financial benefit to the hiring manager. An argument could be made that the manager can now hire a better engineer for the money, but that engineer probably has enough sense to leave when the market rebounds. These managers are looking to cut labor costs and a laid off person has almost no room to negotiate salary or benefits.
There are some guys out there that haven't been laid off and they attribute it to their stellar performances and that's great, good for them! The risk is that you simply never know what is going to happen from one quarter or week to the next. Preparing for a layoff is sort of like a squirrel preparing for winter, you hope it will never come, but you are ready if it does.
Now some of this sounds like words of experience. I've been laid off and it wasn't a good time for about a week and I was bitter about it for a lot longer. A few days after being laid off I started writing a lot of code every day, reading voraciously, dating more, watching a lot of movies, cooking, spending a lot of time outdoors, looking for a new job every day and met my future wife. I had saved ahead of time and had a low mortgage. I look back at that time as being one of the best times of my life, but only because I had the savings.

Remember the Flow Chart?

There is huge value in design reviews and they are almost always worth sitting through. I say almost always because just about everyone has sat through a review where the designer didn’t understand the problem at all and the next hour or more was spent educating. The value in a good design review is that the design is validated, people understand what is involved and can start working on implementing and testing the design. The review is also an opportunity to further refine a design that results in a better, collaborative solution. All of the above is valuable in one way or another.
The makeup of attendees at a review varies, but it often includes project management, QA, developers and architects. This range is why various diagrams become crucial. QA and project management can come from very different backgrounds and thought processes than those of engineers that leads to some interesting communication barriers. Text can often be interpreted in more than one way, and consequently other engineers can miss the point entirely too.
Some QA people are junior engineers working their way into a traditional role as a software engineer by getting a job where the barrier to entry is lower. Others used to work in as an insurance customer service rep and have really good analytical minds. My favorite QA person used to be a Cobol developer and has her own scientific method for finding bugs in a user interface.
Project managers are a disturbing mix of anyone who manages a project. I have had C and VP level people managing projects and pet features as well as a former editor for a publishing house. They can be brilliant orchestrators of people and technology, equally adept at installing the latest Linux flavor, configuring their Blackberry for a new email server and scheduling the next three weeks of your life. Others found their way into project management as they switched from one career to another and may have good management skills and are completely inept when using anything but the simplest features in Word, Excel and Outlook.
Diagrams are a critical component for a design because the variety of people and learning styles require that you provide more than method for conveying information. There are several kinds of diagrams, but two usually drive home the point for any audience. The first is the structural diagram. These are the UML class diagrams and Entity-Relationship models. Engineers love them because a reviewer can figure out from the interfaces what she is supposed to do.
The second diagram type describe process flow and logic. UML activity diagrams and flow charts describe the processes in the order they would execute within the system. These diagrams resonate with non-developer staff. They also help with a another class of reviewer: the schmuck that doesn’t read the specification before the meeting.
Non-developer types don’t care about structural diagrams except when it is an API you will hand to external users. Does a QA person care if you are applying a “Chain of Responsibility” pattern? Likewise, UML Sequence diagrams describing method calls are equally unhelpful to non-developers. The project manager may care if you are following a well-defined design pattern and have a solid structure. It depends on the person and their background. Some CTO’s are technology visionaries that have no real development skills while others are skilled former engineers. Show these people the structure of code and you may get a good response and then again, you may not. Show them how it will execute and how users will experience and you will have told these reviewers something they can act on and contribute to.
ER models are a special case of structural diagrams as they are sometimes necessary for QA to do their job. QA has a wide range of responsibilities and skills. Sometimes they check whether the thing stored through the UI is what was actually stored at the back-end by executing SQL queries. They really need to understand these relationships and an ER diagram is the best way to do it. Applications that have an ETL type process usually have database savvy QA staff.
Nearly every design describes some kind of process and that’s where the flow chart comes in. Now I know just about everyone knows what a flow chart is and the last statement generates a big “duh.” And yet there are a lot of low level sequence diagrams. The flow chart is great at explaining the big picture. Want to explain the logic behind an ETL process? Need to show how your JMS publisher-subscriber dispatcher determines what should get an event? Maybe you want to explain how you write a blog. Here’s how I do it:
This chart clearly shows the entire process from start to end. A sequence diagram may do the same thing, but gets into specific method calls and goes far too deep for most people to understand what the system is trying to accomplish. Personally, I prefer sequence diagrams for explaining a specific process thats already implemented or the details behind an API call.
Back to the diagram; one could easily write a paragraph on each process. In fact, I would argue that you draw the diagram first and then use it as an outline for your document. I should be able to describe my entire blogging process, up to “Publishing Process”, in eleven paragraphs or less. I may write much more than that if I try to write first and then develop the diagram.
I’ve noted some resistance to creating flow charts. The causes are often that the designer doesn’t have a tool to diagram with, its too time consuming or they don’t know the iconography and worries that he will look foolish.
The first cause is very common. Visio is the most common tool but it isn’t included with Office. It can be accomplished in Powerpoint too, but it is very time consuming. I use OmniGraffle for the Mac and think the results are pretty good. UML modeling tools do come with some IDEs now but may not support the activity diagram. I have tried a web site called Gliffy. It’s good in a pinch and cheap to sign up for (free and premium versions), but I still prefer desktop tools at this time.
The second cause drives me batty. Diagramming anything is time consuming. It requires patience and attention to detail. Failing to diagram usually means that your review will be longer, sometimes by hours. The reviewers will sit through that meeting and have their time wasted too. A flow chart would have shown them quickly that your vision of the process is incorrect and they could have quickly alerted you and the meeting could be shorter or rescheduled entirely.
I mentioned earlier that a flow chart can become the outline to your design. You could type a lot of text for hours or you could make a really good diagram and quickly document it. You may spend less time doing the latter method and your reviewers may read through more of your document.
The third cause is surprisingly common and understandable. Picking the wrong symbol or labeling it incorrectly can be embarrassing and may derail what could be a good review. No one wants to look like a fool and they want to be told they are a fool even less. Having one of your designs reviewed is incredibly stressful except to the overconfident. Every novel idea is scrutinized and a target of comment, embarrassment and even ridicule. A review is supposed to be about collaboration, refinement and building something brilliant as a team. It is reasonable for someone to try limiting their exposure by avoiding certain diagrams.
I found that the Internet has plenty of flow charting tutorials, which should help the worried designer. I also found that some tutorials conflict! Take a look at these:
These five examples are similar. They agree on several symbols and their meaning, but not all. Many have the symbols for punch cards, paper and magnetic tape too. Most people don’t use these technologies anymore, however, do a search for “paper tape reader” and you will still find companies producing paper tape readers but I digress.
Above are four symbols they all agree on and will get you through 99% of common process descriptions. You can use them pretty safely and get your point across. Only in a few environments is there reason worry about the iconography and its proper use. I would take care in medical, aerospace and military designs that the iconography is correct by referencing other accepted designs. Small, medium and large businesses outside of those spaces are pretty safe. Your only worry is that guy that brings up spelling or grammar mistakes during a review, he’s bound to have an opinion on the iconography too.
These picky people are great for reviewing designs, but not during meetings. Keeping a design review on track is difficult because of all the interesting technical aspects that other reviews want to explore. Spelling mistakes can be forwarded in an email before or after the meeting. This gives more expensive meeting time to the technical issues. I often send my documents out to these people as early as possible and get their feedback before the meeting. Their spelling and grammar checking actually shows they are reading the document carefully. They have technical opinions too and they want to help, just manage their feedback so it comes out in the best light.
I’ve mentioned a lot of reasons to use flow charts in designs and they appear to be about shortening the design review. My goal is not to shorten a design review at all. Lots of interesting things can be learned from your peers. The goal of diagrams is to quickly describe the structure, process and use of the component you are building so that you can efficiently justify your design, find its flaws, get ideas from other people and to educate those that will be implementing and testing the code. Design reviews can get everyone on board quickly but that can only be accomplished if your team understands both the structure and the processes. So dust off the old flow chart and remember that if you have a class or ER diagram then you probably need a flow chart too.

Javascript Classes: Design Patterns, MVC and Ext 2.0

Few would argue that the advancements in web application design over the five years are anything short of staggering. Five years ago almost all the serious work was done on a server which would churn out all the html, application behavior, storage and marginally improve the user’s life with some javascript that may bring up a few tool tips or validate a form. Now we can write the entire UI layer entirely in Javascript, use the server to serve the application up and act as storage and supplement the server with browser side storage.
The challenge in modern web application design is that browser-side web applications get very complex very quickly so there needs to be a way to organize readable and serviceable code. Javascript’s class functionality has been extended through a number of novel implementations to the point where it is relatively easy to implement the proven design patterns of traditional desktop applications. We are going to take a look at that functionality. Actually, we are going to take a look at a lot of different things.
The Example

Here we see a UI with three entire fields. The idea is you type in one and then press enter. Then other two fields update with the converted value. Its no more difficult than that.
The original example was going to be some simple thing like the mammal-cat-lion, and the rest of the barnyard, class hierarchy that bored everyone with a CS degree to tears. We will look at this temperature conversion utility using several different patterns and implementations to demonstrate how things can work in small and large Javascript applications. There is no argument that this conversion utility could have been done far more simply without classes and many of the other components, but it was just big enough to demonstrate all the major points:
  • MVC Pattern
  • Observer Pattern
  • Composite Pattern
  • Class creation and extension
  • Event handling
  • Factory Pattern
I’ve implemented this using Ext 2.0 and the following components:
  • Ext.extend
  • Events - existing and new events, chains
  • “superclass.constructor.call”
  • Ext.form.FormPanel
  • Ext.form.NumberField
  • Ext.util.Observable
With that said, lets take a look at the basics of MVC and its pattern elements. I’ll explain why I made many of the design decisions and the sometimes conflicting implementation decisions. Code examples are throughout, but the complete example is near the bottom. I’ve annotated some of the dumb and not-so-dumb mistakes I made too. Finally, there is a bibliography at the end, because there was a lot of material worth referencing.

The model-view-controller (MVC) pattern has pretty much been clubbed into the brains of any developer in the MFC days. I’ve been in Java land doing web applications for 8 years and I haven’t followed if .Net has abstracted that model away. The idea is that the model governs the data and its various transformations. You sometimes see it referred to as the document model. The model does much of the logic for loading, saving and sometimes validating data. The model emits events indicating that a given data item has changed or is no longer valid.
The view is the user interface and it performs queries against the model for the value of data items. The view typically registers for change notifications from the model too. The UI updates upon receiving a change notification.
The controller is responsible for performing updates from the UI to the model. It can also determine which view should be active for the current application context. It can also be responsible for loading and saving data contained within the model.
Note that I wrote that both or either the model and the controller can be responsible for loading and saving data. There are a lot of different implementations of this pattern. Apache Struts has almost completely abstracted out the controller. The user only works with the model and the view. The model is responsible for connecting to the a service, EJB, or directly to the database for its data. MFC had the developer load the document model from the controller. Further, elements of the model and the controller can be delineated at the method level, rather than at the class level, in some designs.
The Model

GenericDocument = function() {
this.elementAssocArray = new Array();
this.elementArray = new Array();
this.getAll = function() {
return this.elementArray;
};
this.put = function(name, value, fireEvent) {
if ( typeof(fireEvent) == 'undefined' ) {
fireEvent = true;
}
var documentItem = null;
if ( name ) {
documentItem = this.get(name);
if ( !documentItem) {
documentItem = new DocumentItem( name, value );
this.elementAssocArray[name] = documentItem;
this.elementArray.push(documentItem);
} else {
documentItem.setValue(value, fireEvent);
}
}
return documentItem;
};
this.get = function(name, createNew) {
var documentItem = null;
if ( name ) {
documentItem = this.elementAssocArray[name];
if ( !documentItem && createNew ) {
documentItem = this.put(name);
}
}
return documentItem;
};
this.getValue = function(name) {
var value = null;
var documentItem = this.get(name);
if ( documentItem ) {
documentItem.getValue();
}
return value;
};
this.addHandler = function(name, object, handler) {
var documentItem = this.get(name);
if ( documentItem ) {
documentItem.register(object, handler);
}
};
}
The implementation of the example’s document model is based on two patterns:Observer and Composite. The Composite pattern is a tree-like construct that contains a series of different objects that are either leaves or other composites. The main document class, GenericDocument, is a Composite implementation. The leaves are DocumentItem objects which expose methods for the Observer pattern.
The GenericDocument class is little more than a factory and repository ofDocumentItem objects. However, this class is very useful as we will see later. The biggest contribution is that the GenericDocument stores the master data items from which all other things refer. The construct eliminates the need for lots of global variables and centralizes access- more later.

DocumentItem = function(name, value, object, handler) {

this.setValue = function(value, fireEvent) {
if ( value != this.value ) {
this.value = value;
if ( fireEvent ) {
this.fireEvent( 'valueChange', value );
}
}
};
this.register = function(object, handler) {
if ( object && handler ) {
this.addListener( 'valueChange', handler, object);
}
};
this.getValue = function() {
return this.value;
};
this.addEvents( {'valueChange': true} );
this.name = name;
this.setValue(value);
};

Ext.extend(DocumentItem, Ext.util.Observable);
An Observer pattern implementation relies upon a Subject, theDocumentItem in this case, which exposes one or more methods to allow Observerobjects to register for events. These events indicate that the subject has changed in some way. The observer can observe those state changes rather than visit to see if the subject’s state has changed.
You may ask “What!?” at this point. Another way to say it is that the observer registers for events indicating that the subject has changed in some way. The subject then emits a message, or event, to the observer saying “Hey, I changed. Wake up and do something.” The observer can then visit the subject and look at the value. The observer is not required to do anything beyond that. A slightly different implementation is that the subject notifies the observer and includes the new value. This is fine when the object can be passed by reference, which minimizes memory requirements. The downside is that the observer is then able to modify the value of the subject which can be unwise in some scenarios. We are converting temperatures, so we are sending the observer the new value along with the notification.
Implementing the observer pattern is a snap with Ext. I’m going to describe the operations in the order of writing the code, not the order they appear in the file.
  1. Create your Subject class.
  2. Call Ext.extend with the name of you Subject and derive fromExt.util.Observable. “Ext.extend(DocumentItem, Ext.util.Observable);”
  3. Call addEvents() during the construction of the new class so thatExt.util.Observable will dispatch your new events and let objects register for it.
  4. Add a “register”,”attach”,”bind” or whatever you want to call it, method for registering the objects interested in receiving events about the change in state of your class. Within this method call addListener with the name of the event, the handler function and the scope you want the function to run in. Usually the scope is the object that contains the event handler function.
  5. Call fireEvent with the event name defined in step 3 and the value that changed. Ideally you would fire the event from the same place that governs changes to the value object. You should only fire an event if the value actually changes from one setoperation to the next to avoid dispatching unnecessary updates to the observers.
About half the code is for implementing the Observer pattern, while the rest is for storing and updating the value of the Subject. The Ext.util.Observable object lets you register as many observers as you like. This is great because you can have applications where there are more than one user interface element bound to a given data object. I’ll get into this a little later when I describe why I chose this specific implementation.
The code is very simple because all of the difficult work is being done by theExt.util.Observer base class. The setValue() method just checks to make sure the value is different from the one stored and performs an assignment. Then it callsfireEvent() to notify the observers that the value has changed.
Testing to see if the value is different is meant to limit the number of unnecessary updates. We don’t know the logic of any observer when implementing a document model. The observer’s logic could be very complex or very simple. Consequently, we try to minimize dispatching pointless events.
That if statement is also too simple for anything beyond string and number tests. A complex application may associate more complex types, like an Ext.data.Storeobject or an array, and that test would not work effectively.
There is also a check to see if we should fire the event at all. Sometimes you don’t want to update the value depending upon who is doing the update. It is possible to create a recursive series of events where modifying value A causes an event that modifies of value B which causes another event that modifies the value A until the stack runs out of memory and the application or browser crashes. I successfully accomplished this feat during some late night coding.
The next code related item is the call to addEvents(). We can’t dispatch a new kind of event until we register the event with the Ext.util.Observable base class. Ext will throw a number of errors if we fail to do this when we fire the event.
The last line is critical to all of this where we associate the Ext.util.Observableas the parent class of DocumentItem. The extend() method adds the properties of the parent to the child class.
The behavior of Javascript classes in relation to inheritance and behavior is very different from more traditional languages in part because Javascript never defined a real class structure. Instead some very inventive developers figured out that they could copy the properties of one object into another. Consequently, don’t look for the usual modifiers (constants, access, etc.) in these class definitions nor expect the class to behave exactly like a Java or C++ class.
These DocumentItem instances are managed by the GenericDocument class. The GenericDocument class is an example of a very simple Composite. First, the calling code works through the Composite to manipulate the individual data items. Second, the Composite treats each data item as a leaf. Third, the leaves can be of broader types than just an instance of DocumentItem. We could have several child classes off DocumetItem or we could remove the factory functionality of the putmethod entirely and let the user just add name/value pairs where the value may vary from the DocumentItem class. The Composite could contain other Compositeinstances though this specific implementation does not.
Let’s go into why the document model was done in this particular way. It seems like a lot of work to implement all that code so that we can convert temperatures. Sure, it is a lot of work and it could be written far simpler. Let’s say that you had to develop a real application in Javascript, like maybe Excel or PowerPoint. You can have literally a dozen UI components all sharing a single data item. One way to code this would be through a global variable, or maybe a really simple class with a bunch of member fields.
The first problem is how do you modify the object and have all those dependent components be aware of the change? You could have the changing UI component go around and update the other dependent controls. That would be a lot of work, and the UI control’s event handler would have to have a list of all the other controls. That means you have to maintain some code that populates and manages that list. Then a developer on your team removes one control. Now you have to remove that control from the list. Its a maintenance issue and it can be a convoluted one.
Another way to update those controls is to have each control visit the data item and then the visiting UI control can update its value. That could result in a lot of controls having to visit that data item often. You can poll, but polling can be very inefficient, especially when you have say a dozen controls all polling the same object every 2 or 3 seconds. Your CPU utilization will spike and your application will run more slowly.
Yet another way to do it is through a global variable that is anExt.util.Observable child. This would give you the same event notification strategy but without having the document. Global variables certainly work, but they have a high degree of effort with fewer benefits. For example, global factory and management functions will probably be necessary to manage all these globals in a common way since some of them will be based on the Observer patten. Some of the globals will not be an observable object because they may be a UI control or some other data item. Consequently you will have heterogeneous data objects, making the code more difficult to read and determine which object is of what type.
These scenarios are based on having just one data item being monitored by several UI controls. A complex application will have many data items being shared across many UI controls. Using the Observer pattern ensures that you UI controls only update when data actually changes, thus keeping them always synchronized to the data in the document and keeping CPU utilization low. Associating theDocumentItem objects with a GenericDocument object makes the code more manageable.
This pattern is the basis for another the Publisher-Subscriber pattern too. The publisher-subscriber pattern is usually a little bigger and more distributed, with multiple publishers and multiple listeners for the same event and data. Let’s move on and look at the View.
The View
View = function() {
this.getField = function (label) {
var field = new Ext.form.NumberField( {
allowBlank: true,
allowDecimals: true,
fieldLabel: label,
hideLabel: false
});
field.documentItemName = label;
field.addListener('specialkey', function(field, eventObject) {
if ( eventObject.getKey() == null || eventObject.getKey() == Ext.EventObject.ENTER) {
var value = this.getValue();
documentModel.setTemp( this.documentItemName, value, true);
}},
field
);
documentModel.get(label, true).register(field, function(value) {
this.setValue(value);
} );
return field;
};
this.getForm = function(){
var fahrenheitField = this.getField(documentModel.getFahrenheitLabel());
var celsiusField = this.getField(documentModel.getCelsiusLabel());
var kelvinField = this.getField(documentModel.getKelvinLabel());
var panel = new Ext.FormPanel( {
bodyStyle:'padding:5px 5px 0',
border: false,
frame: false,
items: [
fahrenheitField,
celsiusField,
kelvinField
],
width: 300
});
return panel;
};
}
The view portion of the MVC is governed by, originally enough, the View class. The example application has a really simple implementation. Its job is to create anExt.form.FormPanel with three Ext.form.Numberfield objects that differ by label and the model’s data item. This class has one Factory implementation where the the field creation is performed by only the View.getField() method.
There are a few interesting lines worth looking at. In the getField() method, we see a call to field.addListener() which is registering for keyboard events like the tab,enter and various other keys. We are registering with this method to get enter key events. The handler calls documentModel.setTemp() with the name of the data item, the updated value and to dispatch an event about the value’s change. ThesetTemp() method is defined a little later when I talk more about class derivation.The effect of this code is that any change to a field plus the enter key will cause the update of a DocumentItem object.
The next interesting line is a call to “documentModel.get(label, true).register(” which creates a new DocumentItem, adds it to the document, and then registers the field object to receive events about changes to that DocumentItem. This line simply allows the UI control to be notified of a change to the DocumentItem.
A quick recap may be helpful. The field.addListener() call enables the UI control to notify the DocumentItem that a change has occurred. Thedocument.get().register() call enables the DocumentItem to update the UI control. I mentioned earlier that it was possible to great recursive, or circular, events. I give you another avenue I drove down for crashing your application unless you are careful.
The Controller
If you haven’t guessed yet, there is almost no explicit controller in this application. The GenericDocument, the event handling and dispatching, and the UI initialization all mixes in controller type functionality together. It is not clean but you can’t always make it clean either without rewriting much more code, like down into the Ext library which is exactly where we don’t want to go.

var documentModel = new TemperatureDocument();
function main() {
var view = new View();
view.getForm().render(Ext.getDom('formDiv'));
}
The above code is about the closest thing to a distinct controller as it initializes the and serves the UI, which is an explicit feature of the controller.
Class Derivation
We now get to the last chunk of code worth mentioning. It is generally useful to have a specific document implementation for a given application. TheGenericDocument object is handy for storing data, but we need something to encapsulate the operations that do temperature conversions. TheTemperatureDocument class is a child class of GenericDocument that is application specific. The TemperatureDocument class contains the data item name constants, temperature conversion functions and functions that save the updated values that cause the UI controls to update.
You can do class derivations a couple of different ways. First, you can use theprototype keyword. Second, you can define all your class methods in the constructor and then call Ext.extend to bind a parent class. You saw this in the DocumentItemdeclaration. Third, you can call Ext.extend with your new class, the base class and an object defining the new behaviors to add. You’ll see this in the following snippet. Fourth, you can use the Ext.apply and Ext.applyIf methods to bind properties to arbitrary objects.

TemperatureDocument = function() {
TemperatureDocument.superclass.constructor.call(this);
}
Ext.extend(TemperatureDocument, GenericDocument, {
getFahrenheitLabel : function() {
return 'Fahrenheit';
},
getCelsiusLabel : function() {
return 'Celsius';
},
getKelvinLabel : function() {
return 'Kelvin';
},
setTemp : function(label, value ) {
var validationValue = '0' + value;
if ( validationValue.length > 1) {
if ( label == this.getFahrenheitLabel() ) {
this.fahrenheitConversion(value)
} else if ( label == this.getCelsiusLabel() ) {
this.celsiusConversion(value);
} else if ( label == this.getKelvinLabel() ) {
this.kelvinConversion(value);
}
}
},
round: function(value, decimalPlaces) {
var rounder = Math.pow(10, decimalPlaces);
return Math.round(value * rounder)/rounder;
},
fahrenhietToCelsius: function(value) {
return this.round(( value - 32 ) * 5/9, 3);
},
fahrenheitToKelvin : function(value) {
return this.round((value + 459.67) * 5/9,3);
},
celsiusToFahrenheit : function(value) {
return this.round((value * 9/5) + 32,3);
},
kelvinToFahrenheit : function(value) {
return this.round(( value * 9/5) -459.67,3);
},
fahrenheitConversion : function(value) {
celsius = this.fahrenhietToCelsius(value);
kelvin = this.fahrenheitToKelvin(value);
this.put(this.getCelsiusLabel(), celsius);
this.put(this.getKelvinLabel(), kelvin);
this.put(this.getFahrenheitLabel(), value, false );
},
celsiusConversion : function(value) {
fahrenhiet = this.celsiusToFahrenheit(value);
kelvin = this.fahrenheitToKelvin(fahrenhiet);
this.put(this.getFahrenheitLabel(), fahrenhiet );
this.put(this.getKelvinLabel(), kelvin);
this.put(this.getCelsiusLabel(), value, false);
},
kelvinConversion : function(value) {
fahrenhiet = this.kelvinToFahrenheit(value);
celsius = this.fahrenhietToCelsius(fahrenhiet);
this.put(this.getFahrenheitLabel(), fahrenhiet);
this.put(this.getCelsiusLabel(), celsius);
this.put(this.getKelvinLabel(), value, false);
}
});
I’m going to skip explaining the bulk of the code in favor of talking aboutTemperatureDocument(), setTemp() and fahrenheitConversion(). The only line in TemperatureDocument() calls the GenericDocument() method. This is how you initialize your base classes.
The setTemp() method figures out which conversion method to call. There is an odd line in that method I will talk about later that has to do with zero and null being treated the same.
The fahrenheitConversion() method is where we end our tour to theTemperatureDocument(). It is a short tour. Two straightforward calls convert fahrenheit into celsius and kelvin and then we update the document’s master values. Note that we want to fire events when we update the celsius and kelvin values because we want the UI controls to update. We don’t want the fahrenheit UI control to update because it is the source of the change.
Now look at the code a second time and see the glaring flaw. Our goal was to allow multiple UI controls to all share a common data item. However, we don’t want the source UI control, the one that caused the value to change, to be updated too. We accomplished this by turning off the firing of the change event back to the UI control. That’s the problem. If we turn off the firing of the event then we end up disabling the event dispatching for all the other dependent UI controls. Other controls displaying the fahrenheit value would not update either. It works here because we only have one dependent control. Well, it turns out that you can enable passing the event back to the source UI control with no problems in this application because we are not dispatching events from the UI control as a result of calling the control’s setValue() method. If we were dispatching events caused by setValue(), then we would risk the circular event crash I mentioned, and experienced, earlier.
There isn’t a method that explicitly deals with the change of a value except for “valid” event. Consequently, most applications are probably safe. The only way to find out is to dig deeper into your own application.
This brings us to the end of the MVC pattern. Now lets see the complete application and talk about some of the interesting things that happened while writing it. We’ll also go into the motivations for some of my decisions.
The Code
There’s a lot of code for a temperature conversion application. It could have been done more simply if I wasn’t trying to make an example of design patterns and MVC. I’ve labeled and highlighted the interesting components where I ran into bugs, crashes and strange little error messages. They are talked about a little later.
First, why go MVC? The idea is that I don’t really know how much the application will grow by. I know, its an example application - it isn’t going to grow. Let’s say that it will and that we’ll have historical data, charts, data stores, probes, and lots of UI controls. The MVC pattern lets us add new data items and UI controls in a central store. Its easy to look them up and share them across many different components.
Why have a GenericDocument and then an application specificTemperatureDocument? We have a lot of conversion functions, constants and the need for other helper operations that are specific to the application and the document, but not the UI. The MVC pattern works best when you put these operations in the document itself. In our case, the TemperatureDocument adds helper functions and simplifies the code. All the important data management stays in theGenericDocument while all the application specific operations were in theTemperatureDocument.
Why define the entire class in the constructor of DocumentItem and then defineTemperatureDocument differently? I wanted to show there are different ways of doing pretty much the same thing. Of course, it really isn’t the same thing. These operations occur at completely different times. The DocumentItem got all of its methods assigned when the DocumentItem instance is created. TheTemperatureDocument got all of its methods bound when the document was loaded. The latter method is probably better since you generally want your user to wait for everything to initialize at the start rather than during the normal operation of the application. The better performing TemperatureDocument initialization would probably become more noticeable if you had to create several hundredTemepratureDocument instances and DocumentItem instances. TheDocumentItem objects would take longer to initialize even though they are otherwise simpler.
Why are there two arrays in GenericDocument? One is so that I can quickly get all the items in one pass. The other is so that I can look them up by name. The by-name lookup is speedy and ideal for most operations. The other version is handy if I need to perform some kind of server side automatic updates and such as I can just iterate through them more easily than an associative map. That’s just my opinion though and others will differ on this. The world is a diverse place.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Ext Class Example</title>
<link rel="stylesheet" type="text/css" href="./ext-2.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="./ext-2.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="./ext-2.0/ext-all-debug.js"></script>
<script>
GenericDocument = function() {
this.elementAssocArray = new Array();
this.elementArray = new Array();
this.getAll = function() {
return this.elementArray;
};
this.put = function(name, value, fireEvent) {
if ( typeof(fireEvent) == 'undefined' ) {
fireEvent = true;
}
var documentItem = null;
if ( name ) {
documentItem = this.get(name);
if ( !documentItem) {
documentItem = new DocumentItem( name, value );
this.elementAssocArray[name] = documentItem;
this.elementArray.push(documentItem);
} else {
documentItem.setValue(value, fireEvent);
}
}
return documentItem;
};
this.get = function(name, createNew) {
var documentItem = null;
if ( name ) {
documentItem = this.elementAssocArray[name];
if ( !documentItem && createNew ) {
documentItem = this.put(name);
}
}
return documentItem;
};
this.getValue = function(name) {
var value = null;
var documentItem = this.get(name);
if ( documentItem ) {
documentItem.getValue();
}
return value;
};
this.addHandler = function(name, object, handler) {
var documentItem = this.get(name);
if ( documentItem ) {
documentItem.register(object, handler);
}
};
}


DocumentItem = function(name, value, object, handler) {

this.setValue = function(value, fireEvent) {
if ( value != this.value ) { // 1
this.value = value;
if ( fireEvent ) {
this.fireEvent( 'valueChange', value );
}
}
};
this.register = function(object, handler) {
if ( object && handler ) {
this.addListener( 'valueChange', handler, object);
}
};
this.getValue = function() {
return this.value;
};
this.addEvents( {'valueChange': true} ); // 2
this.name = name;
this.setValue(value);
};

Ext.extend(DocumentItem, Ext.util.Observable);


TemperatureDocument = function() {
TemperatureDocument.superclass.constructor.call(this);
}
Ext.extend(TemperatureDocument, GenericDocument, {
getFahrenheitLabel : function() {
return 'Fahrenheit';
},
getCelsiusLabel : function() {
return 'Celsius';
},
getKelvinLabel : function() {
return 'Kelvin';
},
setTemp : function(label, value ) {
var validationValue = '0' + value; // 3
if ( validationValue.length > 1) {
if ( label == this.getFahrenheitLabel() ) {
this.fahrenheitConversion(value)
} else if ( label == this.getCelsiusLabel() ) {
this.celsiusConversion(value);
} else if ( label == this.getKelvinLabel() ) {
this.kelvinConversion(value);
}
}
},
round: function(value, decimalPlaces) {
var rounder = Math.pow(10, decimalPlaces);
return Math.round(value * rounder)/rounder;
},
fahrenhietToCelsius: function(value) {
return this.round(( value - 32 ) * 5/9, 3);
},
fahrenheitToKelvin : function(value) {
return this.round((value + 459.67) * 5/9,3);
},
celsiusToFahrenheit : function(value) {
return this.round((value * 9/5) + 32,3);
},
kelvinToFahrenheit : function(value) {
return this.round(( value * 9/5) -459.67,3);
},
fahrenheitConversion : function(value) {
celsius = this.fahrenhietToCelsius(value);
kelvin = this.fahrenheitToKelvin(value);
this.put(this.getCelsiusLabel(), celsius);
this.put(this.getKelvinLabel(), kelvin);
this.put(this.getFahrenheitLabel(), value, false );
},
celsiusConversion : function(value) {
fahrenhiet = this.celsiusToFahrenheit(value);
kelvin = this.fahrenheitToKelvin(fahrenhiet);
this.put(this.getFahrenheitLabel(), fahrenhiet );
this.put(this.getKelvinLabel(), kelvin);
this.put(this.getCelsiusLabel(), value, false);
},
kelvinConversion : function(value) {
fahrenhiet = this.kelvinToFahrenheit(value);
celsius = this.fahrenhietToCelsius(fahrenhiet);
this.put(this.getFahrenheitLabel(), fahrenhiet);
this.put(this.getCelsiusLabel(), celsius);
this.put(this.getKelvinLabel(), value, false);
}
});

View = function() {
this.getField = function (label) {
var field = new Ext.form.NumberField( {
allowBlank: true,
allowDecimals: true,
fieldLabel: label,
hideLabel: false
});
field.documentItemName = label;
field.addListener('specialkey', function(field, eventObject) { // 4
if ( eventObject.getKey() == null || eventObject.getKey() == Ext.EventObject.ENTER) {
var value = this.getValue();
documentModel.setTemp( this.documentItemName, value, true);
}},
field
);
documentModel.get(label, true).register(field, function(value) {
this.setValue(value);
} );
return field;
};
this.getForm = function(){
var fahrenheitField = this.getField(documentModel.getFahrenheitLabel());
var celsiusField = this.getField(documentModel.getCelsiusLabel());
var kelvinField = this.getField(documentModel.getKelvinLabel());
var panel = new Ext.FormPanel( {
bodyStyle:'padding:5px 5px 0',
border: false,
frame: false,
items: [
fahrenheitField,
celsiusField,
kelvinField
],
width: 300 // 5
});
return panel;
};
}

var documentModel = new TemperatureDocument();
function main() {
var view = new View();
view.getForm().render(Ext.getDom('formDiv'));
}
</script>
</head>
<body>
<div style="margin: 10px 10px;">
<div style="font: normal normal 110% helvetica">
Pick a field and type in a temperature and press enter to convert.
</div>
<div id="formDiv"/>
</div>
<script>
Ext.onReady( main ); // 6
</script>
</body>
</Html>
Now on to some of the interesting things that happened while writing this. Look for red code and comments to match them to item numbers.
  1. This was interesting. Originally I checked for null too. Turns out that null and zero are the same, big surprise. That holds true in pretty much every language too. Well, I thought I would get the string “0” rather than an actual zero. Had to remove the value so 0 degrees would be valid.
  2. I had this line commented out to figure out a different bug and started to get this error message in FireBug “this.events has no properties: var ce = this.events[eventName] || true;”. Always add your events before you try to use them!
  3. I had a similar problem as in item 1. I had to prepend 0 to the beginning of the value to ensure that it got processed, but only if the value was 00 rather than a completely empty field. So a user could type 0 and it would get processed and a blank field won’t.
  4. This was really annoying. Again, part 1 strikes in yet another way. Turns out that a value of zero gets processed slightly differently when you hit the enter key or any other special key. The key code is null! Who would have thought that so much work went into handling zero?
  5. Ext in Internet Explorer 6 is a little odd with width calculation at times. I often find that I have to define a hardcoded width or the control will take the entire screen.
  6. I accidentally had this instead “Ext.onReady( main() );”. Note that this is now a function call inside of onReady which means that main() was getting called and passing its null result into Ext.onReady. Firebug gave me this error message “l.fireFn has no properties: if(l.fireFn.apply(l.scope||this.obj||window, arguments) === ...”. The bad bit is that everything worked except I got this error message. Seems like a T-shirt title.
Summary
The goal was to show how you can build an MVC application using Ext 2.0. We used a number of different patterns and components to accomplish something that can be used effectively in much larger applications than this little thing. It wasn’t necessary to use Ext to demonstrate this though. Many of the Javascript libraries use some kind of OO contraption and consequently, you can take advantage of some of the well proven patterns that have built a lot of very succesfull applications.

Eckstein, Robert. “Java SE Application Design with MVC.” java.sun.com. March 2007.<http://java.sun.com/developer/technicalArticles/javase/mvc/>
Gamma, Erich., Helm, Richard., Johnson, Ralph., and John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Reading: Addison-Wesley, 1995
Jacobs, Kurt. “Subscribe now for rapid prototyping.” Javaworld.com, Septemer 2001.<http://www.javaworld.com/javaworld/jw-11-2001/jw-1109-subscriber.html>