<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6798278</id><updated>2012-01-23T03:01:14.554+08:00</updated><title type='text'>Life as a struct</title><subtitle type='html'>...software culture, ColdFusion, and daily dosage</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6798278.post-114284965118220460</id><published>2006-03-20T17:47:00.000+08:00</published><updated>2006-03-21T14:10:52.050+08:00</updated><title type='text'>Drools on AppFuse</title><content type='html'>Recently got a chance to adopt rule engine into project to allow abstraction of business rules from the service layer, that way, business rules can be maintained in it's own space.  I pick &lt;a href="http://drools.org/"&gt;Drools&lt;/a&gt; as the underlying rule engine because it is intuitive, simple, and robust JSR94 compliant rule engine, plus it's open source.  Below are steps to integrate this powerful rule engine into &lt;a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse"&gt;AppFuse&lt;/a&gt;.  I use the &lt;a href="https://springmodules.dev.java.net/"&gt;Spring Modules&lt;/a&gt; distribution to make it easier for the integration since all the plumbing is done nicely with &lt;a href="http://springframework.org/"&gt;Spring&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;1.  Add required libraries:&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a. springmodules-jsr94-0.2.jar&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b. /jsr94&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c. /drools&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;d. /janino&lt;br /&gt;    &lt;br /&gt;    Refer to &lt;a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseAddLibrary"&gt;How to add a Library into AppFuse&lt;/a&gt; for information on how to add new library into AppFuse.  &lt;br /&gt;&lt;br /&gt;2.  Drop the Spring ApplicationContext for Drools configuration, &lt;code&gt;applicationContext-rules.xml&lt;/code&gt;, into &lt;code&gt;[appfuse]\web\WEB-INF\&lt;/code&gt;:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    &amp;lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"&lt;br /&gt;    "http://www.springframework.org/dtd/spring-beans.dtd"&gt;&lt;br /&gt;    &amp;lt;beans&gt;&lt;br /&gt;      &amp;lt;bean id="ruleServiceProvider"&lt;br /&gt;  class="org.springmodules.jsr94.factory.DefaultRuleServiceProviderFactoryBean"&gt;&lt;br /&gt;        &amp;lt;property name="provider"&gt;&lt;value&gt;http://drools.org/&amp;lt;/value&gt;&amp;lt;/property&gt; &lt;br /&gt;        &amp;lt;property name="providerClass"&gt;&amp;lt;value&gt;org.drools.jsr94.rules.RuleServiceProviderImpl&amp;lt;/value&gt;&lt;br /&gt;  &amp;lt;/property&gt;&lt;br /&gt;     &amp;lt;/bean&gt;&lt;br /&gt;     &amp;lt;bean id="ruleRuntime"&lt;br /&gt;  class="org.springmodules.jsr94.factory.RuleRuntimeFactoryBean"&gt;&lt;br /&gt;       &amp;lt;property name="serviceProvider"&gt;&amp;lt;ref local="ruleServiceProvider"/&gt;&amp;lt;/property&gt;&lt;br /&gt;     &amp;lt;/bean&gt;&lt;br /&gt;     &amp;lt;bean id="ruleAdministrator"&lt;br /&gt;  class="org.springmodules.jsr94.factory.RuleAdministratorFactoryBean"&gt;&lt;br /&gt;       &lt;property name="serviceProvider"&gt;&amp;lt;ref local="ruleServiceProvider"/&gt;&amp;lt;/property&gt;&lt;br /&gt;     &amp;lt;/bean&gt;&lt;br /&gt;     &amp;lt;bean id="ruleSource" class="org.springmodules.jsr94.rulesource.DefaultRuleSource"&gt;&lt;br /&gt;       &amp;lt;property name="ruleRuntime"&gt;&amp;lt;ref local="ruleRuntime"/&gt;&amp;lt;/property&gt;&lt;br /&gt;       &amp;lt;property name="ruleAdministrator"&gt;&amp;lt;ref local="ruleAdministrator"/&gt;&amp;lt;/property&gt;&lt;br /&gt;       &amp;lt;property name="source"&gt;&amp;lt;value&gt;/WEB-INF/authorizedUsers.drl&amp;lt;/value&gt;&amp;lt;/property&gt;&lt;br /&gt;       &amp;lt;property name="bindUri"&gt;&amp;lt;value&gt;authorizedUsers&amp;lt;/value&gt;&amp;lt;/property&gt;&lt;br /&gt;     &amp;lt;/bean&gt;&lt;br /&gt;     &amp;lt;bean id="rulesService" class="org.appfuse.service.impl.RulesServiceDrools"&gt;&lt;br /&gt;       &amp;lt;property name="ruleSource"&gt;&amp;lt;ref local="ruleSource"/&gt;&amp;lt;/property&gt;&lt;br /&gt;     &amp;lt;/bean&gt;&lt;br /&gt;   &amp;lt;/beans&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;    The file, &lt;code&gt;authorizedUsers.drl&lt;/code&gt;, is the ruleset, and  &lt;code&gt;RulesServiceDrools&lt;/code&gt; is the Drools rule implementation we have in this sample setup.&lt;br /&gt;&lt;br /&gt;3.  The signature for the ruleset, &lt;code&gt;authorizedUsers.drl&lt;/code&gt;, in &lt;code&gt;[appfuse]\web\WEB-INF\&lt;/code&gt;: &lt;pre&gt;&lt;code&gt;&lt;br /&gt;    &amp;lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;    &amp;lt;rule-set &lt;br /&gt;    name="Get authorized users"&lt;br /&gt;    description="Rules to retrieve authorized users"&lt;br /&gt;    xmlns="http://drools.org/rules"&lt;br /&gt;    xmlns:java="http://drools.org/semantics/java"&lt;br /&gt;    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;        xs:schemaLocation="http://drools.org/rules rules.xsd&lt;br /&gt;                           http://drools.org/semantics/java java.xsd"&gt;&lt;br /&gt;    &amp;lt;rule name="Enabled users"&gt;&lt;br /&gt;      &amp;lt;parameter identifier="user"&gt;&lt;br /&gt;        &amp;lt;class&gt;org.appfuse.model.User&amp;lt;/class&gt;&lt;br /&gt;      &amp;lt;/parameter&gt;&lt;br /&gt;      &amp;lt;java:condition&gt; user.isEnabled() != true &amp;lt;/java:condition&gt;&lt;br /&gt;      &amp;lt;java:consequence&gt; drools.retractObject(user); &amp;lt;/java:consequence&gt;&lt;br /&gt;    &amp;lt;/rule&gt;&lt;br /&gt;    &amp;lt;rule name="Valid credentials"&gt;&lt;br /&gt;      &amp;lt;parameter identifier="user"&gt;&lt;br /&gt;        &amp;lt;class&gt;org.appfuse.model.User&amp;lt;/class&gt;&lt;br /&gt;      &amp;lt;/parameter&gt;&lt;br /&gt;    &amp;lt;java:condition&gt; &lt;br /&gt;       user.isCredentialsExpired() == true || user.getRoles().size() == 0&lt;br /&gt;    &amp;lt;/java:condition&gt;&lt;br /&gt;    &amp;lt;java:consequence&gt; &lt;br /&gt;      drools.retractObject(user); &lt;br /&gt;    &amp;lt;/java:consequence&gt;&lt;br /&gt;  &amp;lt;/rule&gt;&lt;br /&gt;  &amp;lt;/rule-set&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;   Two rules are defined in the ruleset: Enabled users and Valid credentials.  Both rules check for condition, if met, the user is removed from list.  Basically, the two rules mean:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   if (!user.isEnabled()  &amp;&amp; (user.isCredentialsExpired() &lt;br /&gt;       || user.getRoles().size() == 0)) &lt;br /&gt;     userList.remove(user); &lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;4. The interface for the rules service, &lt;code&gt;RulesService&lt;/code&gt;, is simple enough:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   public interface RulesService {&lt;br /&gt;     public List getAuthorizedUsers(List users);&lt;br /&gt;   }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;   And the associated implementation, &lt;code&gt;RulesServiceDrools&lt;/code&gt;:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   public class RulesServiceDrools extends Jsr94RuleSupport implements RulesService {&lt;br /&gt;     public final static String ACTIVE_USERS_URI="authorizedUsers";        &lt;br /&gt;     public List getAuthorizedUsers(List users) {&lt;br /&gt;       return executeStateless(ACTIVE_USERS_URI, users);&lt;br /&gt;     } &lt;br /&gt;   }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;   I couldn't get the Spring Jsr94Template to work properly.  Ideally, the output list from Drools should be access via Spring template:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   public List getAuthorizedUsers(List users) {&lt;br /&gt;     List outputList = getTemplate().executeStateless(ACTIVE_USERS_URI,null,&lt;br /&gt;       new StatelessRuleSessionCallback() {&lt;br /&gt;         public Object execute(StatelessRuleSession session) &lt;br /&gt;         throws InvalidRuleSessionException, RemoteException {&lt;br /&gt;           return session.executeRules(users);&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     );&lt;br /&gt;     return outputList; &lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;5.  The &lt;a href="http://jakarta.apache.org/tapestry/"&gt;Tapestry&lt;/a&gt; action code to get the list of users:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    public abstract class AuthorizedUsers extends BasePage implements PageRenderListener {&lt;br /&gt;      public abstract UserManager getUserManager();&lt;br /&gt;      public abstract void setUserManager(UserManager manager);&lt;br /&gt;      public abstract RulesService getRulesService();&lt;br /&gt;      public abstract void setRulesService(RulesService svr);&lt;br /&gt; &lt;br /&gt;      public void pageBeginRender(PageEvent event) {&lt;br /&gt;        List authorizedUsers = getRulesService().getAuthorizedUsers(getUserManager().getUsers(null));&lt;br /&gt;        ...&lt;br /&gt;      }&lt;br /&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's pretty much it to setup Drools in AppFuse and starts ruling away.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-114284965118220460?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/114284965118220460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=114284965118220460' title='29 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/114284965118220460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/114284965118220460'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2006/03/drools-on-appfuse.html' title='Drools on AppFuse'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>29</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-113652420603775163</id><published>2006-01-06T12:58:00.000+08:00</published><updated>2006-01-06T13:15:08.043+08:00</updated><title type='text'>Braille, braille</title><content type='html'>What is this?&lt;br /&gt;&lt;img src="http://static.flickr.com/38/82825294_f51bd78647_o.gif" width="330" height="110" alt="braille" /&gt;&lt;br /&gt;&lt;br /&gt;The color combo looks familiar isn't it?  Yap, you guess it, it's the color combo for Google logo, and it's the current logo on Google US site, head over there and take a look. (Well, guess you can only see it on Google site next year on 2007/1/4.)&lt;br /&gt;&lt;br /&gt;Not sure what that means really, I know Google always have seasonal logo's but this one got me.  Try clicking on the logo and see what happens.  It actually brings you to Google search result page with "louis braille birthdate" as key word.  Louis braille who?  Following the link identifies Louis Braille was the man who invented &lt;em&gt;braille&lt;/em&gt;, the six raised-dot system that "has been adapted to almost every major national language and is the primary system of written communication for visually impaired persons around the world."&lt;br /&gt;&lt;br /&gt;Not sure what that means?  Try this:&lt;br /&gt;1.  Go back to the Google logo above.  Get it?  No?  Ok, try the next one.&lt;br /&gt;2.  &lt;a href="http://upload.wikimedia.org/wikipedia/en/4/48/LouisBraille.png"&gt;Here&lt;/a&gt; is Louis Braille name in braille.&lt;br /&gt;&lt;br /&gt;Get it now?  Good.  The Google logo above is the name Google in braille.&lt;br /&gt;&lt;br /&gt;Now, how about this?&lt;br /&gt;&lt;img src="http://static.flickr.com/41/82825295_af0000e82d_o.gif" width="481" height="68" alt="braille_lvk" /&gt;&lt;br /&gt;               &lt;br /&gt;That's the name of yours truly in braille.  How about finding your name in the &lt;a href="http://www.nbp.org/ic/nbp/braille/index.html?id=ysB3R7XB"&gt;braille alphabet&lt;/a&gt;?  Read more on &lt;a href="http://en.wikipedia.org/wiki/Louis_Braille"&gt;braille&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Yeh, you might think that I'm either crazy or too bored.  I could very well be both any time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-113652420603775163?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/113652420603775163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=113652420603775163' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/113652420603775163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/113652420603775163'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2006/01/braille-braille.html' title='Braille, braille'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-112960048108633102</id><published>2005-10-18T09:41:00.000+08:00</published><updated>2005-10-19T16:43:53.773+08:00</updated><title type='text'>Preferred Locale on AppFuse</title><content type='html'>The solution provided here are based on locale issues on &lt;a href="http://issues.appfuse.org/secure/Dashboard.jspa"&gt;AppFuse JIRA&lt;/a&gt;, specifically, &lt;a href="http://issues.appfuse.org/browse/APF-141"&gt;APF-141&lt;/a&gt; which is further refined in &lt;a href="http://issues.appfuse.org/browse/APF-142"&gt;APF-142&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here are the steps to change the request-based locale to user-preferred locale, i.e., implement a session-based locale on AppFuse:&lt;br /&gt;1. Add session-scope PREFERRED_LOCALE and optional request scope DEFAULT_LOCALE constants.&lt;br /&gt;2.  Use &lt;em&gt;LoginServlet&lt;/em&gt; to set locale session.  The parameter, locale, is passed from &lt;em&gt;loginForm.jsp&lt;/em&gt;,  a selected locale from a dropdown for example.   &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public final class LoginServlet extends HttpServlet {&lt;br /&gt;  ...&lt;br /&gt;  public void execute(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;  throws IOException, ServletException {&lt;br /&gt;    ...&lt;br /&gt;    request.getSession().setAttribute(Constants.PREFERRED_LOCALE, request.getParameter("locale"));&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;3.  Persist &lt;em&gt;preferredLocale&lt;/em&gt; for user in &lt;em&gt;ActionFilter&lt;/em&gt;:     &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class ActionFilter implements Filter {&lt;br /&gt;  public void doFilter(ServletRequest req, ServletResponse resp,&lt;br /&gt;          FilterChain chain)&lt;br /&gt;         throws IOException, ServletException {&lt;br /&gt;    ...&lt;br /&gt;    if ((username != null) &amp;#38;&amp;#38; (user == null)) {&lt;br /&gt;      ...&lt;br /&gt;      String preferredLocale = session.getAttribute(Constants.PREFERRED_LOCALE).toString();&lt;br /&gt;      if (preferredLocale != null) {&lt;br /&gt;        if (preferredLocale  "") {&lt;br /&gt;          if (user.getPreferredLocale()  null) {&lt;br /&gt;                      user.setPreferredLocale(Constants.DEFAULT_LOCALE);&lt;br /&gt;          }&lt;br /&gt;        } else {&lt;br /&gt;                  user.setPreferredLocale(preferredLocale);&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }      &lt;br /&gt;    session.setAttribute(Constants.PREFERRED_LOCALE, user.getPreferredLocale());&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4.  Add locale filter, &lt;em&gt;LocaleFilter&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class LocaleFilter implements Filter {&lt;br /&gt;  private static final transient Log log = LogFactory.getLog(LocaleFilter.class);&lt;br /&gt;  public void init(FilterConfig filterConfig) {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void destroy() {&lt;br /&gt;  }&lt;br /&gt;  public void doFilter(ServletRequest request, ServletResponse response,&lt;br /&gt;                                      FilterChain chain)&lt;br /&gt;           throws IOException, ServletException {&lt;br /&gt;      HttpServletRequest servletRequest = (HttpServletRequest) request;&lt;br /&gt;      HttpSession session = servletRequest.getSession(false);&lt;br /&gt;&lt;br /&gt;      if (log.isDebugEnabled()) {&lt;br /&gt;          log.debug(servletRequest.getRequestURL());&lt;br /&gt;      }&lt;br /&gt;      Locale preferredLocale = null;&lt;br /&gt;&lt;br /&gt;      if (session!=null){          &lt;br /&gt;          if (session.getAttribute(Constants.PREFERRED_LOCALE) != null) {&lt;br /&gt;              String localeKey = session.getAttribute(Constants.PREFERRED_LOCALE).toString();&lt;br /&gt;              if (localeKey != null) {&lt;br /&gt;                  if (localeKey.equals("")) {&lt;br /&gt;                      String[] keys = Constants.DEFAULT_LOCALE.split("-");&lt;br /&gt;                      preferredLocale = new Locale(keys[0],keys[1]);&lt;br /&gt;                  } else {&lt;br /&gt;                      String[] keys = localeKey.split("-");&lt;br /&gt;                      preferredLocale = new Locale(keys[0],keys[1]);&lt;br /&gt;                  }&lt;br /&gt;              }    &lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      if (null != preferredLocale&lt;br /&gt;              &amp;#38;&amp;#38; !(request instanceof LocaleResponseWrapper)) {&lt;br /&gt;          request = new LocaleResponseWrapper(servletRequest, preferredLocale);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      chain.doFilter(request, response);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;5.   The associated &lt;em&gt;LocaleResponseWrapper&lt;/em&gt; is equivalent to &lt;a href="http://issues.appfuse.org/browse/APF-142"&gt;&lt;em&gt;LocaleRequestWrapper&lt;/em&gt;&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class LocaleResponseWrapper extends HttpServletRequestWrapper {&lt;br /&gt;  private final Locale preferredLocale;&lt;br /&gt;  private Enumeration locales;&lt;br /&gt;&lt;br /&gt;  public LocaleResponseWrapper(HttpServletRequest request, Locale sessionLocale) {&lt;br /&gt;       super(request);&lt;br /&gt;       preferredLocale = sessionLocale;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Locale getLocale() {&lt;br /&gt;      if (null != preferredLocale) {&lt;br /&gt;          return preferredLocale;&lt;br /&gt;      } else {&lt;br /&gt;          return super.getLocale();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;  public Enumeration getLocales() {&lt;br /&gt;      if (null != preferredLocale) {&lt;br /&gt;          return setLocales();&lt;br /&gt;      } else {&lt;br /&gt;          return super.getLocales();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;  private Enumeration setLocales() {&lt;br /&gt;      if (null == locales) {&lt;br /&gt;          List l = Collections.list(super.getLocales());&lt;br /&gt;          l.add(0, preferredLocale);&lt;br /&gt;          locales = Collections.enumeration(l);&lt;br /&gt;      }&lt;br /&gt;      return locales;&lt;br /&gt;  }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;6.  Put the locale filter in &lt;em&gt;web.xml&lt;/em&gt; or &lt;em&gt;appfuse/metadata/web/filters.xml&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;filter&gt;&lt;br /&gt;  &amp;lt;filter-name&gt;localeFilter&amp;lt;/filter-name&gt;&lt;br /&gt;  &amp;lt;display-name&gt;Locale Filter&amp;lt;/display-name&gt;&lt;br /&gt;  &amp;lt;filter-class&gt;org.appfuse.webapp.filter.LocaleFilter&amp;lt;/filter-class&gt;&lt;br /&gt;&amp;lt;/filter&gt;&lt;br /&gt;&lt;/pre&gt;  &lt;br /&gt;7.  Modify JSP&amp;#8217;s: add page-scope locale setting:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;fmt:setLocale value="${preferredLocale}" /&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt;Now AppFuse is powered by preferred locale!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-112960048108633102?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/112960048108633102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=112960048108633102' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112960048108633102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112960048108633102'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2005/10/preferred-locale-on-appfuse.html' title='Preferred Locale on AppFuse'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-112959267502301547</id><published>2005-10-18T07:43:00.000+08:00</published><updated>2005-10-18T08:22:22.990+08:00</updated><title type='text'>告訴你為什麼程式不 work</title><content type='html'>為什麼程式不 work？  我不是跟你說了嗎？&lt;br /&gt;&lt;br /&gt;10. 'That's weird...'&lt;br /&gt;9. 'It's never done that before.'&lt;br /&gt;8. 'It worked yesterday.'&lt;br /&gt;7. 'You must have the wrong version.'&lt;br /&gt;6. 'It works, but it hasn't been tested.'&lt;br /&gt;5. 'Somebody must have changed my code.'&lt;br /&gt;4. 'Did you check for a virus?'&lt;br /&gt;3. 'Where were you when the program blew up?'&lt;br /&gt;2. 'Why do you want to do it that way?'&lt;br /&gt;&lt;br /&gt;and finally ...&lt;br /&gt;&lt;br /&gt;1. 'I thought I fixed that.'&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cenriqueortiz.com/weblog/General/?permalink=Developers-Top-10-replies-when-code-doesnt-work.html"&gt;source&lt;/a&gt;  , &lt;a href="http://www.theserverside.com/news/thread.tss?thread_id=37111"&gt;link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;慚愧，這些藉口我都用盡了，不曉得有否其他可以借用？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-112959267502301547?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/112959267502301547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=112959267502301547' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112959267502301547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112959267502301547'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2005/10/work.html' title='告訴你為什麼程式不 work'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-112919094862536904</id><published>2005-10-13T16:07:00.000+08:00</published><updated>2007-11-06T19:50:27.876+08:00</updated><title type='text'>AJAX on AppFuse</title><content type='html'>Steps in setting up &lt;a href="http://getahead.ltd.uk/dwr/"&gt;DWR&lt;/a&gt; on &lt;a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse"&gt;AppFuse&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;1.  Add DWR jar in /lib/dwr-1.0&lt;br /&gt;2.  Add to /lib/lib.properties:&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# DWR - https://dwr.dev.java.net/ (Direct Web Remoting)&lt;br /&gt;#&lt;br /&gt;dwr.version=1.0&lt;br /&gt;dwr.dir=${lib.dir}/dwr-${dwr.version}&lt;br /&gt;dwr.jar=${dwr.dir}/dwr.jar&lt;/pre&gt;&lt;br /&gt;3.  Add to /properties.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!-- Web --&amp;gt;&lt;br /&gt;&amp;lt;path id="web.compile.classpath"&amp;gt;&lt;br /&gt; ...&lt;br /&gt; &amp;lt;pathelement location="${dwr.jar}"/&amp;gt;&lt;br /&gt;&amp;lt;/path&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4.  Add to /build.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;target name="package-web" depends="compile-web,jsp-2" description="Package WAR"&amp;gt;&lt;br /&gt; ...&lt;br /&gt; &amp;lt;war destfile="${webapp.dist}/${webapp.war}"&lt;br /&gt;       webxml="${webapp.target}/WEB-INF/web.xml" compress="true"&amp;gt;&lt;br /&gt;   ...&lt;br /&gt;   &amp;lt;lib file="${dwr.jar}"/&amp;gt;&lt;br /&gt; &amp;lt;/war&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;5.  Add DWR servlet in /metadata/web/servlets.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!-- dwr servlet --&amp;gt;&lt;br /&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt; &amp;lt;servlet-name&amp;gt;dwr-invoker&amp;lt;/servlet-name&amp;gt;&lt;br /&gt; &amp;lt;display-name&amp;gt;DWR Servlet&amp;lt;/display-name&amp;gt;                &lt;br /&gt; &amp;lt;servlet-class&amp;gt;uk.ltd.getahead.dwr.DWRServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt; &amp;lt;init-param&amp;gt;&lt;br /&gt;   &amp;lt;param-name&amp;gt;debug&amp;lt;/param-name&amp;gt;&lt;br /&gt;   &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/init-param&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;6.  Add DWR servlet mapping in /metadata/web/servlet-mappings.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!-- dwr mapping --&amp;gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt; &amp;lt;servlet-name&amp;gt;dwr-invoker&amp;lt;/servlet-name&amp;gt;&lt;br /&gt; &amp;lt;url-pattern&amp;gt;/dwr/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;7.  Exclude DWR from sitemesh in /web/WEB-INF/classes/decorators.xml:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;excludes&amp;gt;&lt;br /&gt; &amp;lt;pattern&amp;gt;/dwr/*&amp;lt;/pattern&amp;gt;&lt;br /&gt;&amp;lt;/excludes&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;8.  Add DWR configuration, /WEB-INF/dwr.xml: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;dwr&amp;gt;&lt;br /&gt; &amp;lt;allow&amp;gt;&lt;br /&gt;   &amp;lt;convert converter="bean" match="com.octasoft.fp.*"/&amp;gt;&lt;br /&gt;   &amp;lt;create creator="spring" javascript="userManager"&amp;gt;&lt;br /&gt;     &amp;lt;param name="beanName" value="userManager"/&amp;gt;&lt;br /&gt;     &amp;lt;include method="getUser"/&amp;gt;&lt;br /&gt;     &amp;lt;include method="getUsers"/&amp;gt;&lt;br /&gt;   &amp;lt;/create&amp;gt;&lt;br /&gt; &amp;lt;/allow&amp;gt;&lt;br /&gt;&amp;lt;/dwr&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; Here we use DWR provided Spring creator, and utilizes &lt;em&gt;userManager&lt;/em&gt; for remoting.  Also, we use default-deny policy for the service.&lt;br /&gt;&lt;br /&gt;To browse and test &lt;span class="caps"&gt;DWR&lt;/span&gt;-enabled Spring beans: http://server:port/fpweb/dwr/index.html.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br /&gt;It might be required to delete the existing &lt;em&gt;web.xml&lt;/em&gt; in \build\fpweb\WEB-INF\ in order to successfully add in &lt;span class="caps"&gt;DWR&lt;/span&gt; servlet into &lt;em&gt;web.xml&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Use case&lt;/strong&gt;&lt;br /&gt;Verifying user by username before authentication on loginForm.jsp; on verification, user’s nickname is shown:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;script src="/appfuse/dwr/engine.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;   &lt;br /&gt;&amp;lt;script src="/appfuse/dwr/util.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script src="/appfuse/dwr/interface/userManager.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;DWREngine.setErrorHandler(doNothing);&lt;br /&gt;var nickname = "";&lt;br /&gt;function doNothing() {&lt;br /&gt; return false;&lt;br /&gt;}&lt;br /&gt;function getNickname() {&lt;br /&gt; if (nickname == "") { &lt;br /&gt;     userManager.getUser(popUser,document.loginForm.j_username.value);&lt;br /&gt;   document.loginForm.j_password.focus();&lt;br /&gt;   return false;&lt;br /&gt; } else {&lt;br /&gt;   return validateForm( document.loginForm, false, true, true, false, 1)&lt;br /&gt; }   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var popUser = function(user) {&lt;br /&gt; if (user == undefined) {&lt;br /&gt;   return false;&lt;br /&gt; } else {   &lt;br /&gt;   DWRUtil.setValue("nick", "Hello, " + user.nickName);&lt;br /&gt;   nickname = user.nickName;&lt;br /&gt; }   &lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;form method="post" name="loginForm" id="loginForm"&lt;br /&gt;      action="&amp;lt;c:url value="/authorize"/&amp;gt;" onsubmit="return getNickname();"&amp;gt;&lt;br /&gt; &amp;lt;div id="nick"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt; &amp;lt;input name="j_username" type="text" id="j_username"/&amp;gt;&lt;br /&gt; &amp;lt;input name="j_password" type="password" id="j_password"/&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-112919094862536904?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112919094862536904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112919094862536904'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2005/10/ajax-on-appfuse.html' title='AJAX on AppFuse'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-112744711691476528</id><published>2005-09-23T11:44:00.000+08:00</published><updated>2005-10-18T13:14:33.263+08:00</updated><title type='text'>Meet Mr. Writely</title><content type='html'>The beginning of Web office suite is here on &lt;a href="http://www.writely.com/"&gt;Writely&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;Some of the features provided:&lt;br /&gt;1.  Print&lt;br /&gt;2.  Redo/Undo&lt;br /&gt;3.  Special characters&lt;br /&gt;4.  3M note&lt;br /&gt;&lt;br /&gt;What's the big deal? You ask. The value of Writely is document collaboration. You can co-author document with any registered Writely users, changes of your document is updated and saved automatically, so collaborators always get the most updated version of the document. You can also save your document as Word document or as a ZIP. Both works except that image can't be resolved.&lt;br /&gt;&lt;br /&gt;Internet document collaboration has been used in many forms, most popular includes email, forum, wiki, and blog. They all lack the crucial feature: real time update, and it's being implemented on Writely. The addition of AJAX and rich UI has brought all kinds of interesting Web 2.0 projects on the Net, besides Writely, you might try &lt;a href="http://www.backpackit.com/"&gt;Backpack&lt;/a&gt; and &lt;a href="http://www.tadalist.com/"&gt;Ta-da List&lt;/a&gt;.  Play with them now, and think about how you're going to develop Web 2.0 applications for your future projects.&lt;br /&gt;&lt;br /&gt;Main technology under the hood: AJAX and Rich Text HTML widget.  Some great Web 2.0 DHTML library: &lt;a href="http://script.aculo.us/"&gt;script.aculo.us&lt;/a&gt;, &lt;a href="http://openrico.org/rico/home.page"&gt;Rico&lt;/a&gt;, and they both are based on &lt;a href="http://prototype.conio.net/"&gt;Prototype&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;NOTE:&lt;br /&gt;Writely is still under heavy development, for example, you might need to go to HTML view to tweak your document for Table, although I find Writely is quite useful at it's present state. Too bad, Opera is currently not supported.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-112744711691476528?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/112744711691476528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=112744711691476528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112744711691476528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112744711691476528'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2005/09/meet-mr-writely.html' title='Meet Mr. Writely'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-112262019506240559</id><published>2005-07-29T14:55:00.000+08:00</published><updated>2005-10-18T13:49:12.453+08:00</updated><title type='text'>網際網路的最後一頁</title><content type='html'>十年的網路生活，果真還撞上了…原來在&lt;a href="http://home.att.net/~cecw/lastpage.htm"&gt;這裡&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.digitalmediaminute.com/article/1573/the-last-page-of-the-internet"&gt;link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-112262019506240559?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/112262019506240559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=112262019506240559' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112262019506240559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/112262019506240559'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2005/07/blog-post_29.html' title='網際網路的最後一頁'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-110084304977570983</id><published>2004-11-19T13:43:00.000+08:00</published><updated>2004-11-25T03:20:34.426+08:00</updated><title type='text'>小螞蟻最短篇</title><content type='html'>&lt;b&gt;流浪狗&lt;/b&gt;&lt;br /&gt;《&lt;a href="http://www.books.com.tw/exep/prod/booksfile.php?item=0010221713"&gt;流浪狗之歌&lt;/a&gt;》是一本默書，幾張寥寥幾筆的鉛筆畫，卻比千萬字，千萬個影音來的真誠感人。我在&lt;a href="http://www.eslitebooks.com/"&gt;誠品&lt;/a&gt;的兒童圖畫區發覺到這隻流浪狗，因太動人之故，就給領回家了。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;軟體文化&lt;/b&gt;&lt;br /&gt;富裕的文化背後必有豐富的故事，正如&lt;a href="http://dailydosage-lifeasastruct.blogspot.com/2004/03/blog-post_15.html"&gt;小說軟體&lt;/a&gt; ，說故事是軟體開發者必要條件。&lt;br /&gt; &lt;br /&gt;&lt;b&gt;小螞蟻&lt;/b&gt;&lt;br /&gt;在一個偶然的機會，我把小螞蟻和軟體湊在一起，那是給公司做簡報的一部份。小螞蟻的選擇並不是刻意的，反而是自然的，後來我想或許是小螞蟻的草根性和堅持的精神吧。當時全場有人在打哈欠，有人在看 notebook ，倒是有一小部份是用心在聽。雖然我一直提倡&lt;a href="http://dailydosage-lifeasastruct.blogspot.com/2004/06/blog-post_18.html"&gt;說故事&lt;/a&gt;，但自己本身在這方面卻是蠻弱的。不管怎樣，這是我的&lt;a href="about;" onclick="window.open('http://home.ripway.com/2004-8/156265/docs/ma/musically_ants_tw.html','slides','width=815,height=580,scrollbars=yes,status=yes,resize=yes');return false"&gt;嘗試結果&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;稗類&lt;/b&gt;&lt;br /&gt;針對評論家把他的小說比成「&lt;a href="http://www.books.com.tw/exep/prod/booksfile.php?item=0010275408"&gt;稗類&lt;/a&gt;」，張大春有此解說：「說小說如稗，我又滿心景慕。因為它很野、很自由、在濕泥和粗礫上都能生長」。「&lt;a href="about;" onclick="window.open('http://home.ripway.com/2004-8/156265/docs/ma/musically_ants_tw.html','slides','width=815,height=580,scrollbars=yes,status=yes,resize=yes');return false"&gt;小螞蟻&lt;/a&gt;」不正附合稗類的要求？「很野、很自由、在濕泥和粗礫上都能生長」不正是 open source 的精神嗎？我想，當別人把我對軟體的認知定為稗類，我也應該感到安慰，不是嗎？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-110084304977570983?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/110084304977570983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=110084304977570983' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/110084304977570983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/110084304977570983'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/11/blog-post.html' title='小螞蟻最短篇'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-109259214644172002</id><published>2004-08-16T01:45:00.000+08:00</published><updated>2004-08-16T21:57:58.620+08:00</updated><title type='text'>自行其是</title><content type='html'>那天在&lt;a href="http://www.eslitebooks.com/"&gt;誠品&lt;/a&gt;翻了一本關於設計的書叫《&lt;a href="http://www.eslitebooks.com/cgi-bin/eslite.dll/search/book/book.jsp?idx=1&amp;pageNo=1&amp;PRODUCT_ID=2910445631005"&gt;小處著手－追求完美的設計&lt;/a&gt;》，作者是亨利．波卓斯基（Henry Petroski），譯者是陳正芬。這是&lt;a href="http://www.readingtimes.com.tw/"&gt;時報出版&lt;/a&gt;的＜NEXT系列＞之一。看了幾頁，總是無法進入狀況。倒是時報出版在前面對＜NEXT系列＞的介紹吸引了我：&lt;br /&gt;&lt;div class="note"&gt;&lt;br /&gt;關於 next&lt;br /&gt;這個系列，希望提醒兩點：&lt;br /&gt;1. 當我們埋首一角，汲汲於清理過去的包袱之際，不要忽略世界正在如何變形，如何遠離我們而去。&lt;br /&gt;2. 當我們自行其是，卻慌亂於前所未見的難題和變動之際，不要忘記別人已經發展出的規則與答案。&lt;br /&gt;&lt;br /&gt;我們希望這個系列 有助於面對未來。&lt;br /&gt;我們也希望這個系列 有助於整理過去。&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;忽略爭取優勢和閉門造車，這真是台灣軟體業所繼承了好幾年的盲點。什麼時候才能看到軟體業的曙光？或許應該多鼓勵軟體開發者多閱讀而不是多寫程式？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-109259214644172002?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/109259214644172002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=109259214644172002' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/109259214644172002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/109259214644172002'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/08/blog-post.html' title='自行其是'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108797073100597902</id><published>2004-06-23T14:03:00.000+08:00</published><updated>2004-07-05T10:33:52.996+08:00</updated><title type='text'>迷上喬治亞</title><content type='html'>（註：在認識喬治亞之前，請先分辯下面這兩組相同的字。如有發覺明顯的差異，那這篇關於喬治亞的 post 讀起來會比較有意義。&lt;br /&gt;&lt;font style="font-size:11pt;font-family:verdana;font-weight:normal"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Life as a struct: 喬治亞, June 23, 2004 &lt;/font&gt;&lt;br /&gt;&lt;font style="font-size:11pt;font-family:georgia;font-weight:normal"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Life as a struct: 喬治亞, June 23, 2004 &lt;/font&gt;&lt;br /&gt;）&lt;br /&gt;&lt;br /&gt;初次接觸到喬治亞是在 &lt;a href="http://www.hacknot.info/hacknot/action/home"&gt;Hacknot&lt;/a&gt; 和 &lt;a href="http://www.joelonsoftware.com/"&gt;Joel on Software&lt;/a&gt;，那是在我 blogging 之前。他那文質彬彬的外表，給我留下了很深的印象。沒有嗎？在看一次。還看不到？你沒觀察到他的才華都顯露在那秀氣的字體上嗎？這迷人的字體，有否激勵起你寫作的慾望？喬治亞也讓我連想起作家和他心愛的打字機。（年紀較輕的讀者可能還沒見過打字機的模樣，請參考&lt;a href="http://www.typewritermuseum.org/index.html"&gt;打字機博物館&lt;/a&gt;。）&lt;br /&gt;&lt;br /&gt;喬治亞不只寫得一手好筆，還有個爵士似的名稱呢！據說，喬治亞這名字的靈感是他父親從一份通俗小報的標題得來的。那是一篇有關於外星人的頭部在喬治亞州的某個偏僻小鎮被挖掘出來。這樣的流言，讓喬治亞這名字添加了幾分藍調的味道。&lt;br /&gt;&lt;br /&gt;開始 blogging 的時候，就嘗試找喬治亞幫忙，希望我那糟糕的文字能沾上一點喬治亞的文化氣質。奇怪的是，為什麼喬治亞在我的 blog 看起來卻是那麼粗糙？字體一點也不吸引人，更是烏黑一團似的，完全不像其它有喬治亞的地方。為什麼？難道喬治亞不懂得寫中文，或是像大多數人一樣，看不懂我寫的中文？當然，喬治亞是不會說的，他只愛寫。&lt;br /&gt;&lt;br /&gt;後來因找不到問題所在，唯有找來 Verdana 。雖然沒有喬治亞清秀，Verdana 的字體其實也挺不錯的。你可以&lt;a href="http://www.37signals.com/svn/"&gt;瞧瞧&lt;/a&gt;。不少人拿喬治亞和 Verdana 來做比較，這是&lt;a href="http://www.will-harris.com/verdana-georgia.htm"&gt;其中之一&lt;/a&gt;。跟其他字體&lt;a href="http://psychology.wichita.edu/surl/usabilitynews/41/onlinetext.htm"&gt;比起來&lt;/a&gt;，喬治亞和 Verdana 是公認最受歡迎的兩個。雖然 Verdana 和喬治亞都被列為螢幕字體寵兒，倒是比較多人選擇 Verdana，原因通常是 Verdana 看起比較易以接受。對這點，我也認同。但是，跟很多人一樣，我覺得喬治亞的氣質比較吸引人。我想，這或許是審美觀的問題吧！如客家人說的：「各花入各眼」。不管怎樣，喬治亞在我心是肯定的。可是，如何讓他的光彩照上我的 blog 呢？&lt;br /&gt;&lt;br /&gt;後來在其他類似我雙語版的 blog，我見到喬治亞的風貌，神氣洋洋的樣子令我驚喜。原來喬治亞不只懂得寫中文，還寫得跟拉丁文一樣好！仔細觀查了一下，喬治亞看起來有點不大一樣，臉上似乎有點暗淡。更進一步的觀查，突顯了喬治亞懂得寫好中文的秘密：原來喬治亞在這些地方都有用灰色的陰影！好狡猾的喬治亞！&lt;br /&gt;&lt;br /&gt;好吧，讓我也來試試。果真是的，我的 blog 也加入了喬治亞的風貌！順便提提，喬治亞在這裡是用第四度的灰影，也就是 ＃181818。你可以嘗試&lt;a href="http://www.w3schools.com/html/html_colorsfull.asp"&gt;其他的灰影&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;以下是喬治亞出現前後的差異。&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Verdana 的字體&lt;/u&gt;&lt;br /&gt;&lt;font style="font-family:verdana;font-weight:normal"&gt;為什麼說故事？答案或許在 Annette Simmons 著作的 The Story Factor: Inspiration, Influence, and Persuasion through the Art of Storytelling（台灣譯本：《說故事的力量》，譯者是陳智文。）《說故事的力量》封面的引言：「 創造以及訴說故事的能力，是 21 世紀企業所能擁有的最重要技能。」，可說是創新的言辭。-- June 18, 2004&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;喬治亞的字體&lt;/u&gt;&lt;br /&gt;&lt;font style="font-family:georgia;font-weight:normal"&gt;為什麼說故事？答案或許在 Annette Simmons 著作的 The Story Factor: Inspiration, Influence, and Persuasion through the Art of Storytelling（台灣譯本：《說故事的力量》，譯者是陳智文。）《說故事的力量》封面的引言：「 創造以及訴說故事的能力，是 21 世紀企業所能擁有的最重要技能。」，可說是創新的言辭。-- June 18, 2004&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;喬治亞加上灰影&lt;/u&gt;&lt;br /&gt;&lt;font style="font-family:georgia;font-weight:normal;color:#383838"&gt;為什麼說故事？答案或許在 Annette Simmons 著作的 The Story Factor: Inspiration, Influence, and Persuasion through the Art of Storytelling（台灣譯本：《說故事的力量》，譯者是陳智文。）《說故事的力量》封面的引言：「 創造以及訴說故事的能力，是 21 世紀企業所能擁有的最重要技能。」，可說是創新的言辭。-- June 18, 2004&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108797073100597902?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108797073100597902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108797073100597902' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108797073100597902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108797073100597902'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/06/blog-post_23.html' title='迷上喬治亞'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108746696303551674</id><published>2004-06-17T17:40:00.000+08:00</published><updated>2004-06-18T00:06:22.653+08:00</updated><title type='text'>Where are they when you're ready for more? </title><content type='html'>As of June 15, my 10-year old free email account with &lt;a href="http://www.yahoo.com/"&gt;Yahoo&lt;/a&gt; gets a new look and a bigger stomach (from 6MB to 100MB).  Total message size also gets a boost from 3MB to 10MB.  The new interface is CSS-driven(finally, Yahoo!) although it doesn't look much different from the old one.  The login page is the exact opposite.  It's almost a 100% change in look 'n' feel except for one thing: it still sticks to table for layout.  And I must say that the new entrance doesn't appeal to me a bit.  I think it's over-killed in a lot of ways. The classic one makes the new one looks so artificial.  It's just not the tasteful Yahoo that I've known for a decade! &lt;a href="http://mail.yahoo.com/"&gt;See&lt;/a&gt; for yourself.  &lt;br /&gt;&lt;br /&gt;Going into the digital age, 6MB of storage doesn't do much, really. Free mail services that provide giant storage up to 1GB already a reality, with &lt;a href="http://gmail.google.com/"&gt;Gmail&lt;/a&gt; in beta and &lt;a href="http://www.spymac.com/"&gt;Spymac&lt;/a&gt; in production. Feeling the heat going up to it's nose, Yahoo also joins in the battle with 1/10 capacity of it's likely competitors.  I signed up for Spymac not too long ago, and now Yahoo also upgraded my account. I don't know if I should be thankful for the upgrade but, ever since I have bigger and more mailboxes, the number of mails that I have received per week seems to get smaller. Could it be that mail agents get smarter in dealing with spam? Maybe Yahoo is right, 1/10 probably is more than enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108746696303551674?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108746696303551674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108746696303551674' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108746696303551674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108746696303551674'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/06/where-are-they-when-youre-ready-for.html' title='Where are they when you&apos;re ready for more? '/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108729585534156007</id><published>2004-06-15T18:34:00.000+08:00</published><updated>2004-06-16T23:01:38.496+08:00</updated><title type='text'>版面與色彩的選擇</title><content type='html'>我的 blog 改版面了！應該說是顏色的調整吧！這是經過讀者的建議而做的改變。說實在的，我還是較喜歡我之前的版面（之前的版面，除了標題那一塊是藍色之外，其餘是純白的。參照我的 &lt;a href="http://vklo.blogspot.com/"&gt;home&lt;/a&gt; 。）這樣的色彩對我來說是太重口味了一點，但是看起來是比較有活力。我想活潑這一點就當作是我的補償吧！&lt;br /&gt;&lt;br /&gt;這新版面的顏色組合希望敏感的台灣讀者別過於解讀，這並不是一個政治立場的表態。這只是從 &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt; 的 Powered By 標識得來的靈感（參考右下角的圖案）。如果選擇這顏色組合就被貼上藍軍的標籤，那 Blogger 不也變「藍」了？（&lt;a href="http://www.uip.com.tw/shrek2/"&gt;史瑞克&lt;/a&gt;是「深綠」不成？）況且，我從不隱藏我對&lt;a href="http://dailydosage-lifeasastruct.blogspot.com/"&gt;政治的觀點&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;當然，我並不否認我對藍的偏好。打從我懂得分辨顏色開始，藍是我的主色。誰不喜歡藍？上帝也愛藍，不是嗎？要不然我們怎麼會有藍天，藍海呢？直到我年紀較大的時候，黑成了我另一個偏好。咦，藍與黑？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108729585534156007?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108729585534156007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108729585534156007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108729585534156007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108729585534156007'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/06/blog-post.html' title='版面與色彩的選擇'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108697469381378592</id><published>2004-06-12T01:23:00.000+08:00</published><updated>2004-06-15T06:52:34.750+08:00</updated><title type='text'>IE 不乖的原因</title><content type='html'>終於解答了我給自己的難題：為什麼 IE 閱覽器不懂得顯示我的 blog  的其中一個虛擬類別，&lt;a href="http://dailydosage-lifeasastruct.blogspot.com/"&gt;日常毒藥與養料&lt;/a&gt;？&lt;br /&gt;&lt;br /&gt;這問題已存在了一段時間，一直都沒想去把它解決。並不是對IE 使用者有任何的成見。當然，我不會否認我個人對 IE 的偏見，不管是戴著軟體開發者或使用者的眼鏡。我知道這是有關於編碼選擇的問題。IE 總自作主張的用 Big5 編碼來顯示我的 blog 。可是我是選擇 UTF-8 呢！IE 竟然不以為然。結果呢，IE 使用者看到的頁面是空白的，雖然「檢視原始檔」顯示頁面是完整的。真拿它沒辦法。當然，我可以改用 Big5 編碼，但是我堅持 UTF-8。畢竟已是開放，國際化的時代了，不是嗎？所以我採取建議式的方法來處理這個難題。前幾天我有這個註釋在我的 blog 上：&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;em&gt;NOTE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IE users might need to force page&lt;br/&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;encoding to Unicode(UTF-8) to&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view this section. Or get the&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;better &lt;a href="http://www.mozilla.org/products/firefox/"&gt;Mozilla Firefox&lt;/a&gt;.&lt;/em&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IE 使用者或許需要強迫選擇編碼&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;為 Unicode(UTF-8)。或使用較&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;好的 &lt;a href="http://www.csie.ntu.edu.tw/~piaip/mozilla/"&gt;Mozilla Firefox&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;我承認這樣對 IE 使用者並沒有特別的幫助，反而有可能會招來反感。但是這對我來說也是無可奈何。&lt;br /&gt;&lt;br /&gt;昨天又有朋友問了同樣的問題。 反正閒著也是閒著，不如找找 IE 不乖的原因。再仔細的視察&lt;a href="http://dailydosage-lifeasastruct.blogspot.com/"&gt;日常毒藥與養料&lt;/a&gt;這個 blog 跟其它兩個 blog （ &lt;a href="http://lifeasastruct.blogspot.com/"&gt;Software Culture&lt;/a&gt; 和 &lt;a href="http://coldfusion-lifeasastruct.blogspot.com/"&gt;ColdFusion&lt;/a&gt;）在頁面上有什麼不一樣。除了中文字比較多之外，我實在無法判斷問題的所在。等一下，唯一較明顯的是 blog 的標題。其它兩個 blog 的標題是全英文的，而「日常毒藥與養料」的標題是混合英文跟中文的（Life as a struct：日常毒藥與養料）。難道是這個東東？試試無妨，反正只需要幾秒的時間就能確定。（註：&lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt; 的 blog 標題等於 HTML META 的 TITLE。） &lt;br /&gt;&lt;br /&gt;把頁面原始碼存下，再把標題改成 Life as a struct: daily dosage。再讓 IE 自作主張。Bingo！IE 終於認同我的編碼選擇是 UTF-8！我差點要掉眼淚了。倒底標題有什麼獨特的地方？難道 IE 是用它來決定頁面的編碼？&lt;br /&gt;&lt;br /&gt;So， the moral of the story is：如果你選擇用 UTF-8 做為網頁編碼，記得標題要用全 ANSCII 編碼。當然，這或許是獨特的實例，並不能當定則。我也無暇追究。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108697469381378592?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108697469381378592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108697469381378592' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108697469381378592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108697469381378592'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/06/ie.html' title='IE 不乖的原因'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108656848190227942</id><published>2004-06-07T08:31:00.000+08:00</published><updated>2004-06-10T19:44:14.990+08:00</updated><title type='text'>Open source .NET</title><content type='html'>A post from &lt;a href="http://www.corfield.org/blog/past/2004_06.html#000451"&gt;Corfield&lt;/a&gt; brings to this interesting open source &lt;a href="http://www.go-mono.org/"&gt;Mono&lt;/a&gt;, a .NET framework runs on Linux, Unix and of course, Windows.  The core includes CLI, C# compiler, Java VM, and embeddable runtime to be called from C, Perl, and Apache.  And the stack provides ASP.NET, ADO.NET, LDAP, and GTK# which is a .NET implementation of Gtk+ rich client applications.  Amazing?  &lt;br /&gt;&lt;br /&gt;What is more interesting is the Mono project is sponsored by &lt;a href="http://novell.com/"&gt;Novell&lt;/a&gt;.  Novell seems to be everywhere now owning a Linux distribution, &lt;a href="http://www.suse.com/us/"&gt;SUSE&lt;/a&gt;, and an open source port of the .NET framework.  Is Novell back like &lt;a href="http://www-136.ibm.com/developerworks/"&gt;IBM&lt;/a&gt; on software?  So I can finally dust off my &lt;a href="http://www.novell.com/training/certinfo/cna/"&gt;CNA&lt;/a&gt;? Nonetheless, welcome back, Novell!  Now that we have IBM and Novell on the side of open source and Linux, it's no wonder that &lt;a href="http://www.microsoft.com/"&gt;Microsoft&lt;/a&gt; and &lt;a href="http://www.sun.com/"&gt;Sun&lt;/a&gt; are back together again.  The war on software is no longer on operating systems but on frameworks and open-standard systems.  This is a good sign.&lt;br /&gt;		 &lt;br /&gt;	&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108656848190227942?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108656848190227942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108656848190227942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108656848190227942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108656848190227942'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/06/open-source-net.html' title='Open source .NET'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108383469676825131</id><published>2004-05-06T15:46:00.003+08:00</published><updated>2004-06-02T00:52:36.306+08:00</updated><title type='text'>輕鬆一下，吃兩口餅乾</title><content type='html'>自從進入e 時代之後，已有一段時間冇寫中文了。原因是不會輸入中文。我曾徑嘗試用「 自然輸入法 」，覺得它一點也不自然。我也不懂注音，「注音輸入法 」就免談了。「倉頡」？腦袋不夠用。「嘸蝦米」？蝦米？還好懂得 「剪黏 」，勉強可以溝通 。真得是很勉強。有些中文字英文是沒有的。例如 ，「吧 」、「呢 」。&lt;br /&gt;&lt;br /&gt;在這段狩獵時期，認識了一位新朋友，一個讓我尊敬的電腦講師，也就是我要介紹的另一個輸入法，「輕鬆輸入法」，的創始人，高衡緒老師。對我來說，「輕鬆輸入法」不是另一個輸入法，而是我第一個，也是我唯一可用的。&lt;br /&gt;&lt;br /&gt;像「倉頡」，「輕鬆」是用拆字法，但相同地方到此為止。「輕鬆」的輸入法原則是：&lt;b&gt;「有餅乾吃餅乾，沒有餅乾才吃餅乾渣」&lt;/b&gt;。餅乾包括部首和字形。聽起來似是有一堆字根要背才能打幾個字。剛好相反，「輕鬆」並不貪吃，就算是吃餅乾渣，也只是吃最後的一小塊而已。換句話說，「輕鬆」最多吃兩口就完成一個字的建議。&lt;br /&gt;&lt;br /&gt;&lt;u&gt;餅乾&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;餅乾，除了部首如「手」，「心」，「土」，之外，「輕鬆」最特別的是「容器」字鍵的應用。「容器」是容納其它字根的字形如：&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_23.jpg" /&gt;：「田」、「圈」&lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_12.jpg" /&gt;：「月」、「高」&lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_11.jpg" /&gt; ：「定」、「寶」&lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_05.jpg" /&gt;：「這」、「建」&lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_19.jpg" /&gt;：「有」、「春」&lt;br /&gt;&lt;br /&gt;還有其它的「輕鬆」字鍵：「系」、「言」、「貝」、「雨」。&lt;br /&gt;&lt;br /&gt;&lt;u&gt;餅乾渣&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;以上餅乾類字鍵是容易懂的。餅乾渣的定義開始會比較難適應，但只要了解「輕鬆」拆字的規則，餅乾渣也不難吃。餅乾渣有：&lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_14.jpg" /&gt; &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_17.jpg" /&gt;  &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_08.jpg" /&gt; &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_09.jpg" /&gt; &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_10.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;的確是渣。可是怎麼吃啊？&lt;br /&gt;&lt;br /&gt;之前提到「輕鬆」拆一個字最多吃兩口，不管是餅乾或是餅乾渣。奇怪了，繁雜中文字如「繁雜」，到底是怎麼吃啊？「輕鬆」拆字的規則，除了吃餅乾的原則為優先，另一個吃餅乾的禮儀是先吃左上角的部分，後吃右下角的部分。「輕鬆」注重的是角落或外層部分，不是筆畫的順序，也不講究形狀。所以「繁」的兩口吃是：「每」的 &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_14.jpg" /&gt;（餅乾渣）加「系」（餅乾渣）。「雜」的兩口吃是：左上角的「、」（餅乾渣）加「隹」（餅乾）。&lt;br /&gt;&lt;br /&gt;如果拆的字本身是「容器」字如「圈」，拆的規則沒變：「圈」的 &lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_23.jpg" /&gt;（餅乾）加「已」的&lt;img src="http://homepage.mac.com/eshen/ez/ez/word_files/04_10.jpg" /&gt;（餅乾渣）。&lt;br /&gt;你看，輕鬆吧？&lt;br /&gt;&lt;br /&gt;請看&lt;a href="http://homepage.mac.com/eshen/ez/ez/lookkeys.html"&gt;「輕鬆」鍵盤&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;&lt;u&gt;輕鬆简体&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;「輕鬆」還讓你輸入简体字呢！開玩笑，我不懂简体呢，怎麼輸入啊？「輕鬆」讓你用繁體的輸入方法來輸入简体字。換句話說，&lt;b&gt;「想繁體而輸出简体」&lt;/b&gt;。感謝你，謝謝你，高老師！&lt;br /&gt;&lt;br /&gt;「輕鬆」還是開放的「自由軟體」呢！&lt;br /&gt;&lt;br /&gt;詳情下載: &lt;a href="http://homepage.mac.com/eshen/ez/"&gt;輕鬆輸入法之家&lt;/a&gt; &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108383469676825131?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108383469676825131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108383469676825131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108383469676825131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108383469676825131'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/05/blog-post.html' title='輕鬆一下，吃兩口餅乾'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108254117858874156</id><published>2004-04-21T14:56:00.003+08:00</published><updated>2004-06-02T00:53:29.310+08:00</updated><title type='text'>版本控制</title><content type='html'>如果你有這些問題:&lt;br /&gt;1. 昨天剛改的 2000 行程序碼今天被 overwrite 掉了&lt;br /&gt;2. 客戶要上星期的銷售模組的定貨程序版本&lt;br /&gt;3. 主管要早上的財務模組的文件版本, 剛剛被錯誤更新了.&lt;br /&gt;4. 你要的檔案被 lock 住了.&lt;br /&gt;&lt;br /&gt;那麼你需要版本控制系統.  明顯的, 以上的問題不只是限制於團隊軟體開發環境.&lt;br /&gt;&lt;br /&gt;市面上有不少數的版本控制軟體, &lt;a href="http://www.cvshome.org/"&gt;CVS&lt;/a&gt; 應該是最受使用的一個.我覺得它的 API 不那麼的容易使用. 對比之下, 我寧可選擇 &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt;.  Subversion 是一個較好的 下一代  CVS.  從安裝, 設定, 到使用, subversion 處處顯出它比 CVS 優越. 我最感到興趣的是它用 URL's 來存取 repository. URL's 包括 &lt;code&gt;file:///, http://, https://, svn://, svn+ssh://&lt;/code&gt;, 也就是說 Subversion 支援 SSH 和 WebDAV (Apache).&lt;br /&gt;&lt;br /&gt;這是從安裝到使用 Subversion 的步驟:&lt;br /&gt;0. 下載 Apache 和 Subversion.&lt;br /&gt;1.  設定 servers (Apache, Subversion)&lt;br /&gt;	&amp;nbsp;&amp;nbsp;從 Subversion 複製 mod_dav_ svn 和 mod_auth_svn 到 Apache&lt;br /&gt;	&amp;nbsp;&amp;nbsp;修改 Apache 的 httpd.conf:&lt;br /&gt;	&amp;nbsp;&amp;nbsp;Uncomment LoadModule dav_module modules/mod_dav.so &lt;br /&gt;	&amp;nbsp;&amp;nbsp;加上 LoadModule mod_dav_svn 和在末尾加上&lt;br /&gt;	&amp;nbsp;&amp;nbsp;&amp;lt;Location /repos&gt;&lt;br /&gt;	&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DAV svn&lt;br /&gt;	&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SVNPath physical_path_to_repository&lt;br /&gt;	&amp;nbsp;&amp;nbsp;&amp;lt;/Location&gt;	&lt;br /&gt;2.  重新啟動 Apache&lt;br /&gt;3.  在 local 端建立 project directory 和 files 類似結構:&lt;br /&gt;     &amp;nbsp;&amp;nbsp;/project_name&lt;br /&gt;     &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/trunk&lt;br /&gt;     &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;project files&lt;br /&gt;     &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/branch&lt;br /&gt;4. Import project 到 server 端的 repository&lt;br /&gt;    &amp;nbsp;&amp;nbsp;$ svn import -m "New import" project_path http://server:8080/repos&lt;br /&gt;    &amp;nbsp;&amp;nbsp;瀏覽到 http://server:8080/repos/, 你應該在頁面上看見 "Revision 0: /". &lt;br /&gt;5.  Checkout project&lt;br /&gt;     &amp;nbsp;&amp;nbsp;$ svn checkout http://server:8080/repos/calc/trunk local_path&lt;br /&gt;6.  Commit 變更到 repository&lt;br /&gt;     &amp;nbsp;&amp;nbsp;$ svn commit -m "modified finance module"&lt;br /&gt;7.  View log&lt;br /&gt;     &amp;nbsp;&amp;nbsp;$ svn log&lt;br /&gt;8.  檢查 local copy 和 server 端的最新版本&lt;br /&gt;     &amp;nbsp;&amp;nbsp;$ svn diff main.c&lt;br /&gt;&lt;br /&gt;如果你習慣 Windows client, &lt;a href="http://tortoisesvn.tigris.org/docs.html"&gt;TortoiseSVN&lt;/a&gt; 是好選擇. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108254117858874156?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108254117858874156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108254117858874156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108254117858874156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108254117858874156'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/04/blog-post.html' title='版本控制'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108234818380420878</id><published>2004-04-15T12:15:00.000+08:00</published><updated>2004-06-02T01:01:13.970+08:00</updated><title type='text'>永久的 email account</title><content type='html'>進入數位時代, 數位庫存, 應該說龐大的庫存量, 已不是一種選擇而是一種需要. Emailing 是一種耗庫存量的活動.&lt;br /&gt;&lt;br /&gt;通常 email account 庫存量是有限制的(&lt; 20 mb). 當然多個 email account 是一個解決辦法, 公司, hotmail, yahoo, msn, etc., 可是維持多個 email account 不是件容易的事, 甚至是一種負擔.多個 email account 還有一個很大的問題: 如何搜尋 email 內容? 如果是 desktop email client 如 Thunderbird 或 Outlook, 這不是難事, 但如果是 browser email client, 情況就不一樣了.&lt;br /&gt;&lt;br /&gt;針對這些 email 問題, &lt;a href="http://www.spymac.com/"&gt;Spymac&lt;/a&gt; 和 &lt;a href="http://gmail.google.com/gmail/help/about.html"&gt;GMail&lt;/a&gt; 提供解決方案: 1GB email 庫存量和 email 搜尋引擎!&lt;br /&gt;&lt;br /&gt;GMail 是 Google 最近的產品提供. 目前 Gmail 只提供邀請 account, Spymac 已完全公開服務. Spymac 也提供 POP3 access, 雖然 Gmail 仍考慮中. 就是說除了broswer 界面之外, 你還可以用喜愛的Thunderbird 或 Outlook 來收發 email!&lt;br /&gt;&lt;br /&gt;這是我新的 Spymac account, vklospy@spymac.com, 我想我不需要再憂慮 email 會否"爆"或搜尋的問題了. 當然 Gmail 也是我期待的.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108234818380420878?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108234818380420878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108234818380420878' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108234818380420878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108234818380420878'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/04/email-account.html' title='永久的 email account'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235848527213078</id><published>2004-03-30T16:05:00.001+08:00</published><updated>2004-06-02T01:01:52.243+08:00</updated><title type='text'>What Microsoft considers as threats</title><content type='html'>Microsoft doesn't usually make item-by-item comparison with its competitive products due to its enormous market shares unless, of course, the competiting products become highly relevent in the playing field. Most of the threats come from the Open Source community. One of the most significant is OpenOffice.&lt;br /&gt;&lt;br /&gt;Recognizing it's alarming rate of adoption in the corporate level by IBM and Novell, Microsoft provides a &lt;a href="http://members.microsoft.com/partner/salesmarketing/opensource/discguides/OpenOffice.pdf"&gt;Competitive Guide&lt;/a&gt; to challenge what OpenOffice claims to provide, i.e., on the basis of these arguments:&lt;br /&gt;free, good enough, compatible to total value delivered by Microsoft Office&lt;br /&gt;&lt;br /&gt;In response to the Competitive Guide, NewsForce has a different and extensive view: &lt;a href="http://software.newsforge.com/software/04/03/27/0134204.shtml"&gt;Microsoft displays fear, uncertainty, and doubt toward OpenOffice.org&lt;/a&gt;. The author concludes with the following comment, "Microsoft used to have an advertisement asking where you wanted to go today; this is more true of OpenOffice since it allows you more control of your data through vendors and even inhouse staff who can help with it. Microsoft is dictating a future; this is why they do not allow Open Standards."&lt;br /&gt;&lt;br /&gt;Microsoft has not made any public response on another Open Source project that has been gaining attention, Mozilla. The funny thing is, it's upcoming Windows software development architecture, most notably XAML, based mainly on the highly successful XUL developed by Mozilla.&lt;br /&gt;&lt;br /&gt;Recently, Microsoft also has a migration guide to sway users of the highly successful ColdFusion MX to adopt ASP.NET in this &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/coldfusiontoaspnet.asp?frame=true"&gt;entry&lt;/a&gt; of MSDN Library.&lt;br /&gt;&lt;br /&gt;How do you decide your choice of software? In my opinion, it depends on how and where you use and see software in general. It's not a clear cut question. In the end it's what you do with software that counts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235848527213078?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235848527213078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235848527213078' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235848527213078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235848527213078'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/what-microsoft-considers-as-threats.html' title='What Microsoft considers as threats'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235833020288929</id><published>2004-03-30T16:05:00.000+08:00</published><updated>2004-06-02T01:01:39.683+08:00</updated><title type='text'>Let's get serious</title><content type='html'>The following message is of my personal view points and not of my employer.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The underdeveloped software industry and the enterprise&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This letter is intended for the serious, connected audience. If you don't know what it means by connected, try disconnecting yourself from the network and see what happen. (If you still know know what it means then you can excuse yourself from reading on.) The fact of the matter is, we're connected to each other either directly or indirectly, wired or wiredless, like it or not. Since we're a connected whole, we better know what's being transported in the information highway. Another words, you need to be able to define the information you create or to be able to interpret information you receive intentionary or accidentally, to allow a meaningful communication.&lt;br /&gt;&lt;br /&gt;Yes, communication is all about passing on information. Another words, improperly defined and/or misinterpreted information leads to breakdowm on communication. What's the purpose of communication anyway, in a working environment? To get job done mostly. Ya, that's the routine part. What I'm interesting in is the the process of communication and the information it generates before the production phase. The problem definition and modeling proceess that is. Methodology, attitude, culture, social politics, are factors that we deal with one way or another in the problem context. Each and everyone of them are significant in itself. Here, we focus on a different issue. Here, we focus on seeing problem by it's purpose not by it's solution.&lt;br /&gt;&lt;br /&gt;A lot of time, in the process of solving a problem, we treat solution of the problem as an end itself rather than as fulfillment to it's purpose. Hence we have two approaches to the problem resolution: project-oriented and service-oriented. The first see the problem as an isolated one while the latter treats the problem as an integrated part of a larger problem. Another words, project-orientation in problem solving are inherently inward looking while service-orientation in problem solving is forward looking. As pointed out earlier, we're a connected whole, except for the trivial ones, any resulting solution of problems affects more than the context that it defines directly or indirectly.&lt;br /&gt;&lt;br /&gt;What that mean is we need to have a well-defined purpose of the problem and to provide a service-oriention interface of it's integrated part to it's external system as solution. By well-defined problem, I mean the problem must be a self-contained one to be model. Modeling is a necessary step to capture the behavior of the problem and it's purpose to the external system. We need to start looking into the service nature of the problem to allow a more natural integration of the soluition to the system. Another words, treat each business process as a service to the next.&lt;br /&gt;&lt;br /&gt;What's the point? You might ask? If you look into it deeper and in a larger context like modeling enterprise business processes, you see that the project-based approach to problem resolution leads to a closed, inward looking system. Another words, there is no easy way to get information in and out of the system unless otherwise provided by the closed application. Such system is hard to scale, hard to integrate, and even hard to maintain, for the system is the sum of it's parts as a whole rather than it's integrated parts as a whole.&lt;br /&gt;&lt;br /&gt;So service is the key to allow a more natural integration of the systems around us. We're not alone after all. Unfortunately I don't see that happens in software development. In fact, software development in Taiwan are project-oriented. Both the client and solution provider approach the problem as an end of itself. There is no coincidence that the software is an underdeveloped industry in Taiwan. The truth is, business needs software to materialize it's processes and to compete in the industry. And software developer needs business to grow it's solution scope. Why don't we see the integration between the two? Where is the partnership between the two? The only thing that connects the two is the project itself. The end of the project is ultimately the end of relationship. To me, that's a serious problem to both the business and the software industry as a whole. Every solution is an isolated one and an end of itself. Where is the growth factor?&lt;br /&gt;&lt;br /&gt;Are we ready to start the dialog of a service-oriented solution?&lt;br /&gt;&lt;br /&gt;NOTE: This is a message I sent on 2003/11/28 to my colleague and all the friends that I've worked with outside of the company. I repost it here without any editing as a reminder to myself what I believe in software development. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235833020288929?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235833020288929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235833020288929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235833020288929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235833020288929'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/lets-get-serious.html' title='Let&apos;s get serious'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235925804582599</id><published>2004-03-29T16:19:00.000+08:00</published><updated>2004-04-19T15:25:00.966+08:00</updated><title type='text'>不需要安裝的 Linux 系統</title><content type='html'>想嘗試 Linux 機能性, 但是不想太花時間學習安裝, 和確認硬體支援的程度? 可以花一片的燒錄光碟, 幾分鐘的燒錄時間?&lt;br /&gt;&lt;br /&gt;如果答案是可以, 放置已燒錄的光碟之後, 重新啟動電腦, 在幾分鐘內就可以嘗試到 Linux 了! 再者, 這過程完全不需要使用者的反應. 從啟動到看到 Linux desktop 在我面前, 除了音效卡之外, 一切都工作正常, 我的個人電腦還是 AMD 系統呢! 真的是令人佩服感嘆!&lt;br /&gt;&lt;br /&gt;測試 Linux 步驟 (任何版本都適用, 這裡用的是 SUSE 9.0 LiveEval):&lt;br /&gt;&lt;br /&gt;1. 下載 iso 檔案&lt;br /&gt;&lt;a href="http://www.suse.com/us/private/download/ftp/int_mirrors.html"&gt;ftp.suse.com: International Mirrors&lt;/a&gt;&lt;br /&gt;2. 檢驗iso 檔案 (隨意)&lt;br /&gt;建議確定檔案的完整性. 下載 &lt;a href="http://www.etree.org/md5com.html"&gt;MD5 Checksum&lt;/a&gt;,&lt;br /&gt;在 DOS, 執行檢驗檔案: C:/&gt; md5sum SuSE-9.0-LiveEval-i386-Int-RC1.iso. 產生的32個 md5sum 數字必須相等: 13d85e6f712e15c4ecff55cd9dd751ae. 如不是, 檔案不完整, 必須重新下載 iso 檔案.&lt;br /&gt;&lt;br /&gt;3. 重建/燒錄 iso 光碟&lt;br /&gt;啟動Nero (或其他燒錄軟體), 燒錄選擇項目: 光碟影像檔, 開始燒錄.&lt;br /&gt;&lt;br /&gt;4. 放置已燒錄的光碟, 重新啟動電腦, 去拿杯咖啡, 回來享受全新的 Linux desktop!&lt;br /&gt;&lt;br /&gt;註: 這也許是多餘的, 較新的系統通常預設啟動次序為: CD-ROM, C, A. 如不是, 重新啟動之前, 變更次序, 讓 CD-ROM 為首位 .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235925804582599?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235925804582599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235925804582599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235925804582599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235925804582599'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/linux.html' title='不需要安裝的 Linux 系統'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235912245311752</id><published>2004-03-29T16:17:00.000+08:00</published><updated>2004-04-19T15:22:45.390+08:00</updated><title type='text'>Ever evolving Google</title><content type='html'>From a mere search engine on popular Web sites started in the mid 1990's, Google has become a household name of superior Web search engine. Since then it has evolved itself and now offers a wide range of search services including Web search news search, and &lt;a href="http://www.google.com/options/index.html"&gt;more&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Today it just got a &lt;a href="http://www.google.com/search?hl=en&amp;ie=UTF-8&amp;oe=UTF-8&amp;q=google"&gt;new UI&lt;/a&gt; in about ten years! Surprisingly, little CSS layout and structure are used on the new UI. Nonetheless, Go Google! &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235912245311752?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235912245311752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235912245311752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235912245311752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235912245311752'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/ever-evolving-google.html' title='Ever evolving Google'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235948402195466</id><published>2004-03-26T16:24:00.000+08:00</published><updated>2004-04-19T15:31:36.810+08:00</updated><title type='text'>告訴我你到過哪裡</title><content type='html'>告訴我你到過的國家?&lt;br /&gt;台灣, 美國, ...&lt;br /&gt;&lt;br /&gt;告訴我你到過美國哪裡?&lt;br /&gt;加州, 紐約, ...&lt;br /&gt;&lt;br /&gt;可以指出地圖的位置嗎?&lt;br /&gt;... (沉思中)... (思考中)... (當機)&lt;br /&gt;&lt;br /&gt;讓我幫忙. 你到過的國家: &lt;a href="http://world66.com/myworld66/visitedCountries/worldmap?visited=CAUSMYSGTW"&gt;台灣, 美國&lt;/a&gt;.&lt;br /&gt;你到過美國州: &lt;a href="http://world66.com/myworld66/visitedStates/statemap?visited=CANY"&gt;加州, 紐約&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這是個有趣的關於旅遊的 &lt;a href="http://world66.com/home"&gt;site&lt;/a&gt;.  目前提供的地圖服務:&lt;br /&gt;&lt;a href="http://world66.com/myworld66/visitedStates"&gt;美國地圖&lt;/a&gt;  &lt;a href="http://world66.com/myworld66/visitedCountries"&gt;世界地圖&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;如果你像我不喜歡用 form, 你可以用 URL 查尋. 範例:&lt;br /&gt;&lt;br /&gt;國家: 台灣(TW), 美國(US), 西班牙(ES)   &lt;br /&gt;URL = http://world66.com/myworld66/visitedCountries/worldmap?visited=USESTW&lt;br /&gt;&lt;br /&gt;美國: 加州(CA), 紐約(NY), 佛羅里達(FL)&lt;br /&gt;URL=http://world66.com/myworld66/visitedStates/statemap?visited=CANYFL&lt;br /&gt;&lt;br /&gt;可以應用範圍包括: 個人參考, 網站簡單地圖服務, blog, IM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235948402195466?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235948402195466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235948402195466' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235948402195466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235948402195466'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/blog-post.html' title='告訴我你到過哪裡'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235978988487764</id><published>2004-03-24T16:27:00.000+08:00</published><updated>2004-04-20T10:36:19.936+08:00</updated><title type='text'>Bye bye, Microsoft!?</title><content type='html'>終於可以完全的 go open source 了!&lt;br /&gt;&lt;br /&gt;這是另一個取代微軟產品的軟體: OpenOffice&lt;br /&gt;&lt;br /&gt;OpenOffice 供給全部 Microsoft Office 的功能: Word, PowerPoint, Excel, Photo Editor. 更要的是 OpenOffice 能轉換 Microsoft Office 檔案. 如果你想要不當機的 Microsoft Office, 那麼 OpenOffice 是你最佳的選擇. 還有另一個理由: open source!&lt;br /&gt;&lt;br /&gt;終於可以跟微軟 kiss goodbye 了? 如果 Linux 的 desktop 能夠像 Mac 的話... 有 IBM 跟 Novell 的完全投入, 我想也快了.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://taiwan.cnet.com/download/pc/swinfo/0,2000032013,20007141s,00.htm"&gt;OpenOffice 1.0 繁體中文版下載&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ooo.tnc.edu.tw/modules/news/index.php?storytopic=6"&gt;OpenOffice.org 補給站&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;其他的 open source 產品:&lt;br /&gt;&lt;a href="http://lifeasastruct.blogspot.com/2004_03_01_lifeasastruct_archive.html#108235983504466180"&gt;Eclipse&lt;/a&gt;&lt;br /&gt;&lt;a href="http://lifeasastruct.blogspot.com/2004_03_01_lifeasastruct_archive.html#108236030860269603"&gt;Mozilla Thunderbird&lt;/a&gt;&lt;br /&gt;&lt;a href="http://lifeasastruct.blogspot.com/2004_03_01_lifeasastruct_archive.html#108236053505048142"&gt;UML tools&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235978988487764?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235978988487764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235978988487764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235978988487764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235978988487764'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/bye-bye-microsoft.html' title='Bye bye, Microsoft!?'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108235983504466180</id><published>2004-03-23T16:30:00.000+08:00</published><updated>2004-04-19T15:37:15.950+08:00</updated><title type='text'>Eclipse and SWT</title><content type='html'>For those of you who have tried on Eclipse which I introduced in my last post, &lt;a href="http://192.168.100.23/archives/000012.html"&gt;How about CFMX on Eclipse?&lt;/a&gt;, have probably noticed somthing unusual for a Java GUI application, it's extremely fast!&lt;br /&gt;&lt;br /&gt;In an email response, &lt;a href="http://www.rohanclan.com/"&gt;Rohan&lt;/a&gt;, author of &lt;a href="http://www.rohanclan.com/index.cfm?mode=product&amp;product=cfeclipse/index"&gt;CFEclipse&lt;/a&gt;, kindly answers the question that underneath, Eclipse uses SWT for GUI manipulation. What's SWT (Standard Widget Toolkit)?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html"&gt;SWT&lt;/a&gt; (and &lt;a href="http://www-106.ibm.com/developerworks/library/os-ecjfw/"&gt;JFace&lt;/a&gt;) are GUI components originally developed by IBM for the open source &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; project. Unlike Swing or AWT, SWT relies on native widgets of the underlying operating system which results in Java applications which look and feel like native applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108235983504466180?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108235983504466180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108235983504466180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235983504466180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108235983504466180'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/eclipse-and-swt.html' title='Eclipse and SWT'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236030860269603</id><published>2004-03-18T16:38:00.000+08:00</published><updated>2004-04-19T15:43:12.530+08:00</updated><title type='text'>高飛吧, 雷鳥!</title><content type='html'>這是另一個軟體 by Mozilla: Mozilla Thunderbird&lt;br /&gt;&lt;br /&gt;像 Mozilla Firefox 取代 Internet Explorer, 這是取代 Outlook 的客戶端郵 件軟體. 我使用 Thunderbird 已經有快三個月了, 我還沒有考慮恢復使用 Outlook. 如果你想使用一個沒有安全性問題的 Outlook, get &lt;a href="http://www.csie.ntu.edu.tw/~b7506051/mozilla/"&gt;Thunderbird&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;我想微軟一定有 Deja Vu 的感覺: it's 1990's or over again!&lt;br /&gt;NOTE: 當Netscape 在 1990's 給 Internet 下定義的時期, 微軟完全不認同 Internet 的價值. 再次的, 微軟凝視地上燃燒的火鳥, 瞭望天上高飛的雷鳥, 這 巨人在想什麼?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236030860269603?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236030860269603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236030860269603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236030860269603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236030860269603'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/blog-post_18.html' title='高飛吧, 雷鳥!'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236053505048142</id><published>2004-03-16T16:39:00.000+08:00</published><updated>2004-04-19T15:46:17.780+08:00</updated><title type='text'>Other UML tools</title><content type='html'>Tired of using Visio as tool for UML diagrams like I am? How about some other options which are free or open source?&lt;br /&gt;1. (Open source) &lt;a href="http://argouml.tigris.org/"&gt;ArgoUML&lt;/a&gt; &lt;br /&gt;I highly recommemd.&lt;br /&gt;2. (Commercial) &lt;a href="http://www.gentleware.com/products/screenshots/index.php4"&gt;Poseidon for UML Community Edition&lt;/a&gt; (nonprintable) &lt;br /&gt;I like it for better GUI as compared to ArgoUML but printing is not available. By the way, it's core is ArgoUML.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236053505048142?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236053505048142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236053505048142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236053505048142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236053505048142'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/other-uml-tools.html' title='Other UML tools'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236136456258397</id><published>2004-03-10T16:55:00.000+08:00</published><updated>2004-04-19T16:00:07.763+08:00</updated><title type='text'>隱藏的領域知識</title><content type='html'>"Analysis Patterns 是針對領域結構, 而 Design Patterns 是針對某方面的領域 結構的實行技巧. 簡潔的來說, Analysis Patterns 是較高積層亦較功能導向."&lt;br /&gt;&lt;br /&gt;"Analysis pattern are for domain architecture, and design pattern are for implementation mechanism for some aspect of the domain architecture. In brief, analysis pattern are more high level and more (end-user) functional oriented."&lt;br /&gt;&lt;br /&gt;假設這是正確的答案, 那麼以下應該也是正確的:&lt;br /&gt;1. Design Patterns 在 Software development 是扮演協助性的而不是指導性的 角色.&lt;br /&gt;2. 實際的領域知識是在 Analysis Patterns 的積層裡面&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jguru.com/faq/view.jsp?EID=51213"&gt;original source&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236136456258397?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236136456258397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236136456258397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236136456258397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236136456258397'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/blog-post_10.html' title='隱藏的領域知識'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236142166857269</id><published>2004-03-08T16:56:00.000+08:00</published><updated>2004-04-22T08:59:32.076+08:00</updated><title type='text'>A programmer's summary of the Estee's GM speech</title><content type='html'>A quick class diagram to the Brand Building model:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;&lt; Marketing &gt;&gt; ---  &lt;&lt; Brand &gt;&gt; --- &lt;&lt; Party &gt;&gt;&lt;br /&gt;&lt;br /&gt;         |                |                  |&lt;br /&gt;   -----------         --------              ---------                       &lt;br /&gt;   |          |      |         |            |          |&lt;br /&gt; Global     Local    BrandA    BrandB   Person   Organiztion        &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now how do I model the most important and abstract incredient, according to &lt;br /&gt;Estee Lauder: Integrity?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236142166857269?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236142166857269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236142166857269' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236142166857269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236142166857269'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/programmers-summary-of-estees-gm.html' title='A programmer&apos;s summary of the Estee&apos;s GM speech'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236169989110955</id><published>2004-03-04T17:00:00.000+08:00</published><updated>2004-04-19T16:09:52.326+08:00</updated><title type='text'>小規模的再造</title><content type='html'>Refactoring 結構再造&lt;br /&gt;&lt;br /&gt;Refactoring 是有規律的技巧重新結構現有的程序碼,改變內部的結構而保留外部的性質.它的核心是一系列小規模的性質保留的轉換.各自的轉換(refactoring) 做一點點,可是一連串的轉換能夠引起重大的結構再造.&lt;br /&gt;&lt;br /&gt;一些 Refactoring 實例:&lt;br /&gt;&lt;br /&gt;-------------------------------------------&lt;br /&gt;Decompose Conditional 分解條件&lt;br /&gt;-------------------------------------------&lt;br /&gt;你有復雜的條件述句 (if-then-else statement)&lt;br /&gt;=&gt;&lt;br /&gt;從條件抽出方式,然後部分,然後其他部分.&lt;br /&gt;&lt;br /&gt;if (date.before (SUMMER_START) || date.after(SUMMER_END)) {&lt;br /&gt;    charge = quantity * _winterRate + _winterServiceCharge;&lt;br /&gt;} else {&lt;br /&gt;    charge = quantity * _summerRate;&lt;br /&gt;}&lt;br /&gt;=&gt;&lt;br /&gt;if (notSummer(date)) {&lt;br /&gt;    charge = winterCharge(quantity);&lt;br /&gt;} else {&lt;br /&gt;       charge = summerCharge (quantity);        &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;----------------------------------------&lt;br /&gt;Reverse Conditional 反向條件&lt;br /&gt;----------------------------------------&lt;br /&gt;你有條件,如果反向它的意思會比較容易明白&lt;br /&gt;=&gt;&lt;br /&gt;反向條件的意思,重排條件述句次序&lt;br /&gt;&lt;br /&gt;if ( !isSummer( date ) )&lt;br /&gt;  charge = winterCharge( quantity );&lt;br /&gt; else&lt;br /&gt;  charge = summerCharge( quantity );&lt;br /&gt;=&gt;&lt;br /&gt; if ( isSummer( date ) )&lt;br /&gt;  charge = summerCharge( quantity );&lt;br /&gt; else&lt;br /&gt;  charge = winterCharge( quantity );&lt;br /&gt;&lt;br /&gt;----------------------&lt;br /&gt;Split Loop 分化回圈&lt;br /&gt;----------------------&lt;br /&gt;你有做兩件事的回圈&lt;br /&gt;=&gt;&lt;br /&gt;複製回圈&lt;br /&gt;&lt;br /&gt;void printValues() {&lt;br /&gt;    double averageAge = 0;&lt;br /&gt;    double totalSalary = 0;&lt;br /&gt;    for (int i = 0; i &lt; people.length; i++) {&lt;br /&gt;            averageAge += people[i].age;&lt;br /&gt;            totalSalary += people[i].salary;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    averageAge = averageAge / people.length;&lt;br /&gt;    System.out.println(averageAge);&lt;br /&gt;    System.out.println(totalSalary);&lt;br /&gt;}&lt;br /&gt;=&gt;&lt;br /&gt;void printValues() {&lt;br /&gt;    double totalSalary = 0;&lt;br /&gt;    for (int i = 0; i &lt; people.length; i++) {&lt;br /&gt;            totalSalary += people[i].salary;&lt;br /&gt;    }&lt;br /&gt;    double averageAge = 0;&lt;br /&gt;    for (int i = 0; i &lt; people.length; i++) {&lt;br /&gt;    averageAge += people[i].age;&lt;br /&gt;   }&lt;br /&gt;   averageAge = averageAge / people.length;&lt;br /&gt;   System.out.println(averageAge);&lt;br /&gt;   System.out.println(totalSalary);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;為什麼?&lt;br /&gt;做兩件事的回圈不比分開做的清楚,它也會對進一步的 Refactoring 造成問題.&lt;br /&gt;----------------------------------------------------&lt;br /&gt;&lt;br /&gt;更多的 Refactoring &lt;a href="http://www.refactoring.com/catalog/index.html"&gt;實例&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.refactoring.com/index.html"&gt;Refactoring home page&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;註: Refactoring 和 Analysis Patterns 的創作者是同一個人.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236169989110955?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236169989110955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236169989110955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236169989110955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236169989110955'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/blog-post_04.html' title='小規模的再造'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236221047020405</id><published>2004-03-02T17:07:00.000+08:00</published><updated>2004-04-19T16:14:13.530+08:00</updated><title type='text'>知識的環節</title><content type='html'>在 &lt;a href="http://domaindrivendesign.org/book/"&gt;Domain-Driven Design&lt;/a&gt; Chapter 1 &lt;a href="http://domaindrivendesign.org/book/chapter01.pdf"&gt;Crunching Knowledge&lt;/a&gt; 裡, Eric Evans 強調領域知識 (domain knowledge) 的重要性.知識的累積是分析過的領域模型(domain model). 而累積是從分析出來的範本(patterns). 知識累積的環節是Analysis Patterns?&lt;br /&gt;&lt;br /&gt;語義化的分析&lt;br /&gt;&lt;br /&gt;Analysis Patterns (分析範本)定義&lt;br /&gt;- 確定應用或領域的概念模型語義&lt;br /&gt;- 扮演能重複使用的抽象概念的引出和代表軟體需求的角色&lt;br /&gt;Analysis patterns對軟體開發過程的貢獻&lt;br /&gt;- 加速開發; 提供能重複使用的抽象概念加速捕捉具體問題的主要需求的抽象分析模型(analysis model)&lt;br /&gt;- 透過 design patterns 和可靠常見問題的解答的提議, 助長分析模型到設計模型的轉化&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;具體和抽象 Analysis Patterns&lt;br /&gt;&lt;br /&gt;Fowler's Analysis Patterns (抽象)&lt;br /&gt;&lt;a href="http://www.cis.famu.edu/~stoeckli/publications/JavaDevJournalIthink.doc"&gt;Introduction to Fowler's Analysis Patterns&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.theserverside.com/articles/content/FowlerPatterns/Fowler_ch09.pdf"&gt;The Patterns&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ryangrier.com/news/archives/Analysis_Patterns.pdf"&gt;Analysis Patterns&lt;/a&gt;&lt;br /&gt;具體&lt;br /&gt;&lt;a href="http://jerry.cs.uiuc.edu/~plop/plop99/proceedings/Fernandez2/reservAnalysisPattern3.PDF"&gt;An Analysis Pattern for Reservation and Use of Reusable Entities&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jerry.cs.uiuc.edu/~plop/plop2k/proceedings/Fernandez1/Fernandez1.pdf"&gt;Analysis Patterns for the Order and Shipment of a Product&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;語義化 Analysis Patterns&lt;br /&gt;&lt;a href="http://www.cse.fau.edu/~ed/SAPpaper2.pdf"&gt;Semantic Analysis Patterns&lt;/a&gt;&lt;br /&gt;- Analogy and abstraction play an important role in reusing an analysis pattern&lt;br /&gt;- Using Semantic Analysis Patterns, a methodology is developed to build the conceptual model in a systematic way&lt;br /&gt;* 強調類比和抽象在重複使用分析pattern的角色&lt;br /&gt;* 有系統的構造概念模型的方法&lt;br /&gt;&lt;br /&gt;實例:&lt;br /&gt;電腦維修和醫院的類比(Figure 2 and Figure 5)&lt;br /&gt;抽象(一般化):&lt;br /&gt;進入權利 (Admissions) pattern (Figure 6)&lt;br /&gt;Semantic Analysis Pattern&lt;br /&gt;World Cup 分析模型 (Figure 7)&lt;br /&gt;Article (收集品Collection和Reservation and Use預定patterns)&lt;br /&gt;&lt;br /&gt;Semantic Analysis Patterns 模型構造方法&lt;br /&gt;從審查Use Cases和其他需求&lt;br /&gt;1. 尋找Semantic Analysis Patterns&lt;br /&gt;首先尋找相稱或接近需求的具體patterns. 然後嘗試專門化可能適用的類似或抽象patterns&lt;br /&gt;Figure 8&lt;br /&gt;2. 尋找較小的patterns (例如Admissions pattern Figure 6).&lt;br /&gt;3. 看是否有適用的設計或結構性patterns.&lt;br /&gt;4. 加上Fowler-style patterns加強彈性和延伸能力&lt;br /&gt;&lt;br /&gt;顯明的,語義化的分析方法,Patterns導向的模型構造,是朝向知識累積的關鍵.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236221047020405?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236221047020405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236221047020405' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236221047020405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236221047020405'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/blog-post_02.html' title='知識的環節'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6798278.post-108236203197553015</id><published>2004-03-02T17:06:00.000+08:00</published><updated>2004-04-19T16:11:15.076+08:00</updated><title type='text'>看Design Patterns</title><content type='html'>為什麼 Design Patterns(GoF) 那麼難消化?如果可以從&lt;a href="http://www.agcs.com/supportv2/techpapers/patterns/papers/patexamples.htm"&gt;實體去看&lt;/a&gt;的話...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ida.liu.se/~TDDB61/Teori/Slides/tddb61-8-design-patterns.pdf"&gt;最簡縮完整的Design Patterns(GoF)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6798278-108236203197553015?l=lifeasastruct.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lifeasastruct.blogspot.com/feeds/108236203197553015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6798278&amp;postID=108236203197553015' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236203197553015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6798278/posts/default/108236203197553015'/><link rel='alternate' type='text/html' href='http://lifeasastruct.blogspot.com/2004/03/design-patterns.html' title='看Design Patterns'/><author><name>lo</name><uri>http://www.blogger.com/profile/02667743720053396398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
