2012年10月30日

          Exception VS Control Flow

          每當提到Exeption就會有人跳出來說“Exception not use for flow control”,那到底是什么意思呢?什么情況下Exception就算控制流程了,什么時候就該拋出Exception了呢?

          首先什么是Exception?

          Definition: 

          An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.


          再看什么是“流程”?如果流程是指程序的每一步執行,那異常就是控制流程的,它就是用來區分程序的正常流程和非正常流程的,從上面異常的定義就可以看出。因此為了明確我們應該說”不要用異常控制程序的正常流程“。如何定義正常流程和非正常流程很難,這是一個主觀的決定,沒有一個統一的標準,只能根據實際情況。網上找個例子:
          bool isDouble(string someString) {
              
          try {
                  
          double d = Convert.ParseInt32(someString);
              } 
          catch(FormatException e) {
                  
          return false;
              }
              
          return true;
          }
          這個程序其實不是想convert數字,而是想知道一個字符串是否包含一個數字,通過判斷是不是有異常的方式來決定返回true還是false,這是個Smell,這種應該算”異常控制了正常流程“。我們可以通過正則表達式或其他方式來判斷。

          另外Clean Code上一個例子:
              try {  
                  MealExpenses expenses 
          = expenseReportDAO.getMeals(employee.getID());  
                  m_total 
          += expenses.getTotal();  
              } 
          catch(MealExpensesNotFound e) {  
                  m_total 
          += getMealPerDiem();  
              } 
          MealExpensesNotFound異常影響了正常的計算m_total的業務邏輯。對于這種情況可以通過一下方式改進
              public class PerDiemMealExpenses implements MealExpenses {  
                  
          public int getTotal() {  
                      
          // return the per diem default  
                  }  
              } 

          以上兩個例子是比較明顯的異常控制正常流程,Smell很明顯,不會有很大爭議,但是實際情況中可能有很多例子沒有這么明顯,因為都是主觀判定的。比如一下代碼,算不算異常控制正常流程?

          public int doSomething()
          {
              doA();
              
          try {
                  doB();
              } 
          catch (MyException e) {
                  
          return ERROR;
              }
              doC();
              
          return SUCCESS;
          }

          看到這樣一段程序,如果沒有上下文,我們無法判斷。但是如果doSomething是想讓我們回答yes or no,success or error,我們不應該通過有無異常來判斷yes or no,success or error,應該有個單獨的方法來判斷,這個方法就只做這一件事情。如果doSometing是執行一個操作,那么在這個過程中我們假定是不會出現問題的,否則拋出異常是比較合理的。






          posted @ 2012-10-30 17:03 *** 閱讀(246) | 評論 (0)編輯 收藏

          2012年9月8日

          ClassLoader 加載機制

          1. Java Class Loading Mechanism

          首先當編譯一個Java文件時,編譯器就會在生成的字節碼中內置一個public,static,final的class字段,該字段屬于java.lang.Class類型,該class字段使用點來訪問,所以可以有:
          java.lang.Class clazz = MyClass.class

          當class被JVM加載,就不再加載相同的class。class在JVM中通過(ClassLoader,Package,ClassName)來唯一決定。ClassLoader指定了一個class的scope,這意味著如果兩個相同的包下面的class被不同的ClassLoader加載,它們是不一樣的,并且不是type-compatible的。

          JVM中所有的ClassLoader(bootstrap ClassLoader除外)都是直接或間接繼承于java.lang.ClassLoader抽象類,并且人為邏輯上指定了parent-child關系,實現上child不一定繼承于parent,我們也可以通過繼承它來實現自己的ClassLoader。

          JVM ClassLoder架構,從上到下依次為parent-child關系:
          • Bootstrap ClassLoader - 啟動類加載器,主要負責加載核心Java類如java.lang.Object和其他運行時所需class,位于JRE/lib目錄下或-Xbootclasspath指定的目錄。我們不知道過多的關于Bootstrap ClassLoader的細節,因為它是一個native的實現,不是Java實現,所以不同JVMs的Bootstrap ClassLoader的行為也不盡相同。調用java.lang.String.getClassLoder() 返回null。
          • sun.misc.ExtClassLoader - 擴展類加載器,負責加載JRE/lib/ext目錄及-Djava.ext.dirs指定目錄。
          • sun.misc.AppClassLoader - 應用類加載器,負責加載java.class.path目錄
          • 另外,還有一些其他的ClassLoader如:java.net.URLClassLoader,java.security.SecureClassLoader,java.rmi.server.RMIClassLoader,sun.applet.AppletClassLoader
          • 用戶還可以自己繼承java.lang.ClassLoader來實現自己的ClassLoader,用來動態加載class文件。
          ClassLoader特性
          • 每個ClassLoader維護一份自己的命名空間,同一個ClassLoader命名空間不能加載兩個同名的類。
          • 為實現Java安全沙箱模型,默認采用parent-child加載鏈結構,除Bootstrap ClassLoader沒有parent外,每個ClassLoader都有一個邏輯上的parent,就是加載這個ClassLoader的ClassLoader,因為ClassLoader本身也是一個類,直接或間接的繼承java.lang.ClassLoader抽象類。
          java.lang.Thread中包含一個public的方法public ClassLoader getContextClassLoader(),它返回某一線程相關的ClassLoader,該ClassLoader是線程的創建者提供的用來加載線程中運行的classes和資源的。如果沒有顯式的設置其ClassLoader,默認是parent線程的Context ClassLoader。Java默認的線程上下文加載器是AppClassLoader。

          ClassLoader工作原理:

          了解ClassLoader工作原理,先來看一個ClassLoader類簡化版的loadClass()方法源碼
           1 protected Class<?> loadClass(String name, boolean resolve)
           2         throws ClassNotFoundException
           3     {
           4         synchronized (getClassLoadingLock(name)) {
           5             // First, check if the class has already been loaded
           6             Class c = findLoadedClass(name);
           7             if (c == null) {
           8                 long t0 = System.nanoTime();
           9                 try {
          10                     if (parent != null) {
          11                         c = parent.loadClass(name, false);
          12                     } else {
          13                         c = findBootstrapClassOrNull(name);
          14                     }
          15                 } catch (ClassNotFoundException e) {
          16                     // ClassNotFoundException thrown if class not found
          17                     // from the non-null parent class loader
          18                 }
          19 
          20                 if (c == null) {
          21                     // If still not found, then invoke findClass in order
          22                     // to find the class.
          24                     c = findClass(name);
          25                 }
          26             }
          27             if (resolve) {
          28                 resolveClass(c);
          29             }
          30             return c;
          31         }
          32     }

          首先查看該class是否已被加載,如果已被加載則直接返回,否則調用parent的loadClass來加載,如果parent是null代表是Bootstrap ClassLoader,則有Bootstrap ClassLoader來加載,如果都未加載成功,最后由該ClassLoader自己加載。這種parent-child委派模型,保證了惡意的替換Java核心類不會發生,因為如果定義了一個惡意java.lang.String,它首先會被JVM的Bootstrap ClassLoader加載自己JRE/lib下的,而不會加載惡意的。另外,Java允許同一package下的類可以訪問受保護成員的訪問權限,如定義一個java.lang.Bad,但是因為java.lang.String由Bootstrap ClassLoader加載而java.lang.Bad由AppClassLoader加載,不是同一ClassLoader加載,仍不能訪問。

          2. Hotswap - 熱部署

          即不重啟JVM,直接替換class。因為ClassLoader特性,同一個ClassLoader命名空間不能加載兩個同名的類,所以在不重啟JVM的情況下,只能通過新的ClassLoader來重新load新的class。

           1  public static void main(String[] args) throws InterruptedException, MalformedURLException {
           2         IExample oldExample = new Example();
           3         oldExample.plus();
           4         System.out.println(oldExample.getCount());
           5 
           6         Hotswap hotswap = new Hotswap();
           7         while (true) {
           8             IExample newExample = hotswap.swap(oldExample);
           9             String message = newExample.message();
          10             int count = newExample.plus();
          11             System.out.println(message.concat(" : " + count));
          12             oldExample = newExample;
          13             Thread.sleep(5000);
          14         }
          15     }
          16 
          利用hotswap替換就的Example,每5秒鐘輪詢一次,swap方法實現如下:
           1  private IExample swap(IExample old) {
           2         try {
           3             String sourceFile = srcPath().concat("Example.java");
           4             if (isChanged(sourceFile)) {
           5                 comiple(sourceFile, classPath());
           6                 MyClassLoader classLoader = new MyClassLoader(new URL[]{new URL("file:"+classPath())});
           7                 Class<?> clazz = classLoader.loadClass("Example");
           8                 System.out.println(IExample.class.getClassLoader());
           9                 IExample exampleInstance = ((IExample) clazz.newInstance()).copy(old);
          10                 System.out.println(exampleInstance.getClass().getClassLoader());
          11                 return exampleInstance;
          12             }
          13         } catch ...
          24         return old;
          25     }
          這里必須將exampleInstance轉型為IExample接口而不是Exmaple,否則會拋出ClassCastExecption,這是因為swap方法所在類Hotswap是有AppClassLoader加載的,而且加載Hotswap的同時會加載該類引用的Exmaple的symbol link,而Example是MyClassLoader加載的,不同的ClassLoader加載的類之間直接用會拋出ClassCastException, 在本例中ClassLoader實現如下:
           1 public class MyClassLoader extends URLClassLoader {
           2 
           3     public MyClassLoader(URL[] urls) {
           4         super(urls);
           5     }
           6 
           7     @Override
           8     public Class<?> loadClass(String name) throws ClassNotFoundException {
           9         if ("Example".equals(name)) {
          10             return findClass(name);
          11         }
          12         return super.loadClass(name);
          13     }
          14 }
          而對IExample我們還是調用super的loadClass方法,該方法實現仍是JVM的parent-child委派方式,因此最終由AppClassLoader加載,加載Hotswap時加載的symbol link也是由AppClassLoader加載的,因此能夠成功。

          此外再熱部署時,被替換的類的所有引用及狀態都要遷移到新的類上,本例中只是很簡單的調用copy函數遷移了count的狀態。

          Tomcat的jsp熱部署機制就是基于ClassLoader實現的,對于其類的熱部署機制是通過修改內存中的class字節碼實現的。

          Resource:
          Reloading Java Classes 101: Objects, Classes and ClassLoaders
          Internals of Java Class Loading

          posted @ 2012-09-08 17:58 *** 閱讀(635) | 評論 (0)編輯 收藏

          2012年9月5日

          Java Runtime exec問題

          1. java.lang.IllegalThreadStateException: process hasn't exited

          1 public static void main(String[] args) {
          2         try {
          3             Process process = Runtime.getRuntime().exec("javac");
          4             System.out.println(process.exitValue());
          5         } catch (IOException e) {
          6             e.printStackTrace();
          7         }
          8     }

          exec方法創建了一個native的進程,并返回該process的對象,如果進程還沒有返回,調用exitValue方法就會出現此異常,因為該方法沒有阻塞,其實現如下:
          1 public synchronized int exitValue() {
          2         if (!hasExited) {
          3             throw new IllegalThreadStateException("process hasn't exited");
          4         }
          5         return exitcode;
          6     }

          2. waitFor方法

           1 public static void main(String[] args) {
           2         try {
           3             Process process = Runtime.getRuntime().exec("javac");
           4             int result = process.waitFor();
           5             System.out.println(result);
           6         } catch (IOException e) {
           7             e.printStackTrace();
           8         } catch (InterruptedException e) {
           9             e.printStackTrace();
          10         }
          11     }

          waitFor方法會一直阻塞直到native進程完成,并返回native進程的執行結果。如果native進程無法執行完成,waitFor方法將一直阻塞下去,其實現如下:
          1 public synchronized int waitFor() throws InterruptedException {
          2         while (!hasExited) {
          3             wait();
          4         }
          5         return exitcode;
          6     }

          該程序在jdk1.7 windows下測試工作正常,返回2; 但是jdk1.4 windows下測試出現hang。JDK documention的解釋是
          The methods that create processes may not work well for special processes on certain native platforms,
          such as 
          native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows,or shell scripts.
          The created subprocess does not have its own terminal or console. All its standard io (i.e. stdin, stdout, stderr)
          operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(),
          getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some 
          native platforms only provide limited buffer size for standard input and output streams,
          failure to promptly write the input stream or read the output stream of the subprocess may cause
          the subprocess to block, and even deadlock.

          所以,出現hang時,及時的flush標準輸入輸出或者錯誤流能夠消除hang,如上面的javac,我們知道redirect到stderr中,所以解決hang后的代碼
           1 public static void main(String[] args) {
           2         try {
           3             Process process = Runtime.getRuntime().exec("echo 'abc'>b.txt");
           4             BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
           5             String line;
           6             while((line=reader.readLine())!=null){
           7                 System.out.println(line);
           8             }
           9             int result = process.waitFor();
          10             System.out.println(result);
          11         } catch (IOException e) {
          12             e.printStackTrace();
          13         } catch (InterruptedException e) {
          14             e.printStackTrace();
          15         }
          16     }


          3. exec() is not a command line 并不是所有的command line命令都可以用exec

           1  public static void main(String[] args) {
           2         try {
           3             Process process = Runtime.getRuntime().exec("echo 'abc'>a.txt");
           4             BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
           5             String line;
           6             while((line=reader.readLine())!=null){
           7                 System.out.println(line);
           8             }
           9             int result = process.waitFor();
          10             System.out.println(result);
          11         } catch (IOException e) {
          12             e.printStackTrace();
          13         } catch (InterruptedException e) {
          14             e.printStackTrace();
          15         }
          16     }
          結果為:
          1 'abc'>a.txt
          2 0
          并沒有將創建a.txt,而從命令行執行"echo 'abc'>a.txt"卻正確創建了a.txt

          posted @ 2012-09-05 22:43 *** 閱讀(5084) | 評論 (0)編輯 收藏

          2011年11月3日

          Practices of Extreme Programming - XP

          Extreme programming is a set of simple and concrete practices than combine into an agile development process.
          1. Whole Team - Cutomers, managers and developers work closely with one another. So they are all aware of one another's problem and are collaborating to solve the problem. The customers can be a group of BAs, QAs or marketing persons in the same company as developers. The customers can be the paying customer. But in an XP project, the customer, however defined, is the member of and available to the team.
          2. User Stories - In order to plan a project, we must know something about the requirement, but we don't need to know very much. We need to know only enough about a requirement to estimate it. You may think that in order to estimate the requirement, you need to know all the details. That's not quite true. You have to know that there are details and you have to know roughly the kinds of details, but you don't have to know the sepecifics. Since the sepecific details of the requirements are likely to change with time, especially once the customers begin to see the system together. So when talking about requirements with the customer, we write some key words on a card to remind us of the conversation. A user story is memonic token of an ongoing conversation about a requirement. Every user story should have an estimation.
          3. Short Cycles - An XP project delivers working software every iteration - one or two weeks. At the end of each iteration, the sytem is demonstrated to the customer or the stakeholder in order to get their feedbacks. Every release there is a major delivery that can be put into production.
          4. The Planning Game - The customers decide how important a feature is and the developers decide how much effort the feature will cost to implement. So the customers will select a collection of stories based on the priority and the previous iterations' velocity.
            1. The Iteration Plan - Once an iteration has been started, the business agrees not to change the definition or priority of the stories in that iteration. The order of the stories within the iteration is a technical decision. The developers may work on the stories serially or concurrently. It depends but it's a technical decision.
            2. The Release Plan - A release is usually three months. Similarly, the business or customer selecte collections of user stories and determines the priority based on their buget. But release are not cast in stone. The business can change or reorder at any time. They can write new stories, cancel stroies or change the priority. However, the business should not to change an interation that has been started.
          5. Acceptance Tests - The detail about the user stories are captured in the form of acceptance tests specified by the customer. The acceptance tests are written by BAs and QAs immediately before or concurrently with the implementation of that story. They are written in a scripting form that allow them to be run automatically and repeatlly. These tests should be easy to read and understand for customers and business people. These tests become the true requirement document of the project. Once the acceptance test passes, it will be added the body of passing acceptance tests and is never allowed to fail. So the system is migrated from one working state to another.
          6. Pair Programming - One memeber of each pair drives the keyboard and types the code. The other member of the pair watches the code being typed, finding errors and improvements.
            1. The roles change frequently. If the driver gets tired or stuck, the pair grabs the keyboard and starts to drive. The keybord will move back and forth between them serval times in one hour. The resulting code is designed and authored by both memebers.
            2. Pair memebership changes frequently. A reasonable goal is to change pair partner at least once per day. They should have worked on about everything that was going on in this iteration. Also it is very good for knowledge transfer.
          7. Collective Ownership - A pair has right to check out any module and imporve it. No particular pair or developer are individually responsible for one particular module. Every developer of the project has fully responsible for each line of the code. So don't complain about the code may be written by the other pair. Let's try to improve it. Since it is our code.
          8. Open Workspace - The team works together at one table or in one room. Each pair is within earshot of every other pair. Each has the opportunity to hear when another pair is in trouble. Each konws the state of the other. The sound in this room is a buzz of conversation. One might think that this would be a noise and distracting envrionment. But study suggested, working in a "war room" envrionment may increase productivity.
          9. Simple Design - An XP team makes its designs as simple and expressive as they can be. Furthermore, the team narrows its focus to consider only the stories that are planned for the current iteration, not worrying about stories to come. The team migrates the design of the system from iteration to iteration to be the best design for the stories that the system currently implements.
            1. consider the simplest thing that could possibly work. - XP teams always try to find the simplest possible design option fot the current batch of stories.
            2. You aren't going to need it. - That means an XP team introduces one technology or one infrastructure before it is strictly needed. Yeah, but we know we are going to need that database one day. We are going to have to support multiple threads one day. So don't we need to put the hooks in for those things? The team puts the technology or infrastucture in only if it has proof or at least very compelling evidence. that putting it in now will be more cost-effective than waiting.
            3. Once and only once. XPers don't tolerate duplication of code. Wherever they find it. they remove it. The best way to remove redundancy is to create abstractions. After all, if two things are similar, some abstraction can be from them.
          10. Continuous Integration
          11. Sustainable Pace
          12. Test-Driven Development
          13. Refactoring
          14. Metaphor

          posted @ 2011-11-03 21:44 *** 閱讀(273) | 評論 (0)編輯 收藏

          2011年10月30日

          數據庫范式

          1. 第一范式 - 列的原子性,數據庫表中的每一列都是不可再分的基本數據項
            1. 單一字段有多個有意義的值:比如 (people,address)其中address包括street,city,country,以逗號分割。想要查詢住在某一city的people很不容易
            2. 用很多字段來表示同一事實:比如(people,address1,address2,address3),就算我們假設每個people最多有三個地址,當想要查詢住在同一地址的people時也很不容易,因為有可能people1的address1與people2的address2相同,每一次都要比較3*3次組合
          2. 第二范式 - 符合第一范式;且表中的屬性必須完全依賴于全部主鍵,消除非主屬性對主鍵的部分依賴
            1. 比如(組件ID,供應商ID,供應商姓名,價格),組件ID+供應商ID為主鍵,價格完全依賴于全部主鍵,因為不同組件不同供應商具有不同價格,但是對于供應商姓名,則只依賴于供應商ID,會造成對同一供應商ID,名字數據重復,而且如果供應商改名,需要修改全部數據。因此需要單獨一個表(供應商ID,供應商姓名),(組件ID,供應商ID,價格)
          3. 第三范式 - 非主屬性之間不能有依賴關系,必須都直接依賴于主屬性,消除傳遞依賴
            1. 比如(組件ID,制造商姓名,制造商地址),其中組件ID為主鍵,而制造商地址依賴于制造商姓名,需要(組件ID,制造商姓名)和新表(制造商姓名,制造商地址)其中姓名是主鍵
            2. 比如(訂單ID,組件ID,單價,數量,總價),其中總價=單價*數量,總價依賴于單價和數量,需要去掉總價欄
          4. BC范式 - 任何屬性(包括非主屬性和主屬性)不能被非主屬性所決定。第三范式強調非主屬性不能依賴于其他非主屬性,BC范式是第三范式的加強,強調“任何屬性”。因此如果滿足第三范式,并且只有一個主鍵,則一定滿足BC范式

          一般,范式越高,表越多,數據庫操作時需要表關聯,增加了查詢的復雜性,降低了查詢性能。因此并不是范式越高越好,要根據需要進行權衡,第三范式已經消除了大部分的數據冗余,插入異常,更新異常和刪除異常。

          posted @ 2011-10-30 22:27 *** 閱讀(250) | 評論 (0)編輯 收藏

          2011年10月18日

          Page Object Patter For Functional Test


          Why?
          Functional test characteristic
          1. The number of tests is mostly large.
          2. Page structure and elements may be changed frequently.

          If our tests interact directly with the test driver (selenium,etc).
          1. UI element locators(Xpath, CSS, element Ids, names, etc) are copuled and repeat throughout the tests logic. It is hard to maintain, refactor and change especially when we change the page structure.
          2. The fine-grained UI operations hide our actual test intention. After some time we can not easily to identify what we want to do before.

          What?
          A Page Object models the UI elements that your tests interact with as objects within the test code. It decouples the test logic from the fine-grained details of the UI page.

          Test -> Page Object -> Test Driver

          The driver is the actual executor of browser action, like click, select, type etc. The page object has knowledage of the HTML structure.


          Advantages
          1. When UI changes, only responding page object need to be changed. The tests logic will not be affected.
          2. It makes our tests logic simpler and more readable. Since the tests logic can only focus on its test secinaro rather than the structure of HTML page. As an example, think of login function, it only needs username and password, then do login action. How these are implemented shouldn't matter to the test. We don't care about that it uses a button or link to login.
          3. Complex interactions can be modeled as methods on the page object, which can be used in multiple times.

          Best Practices

          1. Public methods represent the services that the page offers
          2. Try not to expose the internals of the page. Like OO programming, object just expose the behaviour and hide its internal details.
          3. Generally don't make assertions, but it is better to do some kind of check to ensure the browser is actually on the page it should be. Since our following tests are all base on the assumption. It can be done by checking something simple like title.
          4. Methods return other page object. This means that we can effectively model the user's journey through our application.
          5. Don't need to represent the entire page. It can be just a tab or a navigation bar that your test interacts with.
          6. Only one place knows the HTML structure of a particular page. UI changes, the fix need only be applied in one place.
          7. Different results for the same action are modeled as different methods. Since the test knows the expected state.

           

          posted @ 2011-10-18 21:57 *** 閱讀(246) | 評論 (0)編輯 收藏

          2011年8月25日

          Function - Clean Code

          1. Small and the indent level should not be greater than one or two.
          2. Do One Thing - Functions should do one thing. They should do it well. They should do it only.
              Steps of function are one level of abstraction below the name of the function. Then the function is doing one thing.
              Another way to know function is doing more than one thing is if you can extract another function from it.
          3. One level of abstraction per function
              The stepdown rule - reading code from top to bottom.
              switch
          4. Use Descriptive Names
              Don't be afraid to make a name long.
              A long descriptive name is better than a short magic name.
              A long descriptive name is better than a long descriptive comment.
              Dont't be afraid to spend time choosing a name.
              Be consistent in your names.
          5. Function Arguments
              The ideal number of arguments for a function is zero.
              Three arguments should be avoided.
              Flag Arguments - can be split into two function.
              Aruments Objects - group the variables and abstract concept if possible.
              Verbs and keywords - function and argument should form a very nice verb/noun pair.
          6. Have no side effects
          7. Command Query Separation - Functions should either do something or answer something, but not both.
          8. Prefer Exceptions to returning error codes.
              Extract try/catch blocks, error handling is one thing.
          9. DRY - don't repeat yourself - especially the duplicated logic.

          posted @ 2011-08-25 08:45 *** 閱讀(330) | 評論 (0)編輯 收藏

          2011年7月18日

          JavaScript中存在問題但卻難以避免的功能特性

          一,全局變量
          1.全局變量可以被任何部分在任意時間改變,復雜化,降低可靠性
          2.可能與子程序變量名相同,沖突可能導致程序無法運行,難以調試

          三種聲明全局變量模式
          1.脫離任何函數的var foo = value
          2.直接添加屬性至全局對象,全局對象是所有全局變量的容器,在web瀏覽器中全局對象名為window,window.foo = value
          3.直接未經聲明的變量 - 隱式的全局變量 foo = value

          二,沒有塊作用域,有函數作用域

          函數中定義的參數和變量在函數外部不可見,而在一個函數中任何位置的定義的變量在該函數的任何地方可見。

          function f1(){
              var a=1;
              function f2(){
                  if(false){
                      var a=2;    //變量基于函數,而非基于語句塊,沒有塊作用域
                  }
                  console.log(a); //undefined 未定義
              }
              f2();
              console.log(a);//1
          }
          f1();

          大多數語言中,一般聲明變量都是在第一次用到它的地方,在javascript中是一個壞習慣,因為沒有塊作用域,更好的是在每個函數開頭聲明所有變量。

          三,return語句返回一個值,值表達式必須和return在同一行上

          return {
              status:true
          };

          返回包含status成員元素的對象。

          如果用

          return
          {
              status:true
          };

          會返回undefined。

          四,保留字不能用來命名變量或函數,當保留字被用作對象字面量的鍵值時,必須用引號,而且不能用點表示法,必須使用括號表示法。

          var object = {case:value}; //非法
          var object = {'case':value}; //ok
          object.case = value;       //非法
          object['case'] = value;    //ok

          各瀏覽器對保留字使用限制上實現不同,以上語法在FF中合法,但其他瀏覽器不合法;再有不同的保留字行為也不相同。類似int/long/float等保留字在各瀏覽器中都可以做變量名及對象字面量的鍵值。但不建議使用任何保留字。

          五,typeof - 識別運算數類型的字符串

          但typeof null返回'object',更好的檢測null的方法: my_value === null

          對于正則表達式 typeof /a/,一些瀏覽器返回'object',另一些返回'function'

          六,parseInt - 將字符串轉換為整數

          1.此函數遇到非數字時就停止解析,即parseInt('16')和parseInt('16 abc')產生結果相同,都是16.
          2.如果字符串第一個字符是0,則基于八進制解析,而不是十進制。八進制中沒有8,9數字,所以parseInt('08')和parseInt('09')結果為0。此函數可以接收一個基數作為參數,parseInt('08',10)結果為8。

          七,浮點數

          0.1+0.2不等于0.3

          八,NaN

          function isNumber(value){
              return typeof value === 'number' && isFinite(value);
          }

          isFinite篩調NaN和Infinity,但是isFinite會試圖把它的運算數轉換為一個數字,如果運算數事實上不是一個數字,就會報錯,所以加上typeof value === 'number'。

          九,假值

          0,NaN,'',false,null,undefined全部等于假,但它們是不可互換的。

          posted @ 2011-07-18 20:09 *** 閱讀(217) | 評論 (0)編輯 收藏

          2011年7月11日

          羅伯特議事規則

          印象中美國人追求自由,但他們開會時卻是嚴肅認真,說到開會,他們有一本厚厚的開會規則-羅伯特議事規則。作者亨利.馬丁.羅伯特畢業于西點軍校,有一次奉命主持一個地方教會的會議,結果人們爭個不亦樂乎,什么結論都沒有,搞砸啦。于是羅伯特研究出了一些規則,最初只有四五條,放在錢包里,開會時遵守這些規則,就能順利成功。后來1876年羅伯特寫了《通用議事規則》。至今發行五百萬冊,羅伯特議事規則已取得最廣泛的認可和應用,它的根本意圖在于使一個會議能以盡可能最有效的方式達到它的目的。

          話說羅伯特議事規則初現中國是在組織農村開會時,當時會議及其混亂,表現為:
          一,你說周杰倫,我引出周潤發,東一榔頭西一棒子,最后忘了開會的目的是啥,還可能對于已經討論表決的問題,又重新拿來說,反反復復,歸結起來就是跑題;
          二,領導或者權威講個不停,下面人睡著啦,歸結為一家言;
          三,爭論起來,互相指責,甚至人身攻擊,歸結為野蠻爭論。

          其實這三條也是我們日常會議經常出現的問題。

          首先說野蠻爭論問題,很容易解決,羅伯特議事規則限制只對會議討論的問題發言,不允許評議個人,發言時對主持人進行陳述,而非辯論對方。總結起來,用中國言語來說就是“對事不對人”,因為指責個人并不能解決問題,不允許指責一個會員的動機,動機很難衡量,但可以用強烈的語言譴責一個議案的性質或后果。

          第二對于一家言問題,羅伯特議事規則限制每個人發言的次數和時間用以避免一家言問題。其實這是個人智慧和經驗與集體合作的關系,仍用中國言語來說“三個臭皮匠頂個諸葛亮”。對于睡著問題,可能是由于發言人太愛講,可以通過前述方法解決,還可能是由于當前話題不感興趣甚至無關,則可直接離開會議或不參加。

          第三對于跑題問題,羅伯特議事規則規定會議討論的內容應當是一個明確的動議:“動議,動議,就是行動的建議!”動議必須是具體的,明確的,可操作的行動建議,每一個動議都會導致一個action。比如“早上9點上班”,而不是“早上幾點上班?”。發言人應首先表明觀點,贊成還是反對,并陳述理由。與本次會議動議無關的其他動議,應組織其他會議,即我們常說的“一事一議”。經雙方輪流發言后,主持人組織投票。對于已經表決的觀點,除非理由充分,并經所有成員2/3同意再議,再組織再次討論。

          對于第三條,我覺得首先需要把平時會議劃分一下幾類:
          1.session:做session的人事先準備好內容,并計劃和把握session時長,同樣中間遇到與session無關的其他問題或者非常detail的問題,做session的人要打斷討論,對于重要問題組織其他session,對于detail問題offline討論。
          2.discussion:如羅伯特議事規則所說,組織discussion的人要有明確的動議,支持方與反對方輪流發言,如果規定時間未達成一致,組織者須組織投票。
          3.brainstorm:通過集思廣益、發揮集體智慧,迅速地獲得大量的新設想與創意,這是一種極為有效的開啟創新思維的方法。頭腦風暴結束后才開始對觀點進行討論,那針對每一個討論,又是一個discussion。

          另外,并不是所有會議都必須所有人參加,如果感覺對自己影響不大或者有比會議更要緊的事情可以不參加,或中間離席。

          posted @ 2011-07-11 08:27 *** 閱讀(303) | 評論 (0)編輯 收藏

          2011年6月2日

          ORA-00257 archiver error. Connect internal only, until freed

          1. Change to oracle user:$su oracle
          2. Log in as sys user: $sqlplus sys/password as sysdba
          3. Find out flash recovery area usage info, from where we can find the archive log space usage percent: SQL>select * from V$FLASH_RECOVERY_AREA_USAGE;
          4. Caculate the space used by flash recovery area:SQL>select sum(percent_space_used)*3/100 from V$FLASH_RECOVERY_AREA_USAGE;
          5. Show Archive log location: SQL>show parameter log_archive_dest;
          6. Show recovery area location: SQL>show parameter recover;
          7. Delete or move some old archive log files: SQL>rm -rf archive_log_2011_06_0*;
          Notice: After step 7, we must use RMAN to maintain the control files, otherwise, the deletion changes can not be apply.
          8. Log in as RMAN: SQL>rman target sys/password;
          9. Find out unused archive log: SQL>crosscheck archive log all;
          10. Delete expired archive log files: SQL>delete expired archivelog all;
          11. Check the flash recovery area usage info again, make sure archive log files have been deleted: SQL>select * from V$FLASH_RECOVERY_AREA_USAGE;
          12. Finally, increase the recovery file destination size: SQL>alter system set db_recovery_file_dest_size=3G scope=both;

          posted @ 2011-06-02 22:48 *** 閱讀(395) | 評論 (0)編輯 收藏

          僅列出標題  下一頁
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 辽宁省| 临潭县| 万盛区| 安多县| 清徐县| 甘洛县| 库伦旗| 新乡县| 大英县| 安顺市| 青冈县| 瓮安县| 右玉县| 通榆县| 广德县| 奉新县| 二连浩特市| 巫溪县| 乐昌市| 宝丰县| 江阴市| 永靖县| 固始县| 延庆县| 资源县| 张家港市| 扎赉特旗| 吴旗县| 宁津县| 轮台县| 东安县| 乌鲁木齐县| 阿坝县| 苏尼特右旗| 水城县| 仲巴县| 汉阴县| 佛学| 枞阳县| 石城县| 肥城市|