Total Pageviews

2017/09/01

[閱讀筆記] The Long Tail (1/2)


  1. 不要一直想要征服大眾市場,因為那邊有太多強敵與競爭。一定要找到自己的利基,只要能夠把一群小眾的消費者顧好,你就會有很大的生存空間
  2. 市場上還是會有暢銷品,只是過去「只有」暢銷品,未來會被分成:有一些暢銷品,以及很多利基產品。暢銷品的市佔率從過去50%以上,可能會降至20%
  3. 眾多利基商品,以往因為不符合經濟效益,所以未能浮上水面,但這些商品其實存在許久,只不過不易為人見到或找到。舉凡各地戲院沒有上映的電影,各地廣播電台沒播的音樂。現在透過Google、Netflix、iTunes等等,以往隱形的利基市場終於浮上水面
  4. 如果說二十世紀的娛樂產業事由暢銷主導,那麼二十一世紀則是以利基分眾為馬首是瞻
  5. 促成長尾效應的三個力量
    1. 生產工具大眾化:過去只有專業人士才能做的事,現在人人都能做
    2. 配銷工具大眾化:網路降低了接觸更多顧客的成本,有效增加尾巴部分市場的流動性,進而促進消費、提高銷售量
    3. 連接供給與需求:如 Google 降低搜尋利基內容的『尋找成本』
  6. 被強迫、非自動、為薪資而做的勞動,將被自動自發的活動所取代
  7. 長尾的頭部與尾部生產者的差異,是愈靠近尾巴,就越可能必須保有一份正職的工作。「專業」與「業餘」生產者的界線已經日漸模糊,最終可能無關緊要。有的人為報酬而做,有的人為興趣而做,兩者皆可產生價值
  8. 即使99%的 blog 吸引的讀者不多,但是這 1% 能接觸到更多的讀者。這 1% 的 blog 的訪客總數不輸給主流媒體
  9. 長尾間的流動性日益增加,在暢行無阻的數位市場,從尾部開始的內容,如果能引起眾人共鳴,有可輕易移動到長尾的頭部
  10. 長尾市場最基本的原則是:銷售成本越低,銷售量越高。因此,aggregator 代表長尾市場的第二股力量,能促進配銷得大眾化。Aggregator 降低市場的進入障礙,讓更多商品越過障礙、流入市場、找到知音
  11. 今日的資訊取得,簡直易如反掌。搜集資訊不再是問題,如何根據資訊做出明智的決定,才是困難所在
  12. 第一股力量(生產工具大眾化)拉長了市場尾巴,第二股力量(配銷大眾化)讓人人都能進入長尾市場,第三股力量(個性化推薦),幫助人們在豐沛的選擇只選擇中找到他們要的,才能真正釋放長尾的澎湃潛力
  13. 在選擇無限的世界,真正的主宰是context (架構),而非content (內容)。現在的內容太多,你需要有一個 filter (篩選器),帶領人們從已知的世界(暢銷商品),走入未知的世界(利基商品)
  14. Filter (篩選器)的挑戰是,如何慧眼識英雄。如果你善用聰明的搜尋引擎、推薦系統或其他 filter ,就比較容易在長尾中挖到寶。filter 不但能為市場尾部的商品帶來需求,還能撮合人和商品,提升滿意度
  15. 在暢銷導向的世界,我們常高估暢銷商品占整體市場的比例。其實,暢銷商品反而是罕見的例外。這就是Nassim Taleb 提出的 Black Swan Problem
  16. Black Swan 是符合三項特質的隨機事件
    1. 影響重大: 事件的發生會造成重大影響
    2. 機率無法估算:根據事件尚未發生前的資訊,事件發生機率儘管很小,卻無法計算
    3. 出其不意:觀測時無確切跡象顯示事件發生機率會升高,但後來事情偏偏就是發生了
  17. Power-law distribution (冪次分佈) 是指,不管你要找什麼,沿著尾巴走,會出現越多你不要的東西。這就是為何訊號雜訊比會惡化,即使通常你必須走入長尾才能找到你要的東西。這就是 filter 要解決的問題
  18. Law of the Vital Few (重要少數法則):財富與人口的分佈,80%的財富為約20%的人所持有,這也是我們現在所說的80 / 20 法則


2017/08/11

[DB2] Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null

Problem

When I using Apache Commons DBUtils to do batch insert data into IBM DB2, I get this SQLException:
1
2
3
SQL Message: [jcc][t4][102][10040][4.14.88] Batch failure.  
The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null


Code Snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    /**
     * 批次處理.
     * 
     * @param sql
     *            insert/update/delete sql statemet
     * @param params
     *            parameters
     * @throws SQLException
     *             in case of fail to do insert/update/delete
     */
    public void batchUpdate(String sql, Object[][] params) throws SQLException {
        QueryRunner run = new QueryRunner();
        run.batch(this.getConnection(), sql, params);
    }



How-To
According to the troubleshooting information from IBM Support, it said:
The error is caused by the DB2 Transaction log for the Data Warehouse becoming full and not able to process the full batch operation.


But the root case is "value too large" in insert SQL statement, having nothing to do with DB2 Transaction log.   

2017/08/10

How to Improve Code Coverage After Using Apache Lombok?

Problem
After using Project Lombok, we can find out it help use reduce our boilerplate code. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package albert.practice.lambda;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.base.Strings;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

public class LambdaTest {

    public List<Person> filterData() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).filter(p -> !Strings.isNullOrEmpty(p.email))
                .collect(Collectors.toList());
    }

    public List<Person> filterDataWithSort() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).sorted((p1, p2) -> (p1.age - p2.age))
                .sorted((p1, p2) -> p2.name.compareTo(p1.name)).collect(Collectors.toList());
    }

    public List<Person> createData() {
        Person ben = new Person("Ben Whittaker", 70, "ben@gmail.com");
        Person jules = new Person("Jules Ostin", 30, "jules@gmail.com");
        Person fiona = new Person("Fiona Farwell", 68, null);
        Person matt = new Person("Matt", 35, "matt@gmail.com");
        
        return Arrays.asList(ben, jules, fiona, matt);
    }

    @Data
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Person {
        private String name;
        private int age;
        private String email;
    }

}

But you will also notice your code coverage rate is down dramatically.


How to improve the code coverage rate?


How-To
Add two dependencies to your pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<dependencies>
    <dependency>
        <groupId>org.meanbean</groupId>
        <artifactId>meanbean</artifactId>
        <version>2.0.2</version>
    </dependency>

    <dependency>
        <groupId>nl.jqno.equalsverifier</groupId>
        <artifactId>equalsverifier</artifactId>
        <version>2.2.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Check the testPersonBean() and testEqualsAndHashCode() in this test case:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package albert.practice.lambda;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.meanbean.test.BeanTester;

import albert.practice.lambda.LambdaTest.Person;
import lombok.extern.slf4j.Slf4j;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;

@Slf4j
public class LambdaUnitTest {

    private LambdaTest lambdaTest = null;

    @Before
    public void setup() {
        lambdaTest = new LambdaTest();
    }

    @Test
    public void testCreateData() {
        List<Person> people = lambdaTest.createData();
        assertEquals(people.size(), 4);
    }

    @Test
    public void testFilterData() {
        List<Person> people = lambdaTest.filterData();
        log.debug("testFilterData = " + people.toString());
        assertEquals(people.size(), 2);
    }

    @Test
    public void testFilterDataWithSort() {
        List<Person> people = lambdaTest.filterDataWithSort();
        log.debug("testFilterDataWithSort = " + people.toString());
        assertEquals(people.size(), 3);
    }

    // Testing getter and setters methods
    @Test
    public void testPersonBean() {
        new BeanTester().testBean(LambdaTest.Person.class);
    }

    // Testing equals() and hashCode()
    @Test
    public void testEqualsAndHashcode() {
        EqualsVerifier.forClass(LambdaTest.Person.class)
                .suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();
    }

}

After running code coverage analysis, you can find out this problem had been solved:




Reference
[1] http://www.jdev.it/tips-unit-testing-javabeans/

2017/08/09

[Squirrel SQL Client] Is it possible to have Squirrel SQL auto-resize the column width of the result set?

Problem
Is it possible to have Squirrel SQL auto-resize the column width of the result set? 


How-To
Steps:
(1) move your mouse to query result grid
(2) right click on query result grid
(3) check "Always adjust all column widths"



2017/08/08

[Tools] [Text Compare] How to Compare Two Lengthy JSON String

Problem
I have two lengthy JSON String, if I would like to compare the difference between the two JSON string, how to do it?

How-To
Here are the steps to fulfill this requirement:
(1) connect to https://text-compare.com/
(2) copy first JSON string to left hand side
(3) copy second JSON string to right hand side
(4) click Compare button

(5) check the difference

2017/08/07

[SQL Server] How to find similar table / column name by SQL

I am using Microsoft SQL Server...

If I would like to get a list of table name which table name has %arap%, you can use this SQL statement to do query:
SELECT NAME 
FROM   sys.tables 
WHERE  NAME LIKE '%arap%' 



If I would like to get a list of table which has column name %apply%, you can use this SQL statement to do query:
SELECT t.NAME AS 'TableName', 
       c.NAME AS 'ColumnName' 
FROM   sys.columns c 
       JOIN sys.tables t 
         ON c.object_id = t.object_id 
WHERE  c.NAME LIKE '%apply%' 
ORDER  BY t.NAME, 
          c.NAME; 








2017/08/06

[webMethods] How to Restart / Shutdown / Startup Integration Server

Problem
若我要重新啟動 integration server 的話,該去哪裡執行重啟

How-To
有兩個方式:
(1) 到遠端到安裝 integration server 的機器,到 SoftwareAG 的安裝目錄下,如 [SoftwareAG_HOME]\profiles\IS_default\bin\

執行 restart.bat 表示 restart integration server
執行 shutdown.bat 表示 shutdown integration server
執行 startup.bat 表示 startup integration server

(2) login 到 integration server administration console
點選畫面右上角的 ShutDown and Restart



若要 shutdown integration server,click Shut Down button
若要 restart integration server,click Restart button
若要強制馬上關閉,不管 session 的工作結束與否,點選上方的 immediately radio button



2017/08/05

[webMethods] 如何更新 integration server 的 trial license

Problem
今天當我 log in 到 webMethods integration server 的 administration console 時,出現 trial license 即將 expire 的 warning message


How-To
處理步驟如下:
(1) 到 Software AG [1] download trial license
(2) 將 trial license copy 到安裝 integration server 的特定目錄下
(3) 點選 Edit Licensing Details


(4) 修改 License File 的位置與檔名


(5) restart integration server
(6) login administration console,此時可以發現 warning message 已經消失,expire date 延長到 July 31




Reference
[1] http://www.softwareag.com/Corporate/res/download/default.asp

2017/08/04

[webMethods] Software AG Designer 無法編輯 Document Type, Flow Service

Problem
當我要編輯先前已經開發好的 document type, flow service 時,發現無法進行編輯,相關可編輯的選項都被 disabled



How-To
在欲編輯的 document type 或 flow service 中,按下右鍵,選擇 Lock for Edit



此時你會發現,該 document type 的 icon 出現打勾的符號,編輯的選項也都 enabled 了






2017/08/03

[Lombok] Utilize @Builder annotation to produce complex builder APIs for your classes

Problem
If you would like to apply builder pattern in your Java class, the class will looks like:
package albert.practice.designPattern.builder;

public class User {

    private String firstName;
    private String lastName;
    private String email;

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getEmail() {
        return email;
    }

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.email = builder.email;
    }

    @Override
    public String toString() {
        return "User [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
    }

    public static class UserBuilder {
        private String firstName;
        private String lastName;
        private String email;

        public UserBuilder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public UserBuilder lastName(String lastName) {
            this.lastName = lastName;
            return this;
        }

        public UserBuilder email(String email) {
            this.email = email;
            return this;
        }

        public User build() {
            User user = new User(this);
            return user;
        }
    }
}


Compared with POJO class, you may notice the number of lines of code increase at least to double in builder pattern. Does it has any convenient approach to implement and yield the same benefit which builder pattern bring for us?

How-To
You can make good use of @Builder annotation which provide by Project Lombok. The updated code look like:
package albert.practice.designPattern.builder;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

/*
 * The @Builder annotation produces complex builder APIs for your classes.
 * @Builder lets you automatically produce the code required to have your class be instantiable with code such as:
 * Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();
 */
@Builder
@Getter
@ToString
public class User2 {
    
    private String firstName;
    private String lastName;
    private String email;

}


Here is the test code:
package albert.practice.designPattern.builder;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UserTest {

    @Test
    public void testUser() {
        User user = new User.UserBuilder().firstName("Albert").lastName("Kuo")
                .email("test@gmail.com").build();
        log.debug("user = " + user.toString());
        assertNotNull(user);
    }

    @Test
    public void testUser2() {
        User2 user2 = new User2.User2Builder().firstName("Albert").lastName("Kuo")
                .email("test@gmail.com").build();
        log.debug("user2 = " + user2.toString());
        assertNotNull(user2);
    }

}



Maven dependencies are as bellows:
  <dependencies>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <!-- logback -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.7</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.7</version>
        </dependency>
    </dependencies>

Reference
[1] https://projectlombok.org/features/Builder.html



2017/08/02

[閱讀筆記] 惡魔財經辭典 (The Devil’s Financial Dictionary) [4/6]


  1. 投資人的一種習性是,對真正便宜的東西視而不見,就像羊群一樣成群移動,而不是自己獨立思考。人多會追求安全感,所以投資人買進某一項資產並不是因為該資產的價值被低估,而是因為「其他人」都在買;賣出資產也不是因為某種基本面的原因,而是因為「其他人」都在賣
  2. Heuristics (捷思),譬如定錨心理(anchoring)、可得性(availability)、代表性(representativeness),用直覺取代或然率分析和統計分析。短期來看,根據 heuristics 來進行投資的人可以得到很多樂趣;長期來看,根據統計來進行投資的人可以累積很多財富
  3. Income statement(收益表)是一家公司財務報表的一部分,但可能會誇大收益、少列支出
  4. 由於 index fund (指數型基金)收費非常低廉,交易佣金也微不足道,所以華爾街常用『為什麼要甘於平庸(average)?』來奚落 index fund。不過,這個問題的答案是,從年復一年的成果來看,index fund 的績效都超越絕大多數的主動型基金,而且成本少很多
  5. Inflation(通貨膨脹)是今天喪失購買力的過程,錢隨著時間變得越來越不值錢。一般來說,inflation 的原因是,政府用印鈔票來淹沒經濟問題,以此做為解決經濟問題的方法,因此讓百姓的日常生活難以為繼(特別是窮人),使得問題更加惡化
  6. IPO (Initial Public Offerings) 是股票首次公開上市,更精確的來說, IPO 這個縮寫的意思應該是 Insiders’ Private Oportunity(內部人士私人的機會)、 Imaginary Profits Only (獲利只是想像)、It’s Probably Overprices(價格可能太高)
  7. 華爾街的 is ,其實都是現在完成進行式的 has been。當分析師說我知道這隻股票會漲(is going up),他的意思是這隻股票 has been going up
  8. Junk bonds(垃圾債券)是指投資平等不合格的債券,現在已經改名成 high-yield bond(高收益債券),比較好聽但比較不坦率(candid)
  9. Kitchen-sink(運用洗碗槽策略,巨額沖銷),用來比喻公司把所有壞消息都灌進盈餘季報,好讓未來的數字相較之下比較好看。2008到2009年發生金融危機時,很多公司提前登載將淘汰的業務和員工支出、延後認列收入、提早認列虧損。趁著整體經濟大環境壞消息不斷,順勢將自家壞消息盡數公布。如此一來,投資人不僅沒責怪他們無能、犯錯連連,反而激賞他們誠實。此外,把話消息都丟給2009年,2010年的盈餘相較之下就亮麗多了,因為獲利通常是與前一年的同一季度比較
  10. 資產流動性(liquidity)停止時,就會發生清盤(liquidation)。因此,投資人必須隨時保持警覺。盡量追求資產流動性的極大化,同時盡量減少資產清盤的必要性
  11. 華爾街一句最有智慧的俗諺:「liquidity(資產流動性、變現性)只有在你不需要的時候才會出現。」在你一心想持有某個證券時,他當時很好賣;但是當你想賣時,卻賣不掉。小型市場、新興市場的證券尤其如此。
  12. 心理學家的實驗顯示,人是厭惡損失的(lose-averse),虧損 1 元的痛苦比賺 1 元的喜悅還要強烈兩倍以上
  13. 一位善於經營管理出了名的人,去處理一家眾所皆知財務狀況不佳的公司,能保持名聲無損的,是那家公司
  14. 如果一家公司的股價(price)下跌,而公司的價值(value)維持穩定,那麼投資人的安全邊際(margin of safety)就會變大。企業的價值(value)變化緩慢,價格(price)卻會出現爆炸性的變動。因此,股市動盪不穩時,通常安全邊際(margin of safety)會拉大;也就是說,風險最大的時候,正式投資最安全的時刻。懂得善用此一弔詭現象的人,才能充分發揮投資人的潛力。
  15. 雖然你努力不要在熊市賠錢,最常見的結果反而是在牛市賺不了錢
  16. 影響你對金錢的態度的因素,往往是錢怎麼來的、你打算怎麼花,而不是你有多少錢。如年終獎金得到的錢,你會買實用的東西;樂透得到的錢,你會拿去揮霍享受
  17. 動能股(momentum stock)會隨著上漲而日益加速狂飆,無視摩擦力、金融地心引力、牛頓第一運動定律、邏輯和理性。沒有任何理論或經驗可解釋動能的元成因、為何會持續、為何最終會衰退。一旦動能(momentum)停止,動能股也不會減緩,而會以高速去撞牆,把剛好持有的投資人撞得粉身碎骨。
  18. 共同基金(mutual fund)是一點也不互相(mutual)的基金。他的投資人的確很公平地共同分擔所有風險,不過他的經理人則獨享了所有手續費
  19. 在投資裡,短視(myopia)這個缺陷是很正常的,幾乎是全面性的普遍現象,唯一的療法只能靠紀律、耐心、自制力,因此絕大多數投資人都深受其苦
  20. 每當有人試圖以「新經濟」(new economy)說服你冒更大投資風險,請記得一句話:「『新』其實非常舊,甚至可以說是最舊的東西。」
  21. 英文裡代價最高的四個字是:this time, it’s different
  22. News 是噪音,也是混亂的聲音,也是投標的價格上下波動的原因,是交易人的命脈,通常也是投資人的禍根
  23. 經常更新自己投資標的最新消息的投資人,交易頻率會增加兩成,但是平均來說,獲利卻不到不追蹤消息的投資人的一半
  24. 隨時得知金融市場的最新消息,不等於知道未來即將發生什麼
  25. 若是消息不靈通、對這個世界缺乏好奇心,不可能成為成功的投資人;不過,聰明的投資人不會日日夜夜、無時無刻在追蹤消息。財經消息就像陽光,適度吸收是必要的,但是過度曝曬很危險,甚至可能致命
  26. 由於回歸平均值(regression to the mean)的關係,股票和投資經理人在被打入冷宮之前,一定會有一段看似火紅的時期。被預言是 the next Warren Buffet 且長期下來稱得上有 Buffet 影子的人,比例也才不過 0.01%
  27. 每當看到或聽到某支股票、每個投資經理人或某個金融資產號稱是下一個 Apple、下一個 Warren Buffet,下一個你該做的動作就是把它拋到腦後
  28. 如果一開始買進價格就過高,未來業績再怎麼亮麗都於事無補
  29. Overconfidence(過度自信)就是不知道自己無知,在金融市場中,絕對有必要加以克服,但要繳非常多學費
  30. 某支證券的持有部位高於平均,那就是 overweight (過重)。例如,若 Apple 公司佔 S&P 500 總市值的 3.8%,而有一支基金持有 Apple 3.9%資產,那就是 overweight了