2020年3月31日 星期二

編程範式:Functional / Imperative / OO / Procedure Programming

常見的編程範式有以下幾種:
functional programming(函數式編程)
imperative programming(命令式編程)
Objective-Oriented programming(物件導向式編程)
procedure programming(程序式編程)

Functional Programming

Functional programming 沒有只是構想,沒有絕對的規定。
視程式設計為數學函式,每個函式各自獨立,彼此互不影響,
只要每個各自獨立的函式是正確的,那麼整個程式就是正確的。

各程式語言實作不同,但是有共通點:

  • No Side Effect-在表示式(Expression)內不可以造成值的改變。
  • First-Class Function-函數被當作一般值,可當傳入參數、傳出結果。
  • 資料放在堆疊stack-或由堆疊指向heap。
  • 盡量避免[狀態]與[可變資料],一切與函式內部無關。

優點

  • Unit test 相對容易。以函式為單位,且只檢查輸入、輸出是否正確,不管其他狀態。
  • 好除錯,因為沒有外部變數影響,所以錯誤容易重現,好找。
  • 因為可以保留函式內狀態(closure)所以程式可以精簡。
  • 適合寫併發(Concurrency)程式,因為不共享記憶體、沒執行緒、不上鎖、不擔心Critical Section。

Functional Programming到底做了什麼?

  • Higher-Order Functions-可接受函式當參數,或以函式為回傳值的函式,稱為 higher-order function,容易進行資料處理(排序、過濾、對應)。
  • Currying-用currying方式,定義特殊化函式。例如,有個函數為power(x, y),會計算出x的y次方,那麼事先將參數y指定為2,就可以定義一個平方函數square(x)。
  • Lazy Evaluation-表示式可拖到真正需要執行才執行,因此編譯器有更大的優化空間。
  • Continuations-將一個函數的傳出值,傳進另一個函數當作傳入值,也可以產生循序執行的效果。
  • Pattern Matching-模式比對的方式,可以讓系統自動幫我們進行分支與變數的指定。降低switch/case依賴、多型依賴。
  • Closure-函式離開後,其context依然保留,保留在內部函式,可當傳出值。
  • List processing-有好用的list處理函式。
  • Meta-Programming-許多FP語言都提供方便的Meta-Programming工具,讓你可以設計自己的Domain specific language

Imperative Programming(命令式編程)

Imperativ programming 認為程式的執行,就是一連串狀態的改變。
資料大量放在heap中。利用大量的流程控制,或狀態判斷還選擇執行的程式。
例如switch/case就是最好的例子。

Objective-Oriented Programming

2020年3月21日 星期六

Javascript mocha

mocha in webstorm

1. npm install mocha --save-dev  //安裝在專案目錄
2. npm init esm                  //讓test file 可以使用 es6 syntax
   //如果是舊專案 npm i esm

3. 
現在test file 可以使用 require (nodejs)
test file 可以使用 import es6 語法

4. webstorm 設定
Preferences=>
Language & Frameworks=>
Javascript=> Libraries

Add 搜尋 mocha 
新增後名稱是 @types/mocha
(這樣mocha 語法不會顯示錯誤)

5. package.json
 "scripts": {
    "test": "mocha -r esm"     //使用es6語法
   }


6. 執行測試
 npm test
 會執行 test 目錄下的 裡面有 mocha test 的檔案 xxx.test.js

2020年3月12日 星期四

gitlab SSH

Gitlab SSH

官方說明


//create ssh key
eg. rsa ssh key
ssh-keygen -t rsa -b 4096 -C "email@example.com"


//如果有多組 ssh key,可指定使用哪一組

寫入config檔
~/username/.ssh/config

//範例
# GitLab.com
Host gitlab.com
  Preferredauthentications publickey
  IdentityFile ~/.ssh/gitlab_com_rsa

# Private GitLab instance
Host gitlab.company.com
  Preferredauthentications publickey
  IdentityFile ~/.ssh/example_com_rsa

//測試
ssh -T git@gitlab.com

如果成功,會詢問是否把domain加到known_hosts

//刪除 known_hosts
所有的ssh 都會重新詢問一次


2020年3月1日 星期日

Javascript OOJS 物件導向JS

prototype 語言

Javascript 是基於 prototype 的語言,
意思是他是利用 prototype 建立起整個語言架構。

有一個最基礎的 null,
然後所有物件的基礎物件 Object 就是繼承自 null 這個 prototype,
Object 本身自己有一個 prototype 屬性,
這個屬性是他讓別人繼承的,
也就是別的物件要繼承自 Object 時,
他其實繼承的是 Object 的 prototype 屬性(這個屬性裡可以包含很多東西)。

所以用 Javascript 寫的程式,
就是這樣,一個物件繼承自另一個物件的 prototype 屬性,逐步建立起整個程式。

建立物件的方式一:function 回傳物件

利用函式回傳一個物件。
沒彈性,而且每一個物件都是 object。

function createNewPerson(name) {
  var obj = {};
  obj.name = name;
  obj.greeting = function () {
    alert('Hi! I\'m ' + this.name + '.');
  }
  return obj;
}

建立物件的方式二:Object()建構子

//new Object() 建立空白物件
//再把屬性加上去
var person1 = new Object();
person1.name = 'Chris';
person1['age'] = 38;
person1.greeting = function() {
  alert('Hi! I\'m ' + this.name + '.');
}


//或是直接傳入一個物件當參數
var person1 = new Object({
  name : 'Chris',
  age : 38,
  greeting : function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
});

建立物件的方式三:Object.create() 函式 IE8不支援



var person2 = Object.create(person1);

//person2.name
//person2.greeting()

建立物件的方式四:建構子函式 constructor function

WDN
Constructor funciton 是一種特殊的函式,
用來建立物件。
比用傳統方式建立物件好很多。

function Person(name,interests) {
  this.name = name;
  this.interests=interests;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

var person1 = new Person('Bob',[1,2,3]);
var person2 = new Person('Sarah',[1,2,3]);

console.log(person1['name']);        //可以這樣取
console.log(person1.interests[1]);   //可以這樣取
console.log(person1.greeting());
console.log(person2.name);
console.log(person2.greeting());

用建構子函式實體化的物件

建構子函式實體化的物件,
建構子函式定義的prototype屬性,只會有一份,
不會複製到每個實體上。

繼承(更接近於delegate 委託)

Javascript 的繼承,是[原型繼承](Prototypal inheritance)。
子物件不會把父物件可繼承的屬性複製過來,
而是用原型鍊連結他繼承的屬性。
子物件的繼承其實不是繼承,而是連接,
連接父物件prototype屬性。
所以一個父物件,不管延伸出多少子物件,
子物件繼承的屬性都只有一份,
就是存在父物件 prototype 屬性的那份。

  • 繼承方式一:實體化一份父物件,但是owner設成自己


  •    
      //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
         
        var t=new Teacher("a","b",3,1,"book","math");
        console.log(t.name);     //{"a","b"}
    
    



  • 繼承方式二:繼承父物件的 prototype 屬性


  • 每個物件的 prototype 屬性,是要繼承下去的。
    所以父物件的 prototype 屬性要連結在子物件的 prototype 屬性上。
    而子物件要讓孫物件繼承的屬性,也加到自己的 prototype 屬性上。



     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype);
      //**記得要把 constructor 設成自己,否則會是 Person 
       Teacher.prototype.constructor = Teacher;    
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //繼承自父物件的屬性
    
    

    複寫繼承自父物件的屬性

     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            console.log('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype); 
       //**記得要把 constructor 設成自己,否則會是 Person
       Teacher.prototype.constructor = Teacher; 
    
       //複寫父物件的 greeting
       //**要在 Teacher.prototype=Object(Person.prototype) 之後,才有複寫到
       Teacher.prototype.greeting=function(){
             console.log('Hi! I\'m teacher.');
       }   
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //變成自己的屬性
    
    

    Javascript npm

    INSTALL

    npm install takes 3 exclusive, optional flags which save or update the package version in your main package.json

    npm install (with no args, in package dir)
    npm install [<@scope>/]
    npm install [<@scope>/]@
    npm install [<@scope>/]@
    npm install [<@scope>/]@
    npm install 
    npm install 
    npm install 
    npm install 
    npm install /
    


  • S, --save: Package will appear in your dependencies.
  • -D, --save-dev: Package will appear in your devDependencies.
  • -O, --save-optional: Package will appear in your optionalDependencies.


  • install command example

    npm install module-name
    //npm 只會安裝module
    //需手動把 module and version 寫到 package.json 的 dependencies 區塊裡。
    
    npm install module-name -save
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 dependencies 區塊裡。
    
    
    npm install module-name -save-dev
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 devDependencies 區塊裡。
    
    npm install module-name -save-optional
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 optionalDependencies 區塊裡。
    
    

    假設 package.json 已經有 dependencies

    npm install //package.json 中 dependencies 和 devDependencies 都會安裝。 npm install --production //package.json 中 dependencies 會安裝。