26 tháng 8, 2011

Chọn công việc (chọn công ty)


Nếu bạn đi phỏng vấn vào một công ty cho một vị trí bắt đầu được gọi là quan trọng (từ team leader trở lên) thì ngoài các vấn đề thông thường cần nắm như lương bổng, tình hình dự án, môi trường làm việc, thì mình góp vào một số vấn đề cần chú ý sau:

1. Bạn sẽ làm việc với ai?
Bạn cần xác định rõ nếu vào công ty bạn sẽ làm việc cũng nhóm với ai, khả năng của họ ra sao. Sếp trực tiếp của bạn là ai, có đủ khả năng thuyết đối với bạn hay không. Sếp lớn của công ty như thế nào, có đủ tầm để lãnh đạo công ty vươn xa hay hay không, có một hoài bão thực sự lớn và một định hướng đủ tốt hay không? Ban lãnh đạo của công ty có khả năng đánh giá chính xác năng lực của các nhân viên trong công ty hay không.

2. Bộ sậu chính của công ty như thế nào?
Nếu không phải là A-team thì cũng cần đủ mạnh về năng lực nội tại để cạnh tranh với các đối thủ khác khi công ty lớn dần, hẳn bạn sẽ không muốn làm việc với một bộ sậu mà không đủ năng lực cạnh tranh với các đối thủ lớn. Đặc biệt với các công ty start up, những người đi đầu rất quan trọng, nếu sau này công ty phát triển lên, những người đó không đủ tầm để đi cùng sự phát triển của công ty thì sẽ rất khó khăn trong việc giải quyết vấn đề nhân sự giữa người cũ với người mới. Bạn không thể thành công nếu chỉ làm một mình, và nếu bạn không xem xét nghiêm túc vấn đề này, thì cho dù bạn làm tốt tới đâu kết quả chung của toàn công ty cũng vẫn không được cải thiện nếu các bộ phận khác làm không đủ tốt, và ngược lại.

3. Con đường phát triển sự nghiệp của bạn sẽ ra sao sau 2 năm, 5 năm nếu bạn làm việc tốt?
Bạn có thể tham gia một công ty nhưng toàn bộ những vị trí chính yếu của công ty đã có người nắm hoặc bạn được giao làm teamleader nhưng bên trên bạn có 1 programmer lead và 2 CTO cùng một số vị trí quản lý trực tiếp thì liệu sau 5 năm phấn đấu bạn sẽ vươn tới được đâu? Công ty có đầu tư cho bạn phát triển kỹ năng hay không, cam kết đó rõ ràng tới mức nào hay chỉ dừng ở việc nói có và sẽ suy xét?

4. Thu nhập tương lai của bạn ra sao?
Nhiều công ty đưa ra cái bẫy thu nhập mà ứng viên sẽ bị mắc kẹt trong đó, đó là mức lương cao nhưng thưởng gần như không có, các lợi ích khác ngoài tiền như cổ phần, bảo hiểm (loại bảo hiểm thực sự tốt ấy), thiết bị làm việc đều không có hoặc rất hiếm hoi. Bạn nên cân nhắc và làm rõ vấn đề này. Tôi đã từng từ chối một công ty offer mức lương cao gấp đôi mức lương hiện tại chỉ bởi vì một năm chỉ có 14 tháng lương, không có gì khác, khi tôi hỏi nếu tôi phát triển bộ phận này thành công, mở rộng qui mô, đạt nhiều thành quả thì tôi có được hương cổ phần của công ty hay không, và dĩ nhiên là không, vậy nên tôi từ chối cơ hội đó. Dĩ nhiên, vấn đề tiền ở tương lai luôn có rủi ro vì không ai chắc chắn được, nhưng cái này thì tùy từng trường hợp và tùy từng đánh giá của mỗi cá nhân.

5. Và cuối cùng, đừng quên bạn có 2 tháng thử việc để xác định xem quyết định của mình có đúng hay không
Đôi khi việc bỏ qua 2 tháng thử việc thể hiện sự tin tưởng lần nhau giữa bạn và công ty, nhưng đôi khi, 2 tháng thử việc là thực sự cần thiết nếu bạn thấy trong những điều trên có điều nào đó mà bạn chưa chắc chắn. Đôi khi mọi thứ có vẻ đều ổn khi nhìn từ bên ngoài, nhưng ở trong chăn mới biết chăn có rận, bạn tham gia công ty thì muốn mọi người cùng đoàn kết để hướng tới kết quả chung, nếu công ty có mâu thuận nội bộ thì coi như xong: nhân viên làm việc không phối hợp tốt, chỉ chăm chăm đấu đá, chia bè kết phái để thanh trừng lần nhau… điều đó quả thật rất đáng sợ, và rất hay xảy ra ở các ông ty start up, nơi mà tốc độ phát triển rất nhanh, mâu thuẫn về lợi ích thường xuất hiện khi công ty to ra mà sếp không đủ tinh ý để giải quyết các vấn đề này ngay từ đầu. Vậy nên, 2 tháng thử việc thực sự là quan trọng nếu bạn thấy chư đủ chắc chắn.

Chúc phỏng bạn tìm được một công việc như ý!

02 tháng 8, 2011

Barcamp Saigon 24 tháng 7, một ngày ý nghĩa, học được nhiều điều

Hôm nay đi Barcamp Sài Gòn, vòng vòng nghe nhiều topic và xem xét tình hình nên cũng ngộ ra được nhiều điều, ghi chép lại và cũng để chia sẻ luôn.

  1. Các công ty công nghệ muốn lớn mạnh thì phải có một đội ngũ nòng cốt cực mạnh và được đầu tư đúng mức. Cái này quá rõ ràng. Khi nghe các topic của VNG và SkunkWorks thì thấy rõ đội ngũ của họ rất mạnh và mạnh toàn diện: server, client (mobile), web, system admin, product team… Như SkunkWorks, nghe về gamification thấy rõ được cái cách họ đưa ra các tiêu chí phát triển sản phẩm, cách đánh giá và học hỏi từ các sản phẩm thành công. Với VNG, đó là khả năng thiết kế hệ thống server với scalability để đáp ứng một lượng cực lớn user mà vẫn hoạt động tốt… nói chung nghe xong là nể. Dĩ nhiên, những người này cũng nhận được những mức đãi ngộ đủ tốt để họ yên lòng chuyên tâm vào công việc và điều kiện làm việc thì được hỗ trợ đầy đủ rồi.
  2. Các sự kiện trong giới công nghệ nói chung là cơ hội tốt để quảng bá hình ảnh của các công ty, đơn cử như barcamp đợt này, lại là SkunkWorks và VNG đã rất thành công, vì đã có những topic hay vũng như thể hiển được năng lực của người đứng nói, qua đó cho thấy hình ảnh công ty có một nền móng tốt, môi trường chuyên nghiệp và có thể vươn xa, cũng như cho thấy vào đó sẽ có nhiều cơ hội phát triển bản thân. Ngược lại, thật tiếc cho JoomlArt và East Agile, bản thân 2 công ty này không hề kém, nhưng những topic họ nói cho thấy sự thiếu chuẩn bị, người nghe không nhận được gì nhiều từ topic cũng như không thể hiện được năng lực của người thuyết trình nói riêng và đội ngũ công ty nói chung. Nói vậy chứ mình biết East Agile là cty có môi trường làm việc và mức đãi ngộ rất tốt ở SG này.
  3. Cơ hội tuyển dụng là ở đây. Khác với các hội chợ việc làm nơi các công ty có các sạp và chỉ quảng cáo về mình qua các tờ rơi, các sản phẩm, và ứng viên nhận thông tin, đăng ký và chờ phỏng vấn. Ở Barcamp, các công ty cho thấy được sức mạnh, tiềm năng của họ qua các topic, người tham gia có cơ hội nhìn nhận tốt hơn. Ngược lại những head hunter cũng được thấy những người có năng lực qua các topic mà họ thuyết trình hoặc qua cách họ đặt câu hỏi, trao đổi với nhau về các vấn đề công nghệ… hoặc có được những reference khá chính xác về một người qua cách trao đổi với họ hoặc những người trong cuộc. Cá nhân mình thấy những người tham gia barcamp thường là những người trẻ năng động, ham học hỏi hoặc là những người đã ở một trình độ nhất định nào đó trong giới công nghệ, nên chất lượng tuyển dụng ở đây sẽ tốt hơn.
  4. Cơ hội việc làm. Rõ ràng, các công ty tới đây quảng bá hình ảnh của mình cũng chỉ trong mục đích tìm người (người làm hoặc đối tác). Và điều hay là khá nhiều cty start up tham gia, cơ hội làm việc tại một cty start up là cơ hội lớn, tốt hơn rất nhiều so với việc tham gia một cty đã đủ to và có các vị trí chủ chốt. Nếu để ý sẽ thấy SkunkWorks cài người vào các topic hay để ngay cuối topic họ lại xin thông tin liên lạc của diễn giả, dĩ nhiên mục đích chính vlà gì thì ai cũng rõ. Ngoài ra, nếu ai ở lại cuối để nghe topic về cách làm một CV ấn tượng sẽ thấy ngay đó là một cơ hội lớn để tham gia một cty start up trụ sở tại Singapore, cho cả sinh viên thực tập luôn nhé.
  5. Dĩ nhiên, đây cũng là cơ hội tăng kiến thức. Hôm nay có 3 topic mà mình nghe thấy giúp cho mình rất nhiều: ZingMe webchat architect (nghe nhiều kinh nghiệm hay về server scalability), Gamification (thiết kế game cần chú ý các tiêu chí nào, các case study chuẩn), How to write a cv/resumes that gets you hired in a startup (kinh nghiệm làm cv đơn giản, hiệu quả và hướng tới đối tượng tuyển dụng). Ngoài ra còn có một số topic hay nhưng mình không có thời gian nghe nên không liệt kê ra ở đây.

Nhìn chung lại thì hôm nay là một ngày ý nghĩa, mình đúc rút được nhiều điều dù trước đây đã thấy nhưng chưa hề hệ thống lại. Cũng có nhiều suy nghĩ mới. Nhưng ngay trước mắt, mình nên cập nhật CV cho tốt hơn, chứ như hiện tại thì chưa đủ tốt, nghe xong thì phải làm ngay chứ, vậy mới có tinh thần học hỏi http://www.linkedin.com/in/tranvutatbinh


Danh sách các topic tại đây

13 tháng 1, 2011

Ví dụ làm loading ở cuối ListView và tự động load thêm dữ liệu



Nếu các bạn dùng ứng dụng Gmail, Android Market thì sẽ thấy trong các listview ở dưới cùng đều có hiện một cái loading animation sẽ load thêm dữ liệu khi mình scroll xuống tới cái loading đó. Hôm nay mình sẽ demo cách để làm việc này, khá đơn giản thôi.
Các bạn có sẵn code của list14 trong ApiDemos rồi, copy cái adapter đó ra dùng cho tiện nhé. Trong cái adapter đó, các bạn thêm giúp một hàm appendItems() để có thể nối thêm dữ liệu vào adapter hiện hành:
public void appendItems(ArrayList items) {
mItems.addAll(items);
notifyDataSetChanged();
}


Với ListView của mình, các bạn cần thêm vào một FooterView chính là cái hiển thị loading đó, lưu ý cơ bản là chỉ có thể thêm footer/header vào trong ListView trước khi setAdapter, xòn xóa thì lúc nào cũng được

LayoutInflater inflater = LayoutInflater.from(this);
mLoadMoreFooter = inflater.inflate(R.layout.loading_footer_item, null);
getListView().addFooterView(mLoadMoreFooter);

Rồi, giờ cần bắt sự kiện khi nào mình scroll list tới cuối và cái loading được hiện lên thì mình sẽ load thêm dữ liệu mới và add vào list, trong sự kiện onScroll() của ListView mình sẽ xử lý như sau:

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// minus 1 here because the total list item count include the
// loading footer
if (view.getLastVisiblePosition() >= totalItemCount - 1)
checkLoadMore();
}

Rồi, cái hàm checkLoadMore đơn giản chỉ là kiểm tra xem lúc đó có đang load dữ liệu chưa, dĩ nhiên nếu đang load dữ liệu rồi thì mình ko load thêm làm gì nữa, còn nếu chưa thì mình bắt đầu load thêm dữ liệu, vậy thôi
private void checkLoadMore() {
if (mLoading)
return;

/*
* if the loading footer is still there, then we will load more items
*/
if (getListView().getFooterViewsCount() != 0) {
loadMoreItems();
}
}

private void loadMoreItems() {
mLoading = true;

new Thread() {
public void run() {
try {
// in this example, we just simply wait for 2 seconds
Thread.sleep(2000);
Message msg = mMainhandler.obtainMessage(
MSG_APPEND_MORE_ITEMS, generateList());
mMainhandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}

Hàm loadMoreItems() thì vì đây là ví dụ nên mình chỉ cho làm mỗi việc là đợi 2 giây rồi tạo dữ liệu giả ra, coi như là đã lấy được dữ liệu từ server về rồi chẳng hạn. Hàm generateList() tạo ra một list với 15 String.
Vì mình load dữ liệu ở một thread riêng biệt, mà khi muốn cập nhật trên giao diện (chụ thể ở đây là ListView) thì mình cần phải làm trong main thread, nên mình sẽ gửi một message tới handler của main thread để xử lý.
switch (msg.what) {
case MSG_APPEND_MORE_ITEMS:
ArrayList newData = (ArrayList) msg.obj;
if (mAdapter == null) {
mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,
newData);
setListAdapter(mAdapter);
} else {
mAdapter.appendItems(newData);
}

// if the list we get from server is smaller than 15 (in this
// example)
// then that means there's nothing more to get, remove the
// loading item now
if (newData.size() <>
getListView().removeFooterView(mLoadMoreFooter);
}
mLoading = false;
break;
}

Đoạn code ở trên là: nếu như dữ liệu lấy về không đủ số lượng đã yêu cầu thì hiểu như là đã khôngcòn gì để load thêm nữa, vậy thì sẽ xóa cái loading ra khỏi list, vậy là xong :)

Đây là toàn bộ code của Activity:

package tvtbinh.bino.demo.loadingfooter;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

public class LoadingListDemoActivity extends ListActivity {
private SimpleAdapter mAdapter;
private View mLoadMoreFooter;

private boolean mLoading;

private static final int MSG_APPEND_MORE_ITEMS = 0;

private static final int NUMBER_OF_ITEMS_REQUESTED = 15;

/**
* Use this field to count how many trunks that we have loaded if it's more
* than 4 then we will not load anymore
*/
private int mTrunksCount = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// inflate the loading item and add to the ListView
// we all know that the footers/headers must be addded before setting
// the adapter for ListView
LayoutInflater inflater = LayoutInflater.from(this);
mLoadMoreFooter = inflater.inflate(R.layout.loading_footer_item, null);
getListView().addFooterView(mLoadMoreFooter);

getListView().setOnScrollListener(mScrollListener);

mLoading = false;

mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,
new ArrayList());
setListAdapter(mAdapter);
}

/**
* A mocking method for getting data from some source asynchronously
*/
private void loadMoreItems() {
mLoading = true;

new Thread() {
public void run() {
try {
// in this example, we just simply wait for 2 seconds
Thread.sleep(2000);
Message msg = mMainhandler.obtainMessage(
MSG_APPEND_MORE_ITEMS, generateList());
mMainhandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}

/**
* Generate an arrayList with 15 strings
*/
private ArrayList generateList() {
ArrayList results = new ArrayList();

mTrunksCount++;
if (mTrunksCount <= 4) {
for (int i = 0; i <>
results.add(String.valueOf(System.currentTimeMillis()));
}
}
return results;
}

private Handler mMainhandler = new Handler() {
public void handleMessage(Message msg) {

switch (msg.what) {
case MSG_APPEND_MORE_ITEMS:
ArrayList newData = (ArrayList) msg.obj;
if (mAdapter == null) {
mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,
newData);
setListAdapter(mAdapter);
} else {
mAdapter.appendItems(newData);
}

// if the list we get from server is smaller than 15 (in this
// example)
// then that means there's nothing more to get, remove the
// loading item now
if (newData.size() <>
getListView().removeFooterView(mLoadMoreFooter);
}
mLoading = false;
break;
}
};
};

/**
* Check if should load more item at this time
*/
private void checkLoadMore() {
if (mLoading)
return;

/*
* if the loading footer is still there, then we will load more items
*/
if (getListView().getFooterViewsCount() != 0) {
loadMoreItems();
}
}

private OnScrollListener mScrollListener = new OnScrollListener() {

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// We have nothing to do with this right now
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// minus 1 here because the total list item count include the
// loading footer
if (view.getLastVisiblePosition() >= totalItemCount - 1)
checkLoadMore();
}
};

private static class SimpleAdapter extends BaseAdapter {
private ArrayList mItems;
private LayoutInflater mInflater;
private Bitmap mIcon1;
private Bitmap mIcon2;

public SimpleAdapter(Context context, ArrayList items) {
mItems = new ArrayList(items);
mInflater = LayoutInflater.from(context);

// Icons bound to the rows.
mIcon1 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon48x48_1);
mIcon2 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon48x48_2);
}

public void appendItems(ArrayList items) {
mItems.addAll(items);
notifyDataSetChanged();
}

@Override
public int getCount() {
if (mItems == null) {
return 0;
}
return mItems.size();
}

@Override
public Object getItem(int position) {
return mItems.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;

if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text,
null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

holder.text.setText(mItems.get(position));
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

return convertView;
}

static class ViewHolder {
TextView text;
ImageView icon;
}

}
}