Archive for August 2004
Oh, well, count me in into the critics’ crowd. Microsoft.com had redesigned its home page. As Douglas Bowman at Stopdesign notes, this is a step in the right direction. It looks like a lot of work has been done in “de-cluttering” the page and organizing links in clusters — I smell a card-sort or two. As the page layout got simpler, the usability has improved as well — gone are the drop-downs, the concept of audience silos is much better articulated, the home page is full of links, yet the design keeps it “breathy“ and legible. The page loads quickly and conveys a nice tactile feel, inviting further site exploration. Good job on that — it takes a lot of effort to make something as complex as Microsoft Web presence seem so simple and straightforward.
Things are less sunny under the hood. While Douglas praises the improvement (and I join him on that), I’d like to keep the developers focused on things that still need to be fixed (in no particular order and probably incomplete):
- Please eliminate obvious markup errors, such as lack of DOCTYPE declaration, nesting block elements inside inline elements, atavisms such as WBR, etc. Strive to make the page at least XHTML 1.0 Transitional compliant. It’s not that hard.
- Consider removing tables altogether. This is not a very complex layout, you don’t really need them.
- Move your inline style declarations into a separate stylesheet. Having some styles inline and some in the stylesheet is a maintenance nightmare.
- Speaking of CSS styles, clean that up, too: there are some obvious errors, such as unitless padding and margin declarations, and even just plain misspelled elements (xheight).
- Consider organizing ALL of your lists of links into… er, lists, using ul and li elements. Perfect candidate – your bottom navigation bar: semantically, vertical bars that separate links have no meaning. Therefore, they shouldn’t be in your markup.
- Subsections in main content area — “Popular Downloads“, “Popular Destinations“, etc. look pretty as graphics, but do they really need to be? I would suggest replacing them with list items as well. If you’d like to retain the “prettiness“, use one of the image replacement techniques.
- Finally, let’s remove CSS filters (gradients up at the top) on the home page of your site. Why? Because there’s really no reason for it. Your page has a fixed-width layout and replacing the IE-only gradient with a background image will go a long way in making your site look the same on all browsers.
Your Web site’s home page is your company’s face. In your case, the importance of keeping that face well-shaven is critical. If your company made toasters or lightbulbs, I would probably not care as much about the quality of HTML/CSS code. However, given that Microsoft produces world-dominant browser and world-class Web development tools, and how much flak Microsoft takes on a daily basis in regards to Web standards support, a squeaky clean markup of the home page is a foundational practice that has as much marketing and evangelist power as a dozen of boisterous dudes in MSDN t-shirts — at a fraction of the cost.
In my fairly short experience with blogging, I’ve noticed one thing about these new creatures of the Web: they are both connecting and isolating. The are connecting in the sense that anyone can read your stuff and attach their opinions about it, but they are also isolating, because your stuff typically sits in its own blog silo, all alone until some aggregating service graciously decides to let your posts socially mingle with the others. Folks over at weblogs.asp.net and other blog-hosting establishments have this advantage in the form of the front page feed, but what about the rest of us?
Also, the blogs are horrible for sustaining an online conversation: the comments are given such a third-world status that they are easily lost in contrast with the main post. As a solution, bloggers use pingbacks, but those are hard to track navigationally, taking some time to reconstruct the original flow of discussing. Take our recent exchange with Bertrand, Nikhil, and Peter for example. All three of us posted our own posts in our own blogs, and responded in comments of the others’ posts, which created a fairly messy pool of opinions with hard-to-discern direction or conclusion (of course, you know that in this case Nikihl gets the final word, so backtracking might help .
Wouldn’t it be great if there was a way to organize these posts into a forum-like threaded discussion?
Enter coblog: a way to bring blogs together — as needed.
Imagine that at the time of entering the post, you can designate it as the coblog root. Coblog root looks and acts just like an ordinary post, except maybe it has a “coblog” icon next to it (or some other visual hint of this sort).
Suppose your (friend|colleague), after reading your insightful (prose|poem), gets all (upset|excited|riled-up|flabbergasted) and decides to open a discussion on the topic of your post.
At this point, this (great|well-known|total-nobody) acquaintance of yours opens their blog and writes up a (heated|supportive|contemplative) response to your original post. At the end, (he|she) specifies that this is not an ordinary post, but a coblog post.
Coblog post requires a URL to the coblog root or any other coblog post. Using this URL, your buddy’s blog server determines location of the coblog root and sends it a TrackBack to notify of the new post in the coblog.
Instead of (or maybe in addition to) just sending a URL of the actual post in the TrackBack, the server sends the feed URL for all coblog posts that correspond to the specified coblog root on this server. Think of it as a variation on a category feed.
Upon receiving a TrackBack, the coblog host (the server which hosts the coblog root) adds the URL, sent with the TrackBack, to the coblog roll. There may be some moderation functionality in place (no, I don’t accept coblog feed from “MaskedBandit34252” — sorry, you look like a spammer to me) to prevent any server from being able to feed any posts to your coblog.
Coblog roll serves as a list of all potential sources of posts for the coblog. Each coblog root has its own coblog roll.
All of the coblog posts, including the coblog root, will be available as part of the aggregated feed, which always originates from the coblog host.
Now, after the discussion had started, both your and your comrade’s blogs will prominently feature a link to the coblog in the (sidebar|top bar|inconspicuous drop-down menu) of your home page. Clicking on this link will reveal the discussion as a chronological list of coblog posts, starting from the coblog root. Those participants who don’t have their own blogs could use comments as usual.
Naturally, coblogs should not be limited to just two people. The purpose of the coblogs is to facilitate discussion, and a good discussion often takes more than two (voices|flames).
So, what do you think? This is just a concept, but I think it has a pretty good promise.
Between the two, Ian Griffiths and Phil Haack have some good info on coding for multithreading. Developing multithreaded applications is hard. It takes experience, which comes in most painful forms of debugging and learning from engineering mistakes — unless you are a multithreading genius who sports a built-in support of multitasking and thread modeling directly in the brain.
Otherwise, every little bit of information helps. Here’s my contribution:
- If you haven’t started coding yet, please spend some time at the whiteboard, modeling your threads and locks. No need to dive into a UML book — simple lines and arrows will suffice. Try to understand when a resource needs locking along the timeline, what possibilities are there for deadlocks and racing conditions. Multiple threads can be easily expressed in two dimensions — the easiest one is a graph where one axis is relative timeline and the other is application scope (local, thread, application, persisted data). Traverse your application data through it and study any point where it deeps below the application scope. There are more elaborate methods of engineering and modeling multithreaded applications, but if you’ve got nothing to begin with, the whiteboard is your best friend.
- If you are dealing with existing code that is not thread-safe, definitely do try replacing your “lock“ statements with Phil’s TimedLock to trace potential deadlocks. You will still suffer extensive debugging therapy, but the TimedLock pill will help a little.
- When writing a type that has to be thread-safe, pay very close attention to every member and how it is used. Consider marking those members that aren’t changed through the lifespan of the instance as “readonly“. This is not going to affect your performance, but will help you organize your type’s members into mutable and immutable piles.
- Speaking of Immutable — this is a good pattern to use as far as thread safety is concerned. It may or may not apply to your scenarios, but should be considered when dealing with types, especially as a complement to Memento and State patterns.
- Just one more on patterns — Proxy is a good way to encapsulate thread-safe access to data that is known to be continually updated.
- Be twice as careful when writing a type that is instantiated statically. Some people mistakenly assume that once they’ve accomplished the feat of thread-safe instantiation, they are out of the woods. Just the opposite — static instances are the marked men of the “racing condition police“.
- Post-constructor initialization of a static member is a bad smell as far as thread safety is concerned. It may be required to implement it in certain circumstances, but should be avoided at all costs.
- Lazy instantiation is not something you apply blindly to any type — it may not save you much performance or memory, but it will make your architecture more complex. If you have to do lazy instantiation, try to use the lockless static instantiation (fifth version on the referenced page).
- According to latest and greatest, just a simple double-lock is not enough. MemoryBarrier is required to ensure correct order of null comparisons.
- Try to be conscious about where and why you place a lock — and what kind of a lock is it. Generally, you’ll either use a Monitor lock (or the lock statement) or the ReaderWriterLock. Ian warns of being too liberal with the use of ReaderWriterLock. Don’t just place a “lock brace“ around your whole method, although you may be tempted to. The longer is the body of the lock, there more possibilities there are that there are other methods and type instances called in that body, and thus the more possibilities there are for a deadlock.
- Just because the method is documented as “thread-safe“ in .NET Reference doesn’t mean that you can’t use it in a non-thread-safe way.
- And last, but not least — make sure you test and debug your multi-threaded application on at least a dual-processor machine.
Like I mentioned before, multithreaded programming is not an easy task. Hopefully, these tips will help you in your exploration of .NET’s and your own potential of enterprise application development.
Let me first start by saying that ASP.NET is an awesome framework. It is now my primary development platform and it is a joy to work with. It brings to the table something that is not built-in in most of the scripting platforms — a pattern-driven development paradigm, based on “Page Controller” pattern, mentioned in Martin Fowler’s “Patterns of Enterprise Application Architecture” book.
Unfortunately, not all is well in the current (ASP.NET 1.1) model. One of framework’s most significant problems is that the rendering of a control is tightly bound to its implementation (I first mentioned this in one of my earlier posts). In my book, mashing functionality and presentation together is never a good thing. While the initial results may end up looking shnazzy and easy to slap together, the long-term liability of not following the rules will sooner or later catch up with you.
The way Controls are implemented, Render is one of the methods of the control, encouraging (forcing sometimes) developers to embed HTML and CSS code into the actual controls.
Now, from the designer perspective, this effectively shreds the HTML output into a number of small nuggets that are hard-coded into each of the controls. With proliferation of third-party controls, the control of look and feel of the site is placed firmly into the developer’s hands, leaving designer with only maybe a banner and a footer to play. That’s not a very good proposition.
As any good book on Web process methodology would suggest, there are many roles involved in the process of building a site. If you work for a large company that means that you have a team of people working on the project. If you are working alone, that means you have to wear many hats. It does not mean that you have to forego those roles and just hack your site together.
He who wears the developer hat should not be concerned whether the box corners are rounded. He who wears the designer hat should not be concerned whether the box with rounded corners is a control or just a literal markup, emitted by a larger control.
Whidbey made a few good steps forward with the introduction of Themes, but from what I understand, the Themes stop short by simply being a CSS style manager, not a way to manage the actual markup rendering of controls.
Then there is a new layer of abstraction for rendering in the form of Adapters, but they are somewhat locked into a special case of browser/browsing device support. I also have doubts that Adapters will be powerful enough for site of any reasonable complexity without the support of more flexible control selectors.
This maybe too late for ASP.NET 2.0, but if I were developing the next iteration of the framework, I would do the following (this is a first stab, just trying to give a sense of direction):
- Elevate Adapters to the full-citizen status by making them the de facto rendering layer for controls (not just the “special“ case rendering)
- Integrate Themes and Adapters so that the markup can be controled completely by a Theme.
- Take the .skin files out of the theme and into its own Skin category — skins control how a Theme applies to a particular application. In effect, themes become truly interchangeable. Talk about an ISV market potential here!
- Provide more flexible (maybe even CSS2-style) selectors for Skin controls.
- Develop several built-in Themes for the developers.
- Split the current development surface of Visual Studio (the “design“ view) into three views along the lines of Web process roles.
- The first new development surface will be the “proto form“ view, for developers. You can drag and drop controls on this surface, arrange their order and parameters, but not the visual style.
- The second development surface will be the designer view, which would allow designers to visually develop application skins (basically, connect Theme elements to actual controls in the application).
- The third development surface will concentrate on the actual development of Themes and be focused toward more advanced developers.
By creating a well-defined layer of abstraction for rendering, the framework would create a more organized and process-oriented approach to Web application development and most importantly, a way to affect the look and feel of your application without having to change its code.
What’s interesting, if all of this is in place, the development paradigm will not become more complex for beginners and Mort users — it will actually be easier. Instead of tweaking the colors on each individual controls, they would have capability to paint their application with large brush strokes, using themes. And if they want to re-paint — just find another theme, pick out cool gadgety thingies that blink and roll, and brush away.