Total Pageviews

2017/04/01

[閱讀筆記] Waltzing with Bears (1/2)


  1. 經營管理是企業體的成長與永續之道,投資理財是個人的安身之道,而經濟趨勢則是會影響這兩者的變數
  2. 風險管理的事務,著重於成因風險(cause risk)的管理,亦即你能管理的部分
  3. 風險就是還沒發生的問題,問題是已經發生的風險
  4. 風險管理是在問題發生之前,預先思考應變措施的過程;危機管理則是在問題發生之後,嘗試處理善後
  5. 軟體工程規範原地踏步了許多年,他始終缺乏跟上資訊時代並滿足資訊社會所需要的成熟工程規範
  6. 很多軟體專案會失敗,並非風險管理方法不好,而是他根本就沒花任何功夫在風險管理上,反而在祈禱風險不會發生
  7. 風險管理就是把不確定性侷限在一個範圍內,或許你害怕僅憑少量資訊就要把問題解決掉。但是,若連這點資訊都沒有,情況會更糟糕。無窮無盡的不確定性,結果不是讓人過分保守,就是讓人變得莽撞,兩者都不是好事
  8. 進行風險管理不會使問題消失,只能保證不會讓你遭受突如其來的衝擊,殺的你措手不及
  9. 當你在祈禱所有的好運都降臨在你身上,當運氣其成為你整體策略的一部分時,小心,你的麻煩要來了
  10. 風險管理往往能提供你想要的更多事實真相
  11. 有些組織一廂情願的相信可以控制一切,即使心知肚明這並非事實,還是慣用控制的假象來蒙蔽現實。最常見的特徵,就是一開始弄出一個精確到令人可笑的預估結果,事後卻證明他跟事實差了十萬八千里
  12. 你可以管理風險,但不可能使風險消失
  13. 在最糟糕的組織中,報壞消息的人會被懲罰,但壞結果卻不會被檢討。當你提出風險時,就會有另外一位同儕會搶著說包在他身上,他一定可以如期完成。在這種文化中,大家都會先把牛吹大,因為這遠比按時交貨來得重要。如果再這種公司上班,把風險評估收起來,自己私底下用就好
  14. 組織不允許不確定性存在,風險管理就不用做了。這樣的組織,成員不可以對「一切如期完成」表現出一丁點的疑慮。事情做錯沒關係,就是不可以不確定
  15. 組織常常缺少能發出「災難」訊號的自主神經系統,常常自以為掌握了所有風險(潛在問題),其實只掌握了一部份而已(已有解決方案的潛在問題)
  16. 當你決定忽略某個風險時,就等於要賭運氣,賭這個風險不會發生
  17. 當專案包裝成一項挑戰時,就相當於強迫你去賭運氣。例如,你是全公司最後的希望,希望你能在這個月底完成這個專案
  18. 專案一開始就以個人挑戰的形式出發,便很難有明智的風險管理,這種專案就是在賭運氣
  19. 做軟體專案,你一定要把失敗的可能性限制在一定範圍內
  20. 我們在做預估的時候,記得把預估背後依賴的假設統統列舉出來
  21. 專案偏離時程,陷入泥沼,很少是因為工作比預期的更花時間,多半是為了處理原本沒有規劃到的事情
  22. 越棘手的風險,高層主管想弄走他的壓力就越大。根據經驗,高層主管若抓狂到某種地步,就比較不會想去了解為什麼風險會消失,反正只要它不見了就好
  23. 在軟體專案中,你不知道的問題,那通常就是風險所在。無論是什麼事情不知道,只要會造成不利的負面影響,就是風險。蒐集各種「我不知道」的問題,把不知道的根本原因找出來,你就可以得到一份完整的風險列表


2017/03/31

2017/03 Travel

奮起湖
DSC01349

DSC01343

DSC01345

DSC01364


台大杜鵑節
DSC01499

台北北門
DSC01391

DSC01395

2017/03/10

[Agnular2] Notifying parent Components that something has happened via events

Scenario

If we would like to tell the parent Component that the child component has added or deleted subtask. How to implement in Angualr2 ?


How-to
To create a custom event, we can use the new @Output decorator. So let's start by creating a new instance of an Event Emitter and decorate the property with the @Output decorator.

Then we've got an event emitter in place, let's call its emit method, callParent(), to raise the event and pass to parent component. 

The child component's code snippet looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Component({
  selector: 'sub-task',
  directives: [MODAL_DIRECTIVES, SELECT_DIRECTIVES, NgClass],
  providers: [SubtaskService, UserService, IssueService, ProjectService],
  templateUrl: 'sub.task.html'
})
export class SubTaskComponent implements OnInit {

  @Input() issue: Issue;
  @Input() watchers: Watcher[];

  @Output() refreshIssueEvent = new EventEmitter();
  
  callParent() {
    this.refreshIssueEvent.emit(this.issue.id);
  }
  
  //...
}  


The parent component receives that event and its payload. We use event binding to bind to this notify event and call a method.

Our final step is to provide the refreshIssue method to execute when the notify event occurs. 
1
2
3
<div class="container" *ngIf="issue.id">
  <sub-task [issue]="issue" [watchers]="issue.watchers" (refreshIssueEvent)="refreshIssue($event)"></sub-task>
</div>

We have to pass the $event to parent component's handler because that variable holds the event payload.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@Component({
  selector: 'issue-detail',
  templateUrl: 'issue.detail.html',
  providers: [IssueService]
})
export class IssueDetailComponent implements OnInit, OnDestroy {
  refreshIssue(issueId: number){
    this.issueService.getIssue(issueId.toString()).subscribe(
      data => {
        this.issue = data;
      }
    );
  }
  //...
}

2017/03/09

[Angular2] Pass data from parent to child with input binding

Scenario


If we had two html pages which has parent and child relationship. If we would like to pass parameters from parent to child, how to implement in Agnular2?

How-to
Step 1. Define the input parameter names in child component which typically adorned with @Input decorations., the code snippet is as bellows:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Component({
  selector: 'sub-task',
  directives: [MODAL_DIRECTIVES, SELECT_DIRECTIVES, NgClass],
  providers: [SubtaskService, UserService, IssueService, ProjectService],
  templateUrl: 'sub.task.html'
})
export class SubTaskComponent implements OnInit {

  @Input() issue: Issue;
  @Input() watchers: Watcher[];
  
  // ...
}

Step 2. The Parent page, issue.detail.html, is binding its master string property to the child's property. The code snippet is as follows:
1
2
3
<div class="container" *ngIf="issue.id">
  <sub-task [issue]="issue" [watchers]="issue.watchers"></sub-task>
</div>



2017/03/08

[Design Pattern] Command Pattern

在 97 Things Every Programmer Should Know 一書中提到:
雖然在一般遇到的案例裡,使用 if - then - else 比多型更實用些,但絕大多數用 polymorphism 的寫作風格會讓程式碼更精簡、更易讀,且更少脆弱的程式碼。所以在我們的程式碼裡,要是錯過使用 polymorphism 的機會,便會逐漸增加  if - then - else 敘述句的數量。試試 command  pattern 吧

假設我有一個機器人物件,他會執行前進、後退、左轉與右轉,這四種指令

package albert.practice.designpattern.command;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@AllArgsConstructor
@Data
@Slf4j
public class Robot {

    private String robotName;

    public void goAhead() {
        log.debug(robotName + " 前進 !");
    }

    public void turnLeft() {
        log.debug(robotName + " 左轉 !");
    }

    public void turnRight() {
        log.debug(robotName + " 右轉 !");
    }

    public void turnBack() {
        log.debug(robotName + " 後退 !");
    }
}


另外建立一個 enumeration 來判斷,此次呼叫要執行哪一個指令
package albert.practice.designpattern.command;

public enum CommandEnum {
    GO_HEAD, TURN_BACK, TURN_RIGHT, TURN_LEFT;
}


建立機器人物件與執行指令如下:
package albert.practice.designpattern.command;

public class RobotTestClient {

    public static void main(String[] args) {
        Robot robot = new Robot("瓦力");

        RobotTestClient client = new RobotTestClient();
        client.executeRobot(robot, CommandEnum.GO_HEAD);
        client.executeRobot(robot, CommandEnum.TURN_LEFT);
        client.executeRobot(robot, CommandEnum.TURN_RIGHT);        
    }

    public void executeRobot(Robot robot, CommandEnum command) {
        if (CommandEnum.GO_HEAD == command) {
            robot.goAhead();
        } else if (CommandEnum.TURN_BACK == command) {
            robot.turnBack();
        } else if (CommandEnum.TURN_LEFT == command) {
            robot.turnLeft();
        } else if (CommandEnum.TURN_RIGHT == command) {
            robot.turnRight();
        }
    }

}



在上述的程式碼就會發現,如果指令越來越多,就會有越來越多的 if-else 判斷式,此時就可以套用 command pattern

首先,先建立 Command interface
package albert.practice.designpattern.command;

public interface Command {
    void execute();
}



然後,分別建立四個指令的 classes,並實作 Command interface
前進指令:
package albert.practice.designpattern.command;

public class GoAheadCommand implements Command {

    private Robot robot;

    public GoAheadCommand(Robot robot) {
        super();
        this.robot = robot;
    }

    @Override
    public void execute() {
        this.robot.goAhead();
    }

}


後退指令:
package albert.practice.designpattern.command;

public class TurnBackCommand implements Command {
    private Robot robot;

    public TurnBackCommand(Robot robot) {
        super();
        this.robot = robot;
    }

    @Override
    public void execute() {
        this.robot.turnBack();
    }

}



向左轉指令:

package albert.practice.designpattern.command;

public class TurnLeftCommand implements Command {
    private Robot robot;

    public TurnLeftCommand(Robot robot) {
        super();
        this.robot = robot;
    }

    @Override
    public void execute() {
        this.robot.turnLeft();
    }

}



向右轉指令:
package albert.practice.designpattern.command;

public class TurnRightCommand implements Command {
    private Robot robot;

    public TurnRightCommand(Robot robot) {
        super();
        this.robot = robot;
    }

    @Override
    public void execute() {
        this.robot.turnRight();
    }

}



建立機器人物件與操作指令,程式修改如下:

package albert.practice.designpattern.command;

public class RobotTestClient {

    public static void main(String[] args) {
        Robot robot = new Robot("瓦力");
        new GoAheadCommand(robot).execute();
        new TurnLeftCommand(robot).execute();
        new TurnRightCommand(robot).execute();
    }

}



2017/03/07

[Redmine] How to get mail notification value in user page

Problem
I am trying to get admin value from the redmine user object. 
But I cannot get admin value, no matter using Java API or Rest API.
It can only retrieve very limited information:



How-To
We can make good use of jsoup to parse html page and get value from the specific html element.

Firstly, checking the drop down list element in html. 


Secondly, using jsoup to parse HTML
1
2
3
4
5
6
7
8
9
    String url = "http://192.168.0.1/users/" + userId + "/edit";
    Document document = Jsoup.connect(url).get();
    Elements mailNotificationElements = document.select("[name=user[mail_notification]]").select("option");
    for (Element element : mailNotificationElements) {
        if ("selected".equals(element.attr("selected"))) {
            log.debug("the mail_notification value = " + element.val());
            break;
        }
    }


Reference
[1] https://jsoup.org/



2017/03/06

[Redmine] How to get admin value in user page

Problem
I am trying to get admin value from the redmine user object. 
But I cannot get admin value, no matter using Java API or Rest API.
It can only retrieve very limited information:



How-To
We can make good use of jsoup to parse html page and get value from the specific html element.

Firstly, checking the checkbox element in html. 
We can find out the element name and the checked checkbox will add checked="checked" attribute.

If the checkbox does not be checked, it will not have checked="checked" attribute.


Secondly, using jsoup to parse HTML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    String url = "http://192.168.0.1/users/" + userId + "/edit";
    // Connect to redmine url and get HTML document
    Document document = Jsoup.connect(url).get();
    
    // Find elements that match [name=user[admin]]
    Elements adminElements = document.select("[name=user[admin]]");
    for (Element element : adminElements) {
       // if the element has checked="checked" attribute, it means this user is administrator, 
       // or this user is a normal user
       if ("checked".equals(element.attr("checked"))) {
           log.debug("this user is admin");
           break;
       }
    }


Reference
[1] https://jsoup.org/

2017/03/05

[Angular2] Fail to apply bootstrap on checkbox with Angular2

Problem
According to the example in w3schools, http://www.w3schools.com/bootstrap/bootstrap_forms_inputs.asp

If the checkbox is static, it will not have this problem. But if the checkboxes generate dynamically, using *ngFor, the checkbox square is missing


The code snippet is as bellows:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<div class="row" *ngIf="roles">
   <div>
      <label>角色</label>
   </div>
   <div *ngFor="let role of roles" style="display: inline-block">
      <div class="checkbox">
         <label style="padding-right:10px; padding-left:10px" >
         <input type="checkbox" [(ngModel)]="role.isSelected" (change)="checkRole(role)">
         {{ role.name }}
         </label>
      </div>
   </div>
</div>


How-To
It seems that if the checkbox generate dynamically, it will lack of some html tags to assign class for unknown reasons. Therefore, you need to add these span tag manually (line 9).  

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<div class="row" *ngIf="roles">
   <div>
      <label>角色</label>
   </div>
   <div *ngFor="let role of roles" style="display: inline-block">
      <div class="checkbox">
         <label style="padding-right:10px; padding-left:10px" >
         <input type="checkbox" [(ngModel)]="role.isSelected" (change)="checkRole(role)">
         <span class="checkbox-material"><span class="check"></span></span>
         {{ role.name }}
         </label>
      </div>
   </div>
</div>




2017/03/04

[jackson] How to rename JSON attribute name

Problem
I would like to create a Java Bean to do mapping with JSON object.
But the JSON object has an attribute name, public, which has conflict with Java, because public is an reserved word in Java. How to handle this problem?



How-to
You can utilize @JsonProperty to rename it.
The Java bean looks like (publicStr is mapping to public in JSON):
    @Data
    @ToString
    public static class DsnDto {
        @JsonProperty("public")
        private String publicStr;
        private String secret;
        private String csp;
    }


Reference
[1] https://stackoverflow.com/questions/9741134/jackson-annotation-how-to-rename-element-names

2017/03/03

[liquibase] Caused by: liquibase.exception.LockException: Could not acquire change log lock

Problem

I am running a lot of liquibase-scripts on PostgreSQL database, and get error message as I startup Spring Boot:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Caused by: liquibase.exception.LockException: Could not acquire change log lock.  Currently locked by albert-PC (10.11.22.33) since 2016/9/26 下午 2:06
 at liquibase.lockservice.StandardLockService.waitForLock(StandardLockService.java:190) ~[liquibase-core-3.5.1.jar:na]
 at liquibase.Liquibase.update(Liquibase.java:196) ~[liquibase-core-3.5.1.jar:na]
 at liquibase.Liquibase.update(Liquibase.java:192) ~[liquibase-core-3.5.1.jar:na]
 at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:434) ~[liquibase-core-3.5.1.jar:na]
 at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:391) ~[liquibase-core-3.5.1.jar:na]
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 ... 160 common frames omitted


How-to
The problem was the buggy implementation of SequenceExists in Liquibase. Since the changesets with these statements took a very long time and was accidently aborted. Then the next try executing the liquibase-scripts the lock was held.
Therefore, you can execute this DML to update DATABASECHANGELOGLOCK table:

UPDATE DATABASECHANGELOGLOCK SET LOCKED=FALSE, LOCKGRANTED=null, LOCKEDBY=null where ID=1

Reference

[1] https://stackoverflow.com/questions/15528795/liquibase-lock-reasons

2017/03/02

[HTML] How to arrange multiple elements in the same row

Problem
In this dialog, I hope the drop down list should be at the right side of the radio button, not in the new line.




The code snippet looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="row">
   <div class="col-sm-12">
      <div class="form-group" style="display:inline">
         <label>即時應用系統異常追蹤整合</label>
         <div>
            <input type="radio" name="sentryOption" [checked]="newProject.sentryOption==='0'" (click)="newProject.sentryOption='0'">立即建立專案關聯
            <span style="padding-left:20px">
            <input type="radio" name="sentryOption" [checked]="newProject.sentryOption==='1'" (click)="newProject.sentryOption='1'">選擇既有的關聯
            </span>
            <span style="padding-left:5px">
               <select class="form-control" name="sentryProjectId" [(ngModel)]="newProject.sentryProjectId" [style.width.px]="50" *ngIf="newProject.sentryOption==='1'"
               >
               <option value="" selected> 請選擇 </option>
               <option *ngFor="let sp of sentryProjects" [ngValue]="sp.slug">{{sp.slug}}</option>
               </select>
            </span>
         </div>
      </div>
   </div>
</div>


How-to
You can use CSS to fulfill this requirement:
display:inline-block

Just add display:inline-block; to this drop down list's style, the updated code snippet is as bellowing:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="row">
   <div class="col-sm-12">
      <div class="form-group" style="display:inline">
         <label>即時應用系統異常追蹤整合</label>
         <div>
            <input type="radio" name="sentryOption" [checked]="newProject.sentryOption==='0'" (click)="newProject.sentryOption='0'">立即建立專案關聯
            <span style="padding-left:20px">
            <input type="radio" name="sentryOption" [checked]="newProject.sentryOption==='1'" (click)="newProject.sentryOption='1'">選擇既有的關聯
            </span>
            <span style="padding-left:5px">
               <select class="form-control" name="sentryProjectId" [(ngModel)]="newProject.sentryProjectId" [style.width.px]="50" *ngIf="newProject.sentryOption==='1'"
               style="display:inline-block;">
               <option value="" selected> 請選擇 </option>
               <option *ngFor="let sp of sentryProjects" [ngValue]="sp.slug">{{sp.slug}}</option>
               </select>
            </span>
         </div>
      </div>
   </div>
</div>    


See...the radio buttons and drop down list are in the same row.

Reference
[1] https://www.quora.com/I-want-to-put-two-divs-in-HTML-in-the-same-line-but-one-always-comes-under-the-other-one-What-should-I-do
[2] http://crunchify.com/basic-html-how-do-you-create-blank-space-in-html/