﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Brian Sun @ 爬树的泡泡-文章分类-软件</title><link>http://www.blogjava.net/briansun/category/439.html</link><description>&lt;marquee direction="down" scrollamount=4 height="120" align="right"&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/09/03/11884.html"&gt;关于洞穴寓言的几部电影&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/08/31/11634.html"&gt;关于AOP的七个猜想&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/07/31/8813.html"&gt;测试驱动开发全功略&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/07/21/8095.html"&gt;体验经济在软件&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/07/20/8028.html"&gt;NXUnit 中文说明&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/07/15/7765.html"&gt;发表我自己的开源软件&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/04/16/3336.html"&gt;4月16日评点IBM&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/04/04/2808.html"&gt;4月4日评点Google&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/27/2505.html"&gt;3月27日评点版权制度&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/21/2274.html"&gt;天下归一，谈EclipseCon2005&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/20/2270.html"&gt;软件标准的生命周期&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/18/2205.html"&gt;2005年度Jolt大奖&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/14/2067.html"&gt;3月14日评点Microsoft Office&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/14/2063.html"&gt;3月14日评点OMG&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/12/1963.html"&gt;关于UI的不同解释&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/07/1786.html"&gt;非理智的抗议，只为JDO&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/03/01/1597.html"&gt;关于ERP的未来&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/02/27/1534.html"&gt;有没有可能以开源软件为平台建构ERP？&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/02/26/1518.html"&gt;UI框架的组织模式&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.blogjava.net/briansun/archive/2005/02/19/1321.html"&gt;关于人工智能&lt;/a&gt;&lt;br&gt;
&lt;/marquee&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:26:43 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:26:43 GMT</pubDate><ttl>60</ttl><item><title>On Plug-ins and Extensible Architecture[转]</title><link>http://www.blogjava.net/briansun/articles/3148.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Mon, 11 Apr 2005 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/3148.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/3148.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/3148.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/3148.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/3148.html</trackback:ping><description><![CDATA[


<!-- start top nav-->
<h2>On Plug-ins and Extensible Architecture</h2>

<span class="small"><br>
From <a href="http://www.acmqueue.org/modules.php?name=Content&amp;pa=list_pages_issues&amp;issue_id=21">Software Updates</a><br> &nbsp; &nbsp; &nbsp; Vol. 3, No. 2 - March 2005</span>
<br>
<span class="content"><b><i>by Dorian Birsan, Eclipse</i></b></span><br>
<p>In
a world of increasingly complex computing requirements, we as software
developers are continually searching for that ultimate, universal
architecture that allows us to productively develop high-quality
applications. This quest has led to the adoption of many new
abstractions and tools. Some of the most promising recent developments
are the new pure plug-in architectures. </p>
<p>
What began as a callback mechanism to extend an application has become
the very foundation of applications themselves. Plug-ins are no longer
just add-ons to applications; today’s applications are made entirely of
plug-ins. This field has matured quite a bit in the past few years,
with significant contributions from a number of successful projects. </p>
<p>
This article identifies some of the concepts around the foundation of
pure plug-in architectures and how they affect various stakeholders
when taking a plug-in approach. The intention is to discuss the general
issues involved, but the article also presents some lessons learned
from Eclipse (www.eclipse.org) to better illustrate some of the
concepts. </p>


<h4> MOTIVATION FOR PLUG-INS</h4>

<p>
Customers’ requirements control the creation and deployment of
software. Customers demand more and better functionality, they want it
tailored to their needs, and they want it “yesterday.” Very often,
large shops prefer to develop their own in-house add-ons, or tweak and
replace existing functions. Nobody wants to reinvent the wheel, but
rather to integrate and build on existing work, by writing only the
specialized code that differentiates them from their competition. Newer
enterprise-class application suites consist of smaller stand-alone
products that must be integrated to produce the expected higher-level
functions and, at the same time, offer a consistent user experience.
The ability to respond quickly to rapid changes in requirements,
upgradeability, and support for integrating
other vendors’ components at any time all create an additional push for
flexible and extensible applications.</p>
Down in the trenches, developers must deal with complex
infrastructures, tools, and code. The last thing they need is to apply
more duct tape to an already complex code base, so that marketing can
sell the product with a straight face.
The new plug-in architectures are very attractive to developers because
they can focus on providing modular functionality to users. Anyone can
quickly customize
applications by mixing and matching the plug-ins they need, or write
new plug-ins for missing functions. The price to pay for such
flexibility is managing these plug-ins. We discuss this and other
issues later in the article, and you can decide if it is worth the
price.

<h4> TRADITIONAL PLUG-INS VERSUS PURE PLUG-INS</h4>

<p>
Most people are familiar with traditional plug-ins, downloadable
software bundles that extend the functionality of hosting applications
such as Web browsers or
text and graphical editors. They are not compiled into the application,
but linked via well-defined interfaces and extension mechanisms. Most
often, building a plug-in does not require access to the source code of
the application. Plug-ins implement functions that the host application
can recognize and activate when needed.</p>
<p>
In the new pure plug-in architectures, everything is a plug-in. The
role of the hosting application is reduced to a runtime engine for
running plug-ins, with no inherent end-user functionality. Without a
directive hosting application, what is left is a universe of federated
plug-ins, all playing by the rules of engagement defined by the
framework and/or by the plug-ins themselves. </p>
<p>
To support composing a larger system that is not prestructured, or to
extend it in ways you don’t foresee, the architecture must support the
extensibility
of plug-ins by plug-ins. In the absence of a hosting application,
plug-ins themselves become hosts to other plug-ins by providing
well-defined hook points where other
plug-ins can add functionality. These hook points are commonly known as
extension points. When a plug-in contributes an implementation for an
extension point,
we say that it adds an extension. Much like defining any contractual
obligation, an extension model provides a structured way for plug-ins
to describe the ways
they can be extended and for client plug-ins to describe the extensions
they supply.</p>

<p> In a simplified way, figure 1 illustrates the main structural difference between
traditional and pure plug-in architectures.</p>


<p>
<a href="http://www.acmqueue.org/figures/issue021/birsan_1.jpg">Click for figure</a>
</p>


<!--pagebreak-->

<h4> PLUG-IN RUNTIME CONSIDERATIONS</h4>

<p>
As already mentioned, plug-ins are not stand-alone programs; their
execution is orchestrated by a runtime engine. The plug-in runtime
engine—let’s
call it the kernel—is the core engine that is started when a user
launches an application. At a minimum, the kernel must provide runtime
support for the basic plug-in infrastructure by:
</p>

<ul>
<li>Finding, loading, and running the right plug-in code.</li><li>Maintaining a registry of installed plug-ins and the functions they provide.</li><li>Managing the plug-in extension model and inter-plug-in dependencies.</li>
</ul>

<p>Optionally, the kernel can supply other utility services, such as
logging, tracing, or security. The user should also be able to turn off
or remove parts of the application, or dynamically install new
functions. For obvious reasons, it is desirable for the kernel to be
small and simple, yet robust enough to build industrial-strength
functionality on top of it, without many (or any) hacks. </p>
<p>
To illustrate the basic workings of a plug-in environment, let’s take a
behind-the-scenes look at the Eclipse plug-in runtime structure and
control flow. While mostly known as a powerful Java integrated
development environment,
Eclipse is actually a universal plug-in architecture for creating
“anything, but nothing in particular.” The runtime engine itself is
implemented as a number of core plug-ins, except for a tiny bootstrap
code. This code starts
the core plug-ins to initialize the plug-in registry and the extension
model and to resolve plug-in dependencies. Other than the core
plug-ins, no other plug-in code is run at this time. All the needed
plug-in metadata is read from
the plug-in manifest files (plugin.xml and/or manifest.mf).</p>
<p>
Once the initialization is complete, the runtime kernel is ready to run
applications. The extension mechanism, shown in figure 2, kicks in and
an entire application is built progressively, from inside out, as
follows: </p>


<ol>
<li>The runtime core plug-in defines an applications extension point so
that any plug-in can declare itself an application by contributing an
extension to it. </li><li>An applications extension must provide a concrete implementation
for the extension point’s callback interface, IPlatformRunnable.</li><li>Eclipse’s default applications extension is contributed by the IDE
plug-in, by providing a concrete implementation class that, when called
by the
extension point handling code, creates the workbench graphical user
interface and runs the event loop until it exits.</li>
</ol>


<p>
<a href="http://www.acmqueue.org/figures/issue021/birsan_2.jpg">Click for figure</a>
</p>


<p>
This workbench window looks like any standard application: it has
menus, toolbars, views, and editors, and you can launch wizards, open
preference dialogs, and so on. The basic workbench by itself, however,
is just a frame for displaying visual parts and other user interface
elements. Its power comes from the extension points (e.g., views,
wizards, editors, action sets, help support) it defines,
to which other plug-ins, or the workbench plug-in itself, can
contribute extensions.
</p>
<p>In general, the plug-in that defines an extension point is
responsible for looking up its extenders (using the extension
registry), instantiating the associated
callback class, and invoking the appropriate interface methods. Under
the covers, the runtime kernel is responsible for providing the
extension registry lookup
functionality, creating a class loader for the extender plug-in,
loading it, and starting it. This ensures the extender plug-in is
initialized and active before its classes are created and run.</p>
<p>
Finally, it is worth noting that some extension points may require more
than one callback interface and others do not require any. For example,
the help system extension point toc is used for contributing
documentation tables of
contents and does not require any callbacks. When help is invoked, the
help plug-in processes the toc extensions by creating a larger,
integrated table of contents from all contributing plug-ins.</p>


<h4> CONFIGURING AND DISCOVERING PLUG-INS</h4>

<p>
An important consideration when deploying a plug-in system is
configuring and discovering the plug-ins. Unlike monolithic
applications that are typically
installed in one folder on a user’s machine, plug-in-based applications
may have a higher degree of freedom for installation layout and plug-in
discovery.
This flexibility can also be a source of major headaches for installers
and plug-in management.
</p>
<p>Consider a multiuser shared installation where the entire
product is installed by the central administrator on behalf of a
community of users. The individual users do not need to perform any
installation. They are simply given a local
“shortcut” to invoke the shared installation (the shortcut can be in
the form of a command-line invocation or a true desktop shortcut
encapsulating
the command-line invocation). If you’re like most users, you will want
to install some other cool new features, especially when the
third-party plug-in
offerings are plentiful (and often free). Obviously, the new plug-ins,
private to that user, cannot be installed in the read-only, shared
install location, so the product should allow users to install and
configure extra plug-ins in
a location where they have more privileges.
</p>
<p>Configuring only a subset of plug-ins for a particular user
based on access criteria, such as user roles, adds more challenges.
Other configuration issues arise in scenarios where a common set of
plug-ins is shared by many applications running on the same machine, or
where some plug-ins are not installed locally but run from a remote
location (e.g., an application server provider).
</p>
<p>In theory, the platform must find the available plug-ins on its
own and gracefully cope with missing plug-ins or those that are
dynamically coming and going. In practice, many solutions for these
problems involve predefined files and directory locations for key
configuration files or for the plug-ins themselves. More advanced
plug-in systems offer pluggable configuration and plug-in discovery
mechanisms.
Usually some basic bootstrap code is run to start a configurator
plug-in, which will then discover the other plug-ins based on its own
strategy. For example,
Eclipse provides an Update Manager configurator plug-in that picks up
plug-ins from the eclipse/plugins folder, as well as from other local
plug-in folders linked from the eclipse/links folder or dynamically
added when users install
new plug-ins to locations of their choice. Because the configurator is
pluggable, anyone can plug in another configurator, which can provision
and configure the
plug-ins from a remote server.</p>


<!--pagebreak-->

<h4> CHALLENGING ISSUES</h4>

<p>
Pressured by time, budgets, or slick marketing claims, you may be
tempted to adopt a pure plug-in architecture without being aware of its
potential pitfalls. Alternatively, you might truly believe in Murphy’s
law and therefore won’t use plug-ins because they’re doomed to fail,
anyway. I tend to follow those who walk the middle road: if something
can fail, then it first should
be understood and then fixed. The rest of the article presents issues
that are likely to pose some challenges when you employ plug-ins, and
that will help you ask questions or provide answers when evaluating a
plug-in architecture.
</p>
<p>
<b>Installing and updating.</b>Many modern products automatically
detect when they are out of date with respect to available service or
product version. Either on start-up, or as a result of an explicit
update action, the products compare
the current installation level against some network-based baseline. The
product then automatically downloads required fixes or upgrades and
applies them, often as part of the product execution. Additionally,
users can, and most often will, install additional plug-ins from
various sources to extend the functionality provided by their current
application.
</p>
<p>For plug-in-based applications, the installation and update
process can be a real nightmare: on the one hand, there are the
traditional installation issues that arise in any application—ability
to roll back changes, migrate existing program data and preferences, or
ensure the installation is not corrupted. On the other hand, because
plug-ins may originate from various providers that are
not related to each other, the resulting configuration has likely never
been tested. This poses a number of interesting challenges that we
address in the context of the other issues discussed in the next
sections.
</p>
<p>
<b>Security.</b>Systems can never be too secure, and you need to pay
particular attention to securing a system based on plug-ins. Since
arbitrary plug-ins can be installed—for example, by downloading them
from the Web—and are allowed unlimited access to the system they plug
into, security in a plug-in environment must be carefully planned. On
top of this, some plug-ins require support for executing custom install
code during installation, so they can have control over some parts of
their installation. To prevent software security accidents or failures,
the plug-in framework must address the issues of downloading from third
parties and controlling a plug-in’s access to other code and data.
Supporting digitally signed plug-ins or secure connections helps, but
it still relies on trusting the download source or the plug-in
provider. Some programming environments, such as Java, offer built-in
runtime security mechanisms that can be used effectively to close some
of the security gaps.
</p>
<p>The cold reality is that, unless you are careful about what you
install, it is almost impossible to be confident that the installed
plug-ins are not ill-intentioned. Of course, a pure plug-in
architecture also means that even a well-intentioned plug-in with
serious bugs can do as much damage as an ill-intentioned one when
installed.
</p>
<p>
<b>Concurrent plug-in version support.</b> Without a doubt, managing
concurrent plug-in versions and dependencies is one of those problems
that can keep architects, developers, and installation folks awake at
night. Most of you have probably
experienced “DLL hell” at some point and will look with suspicion on
something that has the potential of being a “plug-in hell.”
</p>
<p>Any serious plug-in model defines some versioning scheme, but
allowing multiple versions of a plug-in to be concurrently installed
and executed is an issue that must be considered early on in the
design, and it must be properly enforced by the install and update
processes.
</p>
<p>To illustrate the complexity of this area, let’s start by
considering the scenario of an application suite that integrates two
stand-alone plug-in products, each installed in a separate location. It
is possible to have the
same plug-in, at the same version or at different versions, installed
in two locations. The runtime kernel must deal with the two plug-in
instances by either running them both or dropping one. When both
versions are running, and the plug-ins contribute user interface
elements such as menus or preference pages, the result may be a very
confusing interface, with duplicate menu entries or preference
pages. There is more trouble: would the user need to be exposed to this
anomaly? How would you update or uninstall these plug-ins?
</p>
<p>The difficulty of the problem is amplified by the other
important role plug-in versions play here: they are part of plug-in
dependency specifications. Typically, a plug-in requires the
functionality provided by other plug-ins, and very often there are
strict criteria about what versions are required. For example, a
plug-in may require a certain level of an XML parser contributed by
another plug-in, or it may need to contribute an extension to a
particular version of an extension point only. Version dependency can
be in the form of a fixed version number such as 3.0.1, or as a range
of versions—say, 3.0.1 or newer. Properly resolving plug-in
dependencies at runtime is critical to the correct functioning of the
application. Managing plug-in dependency graphs is also critical to
ensure a consistent configuration state after installing or updating
plug-ins, as well
as for properly rolling back changes. The install/update process may
need to abort installation of plug-ins that leads to an unresolved
dependency, or search for and install the missing plug-ins. Either way,
it is possible to end up with multiple versions of the same plug-in, so
we’re back to the problem of managing concurrent versions.</p>


<!--pagebreak-->

<p>
There is no simple, general solution to managing concurrent versions of
plug-ins. Eclipse has adopted a reasonable trade-off convention for
concurrent plug-in versions: only versions of plug-ins that contribute
code libraries but no plug-in extensions (no user interface
contributions, no documentation, and so on) are allowed to coexist in
the same runtime instance. For all the other plug-ins, the latest
version is usually picked up, unless a configuration file precisely
defines what to run. The main advantage of this approach is that it
still allows various levels of the same code to coexist at runtime, but
hidden to the end users, who will get a consistent user interface. The
downside is that this will not cover all user scenarios, and that
plug-ins are not treated uniformly as elsewhere in Eclipse. This
special treatment of plug-ins is not just a runtime/install
issue, but also something that developers and product packagers must
consider.
</p>
<p>
<b>Scalability, up and down.</b> Another challenge of working with
plug-in architectures is scalability. Just as the problems associated
with multiple versions and dependencies can quickly escalate, so too
can the sheer number of interacting plug-ins quickly become a problem.
For example, when Eclipse was first designed, it was thought
that a product, a large one for that matter, would consist of a few
hundred plug-ins. A few releases later, some enterprise-class products
built on Eclipse are known to have passed the thousand plug-in mark, so
the platform goal has
been revisited to support scaling between 5,000 and10,000 plug-ins.
</p>
<p>When designing a plug-in system for scalability, developers
must consider various mechanisms that make start-up faster and have a
smaller memory footprint. A general principle of runtime is that the
end user should not pay a memory or
performance penalty for plug-ins that are installed but not used. A
plug-in can be installed and added to the registry, but the plug-in
will not be activated unless a function provided by the plug-in has
been requested according to the
user’s activity. In general, this requires support for plug-in
declarative functionality. It is often realized in practice via plug-in
manifest files, so no code has to be loaded for obtaining the function
contributed by plug-ins.
Caching of the plug-in registry and the plug-in manifests/declarations
can reduce processing during start-up in subsequent application
launches, improving response
time. What is gained in performance and memory footprint, however, is
lost in code complexity: more code needs to be written to cache the
data and to synchronize the cache with changes in the installation
configuration.
</p>
<p>Scalability problems almost always surface during plug-in
install/update operations. The larger the product, the larger the
download size of patches and upgrades. For product upgrades, the
download time can be improved by simply downloading only the plug-ins
that changed. Another installation scalability problem can arise during
an interactive install/update operation. Quite often plug-in boundaries
are established for development reasons (such as function reuse) and
present the wrong level of granularity in terms of what the user sees
as the unit of function, and therefore as an installation unit.
Considering that enterprise-level applications can scale up to hundreds
and thousands of plug-ins, with complex dependencies, the user can be
overwhelmed by various installation choices. A
possible solution is to introduce a packaging and installation
component that groups a number of plug-ins to offer a higher level of
function. For example,
in Eclipse, Update Manager does not install plug-ins directly; it
processes features. Features are bundles of plug-ins and are considered
deployment units with install/update semantics.
</p>
<p>The other side of scalability is scaling down, so products can
run on devices with limited resources, such as cellphones and PDAs.
This usually means rethinking
the core framework plug-ins to refactor them into smaller plug-ins,
some of them optionally deployable, so that one can run with a minimal
configuration.</p>



<h4> OVERCOMING THE BUMPS</h4>

<p>
General discussion about plug-in architecture and design issues may not
mean much for you or your company’s bottom line unless you’re a
participant or plan to be one—either by creating a plug-in framework or
developing plug-ins for fun and profit, or by using a plug-in-based
application. Employing a plug-in framework is not without bumps, but
they can be overcome with proper preparation. </p>
<p>
While traditional plug-ins have been around for some time, the pure
plug-in models have only recently emerged as robust, enterprise-level
quality application development environments. As many major industry
players are rapidly adopting plug-in technologies for their software
lines, we can expect further research and development into improving
the current architectures. Some of the areas that will receive
increased focus will be: </p>

<p> • Security at all levels, including installation, update, and runtime.</p>

<p> • Performance: speed and low resource usage.</p>

<p> • Improved tools for development, testing, packaging, and deployment of plug-ins.</p>

<p> • Improved installation and updates, especially by merging changes without taking the system down.</p>

<p> • Remote management of various processes (provisioning, configuration, and so on).</p>

<p> • Convergence, compatibility, or interoperability of various plug-in frameworks.</p>

<p> • Wider range of deployment platforms (from desktop PCs and high-end servers to digital mobile phones and embedded devices). </p>

<p> Increasingly, much of this effort will be happening in the open source domain or standards bodies. </p>

<table>
<tbody><tr><td bgcolor="#eeeeee"><span class="small"><strong>DORIAN BIRSAN</strong> has been working at the IBM Toronto Labs for
almost 10 years, leading a range of technical projects on application development
tools and writing a number of patents in the field. He has played an active
role in Eclipse since its inception, leading the user assistance and the update/install
teams. Mathematician at heart, turned computer scientist, and later husband
and father, he holds a B.Math. in computer science and combinatorics and optimization
from the University of Waterloo, as well as an M.Sc. in computer science from
the University of British Columbia, where he was a National Science and Engineering
Research Council of Canada Fellow.
</span></td></tr></tbody>
</table>

<p align="center"><a href="javascript:history.back(1)" onmouseover="status='Back to On Plug-ins and Extensible Architectures';return true;">Back to On Plug-ins and Extensible Architectures</a></p>

<!-- bottom banner ad start-->
<table cellpadding="5" cellspacing="5" width="100%">
<tbody><tr><td align="center">
<a href="http://www.acmqueue.org/phpAdsNew-rc42/adclick.php?bannerid=196&amp;zoneid=64&amp;source=&amp;dest=http%3A%2F%2Fwww.activestate.com%2Fenterprise.plex%3Futm_source%3DACMQueue%26utm_medium%3Dbanner%26utm_campaign%3DEE" target="_blank"><img style="visibility: hidden ! important;" src="file:///C:/Documents%20and%20Settings/Brian%20Sun/Application%20Data/Mozilla/Firefox/Profiles/qc16y5ld.default/maf/maftemp/1113210839291_106/1112921133113_645/index_files/750x100_activestate.gif" alt="" title="" border="0" height="100" width="750"></a><div id="beacon_196" style="position: absolute; left: 0px; top: 0px; visibility: hidden;"><img src="file:///C:/Documents%20and%20Settings/Brian%20Sun/Application%20Data/Mozilla/Firefox/Profiles/qc16y5ld.default/maf/maftemp/1113210839291_106/1112921133113_645/index_files/adlog_003.gif" alt="" style="width: 0px; height: 0px; visibility: hidden ! important;" height="0" width="0"></div></td></tr></tbody>
</table>

<!--bottom banner ad stop--><!--I/PRO Page Tagging--><!-- START Insight XE-->
<script language="JavaScript">
	var if_Site_ID = "ipro";
	var if_sid="1";
	var if_protocol=window.location.protocol;
	var mep1="&Site="+escape("acmqueue.com");
	</script>
<script language="JavaScript" src="file:///C:/Documents%20and%20Settings/Brian%20Sun/Application%20Data/Mozilla/Firefox/Profiles/qc16y5ld.default/maf/maftemp/1113210839291_106/1112921133113_645/index_files/ipro_if.js"></script>

	
	
	
	
	<!-- END Insight XE-->

<img src ="http://www.blogjava.net/briansun/aggbug/3148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-04-11 17:18 <a href="http://www.blogjava.net/briansun/articles/3148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[大师作品]提问的智慧[转]</title><link>http://www.blogjava.net/briansun/articles/2995.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Fri, 08 Apr 2005 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/2995.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/2995.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/2995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/2995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/2995.html</trackback:ping><description><![CDATA[
<div class="article" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h1>提问的智慧</h1>
<br>
<span class="firstname">作者：</span></div>
<div>
<div class="author">
<h3 class="author"><span class="firstname">Eric</span> <span class="othername">Steven</span> <span class="surname">Raymond</span></h3>
<div class="affiliation"><span class="orgname"><a href="http://www.catb.org/%7Eesr/" target="_top"> Thyrsus Enterprises</a><br>
</span>
<div class="address">
<p><br>
&nbsp;&nbsp;&nbsp;&nbsp;<tt class="email">&lt;<a href="mailto:esr@thyrsus.com">esr@thyrsus.com</a>&gt;</tt><br>
&nbsp;&nbsp;&nbsp;&nbsp;</p>
</div>
</div>
</div>
</div>
<div>
<div class="author">
<h3 class="author"><span class="firstname">Rick</span> <span class="surname">Moen</span></h3>
<div class="affiliation">
<div class="address">
<p><br>
&nbsp;&nbsp;&nbsp;&nbsp;<tt class="email">&lt;<a href="mailto:rick@linuxmafia.com">rick@linuxmafia.com</a>&gt;</tt><br>
&nbsp;&nbsp;&nbsp;&nbsp;</p>
</div>
</div>
</div>
</div>
<div>
<p class="copyright">版权 © 2001 Eric S. Raymond</p>
</div>
<div>
<div class="revhistory">
<table summary="Revision history" border="1" width="100%">
  <tbody>
    <tr>
      <th colspan="3" align="left" valign="top"><b>修订历史</b></th>
    </tr>
    <tr>
      <td align="left">修订版 3.1</td>
      <td align="left">2004年10月28日<br>
      </td>
      <td align="left">esr</td>
    </tr>
    <tr>
      <td colspan="3" align="left">文档‘Google
是你的朋友！’ </td>
    </tr>
    <tr>
      <td align="left">修订版 3.0</td>
      <td align="left">2004年2月2日<br>
      </td>
      <td align="left">esr</td>
    </tr>
    <tr>
      <td colspan="3" align="left">主要增加网页论坛应有的礼节内容 </td>
    </tr>
  </tbody>
</table>
<span style="font-weight: bold;">原文</span>：<a href="http://www.catb.org/%7Eesr/faqs/smart-questions.html">How
To Ask
Questions The Smart Way</a><br>
翻译：王刚 &lt;<a href="mailto:yafrk@yahoo.com">yafrk@yahoo.com</a>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br>
时间：2004年11月2日</div>
</div>
</div>
<hr></div>
<div class="toc">
<p><b>内容<br>
</b></p>
<dl><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#translations">译文</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#disclaimer">弃权申明</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#intro">引言</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#before">提问前</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#asking">提问时</a></span></dt><dd>
    <dl><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#forum">仔细挑选论坛</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#usefora">面向新手的网页论坛和IRC通常响应最快</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#uselists">第二步，使用项目邮件列表</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#bespecific">使用明确而有意义的主题</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#easyreply">使之更易回复</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#writewell">使用清晰、语法与拼写正确的语句</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#formats">使用易懂的格式发送问题</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#beprecise">描述问题应准确且有内容</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#volume">多不等于准确</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#id3001405">别动辄声称找到臭虫</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#id3001578">低声下气不能代替自己应做之事</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#symptoms">描述问题症状而不是猜测</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#chronology">按时间先后罗列问题症状</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#goal">描述目的而不是步骤</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#noprivate">别要求私下回复</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#explicit">问题应明晰</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#homework">别张贴家庭作业</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#prune">删除无意义的问题</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#urgent">不要刻意标明问题紧急</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#courtesy">礼貌总是无害的</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#followup">问题解决后追加一条简要说明</a></span></dt></dl>
  </dd><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#answers">如何解读回答</a></span></dt><dd>
    <dl><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#rtfm">RTFM与STFW：如何知道你已完全搞砸 </a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#lesser">如果还不明白.</a></span></dt><dt><span class="sect2"><a href="http://www.fengnet.com/smart-questions.html#keepcool">对待无礼</a></span></dt></dl>
  </dd><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#not_losing">别象个失败者那样反应 </a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#classic">提问禁忌</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#examples">好问题与坏问题</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#id3002966">如果没有回复 </a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#id3003018">如何更好地回答问题</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#id3003109">相关资源</a></span></dt><dt><span class="sect1"><a href="http://www.fengnet.com/smart-questions.html#id3003139">鸣谢<br>
    </a></span></dt></dl>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="translations"></a>译文</h2>
</div>
</div>
</div>
<p>译文: <a href="http://stare.cz/otazky/index.html" target="_top">捷克语</a>
<a href="http://www.usenet.dk/netikette/udvdebatteknik.html" target="_top">丹麦语</a>
<a href="http://linux.ee/%7Ekala/smart-questions.html" target="_top">爱沙尼
亚语</a> <a href="http://www.gnurou.org/documents/smart-questions-fr.html" target="_top">法语</a> <a href="http://www.lugbz.org/documents/smart-questions_de.html" target="_top">德语</a> <a href="http://www.penguin.org.il/essays/smart-questions-he.html" target="_top">希伯来语</a> <a href="http://www.no.info.hu/%7Ekryss/gnu/esr/smart-questions_hu.html" target="_top">匈牙利语</a> <a href="http://members.xoom.virgilio.it/army1987/domande.html" target="_top">意大利语</a> <a href="http://www.ranvis.com/articles/smart-questions.ja.html" target="_top">日语</a> <a href="http://rtfm.killfile.pl/" target="_top">波
兰语</a> <a href="http://ln.com.ua/%7Eopenxs/articles/smart-questions-ru.html" target="_top">俄语</a> <a href="http://www.sindominio.net/ayuda/preguntas-inteligentes.html" target="_top">西班牙语</a> <a href="http://www.se.linux.org/dokumentation/howto/smartafragor" target="_top">瑞典语</a>
<a href="http://belgeler.org/howto/smart-questions.html" target="_top">土
耳其语</a>.
如果你想复制、镜像、翻译或引用本文，请参阅我的 <a href="http://www.catb.org/%7Eesr/copying.html" target="_top">复制须知</a>.
<br>
</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="disclaimer"></a>弃权申明</h2>
</div>
</div>
</div>
<p><span class="emphasis">许多项目的网站在
如何取得帮助的部分链接了本文，这没有关系，也是我们想要的。但如果你是该项目生成此链接的网管，请在链接附近显著位置注明“<span style="font-style: italic;">我们不是此项目的服务部！</span>”</span></p>
<p>我们已经遭受没有此说明带来的痛苦，不断受到一些白痴的骚扰。他们认为既然我们发表了此文，那么我们就有责任解决世上所有技术问题！</p>
<p>如果你因为需要帮助阅读了本文，然后带着可以直接从作者那取得帮助的印象离开，你就不幸成了那些白痴之一。不要向我们提问，我们不会理睬
的。
我们在这只是给你说明如何从那些真正懂得你软硬件问题的人那里取得帮助的方法，99%的时间我们不会是那些人。除非你确信此文作者是你遇到问题方面的专
家，
请不要打扰，这样大家都更开心一点。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="intro"></a>引言</h2>
</div>
</div>
</div>
<p>在 <a href="http://www.catb.org/%7Eesr/faqs/hacker-howto.html" target="_top">黑客</a>
的世界，你所提技术问题的回答很大程度上取决于你提问的方式与解决此问题的难度，本文将教你如何提问才更有可能得到满意的答复。</p>
<p>开源程序的使用已经很广，你通常可以从其它更有经验的用户而不是黑客那里得到回答。这是好事，他们一般对新手常有的毛病更容忍一点。然尔，使用我们
介
绍的方法象对待黑客那样对待这些有经验的用户，通常能最有效地得到问题的解答。</p>
<p>第一件需要明白的事是黑客喜欢难题和激发思考的好问题。假如不是这样，我们也不会写本文了。如果你能提出一个有趣的问题让我们咀嚼玩味，我们会感激
你。
好的
问题是种激励与礼物，帮助我们发展认知，揭示没有注意或想过的问题。在黑客中，“好问题！”是非常真挚的赞许。</p>
<p>除此而外，黑客有遇到简单问题就表现出敌视或傲慢的名声，有时候我们看起来还对新手和愚蠢的家伙有条件反
射式的无礼，但并不真正是这样。</p>
<p>我们只是毫无歉意地敌视那些提问前
不愿思考、不做自己该做之事的人。这种人就象时间无底洞──他们只知道获取，不愿意付出，他们浪费了时间，这些时间本可用于其它更值得回答的人和
更有趣
的问题。我们将这种人叫做“失败者 (loser)” (由于历史原因，我们有时将“loser”拼为“lusers")</p>
<p>我们注意到许多人只想用我们写的软件，他们对学习技术细节没有兴趣。对大多数人而言，计算机只是种工具，是种达到目的的手段。他们要生活并且有更要
紧的事要做，我们承认这点，也从不指望每个人都对这些让我们着迷的技术问题感兴趣。不过，我们回答问题的风格是为了适应那些真正对此有兴趣并愿意主动参与
问题解决的
人，这一点不会变，也不该变。如果这都变了，我们就会在自己能做得最好的事情上不再那么犀利。<br>
</p>
<p>我们(多数)是自愿者，从自己繁忙的生活中抽时间来回答问题，有时会力不从心。因此，我们会无情地滤除问题，特别是那些看起来象是失败者的，以
便更有效地把回答问题的时间留给那些“胜利者”</p>
<p>如果你认为这种态度
令人憎恶、以施惠者自居或傲慢自大，请检查你的假设，我们并未要求你屈服──事实上，假如你做了该做的努力使之成为可能，我们中的
大多数人非常乐意平等地与你交流并欢迎你接纳我们的文化。试图去帮助那些不愿自救的人对我们简直没有效率，不懂没有关系，但愚蠢地行事不行。</p>
<p>所以，你不必在技术上很在行才能吸引我们的注意，但你<span style="font-weight: bold; font-style: italic;">必须</span>表现出能引导你在行的姿态──机
敏、思考、善于观察、乐于主动参与问题的解决。如果你
做不到这些使你与众不同的事情，我们建议你付钱跟别人签商业服务合同，而不是要求黑客无偿帮助。</p>
<p>如果你决定向我们求助，你不会想成为一名失败者，你也不想被看成一个失败者。得到快速有效回复的最好方法是使提问者看起来象个聪明、自
信的人，并且暗示只是碰巧在某一特别问题上需要帮助。</p>
<p>(欢迎对本文指正，可以将建议发至 <a href="mailto:esr@thyrsus.com" target="_top">esr@thyrsus.com</a>
。
请注意，本文不想成为一般性的 <a href="http://www.dtcc.edu/cs/rfc1855.html" target="_top">网络礼仪</a> 指南，我一般会拒绝那些与引出技术论坛中有用的回复不特别相关的建议)</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="before"></a>提问前</h2>
</div>
</div>
</div>
<p>在通过电子邮件、新闻组或网页论坛提技术问题之前，做以下事情：</p>
<div class="procedure">
<ol type="1"><li>
    <p>尝试搜索互联网以找到答案</p>
  </li><li>
    <p>尝试阅读手册以找到答案</p>
  </li><li>
    <p>尝试阅读FAQ(常见问题)文档以找到答案</p>
  </li><li>
    <p>尝试自己检查或试验以
找到答案</p>
  </li><li>
    <p>尝试请教懂行的朋友以找到答案</p>
  </li><li>
    <p>如果你是程序员，尝试阅读源代码以找到答案</p>
  </li></ol>
</div>
<p>提问时，请先表述你已经做了上述事情，这将有助于建立你不是寄生虫与浪费别人时间的印象。最好再表述你从中<span style="font-weight: bold; font-style: italic;">学到的东西</span>，我们喜欢
回答那些表现出能从答案中学习的人。</p>
<p>使用某些策略，比如用Google搜索你遇到的错误提示(既搜索网页也查查讨论组)，可能就直接找到了解决问题的文档或邮件列表线索。即使没有结
果，在电子邮件或新闻组张贴问题时提一句“我在Google中查过下列句子但没有找到什么有用的东西”也是件好事。</p>
<p>准备你的问题，彻底地思考。轻率的提问只能得到轻率的回答，或者压根没有。在提问时，越是表现出做过思考并在努力解
决问题，你越有可能得到
实际帮助。</p>
<p>注意别提错问题。如果提问基于错误的假设，某黑客多半会一边想”愚蠢的问题……“，一边用按照问题字面的无用答案回复你，并且希望这种只
是得到
字
面回答而不是真正所需的经历给你一个教训。</p>
<p>永远不要假设你<span style="font-weight: bold; font-style: italic;">有资格</span>得
到解答。你没有这种资格，毕竟你没有为此服务付费。如果你能够提出有内容、有趣和激励思考的问题──那种毫无疑问能够向社
区贡献经验而不仅仅是消极地要求从别人那获取知识的问题，你将“挣到”答案。</p>
<p>另一方面，表明你能够也乐意参与问题的解决是个很好的开端。“有没有
人能指个方向？”、“我这还漏点什么？”、“我应该查哪些网站？”通常要比
“请给出我可以用的完整步骤”更容易得到回复，因为你表明了只要有人能指个方向你就很乐意完成剩下的过程。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="asking"></a>提问时</h2>
</div>
</div>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="forum"></a>仔细挑选论坛</h3>
</div>
</div>
</div>
<p>要对在哪提问留心，如果你做了下
述事情，多半会被一笔勾销或被看成“失败者”：</p>
<div class="itemizedlist">
<ul type="disc"><li>
    <p>张贴与论坛主题完全无关的问题</p>
  </li><li>
    <p>在面向高级技术问题的论坛上提非常
初浅的问题，或者反之。</p>
  </li><li>
    <p>在太多不同的新闻组同时交叉张贴</p>
  </li><li>
    <p>给既非熟人也没有义务解决你问题的个人张贴你私人的电子邮件</p>
  </li></ul>
</div>
<p>为保护通信的渠道不被无
关的东西淹没，黑客会除掉那些没有找对地方的问题，你不会想有这种经历的。</p>
<p>所以第一步是找对论坛，Google与其它搜索引擎还是你的朋友，可以用它们搜索与你遇到困难的软硬件问题最相关的项目的网站。那
里通常都有项目的FAQ列表、邮件列表及其文档的链接。如果你的努力(包括阅读FAQ)都没有结果，这些邮件列表就是最后能取得帮助
的地方。项目的网站也许还有报告臭虫的流程或链接，如果是这样，去看看。</p>
<p>向陌生的人或论坛发送邮件极有可能是在冒险。譬如，不要假设一个富含信息的网页的编写者想充当你的免费顾问，不要对你
的问题是否会受到欢迎做乐
观的
估计──如果你
不确定，向别处发或者根本别发。</p>
<p>在选择网页论坛、新闻组或邮件列表时，不要太相信名字，先看看FAQ或者许可书以明确你的问题
是否与其主题相关。张贴前先翻翻已有的帖
子可
以
帮助你感受一下那里行事的方式。事实上，张贴之前在新闻组或邮件列表中搜索与你问题相关的关键词是个很好的主意，也许就找到答案了。即使没有，也能帮助你
整理
出
更好的问题。</p>
<p>别象机关枪似的一次性“扫射”所有的帮助通
道，那就象大嚷大叫并使人不快。一个一个地来。<br>
</p>
<p>弄清楚你的主题！最典型的错误之一是在某种致立于跨Unix和Windows平台的语言、库或工具的论坛中提关于操作系统程序接口的问题。如果你不
明白为什么这是大错，最好在搞清楚概念前什么也别问。</p>
<p>一般来说，在仔细挑选的公共论坛中提问比在私有论坛中提同样的问题更容易得到有用的回复。有许多理由支持这一点，一是看潜在的回复者有多少，二是看
论
坛的参与者有多少，黑客更愿回答能启发多数人的问题。<br>
</p>
<p>可以理解，老练的黑客和一些流行软件的作者正在收到超出他们承受能力的不当消息。就象那根多出来就可以压垮骆驼背的稻草一样，你的
加入也可能会使情况走向极端──已经好几次了，一些流行软件的作者退出了对其软件的支持，因为伴随而来的涌向其私人邮箱的大量无用消息变得无法
忍受。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3><a name="usefora"></a>面向新手的网页论坛和IRC通常响应最快</h3>
</div>
</div>
</div>
<p>本地的用户组织或者你所用的Linux发行版也许正在宣传新手取得帮助的网页论坛或IRC(互联网中继聊天)
(在非英语国家，新手论坛很可能还是邮件列表)，这些
地
方
是开始提问的好去处，尤其是当你觉得遇到的也许只是相对简单或者一般的问题时。经过宣传的IRC通道是个公开邀请提问的地方，通常可以得到实时的回复。</p>
<p>事实上，如果出问题的程序来自某发行版(这很常见)，在程序的项目论坛或列表提问前最好先在发行版的论坛或列表中问问，(否则)项目的黑客可能仅仅
回复“用<span style="font-weight: bold; font-style: italic;">我们</span><span style="font-weight: bold; font-style: italic;">的</span>代码”</p>
<p>在任何网页论坛张贴之前，先看看是否有搜索功能。如果有，就试试用问题的几个关键词搜索一下，也许就有帮助。如果在此之前你已做过全面的网页搜索
(你应该这样做)，还是再搜索一下论坛，搜索引擎最近也许还没有索引此论坛的全部内容。</p>
<p>通过网页论坛或IRC频道提供项目的用户支持有增长的趋势，电子邮件交流则更多地为项目开发保留。先在网页论坛或IRC中寻求与项目相关的帮
助。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="uselists"></a>第二步，使用项目邮件列表</h3>
</div>
</div>
</div>
<p>当某项目存在开发者邮件列表时，即使你确信谁能最好地回答问题，也要向列表而不是其中的个体提问。检查项目的文档和主页，找到项目的邮件列表并使
用它。采用这种策略有几个好理由：</p>
<div class="itemizedlist">
<ul type="disc"><li>
    <p>任何向单个开发者提的足够好的问题也将对整个项目组有益。相反，如果你认为自己的问题对整个项目组来说太愚蠢，这也不能成为打扰
单个开发者的理由。</p>
  </li><li>
    <p>向列表提问可以平衡开发者的负担，单个开发者(特别是项目领导)也许太忙以至于无法回答你的问题。</p>
  </li><li>
    <p>大多数邮件列表有历史文档并被搜索引擎索引，其它人可以通过网页搜索找到你的问题和答案而不用再次在邮件列表中发问。</p>
  </li><li>
    <p>如果某些问题经常被问到，开发者可以利用此信息改进文档或软件本身以使其更清楚。如果只是私下提问，就没有人能看到最常见问题的完整
场景。</p>
  </li></ul>
</div>
<p>如果一个项目既有“用户”也有“开发者”(或“黑客”)邮件列表或网页论坛，而你又不摆弄那些代码，向“用户”列表或论坛提问。不要假设自己在开发
者列表中会受欢
迎，那些人多半会遭受你的噪音干扰。</p>
<p>然尔，如果你<span style="font-style: italic;">确信</span>你的问题不一般，而且在“用户”
列表或论坛中几天都没有回复，可以试试“开发者”列表或论坛。建议你在张贴前最好先暗暗地观察几天
以了解那的行事方式(事实上这是参与任何私有或半私有列表的好主意)</p>
<p>如果你找不到一个项目的邮件列表，而只能查到项目维护者的地址，只管向其发信。即便在这种情况下，也别假设(项目)邮件列表不存在。在你的电子邮
件中陈述你已
经试过但没有找到合适的邮件列表，也提及你不反对将自己的邮件转发给他人(许多人认为，即使没什么秘密，私人电子邮件也不应该被公开。通过允许将你的电子
邮件
转
发他人给
了相应人员处置你邮件的选择)。<br>
</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="bespecific"></a>使用明确而有意义的主题</h3>
</div>
</div>
</div>
<p>在邮件列表、新闻组或网页论坛中，主题是你在五十个或更少的字符以内吸引有资格的专家注意的黄金机会，不要用诸如“请帮我”(更别提大写的“请帮
我！！！！”，这种主题的消息会被条件反射式地删掉)之类的唠叨浪费机会。不要用你痛苦的深度来打动我们，相反，要在这点空间中使用超级简明扼要的问题
描述。</p>
<p>使用主题的好惯例是“对象──偏差”(式的描述)，许多技术支持组织就是这样做的。在“对象”部分指明是哪一个或哪一组东西有问题，在“偏差”部分
则描述与期望
行
为不一致的地方。</p>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="strong"><span class="term"><span class="strong">愚蠢：</span></span></span></span><dt><span class="term"><span class="strong"></span> </span><br>
  </dt><dd>
    <p>救命啊！我的笔记本视频工作不正常！</p>
  </dd><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="strong"><span class="term"><span class="strong">明智：</span></span></span></span><dt><span class="term"><span class="strong"></span></span><br>
  </dt><dd>
    <p>XFree86 4.1扭曲鼠标光标，某显卡MV1005型号的芯片组</p>
  </dd><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="strong"><span class="term"><span class="strong">更明智：</span></span></span></span><dt><span class="term"><span class="strong"></span></span><br>
  </dt><dd>
    <p>使用某显卡MV1005型号芯片组的XFree86 4.1的鼠标光标被扭曲</p>
  </dd></dl>
</div>
<p>编写“对象──偏差”式描述的过程有助于你更具体地组织你的问题。是什么被影响了？仅仅是鼠标光标或者还有其它图形？只在XFree86中出现？或
只是在其4.1版中？是针对某显卡？或者只是其MV1005型号的芯片组？一个黑客只需描一眼就能够立即明白什么是你遇到的问题，什么是你自己的问题。</p>
<p>更一般地，想象一下在只显示主题的文档索引中查找。让你的主题更好地反映问题，可以使下一个搜索类似问题的人能够在文档中直接找到答案的线索而不用
再次张贴提问。</p>
<p>如果你想在回复中提问，确保改变主题以表明你是在问一个问题，一个主题象“re: 测试”或“re: 新臭虫”的消息不太可能引起足够的注意。同
时，将回复中与新主题不甚相关的引用内容尽量删除</p>
<p>对于列表消息，不要直接点击回复(按钮)来开始一个新的线索，这将限制你的观众。有些邮件阅读程序，比如mutt，允许用户按线索排序并通过折叠线
索来隐藏消息，
这样做的人永远看不到你发的消息。</p>
<p>仅仅改变主题还不够。mutt和其它邮件阅读程序还要检查主题以外的其它邮件头信息，以便为其指定线索，所以宁可发一
个全
新的邮件。</p>
<p>在网页论坛，因为消息与特定的线索紧密结合并且通常在线索之外不可见，好的提问方式略有不同，通过回复提问并不要紧(一些论坛甚至不允许在
回复中出现分离的主题，而且这样做了基本上没有人会去看)。不过通过回复提问本身就是令人怀疑的做法，因为它们只会被正在查看该
线索的人读到。所以，除非你只想在该线索当前活跃的人群中提问，还是另起炉灶比较好。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="easyreply"></a>使之更易回复</h3>
</div>
</div>
</div>
<p>以“请向……回复”来结束问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦，我们也觉得花几秒钟
考虑你的问题更麻烦。如果你的邮件客户端程序不支持这样做，换个好点的。如果是操作系统不支持所有这种邮件客户端程序，也换个好点的。</p>
<p>在网页论坛，要求通过电子邮件回复是完全无礼的，除非你确信回复的信息也许是机密的(而且有人会为了某种未知的原因只让你而不是整个论坛知道答
案)。如果
你只是想
在有人回复线索时得到电子邮件提醒，可以要求论坛发送。几乎所有论坛都提供诸如“留意本线索”、“有回复发送邮件”的功能。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="writewell"></a>使用清晰、语法与拼写正确的语句</h3>
</div>
</div>
</div>
<p>经验告诉我们，粗心与草率的作者通常也粗心与草率地思考和编程(我敢打赌)。为这些粗心与草率的思考者回答问题没有什么好处，我们宁可将
时间花在其它地方。</p>
<p>
清楚、完整地表达你的问题非常重要。如果你觉得这样做麻烦，我们也觉得注意(你的问题)麻烦。花点额外的精力斟酌一下字句，用不着太僵硬与正式──事实
上，黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它必须很<span style="font-weight: bold; font-style: italic;">准确</span>，而且有迹象表明你是在思考和关
注问题。</p>
<p>正确地拼写、使用标点和大小写，不要将“its”混淆为“it's”，“loose”搞成“lose”或者将“discrete”弄成
“discreet”。<span style="font-weight: bold;">不要全部用大写</span>，这会被看成无礼的大声嚷嚷
(全部小写也好不到哪去，因为不易阅读。Alan
Cox[注：著名黑客，Linux内核的重要参与者]也许可以这样做，但你不行 )。</p>
<p>一般而言，如果你写得象个半文盲似的傻子，多半得不到理睬。如果象个小孩似地乱写乱画那绝对是在找死，可以肯定没人会理你(或者最多
是给你一大堆指责与挖苦)。</p>
<p>如果在非母语论坛中提问，你的拼写与语法错误会得到有限的宽容，但懒惰完全不会被容忍(是的，我们通常看得出其中的差别)。同时，除非你知道回复者
使用
的语言，请使用
英语书写。繁忙的黑客一般会直接删除用他们看不懂语言写的消息。在互联网上英语是工作语言，用英语书写可以将你的问题不被
阅读就被直接删除的可能降到最低。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="formats"></a>使用易懂的格式发送问题</h3>
</div>
</div>
</div>
<p>如果你人为地将问题搞得难以阅读，它多半会被忽略，人们更愿读易懂的问题，所以：</p>
<div class="itemizedlist">
<ul type="disc"><li>
    <p>使用文本而不是HTML(超文本标注语言) ( <a href="http://expita.com/nomime.html" target="_top">关闭HTML</a> 并不难) </p>
  </li><li>
    <p> 使用MIME(多用途互联网邮件扩展)附件通常没有问题，前提是真正有内容(譬如附带的源文件或补丁)，而不仅仅是邮件客户端程序
生
成的模板(譬如只是消息内容的拷贝)。</p>
  </li><li>
    <p>不要发送整段只是单行句子但多次折回的邮件(这使得回复部分内容非常困难)。设想你的读者是在80个字符宽的文本终端阅读邮件，
设置你的行折回点小于80列。</p>
  </li><li>
    <p>但是，也<span style="font-weight: bold; font-style: italic;">不要</span>用
任何固定列折回数据(譬如直接传送的日
志文件或会话记录)。数据应该原样包含，使回复者确信他们看到的与你看到的东西一样。</p>
  </li><li>
    <p>在英语论坛中，不要使用'Quoted-Printable'
MIME编码发送消息。这种编码对于张贴非ASCII语言可能是必须的，但很多邮件代理程序并不支持。当它们分断时，那些文本中四处散布
的
“=20”符号既难看也分散注意力。 </p>
  </li><li>
    <p><span style="font-weight: bold; font-style: italic;">永远不要</span>指
望黑客们阅读使用封闭的专用格式编写的文档，诸如微软公司的Word或Excel文件等，大多数黑客对此的反应就象有人将还在冒热气的猪
粪倒在你门口时你的反应一样。即使他们能够处理，他们也很厌恶这么做。</p>
  </li><li>
    <p>如果你从使用视窗的电脑发送电子邮件，关闭微软愚蠢的“聪明引用”功能，以免在你的邮件中到处散布垃圾字符。 </p>
  </li><li>
    <p>在网页论坛，勿滥用“表情符号”和“html”功能(当它们提供时)。一两个表情符号通常没有问题，但花哨的彩色文本倾向于使人认为
你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来象个傻笑的小姑娘。这通常不是个好主意，除非你只是对性而不是有用的回复更有兴趣。</p>
  </li></ul>
</div>
<p>如果你使用图形用户界面的邮件客户端程序(如网景公司的Messenger、微软公司的Outlook或者其它类似的)，注意它们的缺省配置不一
定满足这些要求。大多数这类程序有基于菜单的“查看源码”命令，用它来检查发送文件夹中的消息，以确保发送的是没有多余杂质的纯文本文件。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="beprecise"></a>描述问题应准确且有内容</h3>
</div>
</div>
</div>
<div class="itemizedlist">
<ul type="disc"><li>
    <p>仔细、清楚地描述问题的症状 </p>
  </li><li>
    <p>描述问题发生的环境(主机，操作系统，应用程序，任何相关的)，提供销售商的发行版和版本号(如：“Fedora Core
2”、“Slackware 9.1”等) </p>
  </li><li>
    <p>描述提问前做过的研究及其理解。 </p>
  </li><li>
    <p>描述提问前为确定问题而采取的诊断步骤。 </p>
  </li><li>
    <p>描述最近对计算机或软件配置的任何相关改变。 </p>
  </li></ul>
</div>
<p>尽最大努力预测黑客会提到的问题，并提前备好答案。</p>
<p>Simon Tatham写过一篇叫 <a href="http://www.chiark.greenend.org.uk/%7Esgtatham/bugs.html" target="_top">如何有效报告臭虫</a> 的文章，我强烈推荐各位阅读。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="volume"></a>多不等于准确</h3>
</div>
</div>
</div>
<p>你应该(写得)准确且有内容，简单地将一大堆代码或数据“倾倒”在求助消息中达不到目的。如果你有一个很大且复杂的测试样例让程序崩溃，尝
试将其裁剪得越小越好。</p>
<p>至少有三个理由支持这点。第一，让别人看到你在努力简化问题使你更有可能得到回复。第二，简化问题使你更有可能得到<span style="font-style: italic; font-weight: bold;">有用的</span>回复。第三，在提纯臭虫
报告的过程中，你可能自己就找到了解决问题的方法或权宜之计。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="id3001405"></a>别动辄声称找到臭虫</h3>
</div>
</div>
</div>
<p>当你在一个软件中遇到问题，除非你<span style="font-weight: bold; font-style: italic;">非
常、非常</span>的有根据，不要动辄声称找到了臭虫。提示：除非你能提供解决问题的源代码补丁，或者对前一版本的回归测
试
表现出不正确的行为，否则你都多半不够完全确信。对于网页和文档也如此，如果你(声称)发现了文档的“臭虫”，你应该能提供相应位置的替代文本。</p>
<p>记住，还有许多其它用户未经历你遇到的问题，否则你在阅读文档或网页搜索时就应该发现了(你在报怨前已经做了这些，<a href="http://www.fengnet.com/smart-questions.html#before" title="Before You Ask">是吧</a>？)。这也意味着很有可能是你弄错了而不是软件本身有问
题。</p>
<p>编写软件的人通常非常辛苦地使它尽可能完美。如果你声称找到了臭虫，也就暗示他们做错了什么，而这几乎总会使人不快──即使你是对的，
在主题中嚷嚷“臭虫”也是特别不老练的。</p>
<p>提问时，即使你私下非常确信已经发现一个真正的臭虫，最好写得象是<span style="font-weight: bold; font-style: italic;">你</span>做
错了什么。如果真的有臭虫，你会在回复中看到这点。这么做的话，如果真有虫子，维护者就会向你道歉，这总比你弄
砸了然后欠别人一个道歉要强。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="id3001578"></a>低声下气不能代替自己应做之事</h3>
</div>
</div>
</div>
<p>有些人明白他们不应该粗鲁或傲慢地行事并要求得到答复，但他们退到相反的低声下气的极端，“我知道我只是个什么也不是、什么也不懂的失败者，
但……”。这既使人困扰也没有帮助，当伴随着对实际问题含糊的描述时还特别令人反感。</p>
<p>别用低级灵长类动物的策略浪费大家的时间，相反，尽量清楚地表述背景事实和你的问题，这比低声下气更好地摆正了你的位置。</p>
<p>有时，网页论坛设有单独的初学者提问区域，如果你真的认为遇到了初浅的问题，到那去就是了，但一样别低声下气。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="symptoms"></a>描述问题症状而不是猜测</h3>
</div>
</div>
</div>
<p>告诉黑客你认为是什么导致了问题是没有用的(如果你的诊断理论是了不起的东西，你还会向他人咨询求助吗？)。所以，确保只是告诉他们问题的原始
症状，而不是你的解释和理论，让他们来解释和诊断。如果你认为陈述你的猜测很重要，清楚地说明这只是你的猜测并描述为什么它们不起作用。</p>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="strong"><span class="term"><span class="strong">愚蠢：</span></span></span></span><dt><span class="term"><span class="strong"></span> </span><br>
  </dt><dd>
    <p>我在编译内核时接连遇到SIG11错误，怀疑主板上的某根电路丝断了，找到它们的最好办法是什么？</p>
  </dd><dt><span class="term"><span class="strong">明智：</span> </span></dt><dd>
    <p>我组装的电脑(K6/233 CPU、FIC-PA2007主板(威盛Apollo VP2芯片组)、Corsair PC133
SDRAM 256Mb内
存)最近在开机20分钟左右、做内核编译时频繁地报SIG11错，但在头20分钟内从不出问题。重启动不会复位时钟，但整夜关机会。更换所有内存未解决问
题，相关的典型编译会话日志附后。</p>
  </dd></dl>
</div>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="chronology"></a>按时间先后罗列症状</h3>
</div>
</div>
</div>
<p>刚出问题之前发生的事情通常包含有解决问题最有效的线索。所以，记录中应准确地描述你及电脑在崩溃之前都做了些什么。在命令行处理的
情况下，有会话日志(如运行脚本工具生成的)并引用相关的若干(如20)行记录会非常有帮助。</p>
<p>如果崩溃的程序有诊断选项(如-v详述选项)，仔细考虑选择这些能在记录中增加排错信息的选项。</p>
<p>如果你的记录很长(如超过四段)，也许在开头简述问题随后按时间先后罗列详细过程更有用。这样做，黑客在读你的记录时就知道该查哪些内容了。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="goal"></a>描述目的而不是步骤</h3>
</div>
</div>
</div>
<p>如果你想弄清楚如何做某事(而不是报告一个臭虫)，在开头就描述你的目标，此后才描述为此采取的措施所遇到的问题。</p>
<p>经常有这种情况，寻求技术帮助的人在脑袋里有个更高层面的目标，他们在自以为能达到目标的特定道路上被卡住了，然后跑来问该怎么走，但
没有意识到这条路本身有问题，结果要费很大的劲才能通过。</p>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong">愚蠢：</span> </span></dt><dd>
    <p>我怎样才能让某图形程序的颜色拾取器取得十六进制的RGB值？</p>
  </dd><dt><span class="term"><span class="strong">明智：</span> </span></dt><dd>
    <p>我正试图用自己选定数值的颜色替换一幅图片的颜色表，我现在唯一知道的方法是编辑每个表槽，但却无法让某图形程序的颜色拾取器取得十六进
制的RGB值。</p>
  </dd></dl>
</div>
<p>第二种提法是明智的，它使得建议采用更合适的工具完成任务的回复成为可能。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="noprivate"></a>别要求私下回复</h3>
</div>
</div>
</div>
<p>黑客们认为问题的解决过程应该公开、透明，此过程中如果更有才能的人注意到不完整或者不当之处，最初的回复才能够、也应该被更正。同时，作为
回复者也因为能力和学识被其它同行看到而得到某种回报。</p>
<p>当你要求私下回复时，此过程和回报都被中止。别这样做，让<span style="font-weight: bold; font-style: italic;">回复者</span>来决定是否私下回答──如果他
真这么做了，通常是因为他认为问题编写太差或者太肤浅
以
至于对其它人无意义。</p>
<p>对这条规则存在一条有限的例外，如果你确信提问可能会导致大量雷同的回复时，那么“给我发电子邮件，我将为小组归纳这些回复”将是神奇的句子。试图
将邮
件列表或新闻组从洪水般雷同的回复中解救出来是非常有礼貌的──但你应信守诺言。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="explicit"></a>问题应明晰<br>
</h3>
</div>
</div>
</div>
<p>漫无边际的问题通常也被视为没有明确限制的时间无底洞。最有可能给你有用答案的人通常也是最忙的人(假如只是因为他们承担了大多数工作的话)，这些
人
对于没
有限制的时间无底洞极其反感，所以他们也倾向于讨厌那些漫无边际的问题。</p>
<p>如果你明确了想让回复者做的事(如指点方向、发送代码、检查补丁或其它)，你更有可能得到有用的回复。这可以使他们集中精力并间接地设定了他们为帮
助你需要花费的时间和精力上限，这很好。</p>
<p>要想理解专家生活的世界，可以这样设想：那里有丰富的专长资源但稀缺的响应时间。你暗中要求他们奉献的时间越少，你越有可能从这些真正懂行也真正很
忙的专家
那里得到回答。</p>
<p>所以限定你的问题以使专家回答时需要付出的时间最少──这通常还与简化问题不一样。举个例，“请问可否指点一下哪有好一点的X解释？”通常要
比“请解释一下X”明智。如果你有什么代码不运行了，通常请别人看看哪有问题比叫他们帮你改正更明智。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="homework"></a>别张贴家庭作业<br>
</h3>
</div>
</div>
</div>
<p>黑客们善于发现“家庭作业”式的问题。我们大多数人已经做了自己的家庭作业，那是<span style="font-weight: bold; font-style: italic;">该你</span>做的，以便从其经历中学习。问一
下提示没有关系，但不是要求完整的解决方案。</p>
<p>如果你怀疑自己碰到了一个家庭作业式的问题，但仍然无法解决，尝试在用户组论坛或(作为最后一招)在项目的“用户”邮件列表或论坛中提问。尽管
黑客们会看出来，一些高级用户也许仍会给你提示。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="prune"></a>删除无意义的问题</h3>
</div>
</div>
</div>
<p>抵制在求助消息末尾加上诸如“有人能帮我吗？”或“有没有答案？”之类在语义上无任何意义东西的诱惑。第一，如果问题描述还不完整，这些附
加的东西最多也只能是多余的。第二，因为它们是多余的，黑客们会认为这些东西烦人──就很有可能用逻辑上无误但打发人的回复，诸如“是的，你可
以得到帮助”和“不，没有给你的帮助”</p>
<p>一般来说，避免提“是或否”类型的问题，除非你想得到 <a href="http://homepages.tesco.net/%7EJ.deBoynePollard/FGA/questions-with-yes-or-no-answers.html" target="_top">“是或否”类型的回答</a>。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="urgent"></a>不要刻意标明问题紧急</h3>
</div>
</div>
</div>
<p>这是你自己的问题，不要我们的。宣称“紧急”极有可能事与愿违：大多数黑客会直接删除这种消息，他们认为这是无礼和自私地企图得到即时与特殊的关
照。</p>
<p>有一点点局部的例外，如果你是在一些知名度很高、会使黑客们激动的地方使用程序，也许值得这样去做。在这种情况下，如果你有期限压力，也很有礼貌
地提到这点，人们也许会有足够的兴趣快一点回答。</p>
<p>当然，这是非常冒险的，因为黑客们对什么是令人激动的标准多半与你的不同。譬如从国际空间站这样张贴没有问题，但代表感觉良好的慈善或政治原
因这样做几乎肯定不行。事实上，张贴诸如“紧急：帮我救救这个毛绒绒的小海豹！”肯定会被黑客回避或光火，即使他们认为毛绒绒的小海豹很重要。</p>
<p>如果你觉得这不可思议，再把剩下的内容多读几遍，直到弄清楚了再发贴。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="courtesy"></a>礼貌总是无害的</h3>
</div>
</div>
</div>
<p>礼貌一点，使用“请”和“谢谢你的关注”或者“谢谢你的意见”，让别人明白你感谢他们无偿花时间帮助你。</p>
<p>坦率地说，这一点没有语法正确、文字清晰、准确、有内容和避免使用专用格式重要(同时也不能替代它们)。黑客们一般宁可读有点唐突但技术鲜明的臭
虫报告，而不是那种礼貌但含糊的报告。(如果这点让你不解，记住我们是按问题能教我们些什么来评价一个问题的)</p>
<p>然尔，如果你已经谈清楚了技术问题，客气一点肯定会增加你得到有用回复的机会。</p>
<p>(我们必须指出，本文唯一受到一些老黑客认真反对的地方是以前曾经推荐过的“提前谢了”，一些黑客认为这隐含着事后不用再感谢任何人的暗示。我们的
建议是
先说
“提前谢了”，事后再对回复者表示感谢。或者换种方式表达，譬如用“谢谢你的关注”或“谢谢你的意见”)。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="followup"></a>问题解决后追加一条简要说明</h3>
</div>
</div>
</div>
<p>问题解决后向所有帮助过的人追加一条消息，让他们知道问题是如何解决的并再次感谢。如果问题在邮件列表或新闻组中受到广泛关注，在那里追加此消息比
较恰当。</p>
<p>最理想的方式是向最初提问的线索回复此消息并在主题包含“已解决”、“已搞定”或其它同样意思的明显标记。在人来人往的邮件列表里，一个看见线索
“问题X”和“问题X-已解决”的潜在回复者就明白不用再浪费时间了(除非他个人觉得“问题X”有趣)，因此可以用此时间去解决其它
问题。</p>
<p>你追加的消息用不着太长太复杂，一条简单的“你好──是网线坏了！谢谢大家──比尔”就比什么都没有要强。事实上，除
非解决问题的技术真正高深，一条简短而亲切的总结比长篇大论要好。说明是什么行动解决了问题，用不着重演整个排错的故事。</p>
<p>对于有深度的问题，张贴排错历史的摘要是适当的。描述问题的最终状态，说明是什么解决了问题，在此<span style="font-weight: bold; font-style: italic;">之后</span>才指明可以避免的弯路。应避免的
弯路部分应放在正确的解决方案和其它总结材料之后，而不要将此消息搞成侦探推理小说。列出那些帮助过你的名字，那样你会交到朋友的。</p>
<p>除了有礼貌、有内容以外，这种类型的追帖将帮助其他人在邮件列表、新闻组或论坛文档中搜索到真正解决你问题的方案，从而也让他们受益。</p>
<p>除上述而外，此类追帖还让每位参与协助的人因问题的解决而产生一种满足感。如
果你自己
不是技术专家或黑客，相信我们，这种感觉对于你寻求帮助的老手和专家非常重要。问题叙述到最后不知所终总是令人沮丧的，黑客们痒
痒地渴望看到它们被解决。“挠痒痒”为你挣到的好报将对你下次再次张贴提问非常非常的有帮助。 </p>
<p>考虑一下怎样才能避免其他人将来也遇到类似的问题，问问自己编一份文档或FAQ补丁有没有帮助，如果有的话就将补丁发给维护者。</p>
<p>在黑客中，这种行为实际上比传统的礼貌更重要，也是你善待他人而赢得声誉的方式，这是非常有价值的财富。</p>
</div>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2><a name="answers"></a>如何解读回答</h2>
</div>
</div>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="rtfm"></a>RTFM和STFW：如何知道你已完全搞砸</h3>
</div>
</div>
</div>
<p>有一个古老而神圣的传统：如果你收到了“RTFM”的回复，发信人认为你应该去“读读该死的手册”。他多半是对的，去读一下吧。</p>
<p>RTFM有个年轻的亲戚，如果你收到“STFW”的回复，发信人认为你应该“搜搜该死的网络”。他多半也是对的，去搜一下吧。(更温和一点的说法是
“Google
是你的朋友！”)</p>
<p>在网页论坛，你也可能被要求去搜索论坛的文档。事实上，有人甚至可能热心地为你提供以前解决此问题的线索。但不要依赖这种好心，提问前应先搜索
一下文
档。</p>
<p>通常，叫你搜索的人已经打开了能解决你问题的手册或网页，正在一边看一边敲键盘。这些回复意味着他认为：第一，你要的信息很容易找到。第二，自已找
要比别人喂到嘴里能学得更多。</p>
<p>你不应该觉得这样就被冒犯了，按黑客的标准，他没有不理你就是在向你表示某种尊敬，你反而应该感谢他热切地想帮助你。</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="lesser"></a>如果还不明白</h3>
</div>
</div>
</div>
<p>如果你看不懂回复，不要马上回发一个要求说明的消息，先试试那些最初提问时用过的同样工具(手册、FAQ，网页、懂行的朋友等)试着搞懂回
复。如果还是需要说明，展现你已经明白的。</p>
<p>譬如，假如我告诉你：“听起来象是某输入项有问题，你需要清除它”，接着是个<span style="font-weight: bold; font-style: italic;">不好</span>的回帖：“什么是某输入项？”。
而这是一个<span style="font-weight: bold; font-style: italic;">好</span>的跟帖：“是
的，
我读了手册，某输入项只在-z和-p开关中被提到，但都没有提及清除某选项，你指的是哪一个还是我弄错了什么？”</p>
</div>
<div class="sect2" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="keepcool"></a>对待无礼</h3>
</div>
</div>
</div>
<p>很多黑客圈子中看似无礼的行为并不是存心冒犯。相反，它是直接了当、一刀见血式的交流风格，这种风格对于更关注解决问题而不是使别人感觉舒服而混乱
的人
是很自然的。</p>
<p>你如果觉得被冒犯，努力平静地反应。如果有人真的做了过格的事，邮件列表或新闻组或论坛中的前辈多半会招呼他。如果这<span style="font-weight: bold; font-style: italic;">没有</span>发生而你却发火了，那么你发火对
象的言语
可能在黑客社区中看起来是正常的，而<span style="font-weight: bold; font-style: italic;">你</span>将
被视为有错的一方，这将伤害到你获取信息或帮助的机会。</p>
<p>另一方面，你会偶而真的碰到无礼和无聊的言行。与上述相反，对真正的冒犯者狠狠地打击、用犀利的语言将其驳得体无完肤都是可以
接受的。然尔，在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔，黑客们自己莽撞地越线情况并不鲜见。如果你是新
手或外来者，避开这种莽撞的机会不高。如果你
想得到的是信息而不是消磨时光，这时最好不要把手放在键盘上以免冒险。</p>
<p>(有些人断言很多黑客都有轻度的自闭症或阿斯伯格综合症，一定缺少平滑人类社会“正常”交往所需的脑电路。这既可能是真也可能是假。如果你自己不是
黑客，兴许
你认为我
们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了，我们不在乎。我们<span style="font-weight: bold; font-style: italic;">喜欢</span>我们现在这个样子，并且一般都对
临床诊断有相当的怀疑。)</p>
<p>在下一节，我们会谈到另一个问题，当你行为不当时会受到的“冒犯”</p>
</div>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2><a name="not_losing"></a>别象个失败者那样反应</h2>
</div>
</div>
</div>
<p>在黑客社区的论坛中有那么几次你会搞砸──以本文详述或类似的方式。你会被示众是如何搞砸的，也许言语中还会带点颜色。</p>
<p>这种事发生以后，你能做的最糟的事莫过于哀嚎你的遭遇、宣称被口头攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、忘了关马桶盖等
等。相
反，你该这样去做：<br>
</p>
<p>熬过去，这很正常。事实上，它是有益健康与恰当的。</p>
<p>社区的标准不会自己维持，它们是通过参与者积极而<span style="font-weight: bold; font-style: italic;">公开</span>地执行来维持的。不要哭嚎所有的
批评都应该通过私下的邮件传送，这不是事情运作的方式。当有人批评你的
一些主张或者其看法不同时，坚持声称个人被侮辱也毫无用处，这些都是失败者的态度。</p>
<p>也有其它的黑客论坛，受太高礼节要求的误导，要求参与者禁止张贴任何对别人帖子挑毛病的消息，并被告知“如果你不想帮助用户就闭嘴”。有思路的参与
者纷纷
离
开
的结果只会使它们变成了毫无意义的唠叨与无用的技术论坛。</p>
<p>是夸张的“友谊”(以上述方式)还是有用？挑一个。</p>
<p>记住：当黑客说你搞砸了，并且(无论多么刺耳地)告诉你别再这样做时，他正在为关心你和他的社区而行动。对他而言，不理你并将你从他的生活中滤除要
容易得
多。如果你无法做到感谢，至少要有点尊严，别大声哀嚎，也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者，就指望别人象对待脆弱的洋娃娃
那样对你。</p>
<p>有时候，即使你没有搞砸(或者只是别人想象你搞砸了)， 有些人会无缘无故地攻击你本人。在这种情况下，报怨倒是<span style="font-weight: bold; font-style: italic;">真的</span>会把问题搞砸。</p>
<p>这些找茬者要么是什么也不懂但自以为是专家的不中用家伙，要么就是测试你是否真会搞砸的心理学家。其它读者要么不理睬，要么用自己的方式对付他们。
这些找茬者在给自己找麻烦，这点你不用操心。</p>
<p>也别让自己卷入口水战，大多数口水战最好不要理睬──当然是在你核实它们只是口水战、没有指出你搞砸的地方，而且没有巧妙地将问题真正的答案藏于其
中
(这也
是
可能的)之后。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="classic"></a>提问禁忌</h2>
</div>
</div>
</div>
<p>下面是些典型的愚蠢问题和黑客不回答它们时的想法。</p>
<div class="qandaset">
<dl><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002488">我到哪可以找到程序或X资源？ </a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002514">我怎样用X做Y？</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002537">如何配置我的shell提示？</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002563">我可以用Bass-o-matic文件转换工具将AcmeCorp文档转为TeX格式
吗？</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002586">我的{程序、配置、SQL语句}不运行了</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002626">我的视窗电脑出问题了，你能帮忙吗？</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002657">我的程序不运行了，我认为系统工具X有问题</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002681">我安装Linux或X遇到困难，你能帮忙吗？</a></dt><dt>问： <a href="http://www.fengnet.com/smart-questions.html#id3002722">我如何才能破解超级用户口令/盗取频道操作员的特权/查看某人的电子邮件？</a></dt></dl>
<table summary="Q and A Set" border="0">
  <col align="left" width="1%"><tbody>
    <tr class="question">
      <td align="left" valign="top"><b>问：</b></td>
      <td align="left" valign="top">
      <p><a name="id3002488"></a>我到哪可以找到程序或X资源？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><b>答：</b></td>
      <td align="left" valign="top">
      <p>在我找到它的同样地方，笨旦──在网页搜索引擎上。上帝啊，难道还有人不知道如何使用 <a href="http://www.google.com/">Google</a> 吗？</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><b>问：</b></td>
      <td align="left" valign="top">
      <p><a name="id3002514"></a>我怎样用X做Y？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><b>答：</b></td>
      <td align="left" valign="top">
      <p>如果你想做的是Y，提问时别给出可能并不恰当的方法。这种问题说明提问者不但对X完全无知，也对要解决的Y问题糊涂，还被特定形势禁
锢了思维。等他们把问题弄
好再说。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><b>问：</b></td>
      <td align="left" valign="top">
      <p><a name="id3002537"></a>如何配置我的shell提示？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><b>答：</b></td>
      <td align="left" valign="top">
      <p>如果你有足够的智慧提这个问题，你也该有足够的智慧去 <a href="file:///home/frank/work/tran/smart-questions-3.0-cn.html#rtfm">RTFM</a>，
然后自己去找。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：</span><br>
      </td>
      <td align="left" valign="top">
      <p><a name="id3002563"></a>我可以用Bass-o-matic文件转换工具将AcmeCorp文档转为TeX格
式吗？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>试试就知道了。如果你试过，你既知道答案，又不用浪费我的时间了。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：</span><br>
      </td>
      <td align="left" valign="top">
      <p><a name="id3002586"></a>我的{程序、配置、SQL语句}不运行了</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>这不是一个问题，我也没有兴趣去猜你有什么问题──我有更要紧的事要做。看到这种东西，我的反应一般如下：</p>
      <div class="itemizedlist">
      <ul type="disc"><li>
          <p>你还有什么补充吗？</p>
        </li><li>
          <p>噢，太糟了，希望你能搞定。</p>
        </li><li>
          <p>这跟我究竟有什么关系？</p>
        </li></ul>
      </div>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：</span><br>
      </td>
      <td align="left" valign="top">
      <p><a name="id3002626"></a>我的视窗电脑出问题了，你能帮忙吗？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>是的，把视窗垃圾删了，装个象Linux或BSD的开源操作系统吧。</p>
      <p>注意：如果程序有官方的视窗版或与视窗有交互(如Samba)，你<span style="font-weight: bold; font-style: italic;">可以</span>问与视窗电脑相关的问题，只是别
对问题是由视窗操作系统而不是程序本身造成的回复感
到惊讶，因
为视窗一般来说太差，这种说法一般都成立。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：</span><br>
      </td>
      <td align="left" valign="top">
      <p><a name="id3002657"></a>我的程序不运行了，我认为系统工具X有问题</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与库文件有明显缺陷的人，更有可能的是你完全没有根据。不同凡响的说法需
要不同凡响的证据，
当你这样
声称时，你必须有清楚而详尽的缺陷说明文档作后盾。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：<a name="id3002681"></a></span><br>
      </td>
      <td align="left" valign="top">
      <p>我安装Linux或X遇到问题，你能帮忙吗？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>不行，我需要亲手操作你的电脑才能帮你排错，去向当地的Linux用户组寻求方便的帮助(你可以在 <a href="http://www.linux.org/groups/index.html">这里</a> 找到用户组列表)</p>
      <p>注意：在为某一Linux发行版服务的邮件列表或论坛或本地用户组织中提关于安装该发行版的问题也许是恰当的。此时，应描述问题的准确
细节。在此之前，先用
“linux”和<span style="font-weight: bold; font-style: italic;">所有</span>被怀
疑的硬件(为关键词)仔细搜索。</p>
      </td>
    </tr>
    <tr class="question">
      <td align="left" valign="top"><span style="font-weight: bold;">问：</span><br>
      </td>
      <td align="left" valign="top">
      <p><a name="id3002722"></a>我如何才能破解超级用户口令/盗取频道操作员的特权/查看某人的电子邮件？</p>
      </td>
    </tr>
    <tr class="answer">
      <td align="left" valign="top"><span style="font-weight: bold;">答：</span><br>
      </td>
      <td align="left" valign="top">
      <p>想做这种事情说明你是个卑劣的家伙，想让黑客教你做这种事情说明你是个白痴。</p>
      </td>
    </tr>
  </tbody>
</table>
</div>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="examples"></a>好问题与坏问题</h2>
</div>
</div>
</div>
<p>最后，我将通过举例来演示提问的智慧。同样的问题两种问法，一种愚蠢，另一种明智。</p>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">愚蠢：我在哪能找到关于Foonly
Flurbamatic设备的东西？</span></span><dt><span class="term"> </span><br>
  </dt><dd>
    <p>这个问题在乞求得到 <a href="http://www.fengnet.com/smart-questions.html#rtfm">STFW</a>
式的回复。</p>
  </dd><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">明智：我用Google搜索过“Foonly
Flurbamatic
2600”，但没有找到什么有用的，有谁知道在哪能找到这种设备的编程信息？</span></span><dt><span class="term">
    </span><br>
  </dt><dd>
    <p>这个人已经搜索过网络了，而且听起来他可能真的遇到了问题。</p>
  </dd></dl>
</div>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">愚蠢：我不能编译某项目的源代码，它为什
么这么破？</span></span><dt><span class="term"> </span><br>
  </dt><dd>
    <p>他假设是别人搞砸了，太自大了。</p>
  </dd><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">明智：某项目的源代码不能在某Linux
6.2版下编译。我读了常见问题文档，但其中没有与某Linux相关的问题。这是编译时的记录，我做错了什么吗？</span></span><dt><span class="term"> </span><br>
  </dt><dd>
    <p>他指明了运行环境，读了FAQ，列出了错误，也没有假设问题是别人的过错，这家伙值得注意。</p>
  </dd></dl>
</div>
<div class="variablelist">
<dl><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">愚蠢：我的主板有问题，谁能帮我？</span></span><dt><span class="term"> </span><br>
  </dt><dd>
    <p>某黑客对此的反应可能是：“是的，还需要帮你拍背和换尿布吗？”，然后是敲下删除键。</p>
  </dd><dt><span class="term"><span class="strong"></span></span><br>
  </dt><span class="term"><span class="term">明智：我在S2464主板上试过X、Y和
Z，当它们都失败后，又试了A、B和C。注意我试C时的奇怪症状，显然某某东西正在做某某事情，这不是期望的。通常
在Athlon MP主板上导致某某事情的原因是什么？有谁知道我还能再试点什么以确定问题？</span></span><dt><span class="term"></span><br>
  </dt><dd>
    <p>相反地，这个人看来值得回答。他展现了解决问题的能力而不是坐等天上掉馅饼。</p>
  </dd></dl>
</div>
<p>在最后那个问题中，注意“给我一个回复”与“请帮我看看我还能再做点什么测试以得到启发”之间细微但重要的差别。</p>
<p>事实上，最后那个问题基本上源于2001年8月Linux内核邮件列表(lkml)上的真实事件，是我(Eric)当时提了那个问题，我发现
Tyan
S2462 主板有神秘的死机现象，邮件列表成员给我提供了解决此问题的关键信息。<br>
</p>
<p>通过这种提问方式，我给了别人可以咀嚼玩味的东西。我设法使之对参与者既轻松又有吸引力，也表明了对同行能力的尊敬并邀请他们与我一起协商。通
过告诉
他们我已经走过的弯路，我还表明了对他们宝贵时间的尊重。</p>
<p>事后，当我感谢大家并评论这次良好的经历时，一个Linux内核邮件列表的成员谈到，他认为并不是因为我的名字在列表上，而是因为我正确的提问方式
才
得到了答
案。</p>
<p>黑客们在某种方面是非常不留情面的精英分子。我想他是对的，如果我表现得象个不劳而获的寄生虫，不管我是谁都会被忽略或斥责。他建议将整个事件作为
对其它
人
提问的指导直接导致了本文的编写。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="id3002966"></a>如果没有回复</h2>
</div>
</div>
</div>
<p>如果得不到回答，请不要认为我们不想帮你，有时候只是因为小组成员的确不知道答案。没有回复不等于被忽略，当然必须承认从外面很难看出两者的差别。</p>
<p>一般来说，直接将问题再张贴一次不好，这会被视为毫无意义的骚扰。</p>
<p>还有其它资源可以寻求帮助，通常是在一些面向新手的资源中。</p>
<p>有许多在线与本地用户组织，虽然它们自己不编写任何软件，但是对软件很热心。这些用户组通常因互助和帮助新手而形成。</p>
<p>还有众多大小商业公司提供签约支持服务(红帽与Linuxcare是两家最出名的，还有许多其它的)。别因为要付点钱才有支持就感到沮丧！毕竟，如
果你车子的
汽缸垫烧了，你多半还得花钱找个修理店把它弄好。即使软件没花你一分钱，你总不能指望服务支持都是免费的。</p>
<p>象Linux这样流行的软件，每个开发者至少有一万个以上的用户，一个人不可能应付这么多用户的服务要求。记住，即使你必须付费才能得到支持，也比
你还得额外花钱买软件要少得多(而且对封闭源代码软件的服务支持与开源软件相比通常还要贵一点，也要差一点)</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="id3003018"></a>如何更好地回答
问题</h2>
</div>
</div>
</div>
<p><span class="emphasis"><em></em></span><span style="font-weight: bold; font-style: italic;">态度和善一点。</span>问题带来的压力常使人
显得无礼或愚蠢，其实并不是这样。</p>
<p><span class="emphasis"><em></em></span><span style="font-weight: bold; font-style: italic;">对初犯者私下回复。</span>对那些坦诚犯错
之人没有必要当众羞辱，一个真正的新手也许连怎么搜索或在哪找FAQ都不知道。</p>
<p><span class="emphasis"><em></em></span><span style="font-weight: bold; font-style: italic;">如果你不确定，一定要说出来！</span>一个听
起来权威的错误回复比没有还要糟，别因为听起来象个专家好玩就给别人乱指路。要谦虚和诚实，给提问者与同行都树个好榜样。</p>
<p><span class="emphasis"><em></em></span><span style="font-style: italic;"><span style="font-weight: bold;">如果帮不了忙，别妨
碍。</span></span>不要在具体步骤上开玩笑，那样也许会毁了用户的安装──有些可怜的呆瓜会把它当成真的指令。</p>
<p><span class="emphasis"><em></em></span><span style="font-weight: bold; font-style: italic;">探索性的反问以引出更多的细节</span>。如
果你做得好，提问者可以学到点东西──你也可以。试试将很差的问题转变成好问题，别忘了我们都曾是新手。</p>
<p>尽管对那些懒虫报怨一声RTFM是正当的，指出文档的位置(即使只是建议做个Google关键词搜索)会更好。</p>
<p><span class="emphasis"><em></em></span><span style="font-style: italic;"><span style="font-weight: bold;">如果你决意回答，给
出好的答案。</span></span>当别人正使用错误的工具或不当
的方法时别建议笨拙的权宜之计，应推荐更好的工具，重新组织问题。</p>
<p><span class="emphasis"><em></em></span><span style="font-style: italic;"><span style="font-weight: bold;">帮助你的社区从问题中
学习。</span></span>当回复一个好问题时，问问自己
“如何修改相关文件或FAQ文档以免再次解答同样的问题？”，接着再向文档维护者发一份补丁。</p>
<p>如果你的确是在研究一番后才做出的回答，<span style="font-weight: bold; font-style: italic;">展
现你的技巧而不是直接端出结果。</span>毕竟“授
人以鱼，不如授人以渔”。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="id3003109"></a>相关资源</h2>
</div>
</div>
</div>
<p>如果还需要个人电脑、Unix和互联网如何工作的基础知识，参阅 <a href="http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/">Unix
和互联网如何工作的基本原理</a>
</p>
<p>当你发布软件或补丁时，尝试按 <a href="http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/index.html">软
件发布实践</a> 指南进行。</p>
</div>
<div class="sect1" xml:lang="en" lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="id3003139"></a>鸣谢</h2>
</div>
</div>
</div>
<p>Evelyn Mitchell 贡献了一些愚蠢问题样例并启发了编写“如何更好地回答问题”这一节，Mikhail
Ramendik 贡献了一些特别有价值的建议和改进。<br>
</p>
</div>
</div>

<br>
<br>
<br>

Powered&nbsp;by&nbsp;MessageSoft&nbsp;SMG&nbsp;<br>

SPAM,&nbsp;virus-free&nbsp;and&nbsp;secure&nbsp;email&nbsp;<br>

http://www.messagesoft.com&nbsp;<br>

<br>
<img src ="http://www.blogjava.net/briansun/aggbug/2995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-04-08 14:55 <a href="http://www.blogjava.net/briansun/articles/2995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse的前世今生?[转]</title><link>http://www.blogjava.net/briansun/articles/2867.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Tue, 05 Apr 2005 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/2867.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/2867.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/2867.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/2867.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/2867.html</trackback:ping><description><![CDATA[<h3><b><b>Eclipse的前世今生?[转]</b></b></h3>
<br>
Eclipse 最早来源于Object Technology International (OTI)于1994年开发的产品 IBM
VisualAge for Smalltalk，1996年又发布了IBM Visual Age for Java
。以上产品都是用Smalltalk写的，完全用Java编写的IDE则是后来推出的IBM VisualAge Micro
Edition这一产品，这也是Eclipse的主要基础，但这一产品对第三方组件的支持不够。后来经过一个小规模专家团队的研究，在总结过去开发经验的
前提下，提高了IDE的可扩展性，其产品就是Eclipse。2001年11月Eclipse开源项目正式建立，2005年3月24日的最新正式发布版本是
Eclipse3.0.2，稳定版本是Eclipse3.1M5。插件总数(据不完全统计)约742个，涉及软件开发的方方面面。插件分类如下：Bug
Tracker (6)、Code Generation (13)、Code mngt (73)、Database
(44)、Deployment (18)、Documentation (26)、Editor (16)、Electronics
(1)、Entertainment (36)、Graphics (5)、J2EE development platform
(35)、Languages (43)、Middleware (6)、Mobile/PDA (12)、Modelling
(16)、Network (11)、News (7)、Obsolete (3)、Patterns (4)、Profiling
(12)、Project management (4)、Research (3)、Rich Client
(5)、Safety-critical (2)、SCM (20)、Snipets (2)、Snipets/Modelling
(1)、Source Code Analyzer (21)、Team (6)、Testing (25)、Tomcat (5)、Tools
(51)、Tutorial (33)、UI (31)、UI components (9)、UML (20)、Utility (27)、Web
(39)、Web Service (19)、XML (32)。<br>
<img src ="http://www.blogjava.net/briansun/aggbug/2867.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-04-05 10:48 <a href="http://www.blogjava.net/briansun/articles/2867.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Best Practise for Risk-Free Deployment</title><link>http://www.blogjava.net/briansun/articles/2644.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Thu, 31 Mar 2005 03:12:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/2644.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/2644.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/2644.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/2644.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/2644.html</trackback:ping><description><![CDATA[<img src="http://www.theserverside.com/articles/content/BuildManagement/BuildManagement.gif" alt="Best Practices for Risk-Free Deployment" align="middle" border="0">

<br>

<br>

<br>

<b>March 2005</b>
<br>


<h2><b><a href="http://www.theserverside.com/news/thread.tss?thread_id=32929">Discussion</a></b></h2>

<br>





<h2>Overview</h2>

<p>The cost impact to a company of a failed project can be severe indeed. The
  impact on the reputation of the project manager can be disastrous.</p>

<p>Software project management is not easy, and it requires considerable skill
  to successfully manage the many different risks that conspire to de-rail a
  project:</p>

<p><img src="http://www.theserverside.com/articles/content/BuildManagement/IMG01.gif"></p>

<p>Numerous methodologies are available for mitigating these risks – PRINCE2,
RUP, DSDN, eXtreme programming – and these have helped to some extent.</p>

<p>This document introduces the 3D™ methodology – a set of best practices
  and quality tools developed by BuildMonkey, which can be summarised as.</p>

<p><strong> De-risk. Deploy. Deliver.</strong></p>

<p>In any software project, deployment is a milestone on the project plan that
  is usually associated with payment – or staged payment. Through the course
  of development, any number of problems can arise to derail efforts to reach
  this milestone.</p>

<p>The 3D™ methodology and supporting toolset is based on many years of
  experience at the sharp end of projects, understanding what has worked and
  what has not, and the lessons learned from each.</p>

<p>Competent practitioners, and experienced project staff, will find resonance
  with many of the contents of this document and may find themselves saying “<em>this
  is just common sense</em>”. This is certainly true, but the main problem
  with common sense is that it is not as common as people think it is.</p>

<p>This document, and the 3D™ methodology, is an attempt to bring that
  common sense together in a single location, as a coherent set of best practices
  supported by proven tools to help you to <strong><em>release on-time, on-budget,
with no defects</em></strong>.</p>

<h2>The Problem To Be Solved</h2>

<p>No methodology has yet focused on the component that all development projects
  share – the build.</p>

<p>One of the reasons for this is that the term “build” is interpreted
  differently by different people:</p>

<ul>
<li>The development team sees it as compilation and assembly;</li><li>The integration team see it as the bringing together of all of the components
  in the application in a format suitable for release;</li><li>The deployment team see it as something which produces the artifacts that
  they have to install and configure;</li><li>The testing team see it as something which produces the artifacts that
  they have to test;</li><li>The Project Manager sees it as an opaque step that nobody is entirely responsible
  for;;</li><li>The end customer should not see it at all;</li>
</ul>

<p>The BuildMonkey view is that the build is the combination of processes and
  technology that take software from design to deployment – _where the
  return on investment starts to be seen.</p>

<p>It is clear that a methodology is required to de-risk development projects
  and to standardise use of the term “Build Management”.</p>

<p><strong>Best Practice: “<em>Build Management</em>” encompasses
    everything from compilation, all the way through to release to the customer. </strong></p>

<h2>No Release, No Revenue</h2>

<p>Any Finance Director knows that development is just an activity that needs
  to be tolerated in order to produce something that will deliver a return on
  investment.</p>

<p>It may sound strange, but a large number of software developers do not appreciate
  and embrace this basic truth. This is in part due to their closeness to the
  application being constructed.</p>

<p>A common problem faced by development projects is therefore that it is the
  software developers who manage the build. This creates a situation where the
  build is focused on the needs of development, and is not geared towards releasing
  the output of coding such that business value can be realised.</p>

<p>Build Management should therefore focus on the end result of development – a
  return on investment – and ensure that all of the inputs to the process
  are incorporated in pursuit of this goal:</p>

<p>Best Practice: Focus on the end, and accommodate the inputs</p>

<h2>Software Tools Are Only Part of the Answer</h2>

<p>Software projects are a complex set of interdependent people and teams and
  can be likened to a convoy of ships. A convoy has to move at the rate of the
  slowest ship. Increasing the speed of a single ship in the convoy will not
  increase the speed of the convoy – it will simply increase the amount
  of wasted capacity in the speeded-up ship.</p>

<p>Speeding up the slowest ship will, however, have a positive effect since the
  whole convoy can now move faster.</p>

<p> Many Project Managers try to improve productivity by implementing some degree
  of automation in development projects – particularly in the area of the
  build – and often purchase “<em>magic bullet</em>” build
  software that provides this.</p>

<p>Simply using automated build software does not improve productivity any more
  than the example above improves convoy speed - as it only increases the speed
  of a single ship in the convoy.</p>

<p>There is no point in speeding up development, if the target production infrastructure
  cannot keep pace – this just increases the inefficiency. A lot of organisations
  make this mistake – highly agile development processes trying to feed
  into considerably less agile deployment processes. The result is inefficiency,
  waste and over-run.</p>

<p>Before considering using an automated build tool it is essential to ensure
  that the inputs to, and outputs from, the build can cope with the improved
  build speed. It is imperative to ensure that the processes and technology employed
  are geared towards taking the project to a successful conclusion – on-time
  and on-budget.</p>

<p>Best Practice: Don’t rely on software tools alone, they may solve symptoms
whilst creating problems elsewhere</p>

<h2>Configuration Management Best Practices</h2>

<p>Software Configuration Management (SCM) is a relatively mature discipline
  with much written about methodologies and techniques, and these will not be
  recreated here.</p>

<p>We will focus instead on leveraging the SCM repository, and the facilities
  that it offers, to further the goals of the project rather than to consider
  SCM in its own right.</p>

<h2>It All Starts Here</h2>

<p>The SCM repository - how it is managed and used – is the keystone of
  good build management and successful delivery of projects.</p>

<p>The SCM repository is the slave of the project, not the other way round. It
  should be solid and reliable, yet flexible enough to accommodate the needs
  of new projects. Project Managers should not have to retrofit their planning
  to accommodate an inflexible SCM setup.</p>

<p>If used correctly, the SCM repository will enhance productivity, and minimize
  risk, through being able to provide exactly what the project – and project
  management – require. If used incorrectly, it can cause delay and slippage
  through having to do things inefficiently further down the chain.</p>

<p>Best Practice: The SCM repository is the slave of the project, not the other
  way round.</p>

<h2>Configuration Management is not Version Control</h2>

<p>Most software developers regard the SCM repository as a massive storage area
  where they simply check versions in and out – a common cause of problems.</p>

<p>Simply checking things into an SCM repository is not Configuration Management
  any more than karaoke is opera.</p>

<p>A well-maintained SCM repository is so much more than version control, and
  should provide:</p>

<ul>
<li>The ability to recreate any identified baseline, at any time;</li><li>Meaningful statistics on what is changing, when and by whom;</li><li>Management information, such as “<em>how many new defects were introduced
      by the refactoring of component ‘X’?</em>”</li>
</ul>

<p>In order to be truly effective in a project, the SCM repository should store
  all of the artifacts that form part of a baseline or a release.</p>

<b>Source Code</b>
<p>Most development projects simply store the code that is being developed and
  their use of the SCM repository is no more sophisticated than this.</p>

<b>Data</b>
<p>Most applications nowadays are not just source code. Take the example of a
  modern computer game – the vast majority of the code base is made up
  of artifacts other than code such as audio clips, pictures and movie clips.</p>

<b>Database Structure and Contents</b>
<p>Where an application relies on a database this database will have a schema
  and structure that may change from release to release – this schema must
  be captured.</p>

<p>There will normally also be seed data for the database which should be considered
  as part of the baseline.</p>

<b>Application Configuration</b>
<p>In a large distributed application, the software being developed will sit
  atop a number of pieces of software (e.g. application servers, web servers
  and message queues).</p>

<p>The configuration of these underlying applications have an effect on the quality – or
  otherwise – of the software being developed and should, therefore, be
  considered part of the baseline for a release.</p>

<b>Environment Configuration</b>
<p>The underlying environment and infrastructure is a key component of the project,
  particularly in the case of distributed applications.</p>

<p>Such banal considerations as DNS zone files, user account information and
  system parameters have to be considered as some of the moving parts which affect
  the application and therefore be placed under configuration control.</p>

<p>This is of particular importance when there is more than one environment involved
  in the project (e.g. a development environment and a separate test environment)
  since the question of “<em>are these environments the same?</em>” crops
  up again and again.</p>

<p>Best Practice: Everything that can be changed, and affect the behaviour of
  the application, is a candidate for configuration control</p>

<h2>The Point of Labelling</h2>

<p>It is a common misconception that simply applying labels, or tags, to the
  SCM repository creates a baseline but this is only partly true without corresponding
  records of:</p>

<ul>
<li>What label has been applied;</li><li>When that label has been applied;</li><li>Why it has been applied (i.e. what milestone, or other external event,
    the label is associated with);</li>
</ul>

<p>The use of a naming convention for labels can deceive even further. For example,
  a project that uses a date-based labeling convention (<em>dd_mm_yyyy</em>)
  will have several labels of the form (<em>03_05_2004</em>, or <em>09_06_2004</em>)
  and will reasonably assume that they have some kind of record of the baseline
  on those dates.</p>

<p>But what was happening in the project on those dates? Was the <em>03_05_2004</em> label
  applied immediately before a release to test, or immediately after?</p>

<p>Best Practice: Labels should be used to identify and inform about events in
  the project</p>

<b>Don’t Label If There Is No Point</b>
<p>This may seem like stating the obvious, but there should be a reason for a
  label being applied – the whole purpose of labeling is to identify some
  event in the development cycle that may need to be re-visited.</p>

<p>To this end, labels can be divided into two categories:</p>

<ul>
<li>Point-in-time<br>
    Associates particular versions with a particular calendar date, or other
  event that is fixed in time (e.g. <em>MONTH_END_JAN_2004</em>, or <em>RELEASE_1_0_1</em>);</li><li>Point-in-process<br>
    Associates particular versions with events in the project that may recur
      at a later stage (e.g. <em>LATEST_RELEASE</em>, or <em>CURRENTLY_IN_UAT</em>);</li>
</ul>

<p>Best Practice: Every label should have a point, whether point-in-time or point-in-process</p>

<h2>Management Information</h2>

<p>The job of the Project Manager, ultimately, is to bring the project to a successful
  conclusion. If this were an easy task that happened by default, then there
  would be no need for a Project Manager.</p>

<p>In order to be able to do this job well, a Project Manager needs information.
  He needs to know what is going on in the project – who is doing what,
  who is working on which components, and a wealth of information can be obtained
  from a well-managed SCM repository:</p>

<ul>
<li>What is changing in the environment – what has changed since a given
    point in time or how often particular
  elements are changing;</li><li>Who is changing things in the environment;</li><li>Why things are changing in the environment;</li>
</ul>

<p>Of course, the final item in the list requires that committers are using descriptive
  comments to indicate why they are marking a particular change. A well-managed
  SCM repository should enforce this.</p>

<p>Best Practice: The SCM repository should provide meaningful, and accessible,
management information</p>

<h2>Build Best Practices</h2>

<p>As explained at the beginning of this document, the term “build” means
  different things to different people. The most common interpretation is the
  one used by developers, where the term “build” describes the compilation
  and assembly step of their development activities but this narrow interpretation
  is a common cause of problems and over-runs, on development projects.</p>

<h2>Building is not Compiling</h2>

<p>At the outset of the project, the Project Manager will ask the question “<em>how
    long to set up the build?</em>” and a developer – thinking of
    compilation and assembly – will answer something like “<em>1
    day”</em> – a task and duration which is then duly marked on
    the project plan and development begins.</p>

<p>Later in the project, when it is time to start deploying and testing the application,
  this “build” needs to be refactored to accommodate the deployment
  and test tasks. In doing so, it turns out that the way the application is being
  assembled is not conducive to it being deployed or tested correctly – so
  the compilation and assembly staged need to be refactored as well.</p>

<p>In the meantime, the development team sits on its hands whilst the “build” is
  refactored to accommodate the needs of the project – valuable time is
  lost whilst the deadline continues to advance.</p>

<p>Best Practice: Know what will be required of the build before starting to
  write the scripts</p>

<h2>Don’t Throw Out The Baby With The Bathwater</h2>

<p>From a build perspective, projects with similar architecture (both in terms
  of the team and the application) will have similar attributes. There will obviously
  be some changes required, but these will tend to follow the 80/20 rule to a
  large degree.</p>

<p>For example, a web application that is being developed by an in-house team
  and that will be deployed to a Tomcat servlet container and Oracle database
  will follow largely the same steps and require largely the same deployable
  artifacts.</p>

<p>A good SCM repository will enable the latest versions of boiler-plate build
  scripts for such an application to be found. These can be used almost off-the-shelf – meaning
  that development can start apace without having to wait on the build to be
  constructed for similar applications .</p>

<p>Best Practice: Well-crafted builds are re-usable and should be re-used</p>

<h2>The Architecture Drives The Build&lt;</h2>

<p>Following on from the previous section, it should be clear that the architecture
  of what is being developed – and the structure of the team(s) developing
  it – will dictate how the build should look.</p>

<p>There is little value to be gained in trying to retrofit build scripts for
  a computer game (developed by 12 people all in the same room) into a project
  to produce a large J2EE application with development occurring at six different
  sites around the world.</p>

<p>Best Practice: Well-crafted builds are flexible, but a “one-size-fits-all” approach
  can be costly</p>

<h2>Management Information</h2>

<p>There are a number of people who need information that the build can provide:</p>

<ul>
<li>The Project Manager needs to track overall progress against defined milestones – number
  of outstanding defects, whether a committed release date will be met etc;</li><li>Development leads need to be sure that the code is of the quality that
    they require – test reports, bug analysis patterns, code metrics, document
  and UML generation etc;</li><li>The deployment team need to know that the artifacts will work in their
    target environment, and that the environment is as the application expects
    it to be. They also need to know whether two (or more) environments are “<em>the
  same</em>”;</li><li>The test team need to have confidence that they are testing against a known
    baseline, and whether defects that they see have been rectified in development
  (or whether they are re-appearing after already being fixed);</li><li>Everybody needs to be able to communicate effectively using the same language,
    and have a common terminology for release versions – particularly if
  there are multiple threads of development;</li>
</ul>

<p>A good build infrastructure will provide all of the above information, and
  more besides.</p>

<p>Best Practice: The build should tell all project participants what they need
to know</p>

<h2>Deployment Best Practices</h2>

<p>Considering that it is generally an important milestone on a project plan,
  normally resulting in payment or a staged payment, deployment is one of the
  most overlooked areas of software development.</p>

<p>The normal course of events is:</p>

<ol>
<li>Release artifacts are created;</li><li>Some installation and release notes are cobbled together in the form of
  a README;</li><li>The deployment team work frantically to install and configure the application – the
    testing team (or, worse still, the customer) are idle and unproductive in
  the meantime;</li><li>Some symptoms are found which are suspected to be application defects;</li><li>The development team blame the environment;</li><li>The deployment team blame the application;</li><li>Repeat (5) and (6) <em>ad nauseam</em>.</li>
</ol>

<p>When a documentation team are also considered - responsible for creating documentation
  that the end user will need to install, configure and use the application – the
  situation becomes even more difficult.</p>

<p>This situation can be avoided by planning for deployment from the beginning.
  Deployment is an inevitable part of software development, yet it always seems
  to take people by surprise.</p>

<p>Best Practice: Know that deployment is inevitable, and incorporate it into
  the automated processes</p>

<h2>Deployment Is Not Installation</h2>

<p>As part of normal development activities, artifacts are installed into sandbox
  environments – and test environments – many times. But this is
  not deployment, this is installation.</p>

<p>In order to get an application into its production environment, be that an
  internal environment or on hosted-infrastructure, a number of hurdles must
  be overcome:</p>

<ul>
<li>The application must pass UAT;</li><li>The application must be installed and configured correctly:</li><li>All pre-requisites for the application must be satisfied;</li><li>The end customer must accept the handover;</li>
</ul>

<p>Deployment is that point in the life of an application where it starts to
  produce a return on investment. “<em>Launch</em>”, “<em>Go-live</em>”, “<em>Release</em>”, “<em>First
  Customer Shipment</em>” are all phrases which describe the same event.</p>

<p>Best Practice: Deployment is the point where an application starts to provide
  a return on the development investment.</p>

<h2>The Environment Is a Refactorable Component</h2>

<p>This point cannot be stressed enough, particularly in large distributed applications.</p>

<p>Every application, large or small, has a runtime environment in which it operates.
  In a simple desktop application, this is a standalone machine (such as a PC).
  In larger applications, this will be a combination of machines (e.g. an application
  server and a database) operating together to provide the runtime environment.</p>

<p>In either case, the application expects certain facilities to be available
  from the runtime environment and will function incorrectly – or cease
  to function – if these are not present .</p>

<p>The environment itself, whether standalone or a network, contains many moving
  parts that can be independently configured. IP addresses, or hostnames, can
  be changed. User privileges can be modified or revoked. Files and directories
  can be removed. Each of these can have an effect on the way that the application
  behaves.</p>

<p>In an environment that is owned and managed internally this can be bad enough.
  In an environment that is owned and managed by an external third party, and
  where project success is contingent upon successful UAT in that environment,
  this can be disastrous.</p>

<p>Best Practice: Be able to identify whether the deployment environment is as
  prescribed, and “<em>fit for deployment</em>”</p>

<b>Environment Verification Testing</b>
<p>One of the most common questions that arises in development projects containing
  more than one environment is, simply, “<em>are these environments the
  same?</em>” and its answer can be elusive.</p>

<p>It is essential to be able to answer that question – quickly and accurately – so
  that any perceived defects in the application can be categorised as “<em>defect</em>” or “<em>environmental</em>”.</p>

<p>This ability becomes particularly poignant where on or more of the environments
  are owned by different teams, or organisations.</p>

<p>Best Practice: Be able to prescribe what the deployment environment should
  look like, and have a capability to test it quickly.</p>

<b>Regression Testing</b>
<p>The environment, as explained earlier, is a refactorable component. It can
  be changed, and parts can be moved or deleted. However, unlike application
  code, changes may need to be made to the environment in response to external
  events (e.g. hardware failure, or security policies).</p>

<p>Applications, particularly complex ones, use regression tests to ensure that
  observed behaviour after a change is exactly as it was before the change was
  made. The same should be true of the environment.</p>

<p>Best Practice: Automated regression tests for the environment that will compare
  observed behaviour both before and after changes are made.</p>

<p>For example, suppose that a number of operating system patches or service
  packs are applied to an environment where the application has been, or will
  be, deployed. How are these tested? Do you wait for users, or testers, to start
  calling to say that there are problems?</p>

<p>Or do you make sure that you know what problems have been introduced before
  your users do?</p>

<b>Configuration Management</b>
<p>As stated earlier, the SCM repository should be used to store any artifact
  that can be changed and that may have an effect on the environment.</p>

<p>It may not seem obvious, but some of the most obscure environmental changes
  can cause an application to fail:</p>

<ul>
<li>Hostname resolution;</li><li>Non-existent user or group accounts;</li><li>IP and network connectivity;</li><li>Existence, or otherwise, of files and directories ;</li><li>Application or operating system configuration files;</li>
</ul>

<p>It is essential that these environmental variables be placed under configuration
  control and able to be identified as part of a baseline.</p>

<p>Best Practice: Environmental artifacts that are not part of the application
should be part of the baseline</p>

<h2>Automate, Automate, Automate</h2>

<p>Every single task that is performed as part of a development project – throughout
  the entire lifecycle – can be placed into one of two categories:</p>

<ol>
<li>Tasks which require some form of human judgment;</li><li>Tasks which do not;</li>
</ol>

<p>Tasks which fall into the first category can use some degree of automation,
  but should stop and wait for human intervention wherever judgment is required.</p>

<p>Tasks in the second category should be automated. There is no value in having
  expensive resources employed to do mechanical or repetitive tasks that a computer
  could do more quickly, accurately and consistently.</p>

<p>Best Practice: Automate anything that does not require human judgment</p>

<p>A note of caution - it may be tempting to think that automation will increase
  productivity on its own, but this is not necessarily the case. Automating an
  inefficient process will simply magnify its inefficiency – as explained
  in the section on <strong><em>Software Tools are Only Part of the Answer</em></strong>.</p>

<p>This, and it is worth repeating, is a common error – to assume that
  automated build software alone will improve productivity.</p>

<p>Best Practice: Do not automate inefficient processes, or you will only maximize
the inefficiency</p>

<h2>About BuildMonkey</h2>

<p>BuildMonkey is a division of Nemean Technology Limited - a leading technical
  innovator specialising in Agile Deployment and build management.</p>

<p>We have over a decade of experience in helping clients increase productivity
  in their build, integration and test cycles. We have a track record of massively
  reducing costs and defects through process automation and proven methodologies.</p>

<p>Formed in 1999, and profitable every quarter, we invented the discipline of
  BuildMaster - <strong>we are the original and the best.</strong></p>

<p>We provide specialist Build Management products and services - when all you
  do is Build Management, you get pretty good at Build Management. Our world-class
  Professional Services staff are the best in their field, complemented by original
  software products of the finest quality.</p>

<p>We aim to be the leading provider of Build Management products and services
  in the UK by providing excellent service to our customers, and by empowering
  Software Project Managers to aim for <strong><em>release on-time, on-budget,
  with no defects</em></strong>.</p>

<h2>About the Author</h2>

<p>John Birtley has been a specialist in Configuration and Build Management since
  1994 with a focus on deployment - particularly the packaging and installation
  of developed applications. He has worked for a number of blue-chip organisations
  including Sun Microsystems, Hewlett Packard, Sony and Ericsson in the transition
  from development to deployment. BuildMonkey was launched in January 2004, to
  package and commoditise this cumulative experience under the title of "Agile
  Deployment". He lives in Southampton, where dogs and children conspire to take
what little spare time he has. </p>



<p align="center">
<a href="http://www.theserverside.com/articles/content/BuildManagement/article.html">PRINTER FRIENDLY VERSION</a>
<br>
<img src="http://www.theserverside.com/images/tss_white.gif" align="middle">
</p>
<img src ="http://www.blogjava.net/briansun/aggbug/2644.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-03-31 11:12 <a href="http://www.blogjava.net/briansun/articles/2644.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CLR Loader and Java Class Loader Compared[转]</title><link>http://www.blogjava.net/briansun/articles/2520.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Mon, 28 Mar 2005 03:34:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/2520.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/2520.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/2520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/2520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/2520.html</trackback:ping><description><![CDATA[<div class="postText">
		<p class="MsoNormal" style="margin: 0in 0in 0pt;">Flier Lu<span style="font-family: 宋体;" lang="ZH-CN">问到</span>CLR Loader<span style="font-family: 宋体;" lang="ZH-CN">和</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">有什么不一样。要回答这个问题不容易，因为我对</span>Java<span style="font-family: 宋体;" lang="ZH-CN">一窍不通。但既然问题提出来了，打肿脸来充胖子也得回答啊。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">于是今天下午我在</span>google<span style="font-family: 宋体;" lang="ZH-CN">上逛了一圈，找了些关于</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">的文章看了看。我的结论是，和</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">类似的东东，在</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">里是不存在的。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">简单的说，</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">里不存在一个类似于</span>Java.Lang.ClassLoader<span style="font-family: 宋体;" lang="ZH-CN">的东西。所以你无法实现你自己的</span>CLR Loader<span style="font-family: 宋体;" lang="ZH-CN">。</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">里只有一个</span>Loader<span style="font-family: 宋体;" lang="ZH-CN">，那就是</span>CLR Loader<span style="font-family: 宋体;" lang="ZH-CN">。当然，</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">提供了自己独特的方式让你做动态装载。你所拥有的自由度是远比</span>Java<span style="font-family: 宋体;" lang="ZH-CN">要大得多。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">下面是具体分析。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">我对</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">的理解主要是从这两篇文章里来的。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;">“Inside Class Loader” by Andeas Schaefer (<a href="http://www.onjava.com/lpt/a/4337">http://www.onjava.com/lpt/a/4337</a>) <span style="font-family: 宋体;" lang="ZH-CN">和</span><span lang="ZH-CN"> </span>“The basics of Java Class Loaders” by Chuck McManis (<a href="http://www.javaworld.com/javaworld/jw-10-1996/jw-10-indepth_p.html">http://www.javaworld.com/javaworld/jw-10-1996/jw-10-indepth_p.html</a>)<span style="font-family: 宋体;" lang="ZH-CN">。我看了看</span>JVM Spec<span style="font-family: 宋体;" lang="ZH-CN">。但是我觉得不如上面两篇文章清楚。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">先说</span>Java<span style="font-family: 宋体;" lang="ZH-CN">里的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">吧。</span>Java<span style="font-family: 宋体;" lang="ZH-CN">里的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">就是</span>Class <span style="font-family: 宋体;" lang="ZH-CN">。</span>Class<span style="font-family: 宋体;" lang="ZH-CN">就是</span>Namespace + class name.<span style="">&nbsp; </span>Class<span style="font-family: 宋体;" lang="ZH-CN">通过</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">来装载的。</span>System Class Loader<span style="font-family: 宋体;" lang="ZH-CN">缺省的话只在</span>CLASSPATH<span style="font-family: 宋体;" lang="ZH-CN">中寻找</span>Class<span style="font-family: 宋体;" lang="ZH-CN">。如果你要在</span>CLASSPATH<span style="font-family: 宋体;" lang="ZH-CN">之外转载</span>Class<span style="font-family: 宋体;" lang="ZH-CN">的话，你就需要自己的</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">。如果两个</span>Class<span style="font-family: 宋体;" lang="ZH-CN">有相同的名字，并且在同一个</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">里，那么它们就被</span>JVM<span style="font-family: 宋体;" lang="ZH-CN">认为是相同的，可以互相赋值。如果有一个不一样的话，它们就被认为是不一样的。互相赋值会发生</span>ClassCaseException<span style="font-family: 宋体;" lang="ZH-CN">。换句话说，</span>Class name + Class Loader<span style="font-family: 宋体;" lang="ZH-CN">是一个</span>Type<span style="font-family: 宋体;" lang="ZH-CN">的独特的</span>ID<span style="font-family: 宋体;" lang="ZH-CN">。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;">Java<span style="font-family: 宋体;" lang="ZH-CN">的这个模型有很多问题。首先它把</span>Class name<span style="font-family: 宋体;" lang="ZH-CN">做为</span>Type<span style="font-family: 宋体;" lang="ZH-CN">的</span>ID<span style="font-family: 宋体;" lang="ZH-CN">。两个</span>Class<span style="font-family: 宋体;" lang="ZH-CN">如果有同样的名字，但是实际内容不一样的话，如果它们被同一个</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">装载，</span>JVM<span style="font-family: 宋体;" lang="ZH-CN">会认为它们是同一个</span> Type<span style="font-family: 宋体;" lang="ZH-CN">。这个太搞笑了。结果就是</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">必须要有一些特别的办法来管理</span>Class name<span style="font-family: 宋体;" lang="ZH-CN">。一般的办法是加一个前缀，比如说</span>Class<span style="font-family: 宋体;" lang="ZH-CN">的</span>URL<span style="font-family: 宋体;" lang="ZH-CN">。如果</span>Namespace<span style="font-family: 宋体;" lang="ZH-CN">管理不好的话，很容易就是安全漏洞。这是为什么</span>JVM Spec<span style="font-family: 宋体;" lang="ZH-CN">里提到</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">必须要让</span>Parent Class Loader<span style="font-family: 宋体;" lang="ZH-CN">先搜索</span>Class<span style="font-family: 宋体;" lang="ZH-CN">，再自己寻找。而且</span>Class loader<span style="font-family: 宋体;" lang="ZH-CN">必须要保存</span>Class resolution<span style="font-family: 宋体;" lang="ZH-CN">的结果，这样下次</span>Class resolution<span style="font-family: 宋体;" lang="ZH-CN">的时候，</span>Class loader<span style="font-family: 宋体;" lang="ZH-CN">会返回同样的结果。</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">有太多的限制，同时又有太多的责任。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">另一个问题是共享问题。如果同一个</span>Class<span style="font-family: 宋体;" lang="ZH-CN">被两个不同的</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">装载的话，</span>JVM<span style="font-family: 宋体;" lang="ZH-CN">认为这两个</span>Class<span style="font-family: 宋体;" lang="ZH-CN">不是同一个</span>Type<span style="font-family: 宋体;" lang="ZH-CN">，不能互相赋值。结果就是</span>Class<span style="font-family: 宋体;" lang="ZH-CN">无法共享。被不同</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">装载的</span>Class<span style="font-family: 宋体;" lang="ZH-CN">无法直接对话。直接对话会产生</span>linkage<span style="font-family: 宋体;" lang="ZH-CN">错误。它们只能间接对话，比如通过</span>Interface<span style="font-family: 宋体;" lang="ZH-CN">，或者共同的</span>Base Class<span style="font-family: 宋体;" lang="ZH-CN">。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">还有一个问题是</span>Versioning<span style="font-family: 宋体;" lang="ZH-CN">。因为</span>Java<span style="font-family: 宋体;" lang="ZH-CN">的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">里只有名字，所以当你看到一个</span>Type<span style="font-family: 宋体;" lang="ZH-CN">的时候，你无法知道它是第一版，还是第二版。所以如果你需要第二版，但是</span>Class loader<span style="font-family: 宋体;" lang="ZH-CN">给你装载了第一版的时候，祈祷吧。也许上帝能救你。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">现在回过头来看看</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">的模型。</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">包括两部分：</span>Class name + Assembly Name<span style="font-family: 宋体;" lang="ZH-CN">。</span>Class name<span style="font-family: 宋体;" lang="ZH-CN">是和</span> Java<span style="font-family: 宋体;" lang="ZH-CN">的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">类似的东西，就是</span>namespace<span style="font-family: 宋体;" lang="ZH-CN">。</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">是</span>Java<span style="font-family: 宋体;" lang="ZH-CN">没有的东西。</span>Assembly Name<span style="font-family: 宋体;" lang="ZH-CN">的属性包括</span>Name, Version, Culture, PublicKey(Token)<span style="font-family: 宋体;" lang="ZH-CN">。</span><span lang="ZH-CN"> </span><span style="font-family: 宋体;" lang="ZH-CN">如果两个</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">有一个属性不一样，那么它们就认为是不一样的。两个</span>Type<span style="font-family: 宋体;" lang="ZH-CN">如果有同样的</span>Class name<span style="font-family: 宋体;" lang="ZH-CN">，但是</span>Assembly Name<span style="font-family: 宋体;" lang="ZH-CN">不一样的话，它们也认为是不一样的。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;">CLR<span style="font-family: 宋体;" lang="ZH-CN">的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">引用总是包括</span>Class name <span style="font-family: 宋体;" lang="ZH-CN">和</span> Assembly Name<span style="font-family: 宋体;" lang="ZH-CN">的。所以</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">在寻找一个</span>Type<span style="font-family: 宋体;" lang="ZH-CN">的时候，主要是寻找</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">。找到了</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">之后，</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">看看这个</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">里有没有这个</span>Class<span style="font-family: 宋体;" lang="ZH-CN">。有的话就万事大吉，没有的话就是</span>TypeLoadException<span style="font-family: 宋体;" lang="ZH-CN">。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;">CLR<span style="font-family: 宋体;" lang="ZH-CN">区别</span>Type<span style="font-family: 宋体;" lang="ZH-CN">主要靠</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">。</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">有</span>PublicKey(Token)<span style="font-family: 宋体;" lang="ZH-CN">。别人无法冒充你。所以象</span>Java<span style="font-family: 宋体;" lang="ZH-CN">里的</span>namespace<span style="font-family: 宋体;" lang="ZH-CN">的问题就不存在了。</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">有自己的</span>Version<span style="font-family: 宋体;" lang="ZH-CN">。你要第二版的时候</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">不会装载第一版给你。所以象</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">那样的限制，责任和问题都不存在了。从这个角度上讲，这正是为什么</span>CLR<span style="font-family: 宋体;" lang="ZH-CN">里没有象</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">那样的东西。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">但并不是说你就不能动态装载了，而是说你动态装载的时候就不用考虑那些垃圾了。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">关于共享的问题，因为没有了你自己的</span>Class loader<span style="font-family: 宋体;" lang="ZH-CN">，所以任何</span>Type<span style="font-family: 宋体;" lang="ZH-CN">都可以直接对话。同样的</span>Type<span style="font-family: 宋体;" lang="ZH-CN">也不会因为</span>Class Loader<span style="font-family: 宋体;" lang="ZH-CN">不一样而被认为不一样。</span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;">CLR Loader<span style="font-family: 宋体;" lang="ZH-CN">有自己的规则怎么寻找</span>Assembly<span style="font-family: 宋体;" lang="ZH-CN">。它先看</span>GAC<span style="font-family: 宋体;" lang="ZH-CN">，再看你的程序目录。都没有的话它还有一个</span>AssemblyResolveEvent<span style="font-family: 宋体;" lang="ZH-CN">去问你，看你能不能提供。如果你要动态装载的话，你有</span>Assembly.Load, Assembly.LoadFrom, Assembly.LoadFile, Assembly.Load(byte[])<span style="font-family: 宋体;" lang="ZH-CN">。你可以提供</span>privateBin<span style="font-family: 宋体;" lang="ZH-CN">，你也可以提供</span>codebase hint<span style="font-family: 宋体;" lang="ZH-CN">。你还能有</span>policy<span style="font-family: 宋体;" lang="ZH-CN">。总之，你想从哪找，就可以去哪找。细节问题我就不多说了。你可以去看</span><a href="http://msdn.microsoft.com/">MSDN</a><span style="font-family: 宋体;" lang="ZH-CN">，</span>Suzanne<span style="font-family: 宋体;" lang="ZH-CN">的</span><a href="http://weblogs.asp.net/suzcook">Blog</a><span style="font-family: 宋体;" lang="ZH-CN">，</span>Alan<span style="font-family: 宋体;" lang="ZH-CN">的</span><a href="http://weblogs.asp.net/alanshi">Blog</a><span style="font-family: 宋体;" lang="ZH-CN">，和我的英文</span><a href="http://weblogs.asp.net/junfeng">Blog</a>. </p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-family: 宋体;" lang="ZH-CN">结论，</span>CLR Loader<span style="font-family: 宋体;" lang="ZH-CN">远比</span>Java Class Loader<span style="font-family: 宋体;" lang="ZH-CN">要Secure, </span>Powerful and&nbsp;Flexible<span style="font-family: 宋体;" lang="ZH-CN">。</span></p>
	</div>

	<img src ="http://www.blogjava.net/briansun/aggbug/2520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-03-28 11:34 <a href="http://www.blogjava.net/briansun/articles/2520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CLR和JRE的运行机制的初步总结[转]</title><link>http://www.blogjava.net/briansun/articles/2517.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Mon, 28 Mar 2005 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/2517.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/2517.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/2517.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/2517.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/2517.html</trackback:ping><description><![CDATA[<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td width="100%"><span class="postdetails">标题: CLR和JRE的运行机制的初步总结</span></td>
				<td nowrap="nowrap" valign="top"><a href="file:///C:/workplace/bacchus_doc/posting.php?mode=quote&amp;p=567&amp;sid=41b0cf50b4510221cfae9a122df5a850"><img src="file:///C:/workplace/bacchus_doc/templates/subSilver/images/lang_chinese_simplified/icon_quote.gif" alt="引用回复" title="引用回复" border="0"></a>    <a href="file:///C:/workplace/bacchus_doc/addblog.php?type=javaeye&amp;title=CLR%E5%92%8CJRE%E7%9A%84%E8%BF%90%E8%A1%8C%E6%9C%BA%E5%88%B6%E7%9A%84%E5%88%9D%E6%AD%A5%E6%80%BB%E7%BB%93&amp;t=146&amp;postdays=0&amp;postorder=asc&amp;start=0&amp;p=567&amp;sid=41b0cf50b4510221cfae9a122df5a850"><img src="file:///C:/workplace/bacchus_doc/templates/subSilver/images/icon_blog.gif" alt="将这个帖子加入我的Blog" title="将这个帖子加入我的Blog" border="0"></a></td>
			</tr>
			<tr>
				<td colspan="2"><hr></td>
			</tr>
			<tr>
				<td colspan="2"><span class="postbody">概念比较： 
<br>
Java C# 
<br>
byte code IL(字节码，中间语言) 
<br>
jvm.dll mscrolib.dll,mscrojit.dll(虚拟机) 
<br>
JRE CLR(运行环境) 
<br>
JDK .Net Framework(开发框架) 
<br>
package assembly(类库，程序集) 
<br>

<br>

<br>
一、关于类库的版本管理问题 
<br>

<br>
Java和C#代码运行要依靠其运行环境(JRE,CLR)和运行环境带的基础类库(C#称为配件或者程序集Assembly)，此外还会有一些第三方的
类库或者自己开发的类库。如果运行环境版本不一致，或者引用的类库版本不一致都会带来程序不能正常运行。比如一个Java程序是在JDK1.2上开发，如
果在JRE1.4上运行，一般情况下可以向下兼容，但也有例外，有些GUI程序在JDK1.4上面运行结果很可能会不同。 <br>

<br>
JRE的版本管理 
<br>

<br>
Java的解决办法是每个程序自己携带一套JRE。 
<br>
我的机器上已经被安装了好多套JRE和JDK了(JDK包括了同版本的JRE，此外还包括有编译器和其它工具)，它们分别是： 
<br>
BEA Weblogic Server 7.0 自带一套 JDK1.3.1_02 
<br>
我下载了一套最新的JDK1.4.1_02 
<br>
JBuilder9自带一套JKD1.4.1_02 
<br>
Oracle8.1.7自带一套JRE1.1.7 
<br>
Ration Rose自带一套JDK1.3 
<br>
DreamWeaver自带一套JDK1.3 
<br>
6套JRE，每套JRE都被各自安装到不同的目录，不会互相影响。当在控制台执行java.exe，操作系统寻找JRE的方式如下： 
<br>
先找当前目录下有没有JRE 
<br>
再找父目录下有没有JRE 
<br>
接着在PATH路径中找JRE 
<br>
注册表HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\ 查看CurrentVersion的键值指向哪个JRE 
<br>
最常用的是在PATH路径中找JRE，一般情况下，自己的程序运行之前都会先在批处理文件里面临时设置PATH，把自己用的JRE放到PATH路径最前面，所以肯定会运行自己带的JRE，不会造成版本混乱。 
<br>

<br>
.Net Framework的版本管理 
<br>

<br>
.Net
Framework被固定安装在C:\Winnt\Microsoft.NET\Framework\v版本号\目录下，听说刚发行的.Net
Framework1.1已经对1.0做了很多改进，也许在旧版本的.Net Framework开发的程序在往新版本上面迁移的时候需要部分修改。 <br>

<br>

<br>

<br>
JRE的基础类库 
<br>

<br>
JRE自带的基础类库主要是JRE\lib\rt.jar这个文件，包括了Java2平台标准版的所有类库。和JRE的版本一致。 
<br>

<br>
.Net Framekwork的核心类库 
<br>

<br>
.Net Framekwork的核心类库被放置在C:\Winnt\assembly\gac\目录下，按照不同的名称空间放在不同目录中，不像JRE打成了一个包。并且可以同时存在不同的版本，例如： 
<br>
某类库1.0版本 C:\Winnt\assembly\gac\名称\1.0\名称.dll 
<br>
某类库1.1版本 C:\Winnt\assembly\gac\名称\1.1\名称.dll 
<br>
这样做，虽然很灵活，可以随时把类库更新到最新的状态，但是很容易带来版本管理的复杂度，造成版本不一致。 
<br>

<br>

<br>

<br>
JRE类库的查找方法和版本管理 
<br>

<br>
JRE中由ClassLoader负责查找和加载程序引用到的类库，基础类库ClassLoader会到rt.jar中自动加载，其它的类库，
ClassLoader在环境变量CLASSPATH指定的路径中搜索，按照先来先到的原则，放在CLASSPATH前面的类库先被搜到，Java程序启
动之前建议先把PATH和CLASSPATH环境变量设好，OS通过PATH来找JRE，确定基础类库rt.jar的位置，JRE的
ClassLoader通过CLASSPATH找其它类库。但有时候会出现这样的情况，希望替换基础类库中的类库，那么也可以简单的通过-
Djava.endrosed.path=...参数传递给java.exe，于是ClassLoader会先于基础类库使用
java.endrosed.path参数指定路径的类库。因此Java的版本管理是非常简单有效的，也许很原始，不过很好用，简单就不容易出错。(所以
我很奇怪Eric Ramond为什么批评Java的类库管理机制，他还居然批评Java的接口，令人怀疑他对Java的了解程度) <br>

<br>
.Net Framework的类库管理机制 
<br>

<br>
.Net Framework的类库管理机制相当强大和复杂，分为私有类库和共享类库。 
<br>
私有类库就放在exe程序当前路径下，或其相对路径中，只有当前程序可见。 
<br>
共享类库需要在GAC(Global Assembly
Cache)中注册，注册过程比较复杂，首先要用工具生成公开/私有密钥对，然后结合密钥和类库版本号连编，最后使用工具注册到GAC中好以后,会被放在
"C:\Winnt\assembly\gac\类库的名称空间\版本号\"目录下，不同的类库版本在注册的时候会按照版本号分开放置： <br>
某类库1.0版本 C:\Winnt\assembly\gac\名称\1.0\名称.dll 
<br>
某类库1.1版本 C:\Winnt\assembly\gac\名称\1.1\名称.dll 
<br>

<br>
也就是可以同时存在一个类库的n个版本，至于在程序中用哪个版本，在程序的配置文件中声明，CLR会根据声明来调用相应的版本的类库。我觉得.Net实现
方法未免太复杂了一些，将所有共享类库都塞到一个系统目录下，并且同一个类库还有n个版本，将来.Net第三方开发的类库逐渐丰富起来以后，.Net类库
的GAC也会越来越庞大，会不会也搞得和Windows注册表一样难以维护？软件发布到服务器上的时候，类库要再注册一次，服务器会逐渐形成一个庞大的树
状的GAC，GAC里面存放着组件的n个版本。试想经过一段时间之后，C:\Winnt\assembly\gac\目录会越来越庞大，有的组件甚至有n
个版本都放在那里，你又不敢随便删除，不知道是不是有程序需要使用，我不明白MS为什么要把这么简单的事情搞到这么复杂？ <br>

<br>

<br>
综上所述，Java的版本管理方式简单而有效，C#的版本管理方式功能强大，不过是不是太复杂了？会不会搞成第二个注册表一样的东西？ 
<br>

<br>

<br>

<br>
二、虚拟机启动和加载类库的方式 
<br>

<br>

<br>
Java的虚拟机启动和加载类库 
<br>

<br>
在Console执行java.exe xxx命令以后，如前所述的寻找JRE，OS找到JRE目录，根据java.exe的传递参数，选择加载Server版的jvm.dll还是Client版的jvm.dll，然后加载jvm.dll，把控制权交给jvm.dll。 
<br>

<br>
接下来，jvm.dll进行初始化，分配内存等等动作，然后在CLASSPATH路径中寻找class，找到class以后，寻找class中的程序入口
点Main函数，然后从Main函数执行程序，在执行过程中，使用ClassLoader动态加载一系列引用到的类。当调用到native方法时，
jvm.dll告诉OS在JRE\bin目录下寻找某某DLL文件，调入内存，于是实现了JNI调用。 <br>

<br>

<br>
.Net的虚拟机的启动推测 
<br>

<br>
我对.Net的虚拟机的启动过程还一知半解，自己写了一些例程，并且用内存工具来检测观察，推测.Net的运行机制，先来抛砖引玉，请熟悉Windows平台编程的朋友指教。.Net有3个目录中的文件在执行的时候会被加载 
<br>

<br>
1、C:\WINNT\Microsoft.NET\Framework\v版本号\ 
<br>
该目录下的mscorlib.dll,mscorrsn.dll,mscorwsk.dll,mscorjit.dll是核心DLL，大概是运行虚拟机的
必要文件，其中mscrolib.dll是入口点。此外，该目录下还有一些.Net的System名称空间的IL类库，与C:\Winnt\
assembly\gac\相应目录下的IL类库完全一样，这些是最核心的基础类库。.Net的编译器，检查器等等工具软件也在该目录，推测System
名称空间的核心类库之所以在这个目录下copy一份是因为作为.Net的编译器等工具的私有类库之用。 <br>

<br>
2、C:\Winnt\assembly\gac\ 
<br>
该目录下放置.Net共享类库，如前所述 
<br>

<br>
3、C:\Winnt\assembly\nativeimages_.Net版本号\ 
<br>
在该目录下也有一些以System名称空间开头的核心类库，推测是MS为了加快CLR的执行效率把核心类库进行本地化，编译为native
image的同名DLL。可以观察到该目录下的同名DLL文件，比GAC目录下的同名DLL文件体积大，可能是因为link底层DLL库的缘故。 <br>
某核心类库 C:\Winnt\assembly\nativeimages_.Net版本号\名称空间\.Net版本号_散列码\名称.dll 
<br>

<br>
另外值得注意的地方是有两个mscorlib.dll 
<br>
1、C:\WINNT\Microsoft.NET\Framework\v版本号\mscrolib.dll (1.88MB) 
<br>
2、C:\WINNT\assembly\NativeImages1_v版本号\mscorlib\版本号__散列码\mscrolib.dll (3.07MB) 
<br>
mscrolib.dll (1.88MB)还是一个IL码的版本，所以映射了一个native的版本的mscrolib.dll (3.07MB)，来加快CLR的速度。 
<br>

<br>

<br>
当IL的exe程序被双击执行时，OS
Loader读入程序，识别出是IL，根据IL内部的引用定义，加载mscorlib.dll，而mscorlib.dll也是IL，内部引用C:\
winnt\system32\mscoree.dll，于是再加载mscoree.dll，然后把控制权交给mscoree.dll，
mscoree.dll接着加载mscrorsn.dll，mscrowsk.dll，mscrojit.dll，为了加快mscorlib.dll的调
用，加载mscorlib.dll的native
image版本，然后由mscorlib.dll接管控制权(不知道这两个mscorlib.dll是如何来上管IL，下连native
code的？)最后寻找IL码程序的入口点Main函数，开始执行程序，在执行过程中，使用Class
Loader动态加载一系列引用到的类，在当前路径下，在共享类库的GAC中查找等等。 <br>

<br>
这里和jvm.dll不同的一点是，jvm.dll加载的基础类库和加载其它类库方式完全一样，全部都是字节码的class。而mscrolib.dll
加载以System名称开头的核心类库的时候，使用了“不正当竞争手法”。mscrolib.dll从GAC中加载共享核心类库之后，又C:\Winnt
\assembly\nativeimages_.Net版本号\名称空间\
目录下加载了核心类库的native版本，这样一来，自然CLR运行起来要快多了。特别是图形图像类库全部都有native映射版本，所以CLR上运行
GUI焉能不快？ <br>

<br>
对比CLR和JRE的加载过程，比较不同的地方是mscorlib.dll和System核心类库都有一个native image，可能这是CLR运行速度比较快的一个主要原因吧。 
<br>

<br>
分析完以后有一个特别明显的感受，Java的底层运行机制设计的特别简单，而.Net的底层运行机制设计的特别复杂。但是在企业层刚好相反，J2EE设计的特别复杂，而.Net却设计的特别简单，真是有意思！ 
<br>

<br>
Java的底层机制设计虽然简单，但是很健壮，.Net设计使得它的CLR速度快，类库管理功能强大，但是不是比Java更优秀，还要等以后慢慢看了。<br>
      <br>
RE：<br>
      <br>
</span><span class="postbody">我查了一下《.Net Essential》这本书，上面提到这样的说法。 
<br>

<br>
MS更新了Windows各个版本的OS Loader程序，使得OS Loader可以识别.Net PE格式的exe文件，当执行Windows
Native PE格式的exe文件的时候，OS Loader按照以往的方式加载系统DLL。如果是.Net PE格式的exe文件，OS
Loader加载mscorlib.dll，然后把控制权交给mscorlib.dll。<br>
      <br>
      </span></td></tr></tbody>
</table>
<img src ="http://www.blogjava.net/briansun/aggbug/2517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-03-28 11:22 <a href="http://www.blogjava.net/briansun/articles/2517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AOP@Work: AOP tools comparison, Part 2</title><link>http://www.blogjava.net/briansun/articles/1424.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Tue, 22 Feb 2005 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1424.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1424.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1424.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1424.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1424.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: AOP@Work: AOP tools comparison, Part 2Contents:Building aspectsWeaving and performancePerformance considerationsIDE integrationFeatures comparisonAround the cornerThe bottom line ConclusionResou...&nbsp;&nbsp;<a href='http://www.blogjava.net/briansun/articles/1424.html'>阅读全文</a><img src ="http://www.blogjava.net/briansun/aggbug/1424.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-22 15:30 <a href="http://www.blogjava.net/briansun/articles/1424.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AOP@Work: AOP tools comparison, Part 1</title><link>http://www.blogjava.net/briansun/articles/1423.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Tue, 22 Feb 2005 07:29:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1423.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1423.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1423.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1423.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1423.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: AOP@Work: AOP tools comparison, Part 1Contents:Thinning the cropIt's all about join pointsAspect comparisonSyntactic differencesSemantic similaritiesLanguage mechanicsConclusionResourcesAbout th...&nbsp;&nbsp;<a href='http://www.blogjava.net/briansun/articles/1423.html'>阅读全文</a><img src ="http://www.blogjava.net/briansun/aggbug/1423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-22 15:29 <a href="http://www.blogjava.net/briansun/articles/1423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The AspectJ(TM) Development Environment Guide</title><link>http://www.blogjava.net/briansun/articles/1363.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:59:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1363.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1363.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1363.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: The AspectJtm Development Environment Guidethe AspectJ TeamCopyright (c) 1998-2001 Xerox Corporation,          2002 Palo Alto Research Center, Incorporated,         2003 Contributors.           ...&nbsp;&nbsp;<a href='http://www.blogjava.net/briansun/articles/1363.html'>阅读全文</a><img src ="http://www.blogjava.net/briansun/aggbug/1363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:59 <a href="http://www.blogjava.net/briansun/articles/1363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The AspectJ(TM) Programming Guide</title><link>http://www.blogjava.net/briansun/articles/1362.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:57:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1362.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1362.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1362.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1362.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1362.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: The AspectJTM Programming Guidethe AspectJ Team        Copyright (c) 1998-2001 Xerox Corporation,         2002-2003 Palo Alto Research Center, Incorporated.          All rights reserved.      ...&nbsp;&nbsp;<a href='http://www.blogjava.net/briansun/articles/1362.html'>阅读全文</a><img src ="http://www.blogjava.net/briansun/aggbug/1362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:57 <a href="http://www.blogjava.net/briansun/articles/1362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The AspectJTM 5 Development Kit Developer's Notebook</title><link>http://www.blogjava.net/briansun/articles/1361.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:56:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1361.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1361.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1361.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1361.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1361.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: The AspectJTM 5 Development Kit Developer's Notebookthe AspectJ Team        Copyright (c) 2004 Contributors,          All rights reserved.      Abstract        This guide describes the changes...&nbsp;&nbsp;<a href='http://www.blogjava.net/briansun/articles/1361.html'>阅读全文</a><img src ="http://www.blogjava.net/briansun/aggbug/1361.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:56 <a href="http://www.blogjava.net/briansun/articles/1361.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>abstract of aspectj</title><link>http://www.blogjava.net/briansun/articles/1360.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:53:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1360.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1360.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1360.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1360.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1360.html</trackback:ping><description><![CDATA[<table border="0" cellpadding="2" cellspacing="5" width="100%">
<tbody><tr><td style="font-weight: bold; font-family: verdana;" align="left" valign="top" width="60%"><font class="indextop" size="6">aspectj project</font></td>
    <td width="40%">&nbsp;</td>
  </tr>
</tbody>
</table>


  
    
    
      
<table id="AutoNumber1" style="border-collapse: collapse;" border="0" bordercolor="#111111" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
        <td colspan="2">
        <img alt="AspectJ[TM] is" src="http://www.eclipse.org/aspectj/aspectjIs.gif" border="0" height="25" width="241"></td>
        <td colspan="2">
        <img alt="aspectj enables" src="http://www.eclipse.org/aspectj/aspectjEnables.gif" border="0" height="25" width="241"></td>
      </tr>
      <tr>
        <td width="10">&nbsp;</td>
        <td valign="top">- a seamless aspect-oriented extension
        to the Java<sup><small>tm</small></sup> programming language<br>
        - Java platform compatible<br>
        - easy to learn and use<br>
</td>
        <td width="10">&nbsp;</td>
        <td valign="top">clean modularization of crosscutting concerns, such as error 
        checking and handling, synchronization, context-sensitive behavior, 
        performance optimizations, monitoring and logging, debugging support, 
        and multi-object protocols</td></tr></tbody>
</table>
<img src ="http://www.blogjava.net/briansun/aggbug/1360.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:53 <a href="http://www.blogjava.net/briansun/articles/1360.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DRAFT: Eclipse Architecture Plan</title><link>http://www.blogjava.net/briansun/articles/1359.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:51:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1359.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1359.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1359.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1359.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1359.html</trackback:ping><description><![CDATA[
    
<table border="0" cellpadding="2" cellspacing="5" width="100%">

  <tbody><tr> 
    <td align="left" width="72%"> <font class="indextop">DRAFT: Eclipse Architecture Plan</font> <br>
      <font class="indexsub"> the open community driving the eclipse platform</font> </td>
    <td width="28%"><img src="http://www.eclipse.org/images/Idea.jpg" height="86" width="120"></td>
  </tr>
</tbody>
</table>

<table border="0" cellpadding="2" cellspacing="5" width="100%">

	<tbody><tr> 
  	</tr>
	<tr bgcolor="#999999">
    	<td align="left" bgcolor="#0080c0" valign="top"><strong><font color="#ffffff" face="Arial,Helvetica">eclipse projects  </font></strong></td>
	</tr>
</tbody>
</table>

      
<p>
      The <a href="http://www.eclipse.org/org/documents/Eclipse%20Development%20Process%202003_11_09%20FINAL.pdf">Eclipse Development Process</a>
calls for the creation of three Councils: Requirements, Planning and
Architecture. Together, these Councils are responsible for the creation
and maintenance of the Eclipse Roadmap. When approved by the Board, the
intent of the Eclipse Roadmap is to communicate the directions in which
the Eclipse community will be taking its projects over the next year.
New projects started during the life of a Roadmap are expected to be
consistent and complementary to the Roadmap.</p>

      
<p>This document is the first draft of the Eclipse Architecture Plan. We welcome 
  your feedback on the <a href="news://news.eclipse.org/eclipse.foundation">Eclipse 
  Foundation Newsgroup</a>. </p>

      
<p>The
Eclipse community is organized into six top-level projects, each of
which has provided its detailed architecture using the links below.
Alternatively, you may use the image map below to navigate the Eclipse
architecture.</p>

      
<ul>
<li><a href="http://www.eclipse.org/eclipse/temp_eclipse_platform_tlp_main.html">Platform Project</a></li><li><a href="http://www.eclipse.org/tools/architecture/">Tools Project</a></li><li><a href="http://www.eclipse.org/tptp/home/architecture/arch_main.html">Test and Performance Tools Platform Project</a></li><li><a href="http://www.eclipse.org/org/councils/AC/wtpsnapshot/wtp_project_architecture.html">Web Tools Platform Project </a></li><li><a href="http://www.eclipse.org/org/councils/AC/birt/BIRT_architecture_plan.html">Business Intelligence and Reporting Tools Project</a> </li><li><a href="http://www.eclipse.org/org/councils/AC/Technology_main.htm">Technology Project</a></li>
</ul>

      
<p>Other projects may be added over time. </p>

    
<table border="0" cellpadding="2" cellspacing="5" width="100%">

	<tbody><tr> 
  	</tr>
	<tr bgcolor="#999999">
    	<td align="left" bgcolor="#0080c0" valign="top"><strong><font color="#ffffff" face="Arial,Helvetica">project architecture</font></strong></td>
	</tr>
</tbody>
</table>

    
<div class="content">
      <p>Click on the image map below to navigate to the different project architectures.</p>
      <p><img src="http://www.eclipse.org/org/councils/AC/arch1.jpg" alt="" usemap="#tptp_arch_Map" class="image_map" border="0" height="446" width="673">
        <map name="tptp_arch_Map"><area shape="rect" alt="Platform project" coords="0,266,697,600" href="http://www.eclipse.org/eclipse/temp_eclipse_platform_tlp_main.html#Platform"><area shape="rect" alt="JavaDevTools" coords="0,93,133,179" href="http://www.eclipse.org/eclipse/temp_eclipse_platform_tlp_main.html#JDT"><area shape="rect" alt="CDevTools" coords="134,93,263,180" href="http://www.eclipse.org/tools/architecture/cdt.html"><area shape="rect" alt="Frameworks" coords="0,183,697,262" href="http://www.eclipse.org/tools/architecture/"><area shape="rect" alt="TPTP" coords="266,93,412,180" href="http://www.eclipse.org/tptp/home/architecture/arch_main.html"><area shape="rect" alt="WTP" coords="414,93,535,179" href="http://www.eclipse.org/org/councils/AC/wtpsnapshot/wtp_project_architecture.html"><area shape="rect" alt="BIRT" coords="538,92,704,178" href="http://www.eclipse.org/org/councils/AC/birt/BIRT_architecture_plan.html"><area shape="rect" alt="ecosystem" coords="0,0,695,87" href="http://www.eclipse.org/community/index.html"></map>    
    </p>
    </div>

<img src ="http://www.blogjava.net/briansun/aggbug/1359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:51 <a href="http://www.blogjava.net/briansun/articles/1359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统分析师级考试大纲</title><link>http://www.blogjava.net/briansun/articles/1358.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:33:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1358.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1358.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1358.html</trackback:ping><description><![CDATA[系统分析师级考试大纲（2004年新版）<br>
（来自CSAI.cn）　　　2004年05月28日<br>
<br>
一、考试说明<br>
<br>
<br>
1．考试要求：<br>
<br>
<br>
（1）具有系统工程的基础知识；<br>
（2）掌握开发信息系统的综合技术知识（硬件、软件、网络、数据库）；<br>
（3）熟悉企业和政府信息化建设，并具有组织信息化战略规划的知识；<br>
（4）熟练掌握信息系统开发过程和方法；<br>
（5）熟悉信息系统开发标准；<br>
（6）掌握信息安全的相关知识与技术；<br>
（7）理解软件质量保证的手段；<br>
（8）具有经济与管理科学的相关基础知识，熟悉有关的法律法规；<br>
（9）具有大学本科的数学基础；<br>
（10）熟练阅读和正确理解相关领域的英文文献。<br>
<br>
2．通过本考试的合格人员熟悉应用领域的业务，能分析用户的需求和约束条件，写出信息系统需求规格说明书，制订项目开发计划，协调信息系统开发与运行所涉
及的各类人员，能指导制订企业的战略数据规划，组织开发信息系统，能评估和选用适宜的开发方法和工具，能按照标准规范编写系统分析、设计文档，能对开发过
程进行质量控制与进度控制，能具体指导项目开发；具有高级工程师的实际工作能力和业务水平。 <br>
<br>
<br>
3．本考试设置的科目包括：<br>
<br>
<br>
（1）信息系统综合知识，考试时间为150分钟，笔试；<br>
（2）信息系统分析与设计案例，考试时间为90分钟，笔试；<br>
（3）信息系统分析与设计论文，考试时间为120分钟，笔试。 <br>
<br>
二、考试范围<br>
<br>
<br>
考试科目1：信息系统综合知识<br>
<br>
<br>
1．计算机系统综合知识<br>
<br>
1.1 计算机组成与体系结构<br>
• 构成计算机的各类部件的功能及其相互关系<br>
• 各种体系结构的特点与应用（SMP、MPP）<br>
• 计算机体系结构的发展<br>
<br>
1.2 数据通信与计算机网络<br>
<br>
1.2.1 数据通信的基本知识<br>
<br>
1.2.2 网络体系结构与协议<br>
• 开放系统互连参考模型<br>
• TCP/IP 分层模型<br>
• 常用的协议标准<br>
<br>
1.2.3 计算机网络分类<br>
• 分类方法<br>
• 局域网定义及类型<br>
• 广域网定义及类型<br>
<br>
1.2.4 Internet<br>
•路由结构<br>
•地址和域名<br>
•万维网应用<br>
•可扩展标记语言（XML）<br>
<br>
1.3 软件知识<br>
<br>
1.3.1 操作系统<br>
• 操作系统的类型与结构<br>
• 系统的并行机制<br>
• 网络操作系统<br>
• 分布式操作系统<br>
• 嵌入式操作系统<br>
• 主流操作系统产品<br>
<br>
1.3.2 数据库系统<br>
• 数据库管理系统的类型、结构<br>
• 关系数据库及其主流产品<br>
• 数据仓库与联机分析处理<br>
• 数据挖掘<br>
<br>
1.3.3 中间件<br>
<br>
1.4 系统配置与性能评价<br>
• Client/Server与Browser/Server结构、三层或多层结构、分布式系统<br>
• 系统配置方法（双份、双重、热备份、容错、集群）<br>
• 典型基准测试程序（Benchmark）<br>
• 系统性能计算，系统性能指标，系统性能评估 <br>
• 系统可靠性指标、经济效益指标<br>
<br>
1.5 计算机应用知识<br>
• 信息管理、数据处理、辅助设计、自动控制、科学计算、人工智能<br>
• 远程通信服务，Web计算<br>
• 多媒体技术基础<br>
<br>
2．信息化基础知识<br>
<br>
2.1 信息化<br>
• 信息与信息化<br>
• 信息化对组织的意义<br>
• 组织对信息化的需求<br>
<br>
2.2 政府信息化与电子政务<br>
• 政府信息化的服务对象<br>
• 电子政务的概念、内容和技术形式<br>
• 电子政务建设中政府的作用和地位<br>
• 我国政府信息化的策略和历程<br>
• 电子政务建设的过程模式和技术模式<br>
• 信息化建设中政府领导部门、业务部门和技术部门各自的作用<br>
• 新形势（政务公开、公共应急事件预警报警）对政府信息化思路的影响<br>
<br>
2.3 企业信息化与电子商务<br>
• 企业信息化的概念、目的、规划、方法<br>
• 企业资源规划（ERP）的结构和功能<br>
• 客户关系管理（CRM）在企业的应用<br>
• 企业门户<br>
• 企业应用集成<br>
• 供应链管理（SCM）的思想<br>
• 商业智能（BI）<br>
• 电子商务的类型、标准<br>
<br>
2.4 信息资源管理（信息系统的管理，标准、法规的制定与实施，信息资源的安全管理，人力资源管理等）<br>
<br>
2.5 信息化的有关的法律和规定（知识产权、标准、质量、安全、互联网管理等方面的法规）<br>
<br>
3．信息系统知识<br>
<br>
3.1 信息系统<br>
• 信息系统概念<br>
• 信息系统的功能<br>
• 信息系统的类型<br>
• 信息系统的发展<br>
<br>
3.2 信息系统建设<br>
• 信息系统建设的复杂性<br>
• 信息系统的生命周期，各阶段目标和主要工作内容<br>
• 信息系统建设的原则<br>
• 信息系统开发方法（结构化分析设计方法、原型化方法、战略数据规划方法等）<br>
<br>
3.3 软件工程<br>
• 软件需求分析与定义<br>
• 软件设计、测试与维护<br>
• 软件复用<br>
• 软件质量保证及软件质量评价<br>
• 软件配置管理<br>
• 软件开发环境 <br>
• CASE工具<br>
• 软件的知识产权保护<br>
<br>
3.4 项目管理知识<br>
• 信息项目计划<br>
• 项目计划的控制<br>
• 项目工作量估算<br>
• 风险管理<br>
• 资源和任务分配<br>
• 项目的生命周期管理<br>
<br>
3.5 软件过程<br>
• 软件过程的定义和范围<br>
• 软件过程的作用<br>
• 主要的软件过程及其特点<br>
• 软件过程能力评估（CMM、CMMI）<br>
• 软件过程改进<br>
• 软件过程标准<br>
<br>
3.6 质量管理<br>
• 质量保证计划<br>
• 质量认证体系<br>
• 质量管理和质量管理技术<br>
• 全面质量管理<br>
• 质量管理理论<br>
<br>
4．信息系统开发与运行知识<br>
<br>
4.1 软件工程技术<br>
• 软件生命周期<br>
• 软件开发模型（瀑布模型、螺旋模型、喷泉模型）<br>
• 成本模型<br>
• 软件复用技术（构件、逆向工程）<br>
<br>
4.2 软件需求分析和设计方法<br>
• 结构化分析与设计<br>
• 分析设计图示（DFD、ERD）<br>
• 面向对象分析与设计（继承、抽象、代理、封装、多态）<br>
• 统一建模语言（UML）<br>
• 模块设计（内聚性、耦合性）<br>
• I/O设计（报表设计、屏幕设计、代码设计）<br>
• 人机界面设计<br>
<br>
4.3 开发环境与开发工具<br>
• 集成开发环境<br>
• 开发工具（建模工具、分析设计工具、开发平台、测试工具、项目管理工具等）<br>
• 软件开发平台的比较<br>
<br>
4.4 软件包<br>
• 开发工具<br>
• 管理工具<br>
• OA工具<br>
• 群件<br>
<br>
4.5 程序设计<br>
• 程序设计语言（种类、发展和特点）<br>
• 程序设计方法（结构化、面向对象、并行、网络程序设计）<br>
<br>
4.6 测试与评审<br>
• 常用测试方法<br>
• 测试计划和测试过程<br>
• 测试报告和测试结果分析<br>
• 软件测试自动化<br>
• 软件测试规范标准<br>
• 评审方法和原则<br>
<br>
4.7 应用系统构建、集成<br>
• 应用系统开发（分析设计方法的选择，开发的组织、分析设计的实施）<br>
• 软件包的使用<br>
• 数据库设计（E-R模型，范式，SQL，数据分布）和实施 <br>
• 网络工程（网络规划、设计、实施和测试）<br>
• 系统集成（控制集成，数据集成，表示集成，应用集成，外部资源使用）<br>
<br>
4.8 系统运行<br>
• 系统运行管理（计算机系统、数据库、网络）<br>
• 系统成本管理<br>
• 系统运行（作业调度、数据I/O管理、操作手册）<br>
• 用户管理<br>
• 分布式系统管理<br>
• 硬件资源管理<br>
• 软件资源管理（程序库管理、版本管理）<br>
• 数据资源管理，网络资源管理<br>
• 设备和设施管理（电源、设备管理、设施安全管理）<br>
• 系统故障管理（处理手续、监视、恢复过程、预防措施）<br>
• 安全性管理<br>
• 系统运行工具（操作工具、监视工具、诊断工具）<br>
• 系统转换（转入运行阶段、运行测试、版本控制）<br>
• 系统运行服务标准<br>
<br>
4.9 系统维护<br>
• 维护的类型（完善性维护、纠错性维护、适应性维护、预防性维护）<br>
• 维护的实施（日常检查、定期维护、预防性维护、事后维护、远程维护）<br>
• 硬件维护、软件维护<br>
• 合同维护<br>
<br>
4.10 系统评价<br>
• 性能评价<br>
• 经济效益评价<br>
<br>
5．安全性知识<br>
• 数据安全和保密、加密与解密机制<br>
• 通信和网络安全<br>
• 系统访问控制技术<br>
• 数据库完整性<br>
• 计算机安全操作<br>
• 计算机故障诊断和防范，防治计算机病毒，防计算机犯罪，入侵监测<br>
• 安全管理措施，有关的法律、法规、制度<br>
• 风险管理与分析（风险类型、抗风险措施和内部控制）<br>
<br>
6．标准化知识<br>
• 标准化的概念（标准化的意义、标准化的发展，标准的生命周期）<br>
• 标准的层次（国际标准、国家标准、行业标准、地方标准、企业标准、项目规范）<br>
• 标准的对象（代码标准、文件格式标准、安全标准、软件开发规范和文档标准）<br>
• 标准化机构<br>
<br>
7．经济等相关知识<br>
• 会计常识<br>
• 财务成本管理<br>
• 现代企业组织结<br>
• IT审计的相关常识（审计标准、审计实施和审计报告）<br>
<br>
8．数学<br>
• 事件和概率<br>
• 随机变量和分布函数<br>
• 数理逻辑<br>
• 图论<br>
• 组合分析<br>
• 算法及其复杂性<br>
<br>
9．管理科学<br>
• 运筹学模型<br>
• 系统模型<br>
• 数量经济模型<br>
• 系统工程<br>
<br>
10．专业英语<br>
• 具有大学毕业程度的英文词汇量<br>
• 能熟练阅读和准确理解相关领域的英文科技文献<br>
<br>
考试科目2：信息系统分析与设计案例<br>
<br>
1．系统计划<br>
• 信息系统项目的提出与选择，项目优先级的确定<br>
• 基于管理层次的业务评价<br>
• 根据现在的情况对未来的信息系统的目标、功能、构架、能力、维护、应用方法及困难情况进行分析 <br>
• 可行性研究与效益分析<br>
• 系统方案的制订、评价和改进<br>
• 新旧系统的分析和比较<br>
• 遗留系统的评价和处理策略<br>
• 所需资源估计<br>
• 现有软件、硬件和数据资源的有效利用<br>
• 对企业信息战略有益的技术调研和评估<br>
• 制订信息系统的评价标准<br>
• 计划变更与控制<br>
<br>
2．需求获取<br>
<br>
• 业务模型的提取以及图形化和文档化<br>
• 对象业务流的提取和确认<br>
• 从信息系统的观点对确认的内容进行整理<br>
• 对业务问题的分析和解决方法<br>
• 业务功能的模型化<br>
• 全体对象业务以及业务功能整合方面的探讨 <br>
• 现有软件系统的分析<br>
• 确认测试计划<br>
• 流行的需求分析方法<br>
• 前提条件（人员、交付期及成本等）的可满足性以及在技术、经济等方面的可行性的研究<br>
<br>
3.系统分析<br>
• 组织结构与功能分析<br>
• 业务流程分析<br>
• 数据汇总与数据流程分析<br>
• 系统功能划分与数据资源分布<br>
• 主题数据库的建立<br>
• 成本/效益分析<br>
• 系统的故障模型和可靠性模型<br>
• 系统的可靠性分析和可靠度计算<br>
• 提高系统可靠性的措施<br>
• 系统的故障对策和系统的备份与恢复<br>
• 系统分析的实用技术<br>
• 流行的系统分析方法 <br>
<br>
4．系统设计<br>
<br>
4.1 建模技术<br>
• 建模的作用和意义<br>
• 需求建模的步骤<br>
• 用例驱动的开发方式<br>
• 概念模型与设计模型<br>
• 结构化建模技术，数据流图<br>
• 面向对象建模技术<br>
• 逆向工程<br>
• 定义问题与归结模型（目标、功能、性能等）<br>
• 数据库建模<br>
<br>
4.2 系统设计<br>
• 系统构架设计<br>
• 处理流程设计<br>
• 系统人机界面设计<br>
• 数据库管理系统的选择与数据库设计<br>
• 系统的文件设计<br>
• 系统安全性设计<br>
• 网络环境下的计算机应用系统的设计<br>
• 分布式应用系统的设计<br>
• 多媒体应用系统的设计<br>
• 系统运行环境的集成与设计<br>
• 系统处理能力评估<br>
• 系统测试计划以及测试的实施<br>
• 系统转换计划<br>
<br>
5．文档编制和沟通能力<br>
• 信息战略文档化<br>
• 信息系统构想文档化<br>
• 可行性研究报告<br>
• 项目开发计划<br>
• 需求规格说明书<br>
• 数据要求规格说明书<br>
• 用户手册<br>
• 操作手册<br>
• 测试计划、测试分析报告<br>
• 技术报告<br>
• 开发进度记录<br>
• 项目开发总结报告<br>
<br>
6．系统运行和维护<br>
• 系统转换的需求和基本方法（数据库转换、网络环境转换、业务规范的转换与变更）<br>
• 软件维护的实施和管理<br>
• 系统软硬件配置管理<br>
• 系统使用效率的跟踪<br>
• 基本软件和软件包的引入、应用、管理和二次开发<br>
• 系统的集成和扩充<br>
• 操作设计和运行管理<br>
• 系统的更新与维护<br>
• 短期计划和长期计划<br>
• 新旧系统的转换交接<br>
• 日常的故障对策与恢复<br>
• 系统的日常安全管理<br>
• 系统的服务质量和运用评价<br>
<br>
7．软件过程改进<br>
• 软件过程改进的管理<br>
• 软件过程改进的体系设计<br>
• 软件过程改进的技能<br>
• 软件过程改进的工具<br>
<br>
8．系统开发项目管理<br>
• 进度管理<br>
• 成本管理<br>
• 质量管理<br>
• 采购管理 <br>
• 风险管理<br>
• 资源管理<br>
<br>
9．企业信息化战略与实施<br>
• 信息规划与战略规划的关系<br>
• 信息规划的概念、活动与角色<br>
• 信息系统规划方法<br>
• 企业过程重组<br>
• CIO的概念和主要职责<br>
• 管理咨询在信息化中的作用和意义<br>
• 管理咨询的类型<br>
• 我国管理咨询的发展现状<br>
• "信息孤岛"形成的根源、预防，以及应对措施<br>
• 典型的信息化实施过程<br>
• 知识管理的含义<br>
• 知识管理对组织信息化的意义<br>
• 知识管理常用的工具和手段<br>
<br>
考试科目3：信息系统分析与设计论文<br>
<br>
　　根据试卷上给出的与系统分析设计有关的四个论文题目，选择其中一个题目，按照规定的要求撰写论文。论文涉及的内容如下： <br>
<br>
1．信息系统工程<br>
• 系统计划和分析<br>
• 需求分析与定义<br>
• 系统测试<br>
• 系统维护<br>
• 项目管理<br>
• 质量保证<br>
• 面向对象技术<br>
• 计算机辅助软件工程<br>
• 软件过程改进<br>
• 实时系统的开发<br>
• 应用系统分析设计（嵌入式系统、数据仓库、互联网应用等）<br>
<br>
2．数据库工程<br>
• 数据库分析<br>
• 数据库建模<br>
• 数据库管理<br>
<br>
3．系统安全<br>
• 数据安全<br>
• 网络安全<br>
• 容错与容灾<br>
<br>
4．应用系统集成<br>
• 集成的对象 <br>
• 集成的方法<br>
• 集成的工具<br>
<br>
5．企业信息化和政府信息化<br>
• 战略和策略<br>
• 组织和实施<br>
• 方法和步骤<br>
<br>
6．新技术的应用<br>
• 极限编程（XP）<br>
• 敏捷开发<br>
<br>
<img src ="http://www.blogjava.net/briansun/aggbug/1358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:33 <a href="http://www.blogjava.net/briansun/articles/1358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tiger十大特性</title><link>http://www.blogjava.net/briansun/articles/1356.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:23:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1356.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1356.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1356.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1356.html</trackback:ping><description><![CDATA[generic types<br>
metadata<br>
autoboxing<br>
an enhanced for loop<br>
enumerated types<br>
static import<br>
C style formatted input/output<br>
variable arguments<br>
concurrency utilities<br>
simpler RMI interface generation.<br>
<br>
注：Tiger就是J2SE 5.0<br>
<br>
<br>
<img src ="http://www.blogjava.net/briansun/aggbug/1356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:23 <a href="http://www.blogjava.net/briansun/articles/1356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Firefox鼠标快捷方式</title><link>http://www.blogjava.net/briansun/articles/1355.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:19:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1355.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1355.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1355.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1355.html</trackback:ping><description><![CDATA[<div id="mainContent">
<h2 class="headline">鼠标快捷键<br>  
</h2>  
<p>下面是 Mozilla Firefox里面最常用的鼠标快捷键, 相对应的是 Internet Explorer 和 Opera 中的快捷键.  
这些快捷键是 Windows 下的， 但大部分在 linux 下也可以使用.</p>  
					 					  
<table class="keyboard" border="0" cellpadding="2" cellspacing="1">  
					<thead> 						<tr>  
							<th class="keyhead">命令</th>  
							<th class="keyhead">Mozilla Firefox</th>  
							<th class="keyhead">Internet Explorer</th>  
							<th class="keyhead">Opera</th>  
						</tr>  
					</thead> 					<tbody>  
						<tr>  
							<td class="keycommand">后退<br>  
      </td>  
							<td class="keyshortcut"><kbd>Alt</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
						</tr>  
						<tr>  
							<td class="keycommand">减小文字大小</td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
						</tr>  
						<tr>  
							<td class="keycommand">前进</td>  
							<td class="keyshortcut"><kbd>Alt</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Scroll  
up</kbd></td>  
						</tr>  
						<tr>  
							<td class="keycommand">增大文字大小</td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Scroll  
down</kbd></td>  
						</tr>  
						<tr>  
							<td class="keycommand">新建标签(tab)页</td>  
							<td class="keyshortcut">在标签页栏<kbd class="mouse">Double-Click</kbd></td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut">&nbsp;</td>  
						</tr>  
						<tr>  
							<td class="keycommand">在后台打开标签(tab)页</td>  
							<td class="keyshortcut"><kbd>Ctrl</kbd>+<kbd class="mouse">Left-click</kbd><sup><a href="http://www.mozilla.net.cn/firefox/help/mouse.html#1">(1)</a></sup><br>  
      <kbd class="mouse">Middle-click</kbd></td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut"><br>  
      </td>  
						</tr>  
						<tr>  
							<td class="keycommand">在前台打开标签页( Tab)</td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd>Ctrl</kbd>+<kbd class="mouse">Left-click</kbd><sup><a href="http://www.mozilla.net.cn/firefox/help/mouse.html#1">(1)</a></sup><br>  
													<kbd>Shift</kbd>+<kbd class="mouse">Middle-click</kbd><sup><a href="http://www.mozilla.net.cn/firefox/help/mouse.html#1">(1)</a></sup></td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut">&nbsp;</td>  
						</tr>  
						<tr>  
							<td class="keycommand">在新窗口打开</td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Left-click</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Left-click</kbd></td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Left-click</kbd></td>  
						</tr>  
						<tr>  
							<td class="keycommand">刷新 (覆盖缓存)</td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+重载按钮</td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut">&nbsp;</td>  
						</tr>  
						<tr>  
							<td class="keycommand">保存页面为</td>  
							<td class="keyshortcut"><kbd>Alt</kbd>+<kbd class="mouse">Left-click</kbd></td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut">&nbsp;</td>  
						</tr>  
						<tr>  
							<td class="keycommand">逐行滚动</td>  
							<td class="keyshortcut"><kbd>Shift</kbd>+<kbd class="mouse">Scroll</kbd></td>  
							<td class="keyshortcut">&nbsp;</td>  
							<td class="keyshortcut">&nbsp;</td>  
						</tr>  

<!-- 						<tr>  
							<td class="keycommand"></td>  
							<td class="keyshortcut"></td>  
							<td class="keyshortcut"></td>  
							<td class="keyshortcut"></td>  
						</tr>  
 -->					  
  </tbody> 					  
</table>  
					 					  
<p><a name="1"></a><sup>1</sup>: 默认情况下，鼠标中键或 <kbd>Ctrl</kbd>+<kbd class="mouse">Left-click</kbd> 是在后台标签页打开链接 (打开后仍定位于你原先的页面 )&nbsp; <kbd>Shift</kbd>+鼠标中键或 <kbd>Shift</kbd>+<kbd>Ctrl</kbd>+<kbd class="mouse">Left-click</kbd> 是在前台标签页打开链接. 想得到相反的效果, 选择“工具”<tt> &gt;  

选项... &gt; 基本信息 &gt; 窗口 不选</tt>“ 在后台打开链接<q></q>选项.</p>  
</div>
<img src ="http://www.blogjava.net/briansun/aggbug/1355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:19 <a href="http://www.blogjava.net/briansun/articles/1355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Firefox 插件1</title><link>http://www.blogjava.net/briansun/articles/1353.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:18:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1353.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1353.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1353.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1353.html</trackback:ping><description><![CDATA[<p><a href="http://www.mozilla.net.cn/firefox/">FireFox 简体中文增强版</a> 已经包含了最常用的几个扩展插件。以下列出的就是这些插件，你可以自行选择并选择安装这些插件，或者
  <a href="javascript:void(InstallTrigger.install({  'Adblock:%E5%B9%BF%E5%91%8A%E9%98%BB%E6%AD%A2%E6%8F%92%E4%BB%B6':'xpi/Adblock.xpi',  'Search Status:%E5%9C%A8%E7%8A%B6%E6%80%81%E6%A0%8F%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E7%9A%84PR%E5%92%8CAlexa%E6%8E%92%E5%90%8D':'xpi/SearchStatus.xpi',  'All-in-One Gestures:%E4%BD%BF%E7%94%A8%E9%BC%A0%E6%A0%87%E6%89%8B%E5%8A%BF%E5%AF%B9%E6%B5%8F%E8%A7%88%E5%99%A8%E8%BF%9B%E8%A1%8C%E6%8E%A7%E5%88%B6':'xpi/AllinOneGestures.xpi',  'Tabbrowser Extensions:%E6%A0%87%E7%AD%BE%E9%A1%B5%E6%B5%8F%E8%A7%88%E6%8F%92%E4%BB%B6':'xpi/TabbrowserExtensions.xpi',  'Sage:Feed%E9%98%85%E8%AF%BB%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/Sage.xpi',  'Download Manager Tweak:Feed%E4%B8%8B%E8%BD%BD%E7%AE%A1%E7%90%86%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/downloadmgr.xpi',  'Launchy for Windows':'xpi/LaunchyforWindows.xpi',  'SuperDragAndGo:%E8%B6%85%E7%BA%A7%E6%8B%96%E5%BC%8B%E6%8F%92%E4%BB%B6':'xpi/SuperDragAndGo.xpi'  }))" style="color: red;">点击此处</a>
  一次性安装这些常用插件。如果您要浏览那些没有内置在增强版中，但仍然推荐安装的插件，请访问 <a href="http://www.mozilla.net.cn/firefox/extensions/">推荐扩展页面</a> 。</p>

  
<div class="section">
<h2><a name="Adblock" id="Adblock">Adblock</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/Adblock.gif" alt="Adblock" align="right" height="72" width="208"> 可以自行订制广告过滤条件，为您的浏览器提供全面的广告阻止功能。</p>
<ul><li>适用版本：0.7-1.0</li><li>制作人：The Adblock Crew: Henrik, Wladimir, rue</li><li><a href="javascript:void(InstallTrigger.install({'Adblock:%E5%B9%BF%E5%91%8A%E9%98%BB%E6%AD%A2%E6%8F%92%E4%BB%B6':'xpi/Adblock.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="SearchStatus" id="SearchStatus">Search Status</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/SearchStatus.gif" alt="Search Status" align="right" height="72" width="208"> 在浏览器的状态栏显示当前页面的 Google 网页级别和 Alexa 排名。</p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：Craig Raw</li><li><a href="javascript:void(InstallTrigger.install({'Search Status:%E5%9C%A8%E7%8A%B6%E6%80%81%E6%A0%8F%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E7%9A%84PR%E5%92%8CAlexa%E6%8E%92%E5%90%8D':'xpi/SearchStatus.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="AllinOneGestures" id="AllinOneGestures">All-in-One Gestures</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/AllinOneGestures.gif" alt="All-in-One Gestures" align="right" height="72" width="208"> 提供使用鼠标手势对浏览器进行控制的功能。</p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：Marc Boullet</li><li><a href="javascript:void(InstallTrigger.install({'All-in-One Gestures:%E4%BD%BF%E7%94%A8%E9%BC%A0%E6%A0%87%E6%89%8B%E5%8A%BF%E5%AF%B9%E6%B5%8F%E8%A7%88%E5%99%A8%E8%BF%9B%E8%A1%8C%E6%8E%A7%E5%88%B6':'xpi/AllinOneGestures.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="TabbrowserExtensions" id="TabbrowserExtensions">Tabbrowser Extensions</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/TabbrowserExtensions.gif" alt="Tabbrowser Extensions" align="right" height="72" width="208"> 为Firefox提供强大的标签页浏览功能。</p>
<ul><li>适用版本：0.6-1.0</li><li>制作人：Shimoda Hiroshi</li><li><a href="javascript:void(InstallTrigger.install({'Tabbrowser Extensions:%E6%A0%87%E7%AD%BE%E9%A1%B5%E6%B5%8F%E8%A7%88%E6%8F%92%E4%BB%B6':'xpi/TabbrowserExtensions.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="Sage" id="Sage">Sage</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/Sage.gif" alt="Sage" align="right" height="72" width="208"> 一个简便的 RSS 和 ATOM Feed 阅读器。</p>
<ul><li>适用版本：0.7-1.0</li><li>制作人：Peter Andrews</li><li><a href="javascript:void(InstallTrigger.install({'Sage:Feed%E9%98%85%E8%AF%BB%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/Sage.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="downloadmgr" id="downloadmgr">Download Manager Tweak</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/downloadmgr.gif" alt="Download Manager Tweak" align="right" height="72" width="208"> 这个扩展可以增强Firefox下载管理器。</p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：andman</li><li><a href="javascript:void(InstallTrigger.install({'Download Manager Tweak:Feed%E4%B8%8B%E8%BD%BD%E7%AE%A1%E7%90%86%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/downloadmgr.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="LaunchyforWindows" id="LaunchyforWindows">Launchy for Windows</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/LaunchyforWindows.gif" alt="Launchy for Windows" align="right" height="72" width="208"> 让你可以使用外部应用程序诸如 Internet Explorer、Netscape、Opera、Outlook 以及其他程序来打链接或是发送邮件，你也可以自己添加你自己的应用程序，比如 FlashGet、网络蚂蚁......等等，是个功能强大的扩展软件。</p>
<ul><li>适用版本：0.7-1.0</li><li>制作人：Henrik Gemal</li><li><a href="javascript:void(InstallTrigger.install({'Launchy for Windows':'xpi/LaunchyforWindows.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="SuperDragAndGo" id="SuperDragAndGo">Super Drag And Go</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/SuperDragAndGo.gif" alt="Launchy for Windows" align="right" height="72" width="208"> 拖拽一个链接到网页的任意空白位置来在新标签页中打开链接。 <br>
就像 MyIE 中超级拖拽一样。 </p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：asqueella MonkeeSage NetOne</li><li><a href="javascript:void(InstallTrigger.install({'SuperDragAndGo:%E8%B6%85%E7%BA%A7%E6%8B%96%E5%BC%8B%E6%8F%92%E4%BB%B6':'xpi/SuperDragAndGo.xpi'}))">安装此扩展</a></li></ul>
</div>
<img src ="http://www.blogjava.net/briansun/aggbug/1353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:18 <a href="http://www.blogjava.net/briansun/articles/1353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Firefox 插件2</title><link>http://www.blogjava.net/briansun/articles/1354.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 18:18:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1354.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1354.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1354.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1354.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1354.html</trackback:ping><description><![CDATA[<p><a href="http://www.mozilla.net.cn/firefox/">FireFox 简体中文增强版</a> 已经包含了最常用的几个扩展插件。如果你没有安装增强版(或是从其他版本升级到增强版)，可以到<a href="http://www.mozilla.net.cn/firefox/extensions/default.html">这里</a>详细查看并选择安装这些插件，或者
  <a href="javascript:void(InstallTrigger.install({  'Adblock:%E5%B9%BF%E5%91%8A%E9%98%BB%E6%AD%A2%E6%8F%92%E4%BB%B6':'xpi/Adblock.xpi',  'Search Status:%E5%9C%A8%E7%8A%B6%E6%80%81%E6%A0%8F%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E7%9A%84PR%E5%92%8CAlexa%E6%8E%92%E5%90%8D':'xpi/SearchStatus.xpi',  'All-in-One Gestures:%E4%BD%BF%E7%94%A8%E9%BC%A0%E6%A0%87%E6%89%8B%E5%8A%BF%E5%AF%B9%E6%B5%8F%E8%A7%88%E5%99%A8%E8%BF%9B%E8%A1%8C%E6%8E%A7%E5%88%B6':'xpi/AllinOneGestures.xpi',  'Tabbrowser Extensions:%E6%A0%87%E7%AD%BE%E9%A1%B5%E6%B5%8F%E8%A7%88%E6%8F%92%E4%BB%B6':'xpi/TabbrowserExtensions.xpi',  'Sage:Feed%E9%98%85%E8%AF%BB%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/Sage.xpi',  'Download Manager Tweak:Feed%E4%B8%8B%E8%BD%BD%E7%AE%A1%E7%90%86%E5%99%A8%E6%8F%92%E4%BB%B6':'xpi/downloadmgr.xpi',  'Launchy for Windows':'xpi/LaunchyforWindows.xpi',  'SuperDragAndGo:%E8%B6%85%E7%BA%A7%E6%8B%96%E5%BC%8B%E6%8F%92%E4%BB%B6':'xpi/SuperDragAndGo.xpi'  }))">点击此处</a>
  一次性安装这些常用插件。</p>

  
<p>下面列出的是那些没有被包含在增强版中，但是仍然推荐安装的插件：</p>

<div class="section">
<h2><a name="GmailNotifier">Gmail Notifier</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/GmailNotifier.gif" alt="Gmail Notifier" align="right" height="72" width="208"> 为您的 Gmail 邮件帐户提供通知功能，如果您拥有 Gmail 邮件账号，强烈推荐您安装此插件。</p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：Doron Rosenberg</li><li><a href="javascript:void(InstallTrigger.install({'Gmail Notifier:Gmail %E9%82%AE%E4%BB%B6%E5%B8%90%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%9A%E7%9F%A5':'xpi/GmailNotifier.xpi'}))">安装此扩展</a></li></ul>
</div>


<div class="section">
<h2><a name="WebDeveloper">WebDeveloper</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/WebDeveloper.gif" alt="WebDeveloper" align="right" height="72" width="208"></p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：Twanno</li><li><a href="javascript:void(InstallTrigger.install({'WebDeveloper:%E7%BD%91%E9%A1%B5%E5%BC%80%E5%8F%91%E6%89%A9%E5%B1%95':'xpi/WebDeveloper.xpi'}))">安装此扩展</a></li></ul>
</div>


<div class="section">
<h2><a name="WeatherFox">WeatherFox</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/WeatherFox.gif" alt="WeatherFox" align="right" height="72" width="208"> 在工具栏或状态栏中显示最近的天气。</p>
<ul><li>适用版本：1.0</li><li>制作人：Jon Stritar</li><li><a href="javascript:void(InstallTrigger.install({'WeatherFox:%E5%A4%A9%E6%B0%94%E6%98%BE%E7%A4%BA%E6%8F%92%E4%BB%B6':'xpi/WeatherFox.xpi'}))">安装此扩展</a></li></ul>
</div>


<div class="section">
<h2><a name="365Key">365Key</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/365Key.gif" alt="365Key" align="right" height="72" width="208"> 将当前网页和选中的文字提交到天天网摘 </p>
<ul><li>适用版本：1.0+</li><li>制作人：trumanxu</li><li><a href="javascript:void(InstallTrigger.install({'365Key:%E5%A4%A9%E5%A4%A9%E7%BD%91%E6%91%98':'xpi/365Key.xpi'}))">安装此扩展</a></li></ul>
</div>

<div class="section">
<h2><a name="close-tab-on-dblclick">Close Tab On Double Click</a></h2>
<p><img src="http://www.mozilla.net.cn/firefox/extensions/images/close-tab-on-dblclick.gif" alt="Close Tab On Double Click" align="right" height="72" width="208"> 你可以通过双击来关闭标签页。(这个插件的功能和增强版中的内置插件"<a href="http://www.mozilla.net.cn/firefox/extensions/default.html#TabbrowserExtensions">Tabbrowser Extensions</a>"重复，请勿同时安装)</p>
<ul><li>适用版本：0.8-1.0</li><li>制作人：Twanno</li><li><a href="javascript:void(InstallTrigger.install({'Close Tab On Double Click:%E9%80%9A%E8%BF%87%E5%8F%8C%E5%87%BB%E5%85%B3%E9%97%AD%E6%A0%87%E7%AD%BE%E9%A1%B5':'xpi/close-tab-on-dblclick.xpi'}))">安装此扩展</a></li></ul>
</div>
<img src ="http://www.blogjava.net/briansun/aggbug/1354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 02:18 <a href="http://www.blogjava.net/briansun/articles/1354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Firefox键盘快捷方式</title><link>http://www.blogjava.net/briansun/articles/1351.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Sat, 19 Feb 2005 17:41:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1351.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1351.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1351.html</trackback:ping><description><![CDATA[<h2 class="headline">键盘快捷健<br>
</h2>

<p>下面是 Mozilla Firefox最常用的键盘快捷键的列表以及它们在,&nbsp; Internet Explorer 和 Opera 中相对应的快捷键.</p>

<table border="0" cellpadding="2" cellspacing="1">

<tbody><tr>
<th>命令</th>
<th>Mozilla Firefox</th>
<th>Internet Explorer</th>
<th>Opera</th>
</tr>
<tr>
<td>添加为书签</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>D</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>D</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>T</kbd></td>
</tr>
<tr>
<td>后退</td>
<td class="shortcut_moz"><kbd>Backspace</kbd> <sup><a href="http://www.mozilla.net.cn/firefox/help/#f1">1</a></sup><br>
<kbd>Alt</kbd>+<kbd>Left Arrow</kbd></td>
<td class="shortcut"><kbd>Backspace</kbd><br>
<kbd>Alt</kbd>+<kbd>Left Arrow</kbd></td>
<td class="shortcut"><kbd>Backspace</kbd><br>
<kbd>Alt</kbd>+<kbd>Left Arrow</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Left Arrow</kbd><br>
<kbd>Z</kbd></td>
</tr>
<tr>
<td>打开书签</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>B</kbd><br>
<kbd>Ctrl</kbd>+<kbd>I</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>I</kbd></td>
<td class="shortcut"><kbd>F4</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>B</kbd><br>
<kbd>Ctrl</kbd>+<kbd>1</kbd></td>
</tr>
<tr>
<td>插入浏览</td>
<td class="shortcut_moz"><kbd>F7</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut">无此功能</td>
</tr>
<tr>
<td>关闭窗口</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>W</kbd><br>
<kbd>Ctrl</kbd>+<kbd>F4</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>W</kbd><br>
<kbd>Ctrl</kbd>+<kbd>F4</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>W</kbd><br>
<kbd>Ctrl</kbd>+<kbd>F4</kbd></td>
</tr>
<tr>
<td>补充 .com 地址</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Enter</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Enter</kbd></td>
<td class="shortcut"><kbd>Enter</kbd></td>
</tr>
<tr>
<td>补充 .net 地址</td>
<td class="shortcut_moz"><kbd>Shift</kbd>+<kbd>Enter</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut">无此功能</td>
</tr>
<tr>
<td>补充 .org 地址</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Enter</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut">无此功能</td>
</tr>
<tr>
<td>复制</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>C</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>C</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>C</kbd></td>
</tr>
<tr>
<td>剪切</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>X</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>X</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>X</kbd></td>
</tr>
<tr>
<td>减小文字大小</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>-</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>9</kbd></td>
</tr>
<tr>
<td>删除</td>
<td class="shortcut_moz"><kbd>Del</kbd></td>
<td class="shortcut"><kbd>Del</kbd></td>
<td class="shortcut"><kbd>Del</kbd></td>
</tr>
<tr>
<td>下载</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>E</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd><br>
<kbd>Ctrl</kbd>+<kbd>5</kbd></td>
</tr>
<tr>
<td>再次查找</td>
<td class="shortcut_moz"><kbd>F3</kbd><br>
<kbd>Ctrl</kbd>+<kbd>G</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>F3</kbd></td>
</tr>
<tr>
<td>输入查找链接</td>
<td class="shortcut_moz"><kbd>'</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>,</kbd><br>
<kbd>Shift</kbd>+<kbd>/</kbd></td>
</tr>
<tr>
<td>输入查找文本</td>
<td class="shortcut_moz"><kbd>/</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>/</kbd><br>
<kbd>.</kbd></td>
</tr>
<tr>
<td>查找</td>
<td class="shortcut_moz"><kbd>Shift</kbd>+<kbd>F3</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>Shift</kbd>+<kbd>F3</kbd></td>
</tr>
<tr>
<td>本页查找</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>F</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>F</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>F</kbd></td>
</tr>
<tr>
<td>前进</td>
<td class="shortcut_moz"><kbd>Shift</kbd>+<kbd>Backspace</kbd> <sup><a href="http://www.mozilla.net.cn/firefox/help/#f1">1</a></sup><br>
<kbd>Alt</kbd>+<kbd>Right Arrow</kbd></td>
<td class="shortcut"><kbd>Shift</kbd>+<kbd>Backspace</kbd><br>
<kbd>Alt</kbd>+<kbd>Right Arrow</kbd></td>
<td class="shortcut"><kbd>Shift</kbd>+<kbd>Backspace</kbd><br>
<kbd>Alt</kbd>+<kbd>Right Arrow</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Right Arrow</kbd><br>
<kbd>X</kbd></td>
</tr>
<tr>
<td>全屏</td>
<td class="shortcut_moz"><kbd>F11</kbd></td>
<td class="shortcut"><kbd>F11</kbd></td>
<td class="shortcut"><kbd>F11</kbd></td>
</tr>
<tr>
<td>历史</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>H</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>H</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>H</kbd><br>
<kbd>Ctrl</kbd>+<kbd>4</kbd></td>
</tr>
<tr>
<td>首页</td>
<td class="shortcut_moz"><kbd>Alt</kbd>+<kbd>Home</kbd></td>
<td class="shortcut"><kbd>Alt</kbd>+<kbd>Home</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Space</kbd></td>
</tr>
<tr>
<td>增大文字大小</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>+</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>0</kbd></td>
</tr>
<tr>
<td>移到下一帧</td>
<td class="shortcut_moz"><kbd>F6</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut">&nbsp;</td>
</tr>
<tr>
<td>移到上一帧</td>
<td class="shortcut_moz"><kbd>Shift</kbd>+<kbd>F6</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut">&nbsp;</td>
</tr>
<tr>
<td>新建标签页</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>T</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>N</kbd></td>
</tr>
<tr>
<td>下一个标签页</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Tab</kbd><br>
<kbd>Ctrl</kbd>+<kbd>PageDown</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Tab</kbd><br>
<kbd>Alt</kbd>+<kbd>Page Down</kbd><br>
<kbd>Ctrl</kbd>+<kbd>F6</kbd><br>
<kbd>2</kbd></td>
</tr>
<tr>
<td>新建窗口</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>N</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>N</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>N</kbd></td>
</tr>
<tr>
<td>打开文件</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>O</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>O</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>O</kbd></td>
</tr>
<tr>
<td>在新标签页打开网址</td>
<td class="shortcut_moz"><kbd>Alt</kbd>+<kbd>Enter</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>Shift</kbd>+<kbd>Enter</kbd></td>
</tr>
<tr>
<td>页面信息</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>J</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>8</kbd></td>
</tr>
<tr>
<td>页面源代码</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>U</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>F3</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>F3</kbd></td>
</tr>
<tr>
<td>粘贴</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>V</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>V</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>V</kbd></td>
</tr>
<tr>
<td>前一个标签页</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Tab</kbd><br>
<kbd>Ctrl</kbd>+<kbd>PageUp</kbd></td>
<td class="shortcut">无此功能</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>shift</kbd>+<kbd>Tab</kbd><br>
<kbd>Alt</kbd>+<kbd>Page Up</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>F6</kbd><br>
<kbd>1</kbd></td>
</tr>
<tr>
<td>打印</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>P</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>P</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>P</kbd></td>
</tr>
<tr>
<td>重做</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Y</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Y</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Y</kbd></td>
</tr>
<tr>
<td>重新载入</td>
<td class="shortcut_moz"><kbd>F5</kbd> <sup><a href="http://www.mozilla.net.cn/firefox/help/#f1">1</a></sup><br>
<kbd>Ctrl</kbd>+<kbd>R</kbd></td>
<td class="shortcut"><kbd>F5</kbd><br>
<kbd>Ctrl</kbd>+<kbd>R</kbd></td>
<td class="shortcut"><kbd>F5</kbd><br>
<kbd>Ctrl</kbd>+<kbd>R</kbd></td>
</tr>
<tr>
<td>重新载入 (忽略缓存)</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>F5</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>R</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>F5</kbd></td>
<td class="shortcut">&nbsp;</td>
</tr>
<tr>
<td>恢复文本大小</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>0</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>6</kbd></td>
</tr>
<tr>
<td>页面另存为</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>S</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>S</kbd></td>
</tr>
<tr>
<td>全选</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>A</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>A</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>A</kbd></td>
</tr>
<tr>
<td>选择地址条</td>
<td class="shortcut_moz"><kbd>Alt</kbd>+<kbd>D</kbd><br>
<kbd>F6</kbd><br>
<kbd>Ctrl</kbd>+<kbd>L</kbd></td>
<td class="shortcut"><kbd>Alt</kbd>+<kbd>D</kbd><br>
<kbd>F6</kbd><br>
<kbd>F4</kbd><br>
<kbd>Ctrl</kbd>+<kbd>Tab</kbd></td>
<td class="shortcut"><kbd>F8</kbd></td>
</tr>
<tr>
<td>搜索条</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>K</kbd></td>
<td class="shortcut">&nbsp;</td>
<td class="shortcut"><kbd>Shift</kbd>+<kbd>F8</kbd></td>
</tr>
<tr>
<td>选择标签页 [1 to 9]</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+[<kbd>1</kbd> to <kbd>9</kbd>]</td>
<td class="shortcut">无此功能</td>
<td class="shortcut">&nbsp;</td>
</tr>
<tr>
<td>停止</td>
<td class="shortcut_moz"><kbd>Esc</kbd></td>
<td class="shortcut"><kbd>Esc</kbd></td>
<td class="shortcut"><kbd>Esc</kbd></td>
</tr>
<tr>
<td>撤消</td>
<td class="shortcut_moz"><kbd>Ctrl</kbd>+<kbd>Z</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Z</kbd></td>
<td class="shortcut"><kbd>Ctrl</kbd>+<kbd>Z</kbd></td>
</tr>
</tbody>
</table>

<p><a name="1" id="1"></a><sup>1</sup>: 这个快捷键只在windows中起作用.</p>
<img src ="http://www.blogjava.net/briansun/aggbug/1351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-20 01:41 <a href="http://www.blogjava.net/briansun/articles/1351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NCRE Rank 3 Conclusion.c</title><link>http://www.blogjava.net/briansun/articles/1079.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Fri, 11 Feb 2005 16:16:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1079.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1079.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1079.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1079.html</trackback:ping><description><![CDATA[<pre>/*<br> 国家计算机等级考试三级基本要求<br>1、掌握计算机系统和计算机软件的基本概念、计算机网络的基本知识和应用知识、信息安全的基本概念。<br>2、掌握数据结构与算法的基本知识并能熟练应用。<br>3、掌握并能熟练运用操作系统的基本知识。<br>4、掌握数据库的基本概念，深入理解关系数据模型、关系数据理论和关系数据库系统，掌握关系数据语言。<br>5、掌握数据库设计方法，具有数据库设计能力。了解数据库技术发展。<br>6、掌握计算机操作，并具有用C语言编程，开发数据库应用（含上机调试）的能力。<br>考试内容<br>一、基础知识<br>1、计算机系统的组成和应用领域。<br>2、计算机软件的基础知识。<br>3、计算机网络的基础知识和应用知识。<br>4、信息安全的基本概念。<br>二、数据结构与算法<br>1、数据结构、算法的基本概念。<br>2、线性表的定义、存储和运算。<br>3、树形结构的定义、存储和运算。<br>3、排序的基本概念和排序算法。<br>4、检索的基本概念和检索算法。<br>三、操作系统<br>1、操作系统的基本概念、主要功能和分类。6<br>2、进程、线程、进程间通信的基本概念。<br>3、存储管理、文件管理、设备管理的主要技术。<br>4、典型操作系统的使用。<br>四、数据库系统基本原理<br>1、数据库的基本概念，数据库系统的构成。<br>2、数据模型概念和主要的数据模型。<br>3、关系数据模型的基本概念，关系操作和关系代数。<br>4、结构化查询语言SQL。<br>5、事务管理、并发控制、故障恢复的基本概念。<br>五、数据库设计和数据库应用<br>1、关系数据库的规范化理论。<br>2、数据库设计的目标、内容和方法。<br>3、数据库应用开发工具。<br>4、数据库技术发展。<br>六、上机操作<br>1、掌握计算机基本操作。<br>2、掌握C语言程序设计基本技术、编程和调试。<br>3、掌握与考试内容相关的知识的上机应用。<br>考试方法<br>一、笔试：120分钟<br>二、上机考试：60分钟<br>*/<br><br>//------------判定一个数是否为素数----------//<br>int isPrime(int m) {<br>    int i;<br>    for (i = 0; i &lt; sqrt(m); i++)<br>        if (m%i == 0) return 0;<br>    return 1;<br>}<br>//------------判定一个数是否为素数----------//<br><br>//------------基本排序算法----------//<br>    for (i = 0; i &lt; cnt; i++)<br>        for (j = i+1; j &lt; cnt; j++)<br>            if (b[i] &lt; b[j])<br>                { temp = b[i]; b[i] = b[j]; b[j] = temp; }<br>//------------基本排序算法----------//<br><br>//------------查找最大值及最大值的个数----------//<br>     max = MAXINT;<br>     for (i = 0; i &lt; N; i++) {<br>         if (max &lt; xx[i]) {<br>            max = xx[i];<br>            cnt = 0;<br>         } else if (max == xx[i])<br>                cnt++;<br>     }<br>//------------查找最大值及最大值的个数----------//<br><br>//------------反转和轴对称----------//<br>         int len = strlen(s);<br>         for (j = 0; j &lt; len/2; j++)<br>             { c = s[j]; s[j] = s[len - j - 1]; s[len - j - 1] = c; }<br>         for (j = 0; j &lt; len/2; j++)<br>             if (s[j] == s[len - j - 1]) return 0;<br>//------------反转和轴对称----------//<br><br>//------------分析四位数----------//<br>         c1 = a[i]/1000;<br>         c2 = a[i]%1000/100;<br>         c3 = a[i]%100/10;<br>         c4 = a[i]/10;<br>//------------分析四位数----------//<br><br>//------------附加函数总结----------//<br>/*<br>+------------------------------------------------------------------------------------------------+<br>|函数名称                  |意义                                                        |头文件  |<br>+------------------------------------------------------------------------------------------------+<br>|sqrt(float)               |返回参数的开方值                                            |math.h  |<br>|cos(float)                |返回参数的余弦值，参数是弧度                                |math.h  |<br>|strchr(char*, char)       |在字符串中查找给定字符的指针，若没有给定字符，返回null      |string.h|<br>|strcpy(char*, char*)      |把后一个字符串复制给前一个字符串                            |string.h|<br>|strcat(char*, char*)      |把后一个字符串拼到前一个字符串后面                          |string.h|<br>|strcmp(char*, char*)      |比较两个字符串，返回值&gt;=&lt;0分别表示前一个字符串&gt;=&lt;后一个     |string.h|<br>|strlen(char*)             |求字符串的长度                                              |string.h|<br>|memcpy(void*, void*, int) |将一段内存从第一个指针拷贝到第二个指针所指向的空间，        |stdlib.h|<br>|                          |最后一个参数是需拷贝的长度，通常用sizeof()求出              |        |<br>|ltoa(long, char*, int)    |将长整数表示为一个字符串，最后一个参数是进制，整数用itoa    |stdlib.h|<br>|atol(long)                |将字符串变成长整数                                          |stdlib.h|<br>+------------------------------------------------------------------------------------------------+<br>*/<br>//------------附加函数总结----------//<br><br><br></pre>
<img src ="http://www.blogjava.net/briansun/aggbug/1079.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-12 00:16 <a href="http://www.blogjava.net/briansun/articles/1079.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NCRE Rank 3 100 Ques.c</title><link>http://www.blogjava.net/briansun/articles/1078.html</link><dc:creator>Brian Sun</dc:creator><author>Brian Sun</author><pubDate>Fri, 11 Feb 2005 16:15:00 GMT</pubDate><guid>http://www.blogjava.net/briansun/articles/1078.html</guid><wfw:comment>http://www.blogjava.net/briansun/comments/1078.html</wfw:comment><comments>http://www.blogjava.net/briansun/articles/1078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/briansun/comments/commentRss/1078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/briansun/services/trackbacks/1078.html</trackback:ping><description><![CDATA[<pre>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;string.h&gt;<br>#include &lt;conio.h&gt;<br>#include &lt;ctype.h&gt;<br>#include &lt;math.h&gt;<br><br>typedef struct {<br>        char dm[5];<br>        char mc[11];<br>        int dj;<br>        int sl;<br>        long je;<br><br>}PRO;<br><br>//-----------------1---------------//<br>int isP(int m) {<br>    int i;<br>    for (i = 0; i &lt; sqrt(m); i++)<br>        if (m%i == 0) return 0;<br>    return 1;<br>}<br><br>void ques01(int m, int k, int xx[]) {<br>    int i, j = 0;<br>    for (i = m+1; j &lt; k; i++)<br>        if (isP(i)) xx[j++] = i;<br>}<br>//-----------------1---------------//<br><br>//-----------------2---------------//<br>#define  MAX 200<br>int a[MAX], b[MAX], cnt = 0;<br><br>void ques02() {<br>    int c1, c2, c3, c4;<br>    int i, j, temp;<br>    for (i = 0; i &lt; MAX; i++) {<br>        c1 = a[i]%10;<br>        c2 = a[i]%100/10;<br>        c3 = a[i]%1000/100;<br>        c4 = a[i]/1000;<br>        if (c1%2==0 &amp;&amp; c2%2==0 &amp;&amp; c3%2==0 &amp;&amp; c4%2==0) <br>            b[cnt++] = a[i];<br>    }<br>    <br>    for (i = 0; i &lt; cnt; i++)<br>        for (j = i+1; j &lt; cnt; j++)<br>            if (b[i] &lt; b[j])<br>                { temp = b[i]; b[i] = b[j]; b[j] = temp; }<br>}<br>//-----------------2---------------//<br><br>//-----------------3---------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>void ques03() {<br>    int i, j;<br>    char *p, temp[80];<br>    for (i = 0; i &lt; maxline; i++) {<br>        while (1) {<br>            p = strchr(xx[i], 'o');<br>            if (!p) break;<br>            <br>            strcpy(temp, p+1);<br>            *p = 0;<br>            strcat(temp, xx[i]);<br>            strcpy(xx[i], temp);<br>        }<br>    }<br>}<br>//-----------------3---------------//<br><br>//-----------------4---------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>int isLetter(char c) {<br>    return (c &gt;= 'A' &amp;&amp; c &lt;= 'Z') || (c &gt;= 'a' &amp;&amp; c &lt;= 'z');<br>}<br><br>void ques04() {<br>     int i, j;<br>     char *p, *q, temp[80];<br><br>     for( i = 0; i &lt; maxline; i++ ) {<br>          temp[0] = 0;<br>          while (1) {<br>                for (q = xx[i]+strlen(xx[i])-1; q &gt;= xx[i] &amp;&amp; !isLetter(*q); q--);<br>                for (p = q; p &gt; xx[i] &amp;&amp; isLetter(*(p-1)); p--);<br>                if (p &lt; xx[i] || q &lt; xx[i]) break;<br><br>                *(q+1) = 0;<br>                strcat(temp, p);<br>                strcat(temp, " ");<br>                *p = 0;<br>          }<br>          strcpy(xx[i], temp);<br>     }<br>}<br>//-----------------4---------------//<br><br>//-----------------5---------------//<br>#define  MAX 200<br>int aa[MAX], bb[10];<br><br>void ques05() {<br>     int i, j, k, temp;<br><br>     for (i = 0; i &lt; MAX; i++)<br>         for (j = i+1; j &lt; MAX; j++)<br>             if (aa[i]%1000 &gt; aa[j]%1000 || (aa[i]%1000 == aa[j]%1000 &amp;&amp; aa[i] &lt; aa[j]))<br>                {temp = aa[i]; aa[i] = aa[j]; aa[j] = temp;}<br><br>     for (i = 0; i &lt; 10; i++)<br>         bb[i] = aa[i];<br>}<br>//-----------------5---------------//<br><br>//-----------------7---------------//<br>#define MAX 100<br>PRO sell[MAX];<br><br>void ques07() {<br>     int i, j, len = sizeof(PRO);<br>     PRO temp;<br><br>     for (i = 0; i &lt; MAX; i++)<br>         for (j = i+1; j &lt; MAX; j++) {<br>             if (strcmp(sell[i].dm, sell[j].dm)&lt;0 || (strcmp(sell[i].dm, sell[j].dm)==0 &amp;&amp; sell[i].je &lt; sell[j].je))<br>                {<br>                 memcpy(&amp;temp, &amp;sell[i], len);<br>                 memcpy(&amp;sell[i], &amp;sell[j], len);<br>                 memcpy(&amp;sell[j], &amp;temp, len);<br>                }<br>         }<br>}<br>//-----------------7---------------//<br><br>//-----------------8---------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>char encrypt(char p) {<br>    char x = p*11%256;<br>    if (x&lt;=32 || x&gt;130) return p;<br>    else return x;<br>}<br><br>void ques08() {<br>     int i, j;<br>     char x;<br>     for (i = 0; i &lt; maxline; i++)<br>         for (j = 0; j &lt; strlen(xx[i]); j++)<br>             xx[i][j] = encrypt(xx[i][j]);<br>}<br>//-----------------8---------------//<br><br>//-----------------9---------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>void ques09() {<br>     int i, j, k;<br>     char temp;<br>     for (i = 0; i &lt; maxline; i++ )  {<br>         for (j = 0; j &lt; strlen(xx[i]); j++ ) ;<br>         for (k = j+1; k &lt; strlen(xx[i]); k++ ) ;<br>             if ( xx[i][j] &lt; xx[i][k] )<br>                { temp = xx[i][j]; xx[i][j] = xx[i][k]; xx[i][k] = temp; }<br><br>     }<br>}<br>//-----------------9---------------//<br><br><br>//-----------------10--------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>char nextLetter( char c ) {<br>     if ( c &gt;= 'a' &amp;&amp; c &lt; 'z' ) return c+1;<br>     if ( c == 'z' ) return 'a';<br>     return c;<br>}<br><br>void ques10() {<br>     int i, j;<br>     for ( i = 0; i &lt; maxline; i++ )<br>         for ( j = 0; j &lt; strlen(xx[i]); j++ )<br>             xx[i][j] = nextLetter(xx[i][j]);<br><br>}<br>//-----------------10--------------//<br><br>//-----------------11--------------//<br>char nextLetter( char c ) {<br>     if ( (c &gt;= 'a' &amp;&amp; c &lt; 'z') || (c &gt;= 'A' &amp;&amp; c &lt; 'Z') ) return c+1;<br>     else if ( c == 'z' ) return 'a';<br>     else if ( c == 'Z' ) return 'A';<br>     else return c;<br>}<br><br>void ques11(char *s) {<br>     int i;<br>     for (i = 0; i &lt; strlen(s); i++)<br>         s[i] = f3(s[i]);<br>}<br>//-----------------11--------------//<br><br>//-----------------14--------------//<br>#define  MAX 200<br>int a[MAX], b[MAX], cnt = 0;<br><br>void ques14() {<br>     int i, k, temp;<br>     for ( i = 0; i &lt; MAX-5; i++ )<br>         if (a[i]%2 != 0 &amp;&amp; a[i] &gt; a[i+1] &amp;&amp; a[i] &gt; a[i+2] &amp;&amp; a[i] &gt; a[i+3] &amp;&amp; a[i] &gt; a[i+4] &amp;&amp; a[i] &gt; a[i+5] )<br>            b[cnt++] = a[i];<br><br>     for ( i = 0; i &lt; cnt; i++ )<br>         for ( k = i+1; k &lt; cnt; k++ )<br>             if ( b[i] &gt; b[k] )<br>                { temp = b[i]; b[i] = b[k]; b[k] = temp; }<br>}<br>//-----------------14--------------//<br><br>//-----------------15--------------//<br>#define  MAX 200<br>int a[MAX], b[MAX], cnt = 0;<br><br>void ques15() {<br>     int i, j, k, c1, c2, c3, c4;<br>     for ( i = 0; i &lt; MAX; i++ )  {<br>         c1 = a[i]/1000;<br>         c2 = a[i]%1000/100;<br>         c3 = a[i]%100/10;<br>         c4 = a[i]/10;<br>         if ( c1 &lt;= c2 &amp;&amp; c2 &lt;= c3 &amp;&amp; c3 &lt;= c4 &amp;&amp; a[i]%2 == 0 )<br>            b[cnt++] = a[i];<br>     }<br>}<br>//-----------------15--------------//<br><br>//-----------------17--------------//<br>char xx[50][80];<br>int maxline = 0;<br><br>void ques17() {<br>     int i, j, len, k;<br>     char c;<br>     for (i = 0; i &lt; maxline; i++){<br>         c = xx[i][0];<br>         for (j = 0; j &lt; strlen(xx[i])-1; j++)  {<br>             xx[i][j] += xx[i][j+1];<br>         }<br>         xx[i][j] += c;<br><br>         len = strlen(xx[i]);<br>         k = len/2;<br>         for (j = 0; j &lt; k; j++)<br>             { c = xx[i][j]; xx[i][j] = xx[i][len - j - 1]; xx[i][len - j - 1] = c; }<br>      }<br>}<br>//-----------------17--------------//<br><br>//-----------------19--------------//<br>int ques19(char *str, char *substr) {<br>    int i, len = strlen(str), sum = 0;<br>    for (i = 0; i &lt; len-1; i++) {<br>        if (str[i] == substr[0] &amp;&amp; str[i+1] == substr[1]) sum++;<br>    }<br>    return sum;<br>}<br><br>int ques19_ans2(char *str, char *substr) {<br>    int i, j, len1 = strlen(str), len2 = strlen(substr), sum = 0;<br>    for (i = 0; i &lt;= len1 - len2; i++) {<br>        for (j = 0; j &lt; len2; j++) {<br>            if (str[i] != substr[j]) break;<br>        }<br>        if (j == len2) sum++;<br>    }<br>    return sum;<br>}<br>//-----------------19--------------//<br><br>//-----------------20--------------//<br>int ques20(int t) {<br>    int a = 0, b = 1;<br>    while (1) {<br>          if (a&gt;t) return a;<br>          if (b&gt;t) return b;<br>          a = a+b;<br>          b = a+b;<br>    }<br>}<br>//-----------------20--------------//<br><br>//-----------------21--------------//<br>float ques21() {<br>      float x0, x1 = 0.0;<br>      while(1) {<br>            x0 = x1;<br>            x1 = cos(x0);<br>            if (x0-x1 &lt; 1e-6) return x1;<br>      }<br>}<br>//-----------------21--------------//<br><br>//-----------------22--------------//<br>double ques22(int n) {<br>       int i, sum = 0;<br>       for (i = 1; i &lt; n; i++) {<br>           if (i%3==0 &amp;&amp; i%7==0) sum+=i;<br>       }<br>       return sqrt(sum);<br>}<br><br>double ques22_ans2(int n) {<br>       return sqrt((n/21)*(n/21+1)/2*21);<br>}<br>//-----------------22--------------//<br><br>//-----------------23--------------//<br>#define MAX 200<br>float xx[MAX];<br>int N = 0;<br>double aver = 0.0;<br>double sumint = 0.0;<br>double sumdec = 0.0;<br><br>void ques23() {<br>     int i;<br>     float sum = 0.0;<br>     for (i = 0; i &lt; N; i++)  {<br>         sum += xx[i];<br>         sumint += (int)xx[i];<br>         sumdec += xx[i] - (int)xx[i];<br>     }<br>     aver = sum / N;<br>}<br><br>void ques23_ans2() {<br>     int i;<br>     for (i = 0; i &lt; N; i++)  {<br>         aver += xx[i];<br>         sumint += (int)xx[i];<br>     }<br>     sumdec = aver - sumint;<br>     aver /= N;<br>}<br>//-----------------23--------------//<br><br>//-----------------24--------------//<br>int ques24(int bb[]) {<br>    int index = 0, i, c1, c2, c3, d;<br>    for (i = 100; i &lt; 1000; i++) {<br>        c1 = i%10;<br>        c2 = i%100/10;<br>        c3 = i/100;<br>        d = (int)sqrt(i);<br>        if (i==d*d &amp;&amp; (c1==c2 || c2==c3 || c1==c3))<br>           bb[index++] = i;<br>    }<br>}<br><br>int ques24_ans2(int bb[]) {<br>    int index = 0, i, c1, c2, c3, d;<br>    for (d = 10; d &lt;= 31; d++) {<br>        i = d*d;<br>        c1 = i%10;<br>        c2 = i%100/10;<br>        c3 = i/100;<br>        if (i==d*d &amp;&amp; (c1==c2 || c2==c3 || c1==c3))<br>           bb[index++] = i;<br>    }<br>}<br>//-----------------24--------------//<br><br>//-----------------25--------------//<br>int ques25(long m) {<br>    int i, len;<br>    char p[10], temp;<br>    long m2;<br><br>    ltoa(m, p, 10);<br>    len = strlen(p);<br>    for (i = 0; i &lt; len/2; i++) {<br>        temp = p[i]; p[i] = p[len-i-1]; p[len-i-1] = temp;<br>    }<br>    m2 = atol(p);<br>    return m==m2;<br>}<br><br>int ques25_ans2(long n) {<br>    int i, len;<br>    char temp[20];<br>    ltoa(n, temp, 10);<br>    len = strlen(temp);<br><br>    for (i = 0; i &lt; len/2; i++) {<br>        if (temp[i] != temp[len - i - 1]) return 0;<br>    }<br>    return 1;<br>}<br>//-----------------25--------------//<br><br>//-----------------33--------------//<br>#define MAX 1000<br>int xx[MAX], odd = 0, even = 0;<br>double ave1 = 0.0, ave2 = 0.0, totfc = 0.0;<br><br>void ques33() {<br>     int i;<br>     for (i = 0; i &lt; MAX; i++) {<br>         if (xx[i]%2 == 0) { even++; ave2 += xx[i]; }<br>         else ave1 += xx[i];<br>     }<br>     ave1 /= MAX-even;<br>     ave2 /= even;<br><br>     for (i = 0; i &lt; MAX; i++) {<br>         if (xx[i]%2==0)<br>            totfc += (xx[i] - ave2)*(xx[i] - ave2);<br>     }<br>     totfc /= even;<br>}<br>//-----------------33--------------//<br><br>//-----------------34--------------//<br>int cnt, sum;<br><br>void ques34() {<br>     int i, c1, c2, c3;<br>     for (i = 100; i &lt; 1000; i++)<br>         if (isP(i)) { //这个函数是第一题里的<br>            c1 = i%10;<br>            c2 = i%100/10;<br>            c3 = i/100;<br>            if ((c1+c2)%10 == c3) { cnt++; sum+=i; }<br>         }<br>}<br>//-----------------34--------------//<br><br>//-----------------35--------------//<br>int b[3];<br><br>void ques35() {<br>     int n, A = 1, B = 1, C, sum = A+B;<br>     b[0] = b[1] = b[2] = 0;<br>     for (n = 3; ; n++) {<br>         //第n次计算，求An和Sum = A1+...+An<br>         C = A + 2*B;<br>         //把计算出来的An加到累加器<br>         sum += C;<br>         //如果满足条件，且记录器从未记录过<br>         if (sum&gt;=100 &amp;&amp; b[0]==0) b[0] = n-1;<br>         if (sum&gt;=1000 &amp;&amp; b[1]==0) b[1] = n-1;<br>         if (sum&gt;=10000) { b[2] = n-1; break; }<br><br>         //向后递推<br>         A = B;<br>         B = C;<br>     }<br>}<br><br>void ques35_ans2(void){<br>     int n, x = 1, y = 1, z, sum0, sum;<br>     sum0 = sum = x+y;<br>     b[0] = b[1] = b[2] = 0;<br>     for (n = 3; ;n++) {<br>         //第n次计算，已知Sum0 = A1+...+An-1，求An和Sum = A1+...+An<br>         z = x + 2*y;<br>         //把计算出来的An加到累加器<br>         sum = sum0 + z;<br>         //如果满足条件<br>         if (sum0&lt;100 &amp;&amp; sum&gt;=100) b[0] = n-1;<br>         if (sum0&lt;1000 &amp;&amp; sum &gt;= 1000) b[1] = n-1;<br>         if (sum0&lt;10000 &amp;&amp; sum &gt;= 10000) {b[2] = n-1; break;}<br>         //如果不满足则向后递推<br>         x = y;<br>         y = z;<br>         sum0 = sum;<br>     }<br>}<br>//-----------------35--------------//<br><br>//-----------------39--------------//<br>char xx[100][11];<br>int yy[10];<br><br>void ques39() {<br>     int i, j;<br>     for (i = 0; i &lt; 10; i++) yy[i] = 0;<br><br>     for (i = 0; i &lt; 100; i++) {<br>         if (strcmp(xx[i], "1111111111") == 0) continue;<br>         if (strcmp(xx[i], "0000000000") == 0) continue;<br>         for (j = 0; j &lt; 10; j++)<br>             if (xx[i][j] == '1') yy[j]++;<br>     }<br>}<br>//-----------------39--------------//<br><br>//-----------------41--------------//<br>int cnt, sum;<br><br>void ques41() {<br>     int i, j;<br>     cnt = 0, sum = 0;<br>     for (i = 100; i &lt; 1000; i++)<br>         for (j = 1000; j &lt; 10000; j++)<br>             if (i*3 == j*2) {<br>                if (i%100/10 == j%1000/100 &amp;&amp; j%100/10 == j/1000) {<br>                   cnt++;<br>                   sum += i+j;<br>                }<br>             }<br>}<br>//-----------------41--------------//<br><br>//-----------------43--------------//<br>char xx[20][80];<br><br>void ques43() {<br>     int i, j, k;<br>     char temp;<br><br>     for (i = 0; i &lt; 20; i++)<br>         for (j = 1; j &lt; strlen(xx[i]); j+=2)<br>             for (k = j+2; k &lt; strlen(xx[i]); k+=2)<br>                 if (xx[i][j] &gt; xx[i][k])<br>                    { temp = xx[i][j]; xx[i][j] = xx[i][k]; xx[i][k] = temp; }<br>}<br>//-----------------43--------------//<br><br>//-----------------44--------------//<br>char xx[20][80];<br><br>void ques44() {<br>     int i, j, k, len;<br>     char temp;<br><br>     for (i = 0; i &lt; 20; i++) {<br>         len = strlen(xx[i]);<br>         for (j = 0; j &lt; len/2; j++)<br>             for (k = j+1; k &lt; len/2; k++)<br>                 if (xx[i][j] &lt; xx[i][k])<br>                    { temp = xx[i][j]; xx[i][j] = xx[i][k]; xx[i][k] = temp; }<br>         for (j = 0; j &lt; len/2; j++)<br>             { temp = xx[i][j]; xx[i][j] = xx[i][(len+1)/2 - j]; xx[i][(len+1)/2 - j] = temp; }<br>     }<br>}<br>//-----------------44--------------//<br><br>//-----------------50--------------//<br>char xx[20][80];<br><br>void ques50(){<br>     int i, j, k, len;<br>     char temp;<br>     for (i = 0; i &lt; 20; i++){<br>         len = strlen(xx[i]);<br>         for (j = 0; j &lt; len/2; j++){<br>             for (k = j+1; k &lt; len/2; k++){<br>                 if (xx[i][j] &lt; xx[i][k]){<br>                    temp = xx[i][j]; xx[i][j] = xx[i][k]; xx[i][k] = temp;<br>                 }<br>             }<br>         }<br>         for (j = 0; j &lt; len/2; j++){<br>             temp = xx[i][j]; xx[i][j] = xx[i][(len+1)/2+i]; xx[i][(len+1)/2+i] = temp;<br>         }<br>     }<br>}<br>//-----------------50--------------//<br><br>//-----------------57--------------//<br>#define N 100<br>#define S 1<br>#define M 10<br><br>int p[100], n = N, s = S, m = M;<br><br>void ques57 (){<br>     int i, j, k = -1, a[100];<br>     for (i = 0; i &lt; N; i++) a[i] = 1;//1表示在圈内，0表示不在<br><br>     for (i = 0; i &lt; N; i++) {<br>         for (j = 0; j &lt; M; j++) {<br>             do {<br>                k++;<br>                if (k==N) k = 0;<br>             }while(!a[k]);<br>             //编号为k的人报数，报的是j<br>         }<br>         //编号为k的人报了M，此人出列<br>         p[i] = k+1;<br>         a[k] = 0;<br>     }<br>}<br>//-----------------57--------------//<br><br>//-----------------58--------------//<br>char xx[100][11];<br>int yy[10];<br><br>void ques58() {<br>     int i, j, sum;<br>     for (i = 0; i &lt; 10; i++) yy[i] = 0;<br><br>     for (i = 0; i &lt; 100; i++) {<br>         sum = 0;<br>         for (j = 0; j &lt; 10; j++) sum++;<br>         if ( sum &gt; 5 ) {<br>            for (j = 0; j &lt; 10; j++)<br>                if (xx[i][j] == '1') yy[j]++;<br>         }<br>     }<br>}<br>//-----------------58--------------//<br><br>//-----------------60--------------//<br>typedef struct {<br>        int x1, x2, x3;<br>}Data;<br><br>Data aa[200], bb[200];<br><br>int ques60() {<br>    int i, j, cnt = 0, len = sizeof(Data);<br>    Data temp;<br><br>    for (i = 0; i &lt; 200; i++)<br>        if (aa[i].x1 + aa[i].x3 &lt; aa[i].x2)<br>           memcpy(&amp;bb[cnt++], &amp;aa[i], len);<br><br>    for (i = 0; i &lt; cnt; i++)<br>        for (j = i+1; j &lt; cnt; j++)<br>            if (bb[i].x2 + bb[i].x3 &lt; bb[j].x2 + bb[j].x3) {<br>               memcpy(&amp;temp, &amp;bb[i]);<br>               memcpy(&amp;bb[i], &amp;bb[j]);<br>               memcpy(&amp;bb[j], temp);<br>            }<br>}<br>//-----------------60--------------//<br><br>//-----------------63--------------//<br>void ques63(char *s){<br>     int i, j, len = strlen(s);<br>     char temp;<br><br>     temp = s[0];<br>     for (i = 1; i &lt; len; i++) s[i-1] = s[i];<br>     s[len - 1] = temp;<br>}<br>//-----------------63--------------//<br><br>//-----------------66--------------//<br>int cnt, sum;<br><br>void ques66() {<br>     int i, j, flag = 1;<br>     cnt = sum = 0;<br>     for (i = 800; i &gt; 500; i--) {<br>         if (isP(i)) {<br>            cnt++;<br>            if (flag) sum += i;<br>            else sum -= i;<br>            flag = - flag;<br>         }<br>     }<br>}<br>//-----------------66--------------//<br><br>//-----------------90--------------//<br>void ques90(int a[10][9]) {<br>     int b[9];<br>     int i, j, k, len = sizeof(b);<br>     for (i = 0; i &lt; 10; i++) {<br>         memcpy(&amp;b, &amp;a[i], len);<br>         k = 0;<br>         for (j = 8; j &gt; 0; j--)<br>             if (b[j] &lt; b[0]) a[i][k++] = b[j];<br>         a[i][k++] = b[0];<br>         for (j = 0; j &lt; 9; j++)<br>             if (b[j] &gt; b[0]) a[i][k++] = b[j];<br>     }<br>}<br>//-----------------90--------------//<br><br>//-----------------92--------------//<br>#define N 200<br>int max, cnt, xx[N];<br>float pj;<br><br>void ques92() {<br>     int i, j, m = 0;<br>     max = MAXINT;<br>     for (i = 0; i &lt; N; i++) {<br>         if (max &lt; xx[i]) {<br>            max = xx[i];<br>            cnt = 0;<br>         } else if (max == xx[i])<br>                cnt++;<br><br>         if (xx[i]%3 == 0 || xx[i]%7 == 0) {<br>            pj += xx[i];<br>            m++;<br>         }<br>         pj /= m;<br>     }<br>}<br>//-----------------92--------------//<br></pre>
<img src ="http://www.blogjava.net/briansun/aggbug/1078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/briansun/" target="_blank">Brian Sun</a> 2005-02-12 00:15 <a href="http://www.blogjava.net/briansun/articles/1078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>