Skip to content

2015

How to Be a Good Consultant?

I worked as a Software Engineer for a major Australian technology firm. While I am bright, skilled, and dedicated, these qualities alone are not sufficient to make one a successful consultant. Fortunately, after consulting with an experienced coach, I've come up with some insightful tips. Here are the three levels of consulting expertise I've learned:

1st Level

At the basic level, you possess a particular skill that you know better than others. For instance, I specialized in JavaScript front-end development and knew more about it than the employees at my client's company, which happened to be the world's largest gaming company. They sought your services because of the unique skills you can offer. However, this level of work isn't ideal for you in the long term. Mistakes will occur, making it challenging to maintain a professional first impression. Over time, you'll become indistinguishable from the millions of other individuals with similar skills. Your contribution becomes limited, and there's a narrow gap between what the client pays you and the value you deliver.

2nd Level

At the senior level, you offer significant value to clients by leveraging multiple skill sets. Remember, we're humans, not machines; we should all possess diverse talents. Drawing from your previous client experiences, you can provide a unique perspective on current challenges, setting you apart from the client's in-house team. You understand what works and what doesn't, what the client likes or dislikes, and what both the client and consulting firm genuinely need. Cultural awareness can go a long way in building trust.

3rd Level

At the highest level, you serve as a trusted advisor, akin to a king's confidant. Even if the king may not like hearing the truth, it's your responsibility to tell him. Should anything go awry, you will be held accountable from the client's perspective, as people are unlikely to blame themselves or admit they were wrong. You don't have to personally like the client, but you must care about them. Understand their motivations and recommend what's genuinely best for the company with compassion. Love may be a strong word, but it helps humanize your business approach. Your focus isn't solely on your success; you're concerned about the client's success as well. When the client wins, you win.

Final Thoughts

Reaching the highest level of consulting expertise is challenging. To establish a win-win situation, you must continuously learn and offer high-value skills to your client, your consulting firm, and yourself. It won't be easy and will require years of dedication, but these guidelines will serve as valuable markers on your consulting journey.

How to Be a Good Consultant?

I worked as a Software Engineer for a major Australian technology firm. While I am bright, skilled, and dedicated, these qualities alone are not sufficient to make one a successful consultant. Fortunately, after consulting with an experienced coach, I've come up with some insightful tips. Here are the three levels of consulting expertise I've learned:

Welcome to "Continuous Improvement," the podcast where we explore strategies, insights, and personal experiences in the world of consulting. I'm your host, Victor, and today we'll be diving into a topic that is crucial for any consultant looking to excel in their field: the three levels of consulting expertise.

As a former Software Engineer turned consultant, I've had my fair share of experiences and lessons learned along the way. And I'm here to share them with you. So let's get started!

At the basic level of consulting expertise, you possess a specific skill that sets you apart from others. For instance, in my case, it was JavaScript front-end development. Clients sought my services because I had a deep understanding of this skill, even surpassing the knowledge of their in-house team. However, relying solely on specialized skills can have its limitations.

Mistakes can happen, and it becomes challenging to maintain a consistently professional impression. Over time, you risk becoming indistinguishable from the sea of individuals with similar skills. This level limits your contribution, as the gap between what the client pays you and the value you deliver becomes narrower.

That's where the second level of consulting expertise comes into play. At this senior level, you bring significant value by leveraging multiple skill sets. Through previous client experiences, you gain a unique perspective on current challenges. You understand what works, what doesn't, and what the client truly needs from you and your consulting firm.

Cultural awareness also plays a crucial role in building trust with clients. By understanding their preferences and incorporating diverse talents, you set yourself apart from their internal team. This level allows you to contribute more effectively and provide a broader range of solutions.

Now, let's talk about the highest level of consulting expertise. At this level, you become a trusted advisor, someone akin to a king's confidant. Your responsibility is to provide honest feedback and recommendations, even if it's not what the client wants to hear. You hold yourself accountable for any potential issues that arise, as clients often find it difficult to blame themselves or admit their mistakes.

Building a genuine connection with the client becomes essential. It's not about simply liking them, but rather genuinely caring about their success. Understanding their motivations and recommending what's best for their company with compassion is the key. Your focus should extend beyond personal success; it should encompass the client's success as well. After all, when the client wins, you win.

Achieving the highest level of consulting expertise is undoubtedly challenging. It requires continuous learning, honing high-value skills, and offering exceptional value to your clients, your consulting firm, and yourself. It won't happen overnight, but by following these guidelines, you'll find valuable markers on your journey to becoming an exceptional consultant.

That wraps up today's episode of "Continuous Improvement." I hope you found these insights on the three levels of consulting expertise valuable and applicable to your own professional journey. Remember, continuous learning and self-improvement are key to success in this field.

If you enjoyed today's episode, be sure to subscribe to our podcast and stay tuned for future episodes where we'll explore more strategies for personal and professional growth. Until next time, I'm Victor, and thank you for joining me on "Continuous Improvement."

如何成為一個好的顧問?

我曾在一家大型澳洲科技公司擔任軟體工程師。雖然我聰明、擁有技能且我全心全意,但這些品質單獨存在並不足以讓一個人成為成功的顧問。幸運的是,經過與經驗豐富的教練諮詢後,我整理出了一些深刻的建議。以下是我學到的三個等級的諮詢專業知識:

第一等級

在基礎等級上,你擁有一種特定的技能,你比其他人更懂。例如,我專精於 JavaScript 前端開發,我對此知識比我的客戶公司的員工更瞭解,而這公司恰好是全球最大的遊戲公司。他們尋求你的服務是因為你可以提供的獨特技能。然而,這種等級的工作對你來說並不理想的長期工作。錯誤將不可避免地發生,使得維持專業的第一印象變得挑戰性。隨著時間的推移,你將與具有相似技能的其他百萬人口變得容易混淆。你的貢獻變得有限,客戶支付給你的和你提供的價值之間的差距變得狹窄。

第二等級

在資深等級上,你通過利用多種技能為客戶提供重大價值。請記住,我們是人,而不是機器;我們都應該擁有多種才能。從你之前的客戶經驗中學習,對於當前的挑戰,你可以提供獨特的視角,讓你區別於客戶的內部團隊。你知道什麼有效,什麼無效,了解客戶喜歡或不喜歡,知道客戶和諮詢公司真正需要什麼。文化意識可以在建立信任方面長期有效。

第三等級

在最高等級上,你起著受信任的顧問的作用,就像國王的密友一樣。即使國王可能不喜歡聽到事實,你也有責任告訴他。如果有任何事情出錯,從客戶的角度來看,你將被追究責任,因為人們不太可能責怪自己或承認他們是錯的。你不必親自喜歡客戶,但你必須關心他們。理解他們的動機,並以同情之心推薦對公司最好的事情。愛可能是一個強烈的詞,但它有助於人性化你的業務方法。你的關注點不僅僅在於你的成功;你也關心客戶的成功。當客戶獲勝,你也會獲勝。

最後的想法

達到最高等級的諮詢專業知識是困難的。要建立一個雙贏的局面,你必須不斷學習,並向你的客戶、你的諮詢公司和你自己提供高價值的技能。這將不會容易,且需要多年的奉獻,但這些指導方針將成為你諮詢旅程上重要的標誌。

Understanding Optionals and Exclamation Marks in Swift

Swift is a strongly-typed language, meaning all variables must have a defined type.

In Swift, there is a special type called "Optional," which can have only one of two possible values:

  1. A value that is not set, meaning it has never been set, or someone has explicitly set it to an unset state, i.e., to the value nil.
  2. A value that is set to something specific.

For example:

    var something = display.text

What is the type of something? We didn’t specify the type of this variable, but Swift can infer it from the context. It sets something to be the same type as display.text. Let's say display.text is of type String; then something will be an Optional String, which means it's an Optional that can contain a String.

How can you extract a string from an Optional? You can "unwrap" the Optional, meaning you inspect it and retrieve the associated value, using an exclamation mark:

    var something = display.text!

Now, the type of something is String, not an Optional. Note that if the value of display.text is nil, your program will crash!

Understanding Optionals and Exclamation Marks in Swift

Swift is a strongly-typed language, meaning all variables must have a defined type.

Hello everyone, and welcome to another episode of "Continuous Improvement." I'm your host, Victor, and today we'll be discussing a fundamental concept in Swift programming—Optionals. So grab a cup of coffee, sit back, and let's dive right in!

Swift is a strongly-typed language, which means that every variable must have a defined type. But sometimes, there are cases where a variable's value may not always be set or could be set to a specific value. That's where Optionals come in.

In Swift, an Optional is a special type that can have one of two possible values. First, it can have no value set, meaning it's in an unset state, represented by the value nil. And second, it can have a specific value set.

To understand how Optionals work, let's take an example. Imagine we have a variable called something and we assign it the value of display.text. We haven't explicitly specified the type of something, but Swift can infer it from the context.

If display.text is of type String, then something will be an Optional String. In other words, it's an Optional that can contain a String.

But how do we extract a String from an Optional? Well, we can "unwrap" the Optional, which means we inspect it and retrieve the associated value. To do this, we use an exclamation mark after the Optional variable.

So, by writing var something = display.text!, the type of something is now a String, not an Optional. However, it's important to note that if the value of display.text is nil, our program will crash!

Optionals are a powerful feature in Swift that help ensure our code handles both cases—the one where a value is set and the other where it's not. It prevents unexpected crashes by explicitly forcing us to consider the possibility of a variable being nil.

Well, that wraps up today's episode on Optionals in Swift. Remember, Optionals allow us to handle the absence of a value in a structured way and prevent unforeseen errors.

If you enjoyed today's episode, make sure to subscribe to "Continuous Improvement" so you never miss an episode. And don't forget to leave us a review and share the podcast with your friends.

Thank you for joining me today. Stay curious, keep learning, and until next time, happy coding!

在Swift中理解選項和驚嘆號

Swift是一種強類型語言,意味著所有變量都必須有一個定義的類型。

在Swift中,有一種特殊的類型叫做"Optional",它只能有兩種可能的值:

  1. 一個未設定的值,意味著它從未被設定,或者有人明確地將它設定為未設定的狀態,即,設定為nil的值。
  2. 一個設置為特定東西的值。

例如:

    var something = display.text

something的類型是什麼?我們並未指定此變量的類型,但是Swift可以從上下文中推斷出來。它將something設為和display.text同樣的類型。假設display.text的類型是String;那麼something將會是一個Optional String,即,它是一個可能包含String的Optional。

那麼您如何從Optional中提取一個字符串?您可以"解包"Optional,也就是說,您可以檢查它並取出相關的值,使用驚嘆號:

    var something = display.text!

現在,something的類型是String,而不是Optional。請注意,如果display.text的值是nil,那麼您的程式將會崩潰!

Connection between .h and .m files in Objective-C

When you first open an Objective-C project in Xcode, the .h and .m files may look confusing. It's important to understand the simple connections and the hidden code behind the scenes.

These files are used to separate the public and private parts of the class. The .h file serves as a header file for public declarations of your class, functioning like an API, while the .m file contains the private implementation.

When you need to call a function from other files, you just need to import the .h file for referencing. For example,

    #import <Foundation/Foundation.h>

In the .h file, you can declare public @property attributes of the class, which can be accessed from outside:

    @property (strong, nonatomic) NSString *something;

Here, @property is a pointer to an object whose class is NSString. All objects live in the heap, so we need the asterisk (*). As a side note, "strong" means "keep the object in memory until I set this property to nil." "Nonatomic" means "access to this property is not thread-safe;" otherwise, the compiler will generate locking code.

In the .m file, the "getter" and "setter" methods for this property are automatically generated for you behind the scenes to make the @property instance accessible:

    @synthesize something = _something;
    - (NSString *) something
    {
      return _something;
    }
    - (void)setSomething:(NSString *)something
    {
      _something = something;
    }

Note that by default, the backing variable's name is the same as the property's name but with an underscore in front. You don't need to write the above code unless you want to override the method and do something differently.

When you create a new method, you need to put the declaration in the .h file:

    - (int)newMethod:(ArgType *)arg;

And then write the actual details in your .m file.

    - (int)newMethod:(ArgType *)arg
    {
      int num = 0;
      // something in the method...
      return num;
    }

Also, for private declarations, you can include them in the .m file like this:

    @interface Something()
    // private declarations...
    @end

Finally, when you are reading other people's code for the first time, you just need to look at the .h files to get an overview of the projects. If you need to delve into the details, then look at the .m files.

Understanding the fundamental concepts outlined above will make the rest of the code start to make sense. :D

Connection between .h and .m files in Objective-C

When you first open an Objective-C project in Xcode, the .h and .m files may look confusing. It's important to understand the simple connections and the hidden code behind the scenes.

Welcome back to another episode of Continuous Improvement, where we explore different programming concepts and strategies to help you become a better developer. I'm your host, Victor, and today we'll be diving into the world of Objective-C programming. Specifically, we'll be discussing the structure of Objective-C projects in Xcode.

When you first open an Objective-C project in Xcode, you might find the .h and .m files a bit confusing. But fear not, understanding the simple connections and hidden code behind the scenes can help make it clearer.

Objective-C uses these .h and .m files to separate the public and private parts of a class. Think of the .h file as a header file, functioning like an API, where you declare public elements of your class. On the other hand, the .m file contains the private implementation.

To use functions from other files, all you need to do is import the .h file for referencing. It's as simple as adding:

    #import <Foundation/Foundation.h>

Easy, right? Now let's move on to the .h file. Here, you can declare public @property attributes of the class, which can be accessed from outside.

For example:

    @property (strong, nonatomic) NSString *something;

This line of code creates a pointer, @property, to an object of class NSString. The strong keyword means that the object will be kept in memory until the property is set to nil. Additionally, nonatomic indicates that access to this property is not thread-safe. If it were, the compiler would generate locking code.

Now, let's explore the .m file. When you synthesize your @property, the "getter" and "setter" methods for that property are automatically generated for you behind the scenes.

It's as simple as this:

    @synthesize something = _something;
    {
      return _something;
    }
    {
      _something = something;
    }

By default, the backing variable's name is the same as the property's name, but with an underscore prefix. You don't need to write this code unless you want to override the method and customize its behavior.

Are you still following? Great! Let's continue.

When you create a new method, you need to declare it in the .h file. The actual details of the method are then written in the .m file.

For example:

    - (int)calculateSomething {
      int num = 0;
      // Something happens in this method...
      return num;
    }

And there's one more thing. If you have private declarations, you can include them in the .m file using:

    @interface Something()
    // Private declarations...
    @end

And that's it! By understanding these fundamental concepts, you can start making sense of the code structure in Objective-C projects. Remember, when reading unfamiliar code, looking at the .h files gives you an overview, but if you need to delve into the details, check out the .m files.

Well, that brings us to the end of today's episode. I hope you found this dive into Objective-C project structure helpful. As always, keep improving, stay curious, and happy coding!

在Objective-C中,.h和.m檔案之間的連接

當你首次在Xcode中打開一個Objective-C專案,.h和.m檔案可能會讓你感到困惑。理解這些簡單的連接以及背後的隱藏程式碼是很重要的。

這些檔案被用來分離類別的公開和私有部分。.h檔案充當你的類別的公開宣告的標頭檔案,功能就像一個API,而.m檔案則包含私有的實現。

當你需要從其他檔案中調用一個函數時,你只需匯入.h檔案來做參考。例如,

    #import <Foundation/Foundation.h>

在.h檔案中,你可以宣告類別的公開@property屬性,可以從外部訪問:

    @property (strong, nonatomic) NSString *something;

在此,@property是一個指向其類別為NSString的對象的指標。所有对象都居住在堆中,所以我们需要星號(*)。另外,"strong"的意思是"我將這個屬性設置為nil之前,保持此對象在記憶體中。" "Nonatomic"的意思是"這個屬性的訪問不是線程安全的;" 否則,編譯器將生成鎖定程式碼。

在.m檔案中,這個屬性的"取值方法"和"設值方法"會被自動地在背後生成,使得@property實例可訪問:

    @synthesize something = _something;
    - (NSString *) something
    {
      return _something;
    }
    - (void)setSomething:(NSString *)something
    {
      _something = something;
    }

請注意,默認情況下,支持變數的名稱與屬性的名稱相同,但在前面有一個下劃線。除非你想覆寫方法並做一些不同的事情,否則你不需要寫上述程式碼。

當你創建一個新方法,你需要將聲明放在.h檔案中:

    - (int)newMethod:(ArgType *)arg;

然後在你的.m檔案中寫實際的細節。

    - (int)newMethod:(ArgType *)arg
    {
      int num = 0;
      // 方法中的某些東西...
      return num;
    }

此外,對於私有宣告,你可以像這樣將它們包含在.m檔案中:

    @interface Something()
    // 私有宣告...
    @end

最後,當你第一次讀別人的程式碼時,你只需要查看.h檔案來獲取專案的概述。如果需要深入了解細節,那就看.m檔案。

了解上述的基本概念將使你開始理解其餘的程式碼。:D

Install Hadoop on AWS Ubuntu Instance

Step 1: Create an Ubuntu 14.04 LTS instance on AWS.

Step 2: Connect to the instance.

chmod 400 yourKey.pem
ssh -i yourKey.pem ubuntu@your_instance_ip

Step 3: Install Java.

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java6-installer
sudo update-java-alternatives -s java-6-oracle
sudo apt-get install oracle-java6-set-default

Step 4: Add a Hadoop user.

sudo addgroup hadoop
sudo adduser --ingroup hadoop hduser

Step 5: Create an SSH key for password-free login.

su - hduser
ssh-keygen -t rsa -P ""
cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys

Step 6: Test the connection.

ssh localhost
exit

Step 7: Download and Install Hadoop.

cd /usr/local
sudo wget [http://apache.01link.hk/hadoop/core/hadoop-1.2.1/hadoop-1.2.1.tar.gz](http://apache.01link.hk/hadoop/core/hadoop-1.2.1/hadoop-1.2.1.tar.gz)
sudo tar -xzvf hadoop-1.2.1.tar.gz
sudo mv hadoop-1.2.1 hadoop
chown -R hduser:hadoop hadoop
sudo rm hadoop-1.2.1.tar.gz

Step 8: Update .bashrc.

su - hduser
vim $HOME/.bashrc

# Add the following content to the end of the file:
export HADOOP_PREFIX=/usr/local/hadoop
export JAVA_HOME=/usr/lib/jvm/java-6-sun
unalias fs &> /dev/null
alias fs="hadoop fs"
unalias hls &> /dev/null
alias hls="fs -ls"
export PATH=$PATH:$HADOOP_PREFIX/bin

Then save it with :wq and execute .bashrc.

source ~/.bashrc

Step 9: Configure Hadoop, logged in as hduser.

cd /usr/local/hadoop/conf
vim hadoop-env.sh

# Add the following lines to the file:
export JAVA_HOME=/usr/lib/jvm/java-6-oracle
export HADOOP_CLASSPATH=/usr/local/hadoop

Save and exit with :wq.

Step 10: Create a temporary directory for Hadoop.

exit
sudo mkdir -p /app/hadoop/tmp
sudo chown hduser:hadoop /app/hadoop/tmp
sudo chmod 750 /app/hadoop/tmp

Step 11: Add configuration snippets.

su - hduser
cd /usr/local/hadoop/conf
vim core-site.xml

# Put the following content between <configuration> ... </configuration> tags:

Include your Hadoop configuration here.

# Save and exit with :wq

Continue with configuring your additional files as needed.

Step 12: Format the HDFS.

/usr/local/hadoop/bin/hadoop namenode -format

Step 13: Start Hadoop.

/usr/local/hadoop/bin/start-all.sh

Step 14: To check if all processes are up and running.

jps

Step 15: To stop Hadoop, type the following command:

/usr/local/hadoop/bin/stop-all.sh

Step 16: To start Hadoop again.

/usr/local/hadoop/bin/start-all.sh

You are now ready to rock! Have fun :)