Thursday, January 31, 2008

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.

Tuesday, January 29, 2008

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 to test 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.

Thursday, January 24, 2008

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.

Sunday, January 20, 2008

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.


Monday, January 14, 2008

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.

Figure 1: An example diagram of an MVC.

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 of DocumentItem 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, the DocumentItem in this case, which exposes one or more methods to allow Observer objects 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 from Ext.util.Observable. “Ext.extend(DocumentItem, Ext.util.Observable);”
  3. Call addEvents() during the construction of the new class so that Ext.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 set operation 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 the Ext.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 calls fireEvent() 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.Store object 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.Observable as 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 put method entirely and let the user just add name/value pairs where the value may vary from the DocumentItem class. The Composite could contain other Composite instances 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 an Ext.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 the DocumentItem 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 an Ext.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. The setTemp() 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. The document.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. The GenericDocument object is handy for storing data, but we need something to encapsulate the operations that do temperature conversions. The TemperatureDocument 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 the prototype 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 DocumentItem declaration. 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 about TemperatureDocument(), 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 the TemperatureDocument(). 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 specific TemperatureDocument? 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 the GenericDocument while all the application specific operations were in the TemperatureDocument.

Why define the entire class in the constructor of DocumentItem and then define TemperatureDocument 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. The TemperatureDocument 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 hundred TemepratureDocument instances and DocumentItem instances. The DocumentItem 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>

Saturday, January 12, 2008

Gizmodo at CES

Ok, lots of people are arguing about Gizmodo’s trick at CSS and I figure I may as well add an opinion to the fray. CES is packed with a lot of deep pocketed companies. Losing a TV is bad and frustrating, but not devastating. CES also has a lot of small companies, some up and coming and a few trying to keep from going out of business.

I’ve worked on a lot of projects where we had to hit deadlines for the sake of making a demo or a trade show. I’m sure a lot of you out there have lost weekends, nights, sleep, friend and family time too. Some of us have had vacations canceled and Christmas’s and other holidays ruined for the sake of deadlines that can make or break the company.

Gizmodo’s prank and weak apology will probably inspire some schmuck to try it at another conference, like JavaOne, which is packed with a lot of small companies that have a lot of tired engineers. Maybe nothing would be lost, then again, you never know who is walking in front of that TV next. Either way, we all really need to send a message to Gizmodo that we aren’t going to endorse that kind of behavior by continuing to visit their site, cool as it may be.

Thursday, January 10, 2008

Simplify or Dumb Down Code

Many years ago I wandered into a friend’s office to ask a few questions. Before I could even say “hi” he told me that the manager wanted him to “dumb down” his code. Turns out a couple of team mates complained that the hid OO framework was too complex to follow. They wanted the framework to be more straightforward. He was very annoyed by this because he felt that developers should rise up to difficult code. To see it as a challenge and an opportunity to grow.

Years later I produced an interesting chunk of code that bullet-proofed a process. I was pulled off to the side by the chief architect and was asked to change the code so that a junior developer work with it. It was a fairly simple compiler for a subset of Java. Writing a compiler is somewhat specialized and there is a lot of foundation code, however, it isn’t in insurmountable tasks when you are only working with a subset.

I pled my case that a junior developer should be able to dig into the code, refer to the JVM specification and write some code without much difficulty. It was a matter of the developer rising up to the challenge of something new rather than running away afraid. This argument made sense to the architect and we moved on.

Sometimes a brilliant design is simply beyond the capacity of the existing development team. For example, it is probably unwise to have a PHP team try to implement a Java flyweight pattern. They may finish and get it all working, but then again it could be just a little too challenging for the first time out. Dumbing down is a good idea when the available team is just too junior to do the work.

Dumbing down is also reasonable if you are not going to be around for very long, like a contractor. There is nothing like trying to figure out a brilliant contractor’s work six months after he has left. It really is difficult and he may be the only person who really understands why he chose the path he did. Keeping it dumb is sometimes better when you aren’t going to be able to share that knowledge later.

Some designs are needlessly complex and can be simplified. Sometimes we engineers get a little focused on the art of software development instead of the craft. Amazing OO designs need to be checked against real world requirements because they may not scale well. Developers working in Hibernate with a complex data model sometimes find themselves losing a lot of processor cycles to converting the model into rows in a table and back again. Note, I’m saying the the model may be too complex, not Hibernate.

Simplification is about reducing a design to make it run well. Dumbing down is about making life easier for the another developer.

I still think about my friend’s issue with dumbing his code down. Its not always easy to tell when the design needs simplification (AKA re-factoring) of if the problem is that the team isn’t bright enough. The one thing I know is that I was junior developer back then and I learned a lot from implementing parts of his design.

Wednesday, January 9, 2008

Dumb Bugs

Seth Godin wrote Dumbing Down and it reminded me of dumbing down code and dumb bugs. The latter is what interests me for the moment.

My first and second jobs were tech support. I graduated from college just as DEC, Wang and Data General were winding down and preparing to fade away. The result was a saturated job market and I was thankful to get the gigs. Those two jobs taught me a lot about software development and how bugs really affect customers.

The worst bugs were those that didn’t add anything to our products beyond the appropriate level of polish. Bugs like spelling and grammar mistakes, minor UI alignment issues, terminology issues, etc. Customers really do call about these kinds of issues and some customers actually get really angry over them. They have a right to be upset too: they spent a fair amount of money and expect things to look and work right.

Dumb bugs are often really easy to find and fix. Sometimes they get missed anyway or they get a really low priority in the bug database and are prioritized right out of the development cycle. Missing these things is sometimes fine, everyone makes mistakes and some of us can’t spell if it weren’t for spellcheckers. However, they should get fixed quickly once they are entered into the bug database.

It usually takes only 2 or 3 minutes to fix a spelling or nomenclature mistake. Just a couple of dollars to update the code, usually a resource or configuration file, and close out the bug. Its cheap to fix.

Have a customer call and complain about these bugs takes up tech support time and customer time. Tech support time can be cheap unless you have a huge product and receive hundreds of calls a day. Annoyed customer time is a different story. They may get trapped in a long call queue and become progressively more annoyed as time goes on. They were annoyed enough to call in the first place and then they got more annoyed when they had to wait. A customer is not going to drop a product because of minor errors. But they will drop a product if they find too many bugs and thats part of customer churn. Now its expensive.

Tech support lines educate customers as well as improve the product. Tech support staff can log a lot of bugs, the good ones are those that detect an edge case problem such as a crash if you pull up three dialogs in a certain order and drop in a URL in one of the fields. That’s a good bug to fix. Other calls will be about security flaws or other bugs that really improve the product. These are really valuable times for tech support to be there.

Customers will always find bugs. Software is too complex for them not to. What kind of bugs do you want them to call about?

Tuesday, January 8, 2008

The Urge To Jump To Conclusions

I’m sitting on my couch with a huge headache, the results of a cold or flu or a tumor or something. Its not going away anytime soon so I figured I would type until the pain medication kicks in. Thats about 20 minutes form now, I hope.

I was thinking about a recent conversation where a friend asked me to look at some code. He was pissed because it looked really complex and added nothing. He felt is was just adding a lot of new declarations and complexity that made no sense. So he made a brief rant and then showed me the code.

For a moment I was perplexed by what I was seeing. My eyes went to a clause in the declaration of a Java class and it looked pretty ugly. It had lots of greater-than and less-than symbols and stretched across a few lines of code. At first I thought that there was almost certainly someone over-engineering.

And then I looked again and realized that the original developer was actually being rather smart about his declarations and type safety. The original developer was doing something like the following example:


// Abstract Base Classes

public abstract class Animal<S extends FoodPreferences, T extends ForagingBehavior<S> >

{

S foodPreferences;

T foragingBehavior;

public S getFoodPreferences()

{

return foodPreferences;

}

public void setFoodPreferences(S foodPreferences)

{

this.foodPreferences = foodPreferences;

}

public T getForagingBehavior()

{

return foragingBehavior;

}

public void setForagingBehavior(T foragingBehavior)

{

this.foragingBehavior = foragingBehavior;

}

public abstract void forage();

}


public class FoodPreferences

{


}


public class ForagingBehavior<S extends FoodPreferences>

{

S foodPreferences;


public S getFoodPreferences()

{

return foodPreferences;

}


public void setFoodPreferences(S foodPreferences)

{

this.foodPreferences = foodPreferences;

}

}


// Concrete Implementations

public class WombatFoodPreferences extends FoodPreferences

{

public boolean wantsFruit(){ return true;};

}


public class WombatForagingBehavior<S extends WombatFoodPreferences> extends ForagingBehavior<S>

{


}


public class Wombat extends Animal<WombatFoodPreferences, WombatForagingBehavior<WombatFoodPreferences>>

{

public void forage()

{

// concrete implementation

// Note: no casting to the concrete type

this.getFoodPreferences().wantsFruit();

}

}

There is some pretty heavy use of Java generics here. It works surprisingly well, but you do have to look at it carefully to understand what is happening. This example uses generics to define common classes that can have data types on relevant to the concrete implementation. This is really useful when you have a lot of different children off a common parent class. They all have shared data types and such, but those data types may also be very tightly tied to the child class. The use of generics in this case allow you to generically associate concrete child types without adding a lot of casting and type checking at run time.

This kind of code looks bad at first and then you realize that it actually simplifies the code in a single swipe. First, it eliminates a lot of casting that always makes code harder to read. Second, it ensures type safety. The original developer did a really good job of cleaning up some complex code. I sent the original developer en email telling him that too.

I then spent 5 minutes explaining what was going on and my friend responded with “Oh, that’s really good.” A grand total of ten minutes of conversation and a good developer’s code went from bad to great.

Ada Does Not Make The Engineer Of Tomorrow

I read Computer Science Education: Where Are the Software Engineers of Tomorrow? and had a hard time not chuckling through the document. Its main issue is that Java is a bad first programming language to learn and that developers aren’t as good as they used to be as a result. They argue that C, C++, Lisp and Ada are better places to start. Ada is the one that made me blink until I realized that these guys founded AdaCore, an IDE for Ada.

I agree that learning C and C++ is valuable for pretty much every software developer. A subset will find Lisp useful too. And I am sure that a few guys out there will marvel at the perfection of Ada, which continues to be a huge commercial success. If you want to earn a living and be able to choose from a wide pool of employers, then you are better off learning Java, C++ and C#.

I strongly believe that C and C++ are fun languages. You can write device drivers, kernels, video games, embedded software and high performance software. You can also allocate all available memory, exceed the boundaries of a memory allocation, point your pointers at the completely wrong thing and fault the operating system. You can write very powerful and complex applications that fully take advantage of the target platform. Its a lot of fun, challenging and I like it a lot.

Java is my language of choice. I am a web application developer. I have a lot of job opportunities and I work on interesting things too. Java provides a good framework for building an application on one platform and deploying it to another while providing a rich set of services that let me do my job quickly.

Small software companies generally cannot afford to teach recent graduates a new language. You have to know the language well enough to start producing usable code within a few days of starting. Some languages are worth the exercise and others just take up a portion of your life that you hope to forget.

Here are a few survey results of programming language use in the corporate world. They are in no particular order of which is more valuable than another.

These surveys say that employers still look for both high and low level language skills, but especially for the Windows and web development arenas. Languages, like Ada, while interesting may not help you get a job in one of those hot start-ups that can make so many people wealthy. Being strong in multiple languages and carrying the wisdom and the choices of those languages with you is hugely valuable, just be sure that one of them can get you a job when you graduate.

Sunday, January 6, 2008

Anxiety Driven Software Development

Have you ever spent a few days designing something and then asked yourself "is this really a good idea?" Do you have that moment of self doubt and then change your design? Do you do it because you didn't think you could deliver it on time, that it would be too difficult to implement, that it was fundamentally flawed or you didn't like what you were getting yourself into.

I spend a fair amount of time wondering if one of my designs is actually a good idea. A manager once referred to me as a worrier. Of course, the effect of all this worrying is that my code generally works very well. I haven't found all my bugs, but I have tested the feature dozens of times. I fear complex designs and fall back to tried and true methods or prototype and verify that my complex or novel solution will really work.

    // Example 1: Iterating
    void myFunction(List<String> stringList)
    {
        for ( String stringElement: stringList )
        {
            System.out.println( stringElement );
        }
    }

This example seems like a pretty safe piece of code. I only write code like this for examples now. I would look at this code and right away figure that a caller will eventually pass in a null stringList and crash my component. My iteration operations look more like example 2.

    //  Example 2: Iterating
    void myBetterFunction(List<String> stringList)
    {
        if ( stringList != null )
        {
            for ( String stringElement: stringList )
            {
                System.out.println( stringElement );
            }
        }
    }

Adding the if statement is such a trivial change that ensures this code will not crash my application as often. Some people will argue that this is merely a good coding practice. That the check is one of many that should appear in a developer's code. But what motivates me and other developers to add this code? Is it good training, professionalism, the dislike of fixing a dull bug, the fear of looking like a dolt to the rest of the team or something else?

This code is a far too simple example of how anxiety driven software development can benefit a project: good developers write stronger code to avoid simple problems. Algorithmic errors may still remain, but the algorithm will not fail because of an uninitialized parameter.

How do you choose a third-party library? Let's say you have three days to write a very simple user interface with Tomcat running on the server. Do you write you servlet layer using Struts, Tapestry, JSF or something else? Do you choose something you have been reading about or something you know very well? I go back to the library I know the best. I may want to try something new, but I don't know the tricks and traps so I go back to the familiar and ship on time and with a high level of quality. Again, one could argue that the choice of library was dictated by a logical process of elimination. I would argue that my fear of a late delivery dictated that I pick the library I knew best. Given more time I may have read more about other's opinions and write a prototype to verify that a different library will work well.

Fear of failure can be immobilizing. Software development moves far too quickly to allow a developer to become crippled because he is afraid to fail. You can't become immobile because others will simply pass you by. Using your anxieties to your advantage means that you advance along the path that is simplest and most proven. You don't need to worry that you'll get a dumb bug because you bullet-proofed your code. You don't have to worry that you picked the wrong UI library because you have used Tapestry in three other projects and you are rock solid. Instead, you choose the safe bet and code the project.

The risk is that you always go back to your safe bets rather than trying anything new. Writing great software requires taking risks. Riskier code often teaches far more than tried and true code. The reason is fairly obvious: tried and true code has been documented to death, there is nothing new or interesting to learn. Riskier code, like using a new design pattern or library, is an opportunity to try something different and grow. Knowing when to go safe vs new is a difficult problem.

Balancing new vs safe code is a skill. I usually go with safe code when I have very little time to implement a given thing or when I am doing the design work and the implementation will be turned over to significantly junior developers. The vision and spirit of a design is often difficult to impart in documentation. It requires some hands-on work by its creator to really drive home how it should operate. However, you don't always have the time to impart that vision sufficiently when turning over a design to a different team. Its their job to go off and do the implementation and so without the oversight or lots of communication then it is likely that their implementation and your vision will diverge. The divergence could be good if they figured out a few improvements or detrimental if they missed the point entirely. You just can't tell which way it is going to go, so safer code is better.

Novel code is best done when there is plenty of time to prove the concept out in a prototype. If you can't do a prototype then be sure to add time to the schedule for you to get the implementation right. That maybe one or two days depending on the design, but definitely add some room to the schedule.

On-line research is a very useful tool in the balancing act too. I often google for other people's impressions of using a pattern or a library. I often like following the herd. For example, I would rather use a library that has thousands of user, a forum and been around for a few years. Especially if I am going to be highly dependant on that library for a large amount of functionality. I am more willing to try a really new library for something small and isolated- easy to remove later.

Getting the opinions of friends, colleagues and managers is a good idea too. You will almost always find some strong opinions on nearly every technology. It also brings them into the design process earlier and gives you a feel for the ideas that will resonate with them in the design review. Having a lively discourse at a design review is good, but it isn't helpful if people are fundamentally opposed to certain approaches. Knowing this early in the design process is incredibly useful.

Setting expectations is the last aspect I will mention today. Its a good idea to brace people for why you chose to do something. I would rather tell my manager that I am doing something risky and pitch the benefits than say nothing. If you think that something is difficult, then say it is difficult so it isn't a shock if the schedule slips. If it is easy, then say it is easy. The effect is that the manager can trust your judgments and you can be trusted with more complex and interesting projects.

I worked with a really nice engineer awhile back. Everybody loved the guy, including me. The thing was that every time we had to do anything (write code, do a build, setup a new machine) he would just shake his head and start to moan about how it couldn't work because the machine was too small, there wasn't enough time, the code was too complex, the code didn't cover all the possible problems, it takes too long to build, we're all going to die but it really doesn't matter because eventually the sun will expand and scorch our entire planet right off the universe and no one will know that we ever existed. Ok, the last one I made up, but you get the picture. He made it harder on himself because he believed that everything was going to fail and he said it to management every day. Yet the company continued to succeed and grow even though we were faced with constant doom. His opinions were discounted until they became a kind of constant background noise. The point is that setting expectations must be done in a positive and objective way so that people listen to you when you have found serious issues.

Anxiety driven software development is a conservative decision tree. If there is plenty of time, try something risky after researching carefully other developer's experiences and prototyping if possible. If there is little time, go to the thing you have the most experience with so that the job can get done on time. Go with simpler designs when creating a design that you will not be involved in overseeing or implementing. Listen to your team, they have good ideas. Finally, set expectations objectively describing the risks and benefits to an implementation or design.

Remember that taking risks is necessary. You can't get anywhere or do anything new if you don't take risks. Taking foolish risks though is what kills a development cycle. Balance is the key.

I'll leave you with two quotes:

The pessimist sees difficulty in every opportunity. The optimist sees the opportunity in every difficulty.

- Winston Churchill

Great things are not done by impulse but by a series of small things brought together

- Vincent Van Gogh

Thursday, January 3, 2008

Ext Event Handling

Just about all applications are event driven in one way or another. Click on a button in a Windows application and Windows will generate a message and dispatch it off to the main window handler and that will dispatch the message to another handler until something processes the event or returns it to the OS.


Web applications are event driven in a similar sort of way where the DOM defines events, like click, and event handlers. Ext extends the DOM event model through the Ext.util.Observable class. This class exposes three different ways of attaching event listeners and we'll go over all of them. We'll also talk about how some classes add shortcuts for defining specific kinds of events too.


There are three common ways to add a listener. The first is at the time of the object's creation through the listener configuration option. Its an array of event names with listener functions or listener configurations.


// Example 1: Simple Listener

function clickListener(){

alert ( 'Click listener called' );

}


new Ext.Button({

text: 'Click Me',

listeners:{

click: clickListener

}

}).render(document.body, 'example-1');


// Example 1a: Listener configuration

function clickListener2(){

alert ( 'Click listener2 called' );

}


new Ext.Button({

text: 'Click Me Too',

listeners:{

click: {

fn: clickListener2,

scope: this

}

}

}).render(document.body, 'example-1a');


Both examples bind an event listener to a button. The first example binds a listener function directly to an event. The second example binds a listener configuration to an event. Note the scope member lets you set the scope of the operation and that proves very handy for applications that use classes. You can bind event listeners after creation too. The addListener and on methods perform post creation listener binding.


// Example 2: Post creation event listeners

function clickListener3(){

alert ( 'Click listener3a called' );

}


function nextClickListener3(){

alert ( 'Click listener3b called' );

}


var button = new Ext.Button({

text: 'Click Me Now!'

});

button.addListener('click', clickListener3);

button.on('click', nextClickListener3);

button.render(document.body, 'example-2');


Something that I find interesting in this example is that you can chain event handlers. Both clickListener3 and nextClickListener3 will get called when the user clicks the button. This is pretty handy when you have several components working independently from each other but share a common starting point, like a button. Some objects have shortcuts for attaching event handlers. The button class has a configuration option for a handler. It also has a setHandler method for post-creation event binding.


// Example 3: handlers

function clickHandler(){

alert ( 'Click handler called' );

}


new Ext.Button({

text: 'Click Me w/handler',

handler: clickHandler

}).render(document.body, 'example-3');


The downside to using a shortcut is that you have to check the documentation to see which event activates your handler. I am inclined to use the verbose method (configuration, addListener or on) because it is always clear where a handler is bound. You can also create custom events and their handlers.



// Example 4: Custom Events

function firstClickHandler(){

alert ( 'firstClickHandler called' );

button2.fireEvent("customEvent");

}


function customEventHandler(){

alert ( 'customEventHandler called' );

}


var button2 = new Ext.Button({

text: 'Custom Event Button'

});


button2.addEvents( {"customEvent":true} );

button2.addListener('click', firstClickHandler);

button2.addListener('customEvent', customEventHandler);

button2.render(document.body, 'example-4');


We have two event handlers: the first to handle the click and the second to handle a custom even. We then fire the custom event when the click handler executes. The example shows how to create a new event type and how to fire it. A more real world example would be if you had several controls that needed to be updated when another control has changed as a result of a user. The originating component could be written to modify the values of the other controls, but this would require the originating control to understand the behavior of the dependent controls. This kind of code would couple the dependent control's behaviors with the originating control. It would be confusing and harder to maintain, especially if there were many dependent controls.


An alternative would be to expose a new event type in the originating control. Then add a fireEvent call to the originating control's event handler for a state change. Finally, have the dependent controls call the originating control's addListener (or on) method and register for the new event type. The dependent controls each implement an event handler for the new originating control's event. The resulting event handler is written to implement the specific behavior of the single dependent control. The benefit to this scheme is that many developers can work in a single UI and be dependent on the same originating UI control, yet not be stepping on each other since they are basically writing independently from one another.


// Example 5: Multiple dependent observer controls

// initialize the originating control

var button3 = new Ext.Button({

text: 'Custom Event Button'

});


button3.addEvents( {"stateChangeEvent":true} );


function originatingStateChangeEvent(){

alert ( 'originatingStateChangeEvent called' );

button3.fireEvent("stateChangeEvent");

}


button3.addListener('click', originatingStateChangeEvent);

// originating control code complete


// first dependent control

var dependentControl = /* some control type */

dependentControl.changeEventHandler =

function (){

alert ( 'changeEventHandler called' );

// code to update first dependentControl

};


button3.addListener('stateChangeEvent',

dependentControl.changeEventHandler,

dependentControl);


// second dependent control

var dependentControl2 = /* some control type */

dependentControl2.changeEventHandler =

function (){

alert ( 'changeEventHandler 2 called' );

// code to update first dependentControl2

};


button3.addListener('stateChangeEvent',

dependentControl2.changeEventHandler,

dependentControl2);


// etc

button3.render(document.body, 'example-5');


My final example shows how to pass additional parameters when firing an event. The fireEvent method is called with the event, a scope and any additional parameters I want to publish.


// Example 6: Custom Events

function firstClickHandlerParam(){

alert ( 'firstClickHandlerParam called' );

button4.fireEvent("customEvent", button4, 'some value');

}


function customEventHandlerParam(scope, p1){

alert ( 'customEventHandler called with: ' + p1 );

}


var button4 = new Ext.Button({

text: 'Custom Event Button with Param'

});


button4.addEvents( {"customEvent":true} );


button4.addListener('click', firstClickHandlerParam);

button4.addListener('customEvent', customEventHandlerParam);

button4.render(document.body, 'example-6');


Removing a listener is just as simple as adding one. You call either the un or removeListener method.


The event handling and dispatching system in Ext is easy for a developer to hook into. It doesn't take anytime to integrate with and its a breeze to extend. Happy coding!

Tuesday, January 1, 2008

Why I am doing this and Ext

I was ready to write about anxiety driven software development. Its a notion where you think about all the ways your application will fail before you write your first line of code. It was packed with pithy insights on bullet-proofing code and using class hierarchies to ensure that you get really solid code that future well-meaning developers cannot unravel. It was going great until I realized that it just made me sound neurotic.


I started writing this blog because I, like everyone else in the software development world, has an opinion on how to write great code and build amazing web applications. I’ll churn out the occasionally interesting blog about some way to improve code or to keep things from getting worse. I’ll also write about a javascript library that I’m finding more useful each day: Ext. That makes me sounds less neurotic than writing about my anxieties.


In March of 2007 I started a project to test a few theories about javascript and PHP. I spend most of my time writing Java code running on Tomcat and JBoss and the project was a good chance to try something different. The application had a lot of javascript and CSS. I found that the PHP code was relatively small compared to the endless amount of javascript I was writing to implement dialog boxes, grid controls and trees.


My javascript started with Prototype 1.4 , then Dojo 0.4, JQuery, Prototype 1.5, Dojo 0.9, Prototype 1.6 and then settled on Ext 2.0. I kept cycling around because my application needed controls that the library either didn’t provide, and I had to write my own, or the library had the control and then I had to write enormous amounts of code to get simple stuff to work. Ext became a godsend because almost everything was straightforward and I could customize it without having to go really deep into the library’s code nor write a lot of code to get it to work. It took me a matter of weeks to wrap up my first project with Ext. I used it in a second project with a far more elaborate user interface and had it pretty much done in a couple of weeks too. I am still surprised.


The Ext documentation is not as great as one would hope and so I figured it would be helpful to document some of the things I have experienced. With that, let there be Ext musings!