Sunday, May 3, 2015

[iOS] Tạo class DataSource cho TableView

Mở đầu

Để tiếp nối chuỗi bài về TableView, hôm nay mình cũng viết một bài liên quan đến TableView. Trong iOS TableView là class được dùng khá nhiều.
Khi dùng TableView chúng ta thường phải set datasource và delegate cho TableView. Thường thì datasource của TableView là một array.
Khá nhiều bạn thường set datasource cho Tableview ngay trong ViewController (tableview.datasource = self). Và khi đấy trong ViewController chúng ta luôn luôn phải implement delegate cho TableViewDataSource như sau:
// TmpViewController.m

#pragma mark - UITableViewDataSource delegate
- (NSInteger)tableView:(UITalbeView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return [self.dataArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *cellIdentifier = @"MyCell";
  // lấy cell có sẵn
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
  // nếu không có cell có sẵn thì tạo cell mới
  if(cell == nil) {
    cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                 reuseIdentifier:cellIdentifier];
  }

  // lấy dữ liệu cho cell hiện tại. (Ví dụ dữ liệu là NSString)
  NSString *item = [self.dataArray objectAtIndex:indexPath.row];
  // gán dữ liệu cho cell
  [cell.textLabel setText:item];

  return cell;
}
Việc viết như trên đối với những ứng dụng nhỏ thì không vấn đề gì nhưng khi ứng dụng sử dụng nhiều tableview thì trong từng ViewController chúng ta luôn phải viết đi viết lại đoạn code trên. Nếu nhìn kỹ đoạn code trên bạn sẽ thấy thực ra với mỗi TableView khác nhau chúng ta chỉ cần thay đổi phần #gán dữ liệu cho cell tuỳ theo cấu trúc của từng cell. Còn đâu những phần còn lại chúng ta có thể sử dụng lại code. Ngoài ra nếu chúng ta để những đoạn code này trong ViewController sẽ khiến ViewController trở nên dài hơn bởi vì bản thân ViewController đã chứa rất nhiều code như delegate, code xử lý sự kiện, gesture. Vì vậy để có một ViewController ngắn gọn hơn, dễ hiểu hơn, lại tăng tính sử dụng lại code chúng ta sẽ tạo 1 class datasource riêng tên là TVArrayDataSource.


Tạo class TVArrayDataSource

Vậy chúng ta sẽ chuyển hết code ở trên sang class TVArrayDataSource và trong các ViewController chúng ta chỉ cần viết phần #gán dữ liệu cho cell tuỳ theo cấu trúc của cell. Vậy trong TVArrayDataSource cần những property gì?
Đầu tiên là NSArray *items trỏ đến array data của chúng ta trong ViewController để chúng ta có thể lấy data tương ứng cho từng cell và cell identifier NSString *cellIdentifier là string dùng để định danh cell.
// TVArrayDatasource.m


@interface TVArrayDataSource()

@property (strong, nonatomic) NSArray *items;
@property (copy, nonatomic) NSString *cellIdentifier;

@end

@implementation TVArrayDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // tìm cell có sẵn
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier];
    // tạo cell mới nếu không tìm thấy
    if (cell == nil) {
      ...
    }

    // lấy data cho cell
    id item = [self.items objectAtIndex:indexPath.row];

    // gán dữ liệu cho cell
    ...

    return cell;
}

@end
Đầu tiên chúng ta sẽ nói về đoạn ... tại phần gán dữ liệu cho cell. Tại vì tuỳ từng trường hợp của tableview mà cell của chúng ta có cấu trúc khác nhau, data source có cấu trúc khác nhau nên phần gán dữ liệu này là khác nhau. Do đó tại đây chúng ta có thể gọi đến các hàm callback trong ViewController để gán dữ liệu cho cell theo cách mà chúng ta muốn. Có nhiều cách như dùng block, selector hay delegate. Mình thì thấy tiện nhất và ngắn nhất là block và selector nên mình sẽ tạo class TVArrayDataSource có thể dùng block hoặc selector.
Với block thì chúng ta cần tạo 1 property để lưu block và execute block tại đoạn gán dữ liệu. Chúng ta sẽ thêm block property vào TVArrayDataSource.m và tạo 1 method khởi tạo dataSource với block như sau:
/// TVArrayDataSource.m

typedef void (^TVCellConfigureBlock)(id, id);

@interface TVArrayDataSource : NSObject <UITableViewDataSource>

/* khởi tạo datasource với block */
- (id)initWithItems:(NSArray *)items
     cellIdentifier:(NSString *)cellIdentifier
 cellConfigureBlock:(TVCellConfigureBlock) configureBlock;

// TVArrayDataSource.m

...
// thêm block property vào
@property (copy, nonatomic) TVCellConfigureBlock configureBlock;

// và method khởi tạo chỉ đơn giản như sau
- (id)initWithItems:(NSArray *)items
     cellIdentifier:(NSString *)cellIdentifier
 cellConfigureBlock:(TVCellConfigureBlock)configureBlock
{
    self = [super init];
    if(self) {
        self.items = items;
        self.cellIdentifier = cellIdentifier;
        self.configureBlock = configureBlock;
    }
    return self;
}

// và chúng ta thêm phần execute block tại đoạn gán dữ liệu cho cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   // tìm cell có sẵn
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier];
    // tạo cell mới nếu không tìm thấy
    if (cell == nil) {
      ...
    }

    // lấy data cho cell
    id item = [self.items objectAtIndex:indexPath.row];

    // execute block để gán dữ liệu cho cell
    self.configureBlock(cell, item);

    return cell;
}

Khi đó bên ViewController chúng ta chỉ cần tạo 1 block để thực hiện việc gán dữ liệu cho cell. Và block này sẽ được execute bằng self.configureBlock(cell, item) với tham số là cell hiện tại và data tương ứng của cell. Bởi vì tham số của block là cell hiện tại và data cho cell đấy nênchúng ta hoàn toàn có thể tự do tuỳ chỉnh cell theo ý muốn. Và code bên ViewController sẽ rất ngắn và đẹp như sau:
/// ViewController1.m

// configure block. Kiểu tham số có thể tuỳ chỉnh theo kiểu data bất kỳ của bạn.
TVCellConfigureBlock configureCell = ^(CellClassName *cell, DataType *name) {
  // gán dữ liệu cho cell. ví dụ như sau:
  [cell.title setText:name];
};
// tạo instance dataSource của TVArrayDataSource và khởi tạo với block ở trên
dataSource = [[TVArrayDataSource alloc] initWithItems:items
                                       cellIdentifier:@"MYCELL"
                                   cellConfigureBlock:configureCell];
tableView.datasource = dataSource;
Bạn thấy đấy giờ trong ViewController thì phần code cho dataSource của tableView khá là đẹp.
Đôi khi bạn muốn viết đoạn gán dữ liệu cho cell vào một method khác trong class ViewController thay vì dùng block. Để cho những trường hợp đó như đã nói ở trên chúng ta có thể dùng selector. Tương tự như block chúng ta cũng sẽ tạo một @property (assign, nonatomic) SEL configureSelector; và đối tượng để execute method của selector này @property (weak, nonatomic) id target; (Đối tượng này chính là ViewController). Chúng ta cũng cần tạo một hàm khởi tạo datasource khác với selector. Cuối cùng trong phần gán dữ liệu cho cell chúng ta execute method của selector với objc_msgSend(self.target, self.configureSelector, cell, item);. Do phần này tương tự như đối với block nên mình không giải thích thêm mà các bạn có thể xem code trên github.
Tiếp theo còn một đoạn ... tại phần tạo cell mới khi mà không tìm thấy cell có thể dùng lại. Như bạn thấy đấy để tạo cell mới chúng ta cần biết Class của cell. Với Objective-C chúng ta có thể tạo 1 instance từ tên class. Khi đó chúng ta có thể tạo 1 cell như sau:
cell = [[NSClassFromString(CELL_CLASS_NAME) alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:self.cellIdentifier];
Như vậy class TVArrayDataSource chỉ cần có thêm thông tin là tên class của cell là mọi việc có thể hoàn tất. Ngoài ra nhiều khi chúng ta muốn tạo cell từ file Xib. Để tạo cell từ file xib chúng ta cũng chỉ cần biết thêm tên file xib. Thế nên mình tạo thêm một property cellName để lưu tên class của cell hoặc tên file Xib tuỳ theo trường hợp cell tạo từ file xib hay từ code.
Như vậy việc tạo class TVArrayDatasource đã hoàn thành. Và bây giờ trong ViewController chúng ta chỉ implement đoạn code ngắn như sau:
Khi sử dụng với block
// ViewController.m

// tạo block
TVCellConfigureBlock configureCell = ^(CELL_CLASS_NAME *cell, DATATYPE *name) {
  [cell.title setText:name];
};

dataSource = [[TVArrayDataSource alloc] initWithItems:items
                                       cellIdentifier:@"MYCELL"
                                   cellConfigureBlock:configureCell];
[dataSource setXibFileName:@"XibFileName"];
tableview.datasource = dataSource;
Hoặc khi sử dụng với selector.
// ViewController.m
dataSource = [[TVArrayDataSource alloc] initWithItems:items
                                       cellIdentifier:@"MYCELL"
                                               target:self
                                     cellConfigureSel:@selector(configureCell:andItem:)];
[dataSource setCellClassName:@"CELL_CLASS_NAME"];
tableView.dataSource = dataSource;


// selector
- (void)configureCell:(CELL_CLASS_NAME *)cell andItem:(DATA_TYPE *)item
{
    [cell.title setText:item];
}


Tổng kết

Bài viết trình bày về cách tạo class datasource riêng cho tableView thay vì implement trực tiếp trong ViewController. Điều này sẽ giúp ViewController ngắn gọn hơn và code trông đẹp hơn, cũng như tăng khả năng sử dụng lại code. Chúng ta có thể dùng lại class TVArrayDataSource tại nhiều ViewController mà không cần phải implement lại các hàm delegate của TableViewDataSource. Thế nhưng hiện tại class này chỉ dùng cho những tableview có 1 section.
Toàn bộ code của class này cũng như sample bạn có thể tham khảo tại: https://github.com/ktmt/TVDataSource
Hoặc để sử dụng class này bạn có thể cài qua coccoapod bằng cách thêm pod 'TVArrayDataSource' vào Podfile.
Bài viết lấy từ : nghialv.com

Work with vanilla UICollectionViewCell

Problem

Sometimes, you'll work with a very big UICollectionView, ex: A cell contains a UICollectionView, a cell contains a UITableView, a cell contains a bundle UIView and a lot of Auto Layout constraint.
Especially, in that cell contains UIImageView, when you scroll on the screen, it's laggy.

How to solve that

Determine issues

Why does it happen?
  • Rendering UIImage on UIImageView is take time.
  • Draw the Image when scrolling is take time.
  • Auto Layout is take time.
  • Draw UIImageView is take time.
  • Caching on disk is take time.
How I solve that?
  • For rendering UIImage on UIImageView, firstly, avoid use native setUIImage method or setImageWithURL of AFNetworking now. Why?. Look at SDWebImage and see what happen :)
  • For drawing the Image when scrolling, use below method when setup cell.
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
  • For Auto Layout, it is a problem on iOS 8, make the cell have auto layout scroll very laggy. So this is solution: Override 1 method in UICollectionViewCell class.
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
{
    return layoutAttributes;
}
  • For the problem of UIImageView, some properties of it will decrease the performance, ex: clipToBounds
  • Writting and Reading on Disk is taked more time than Memory, therefore, take care when working with Caching.
Sourcec: http://kipalog.com/posts/ARyQ1xPVy2CG6coH711lFg

Tuesday, January 20, 2015

Android case study: placeholder image and memory consumption

I’m trying to optimize and lower memory footprint of an android app, and increase performance by doing that. If you want to see what’s been using up your memory you can use Eclipse MAT - Memory Analyzer Tool. You can plug it in to your Eclipse or use it as a standalone app, it’s easy to use but also have a lot of advanced options. I’ll talk about the tool itself some other time, today I’ll present a case study in which I’ve used it.

Analyzing memory consumption I saw that ImageDownloader, from internal mini framework, holds up a reference to a Bitmap object taking 2 840 000 bytes – 2.7MB on the heap. Instance of this class is an image downloader after all, so it’s not strange to hold large bitmaps but not the class itself. This class have several static bitmaps used as placeholder until actual image is downloaded. It’s clear that placeholder should not be this size so I had to investigate why this was the case.

Lets say you have a placeholder.png in yours /res/drawable folder, and its size is  500×350 px. When you load this image to a Bitmap object in memory it could take 2 800 000 bytes, ~2.67MB. How is that possible when its only 24 509 bytes ~25KB on a filesystem? What’s with all the diffrence?



First of all, image can not take as little in memory as on disk, since its compressed on the disc with png or jpeg compression. This can not be the case in memory and Bitmap has color and transparency data for each and every pixel. Once we know that, it’s easy to see how much this image should take in memory: Total pixel count is 500 x 350, we need 4 bytes per pixel (one for alpha and three colors) so that is 500 x 350 x 4 = 700 000 bytes, ~683KB.

So, image is taking 2 800 000 bytes in memory and it should take 700 000 bytes. we see at once that the difference is exactly 4x. On some other phone it could take 1 400 000 bytes or even an expected 700 000 bytes. This has to do with pixel density of your screen, is your phone ldpi, mdpi, hdpi ili xhdpi configuration. If we know that the phone in question is xhdpi the problem is becoming evident.
The issue here is that the image is in /res/drawable folder. When xhdpi phone needs an image it will look in the /res/drawable-xhdpi folder first, and if it can not find it, eventually it will load from /res/drawable folder but scale it by factor of 2! (ratio ldpi : mdpi : hdpi : xhdpi is 0.75 : 1 : 1.5 : 2 ). Does this explains why our placeholder is holding 4x memory it should? Yes, and perfectly. Image is now actually 1000 x 700px, and thats 1000 x 700 x 4 = 2 800 000 bytes.

By simply moving a image file to /res/drawable-xhdpi bitmap memory consumption will lower to expected 700 000 bytes.

So we fixed this one, but there’s no need to stop here since obviously we can lower still memory consumption for a placeholder image. You can split in half memory consumption per bitmap with one simple trick by asking OS to describe a bitmap not with 4 bytes but with 2. This is not free off course, you’ll have somewhat lesser quality but for a placeholder we can certainly live with that. How is this done: BitmapFactory decode… methods take a Options parameter by which you can configure the decoding process. One of the options is inPrefferedConfig that can take a value of Bitmap.Config.ARGB_8888 (one byte for alpha channel and one per color – red, green, blue) but also can take a value of Bitmap.Config.RGB_565 (5 bits, 6 bits and 5 bits respectively for red, green and blue)

Now every pixel will take up 2 bytes so the whole image will take up 500 x 350 x 2 = 350 000 bytes, one half of previous size.

We could go on, this resolution is probably too high for a placeholder anyway. Or we could convert it to 9patch. This modification will take us to 100KB for this bitmap and that’s a  28x difference :)
Be Sociable, Share!

Sunday, January 4, 2015

Xây dựng Kế hoạch Kinh doanh – P2: Khi nào?

Bài trước tui viết được cái mục lục xong thì bị tư bản rượt đến mãi hôm nay mới tạm xong hết việc, dự định là sẽ viết tiếp loạt bài kế hoạch kinh doanh. Nhưng chợt nhớ từ sau khi viết bài đầu, tui nhận được rất nhiều email gửi về chia sẻ những dự định, kế hoạch làm riêng. Và đặc biệt có một số bạn hỏi tôi là khi nào là thời điểm tốt nhất để thành lập công ty, hoặc cần những yếu tố gì để có thể đảm bảo kinh doanh sẽ thành công.
Xin trả lời ngay là tui cũng không biết và không dám nói cái nào kinh doanh thì sẽ bảo đảm thành công (nếu biết chắc thì tui làm rồi :-D ) do đó tui không dám làm thầy dùi xúi dại. Có một điểm tui nghĩ là tui trả lời được phần nào, đó là khi nào thì thích hợp để mở công ty hoặc đâu là những yếu tố cần có khi quyết định mở công ty. Do đó bài này tui viết thêm tí về cái quan trọng này.
Khi quyết định thành lập công ty nghĩa là ta quyết định tự làm chủ, tự kinh doanh, tự định đoạt đời mình… Đó là câu trả lời thường nhận được của đại đa số các “giám đốc” vừa thành lập công ty, nhưng sâu xa hơn mỗi người đều có mục đích riêng của mình. Sau khi vắt óc, tui chủ quan chia ra thành những nhóm sau:
  1. Nhóm thành lập công ty theo kiểu điếc không sợ súng, quá nhiều nhiệt huyết, quá nhiều mơ ước sẽ trở thành một Steve Jobs hay Bill Gates (nhưng lại thiếu kinh nghiệm).
  2. Nhóm thích có danh thiếp ghi là Giám Đốc nhưng nộp đơn vô vị trí này mãi không ai thuê nên quyết định thành lập công ty riêng để tự làm Giám Đốc.
  3. Nhóm thành lập công ty vì đã có sẵn đầu ra, có khách hàng, có dự án, họ mở công ty vì cần một tư cách pháp nhân của công ty để tiện làm việc.
  4. Nhóm thành lập công ty với hy vọng sẽ trở nên giàu có (nhóm này khác nhóm 3 là chưa biết sẽ làm gì để giàu, chỉ đơn giản nghĩ là làm giám đốc thì sẽ giàu).
  5. Nhóm đam mê kinh doanh, thích công việc kinh doanh, điều hành quản lý và có năng lực thực sự những việc đó.
  6. Nhóm nhìn ra được một cơ hội kinh doanh nào đó, có niềm tin là nó có thể kinh doanh và mang lại lợi nhuận và toàn tâm toàn ý muốn biến ý tưởng đó thành hiện thực.
Trong những nhóm trên, ta hãy cùng lướt qua nhóm nào nên thành lập công ty để ra làm riêng.
Nhóm 1: Nhiều người thường khuyên nhóm này không nên thành lập công ty, nhưng theo tui, nếu họ quá nhiều nhiệt huyết, quá nhiều đam mê thì tui nghĩ cũng nên lập công ty cho biết, 90% chúng ta sẽ gặt hái được một cái rất giá trị đó là… thất bại. Đừng nghĩ tôi châm biếm, vì thất bại xét theo một nghĩa nào đó rất có ích cho sức khỏe, nó giúp chúng ta về sau bớt điếc và bắt đầu biết sợ súng. 10% còn lại là bi kịch, đó là lỡ xui mà nhóm này thành công ngay từ những dự án đầu thì sẽ rất bi kịch, họ sẽ bắt đầu thăng hoa lên tầm mức hoang tưởng, nghĩ mình đang trên đường thành thiên tài bất khả chiến bại và từ đó sẽ dẫn họ đến những vấn đề trầm trọng hơn. Lúc này bệnh sẽ khó chữa hơn bình thường.
Nhóm 2: Nhóm này là nhóm không nên thành lập công ty nhất. Tuy nhiên, nếu quá thích cái danh thiếp và có dư chút đỉnh tiền (để thủ tục thành lập công ty, khoảng 5 triệu hoặc trên dưới đôi chút) + có một khoảng thu ổn định nào đó (để trả cho kế toán báo cáo thuế hàng tháng – đừng lo, báo cáo này thường không phức tạp vì tình hình kinh doanh đa phần là tất cả bằng không, không chi không thu). Và sau đó thật tuyệt vời!!! Bạn đã là Giám Đốc! Xin chúc mừng!
Nhóm 3 nên mở công ty, Bill Gates cũng thành lập Microsoft theo kiểu này (nhưng nhớ là Bill Gates không phải người thường). Nhóm này, khi mở công ty họ sẽ kinh doanh có lãi thời gian đầu, thậm chí có thể giàu… Nhưng trừ khi họ thật sự yêu công việc đó, giữ vững được đam mê, giữ vững được chất lượng dịch vụ/sản phẩm để có thể tiếp tục dự án hoặc công việc đang làm. Còn đa phần sau khi xong/hết dự án, công ty cũng sẽ đến giai đoạn khó khăn là không biết làm gì tiếp theo hoặc giải thể. Tóm lại là nhóm này có khả năng thu được lợi nhuận cao, nhưng để biến nó thành thành công lớn và mang tính lâu dài thì ta cần phải thêm nhiều yếu tố nữa.
Nhóm 4 – thích giàu :X Nhóm này nên mua vé số, đánh đề, cờ cá ngựa, cờ tướng, cờ vua gì đó… hoặc lấy chồng giàu (nếu là nữ và có nhan sắc) hoặc làm gì đó cũng được nhưng đừng mở công ty. Vì đa phần trường hợp cả một thời gian dài ban đầu bạn sẽ sống vô cùng khó khăn, tất cả vốn liến, nhà cửa, xe cộ… đều dồn vào công ty. Tiền lương nhân viên, chi phí hoạt động, văn phòng và hàng tỉ chi phí khác, tháng nào kết toán huề vốn hoặc dư ra được chút đỉnh là mừng hết lớn, và cái khoản dư ra chút đỉnh này thường chẳng thấm vào đâu nếu chúng ta đi làm thuê.
Nhóm 5 nghe có vẻ rất thích hợp để mở công ty riêng, nhưng cũng không nên. Vì nhóm này chỉ thích kinh doanh và kinh doanh giỏi. Nhóm này nên tiếp tục đi làm thuê vì đi làm thuê vẫn được thỏa mãn máu kinh doanh, quản lý của mình, được ở trong những môi trường chuyên nghiệp (giúp cho khả năng của mình ngày càng tốt hơn), được làm những dự án lớn, được tiếp xúc với những khách hàng tầm cỡ, được thu nhập ổn định… Nói chung là đi làm thuê thì nhóm này có tất cả những gì mà họ cần, thế hà cớ gì phải sân si? Đó là lý do tui vẫn đi làm thuê (tui giống nhóm này ở chỗ đang đi làm quản lý thuê, còn giỏi hay không thì phải đợi TGĐ của tui đánh giá).
Nhóm 6 nghe có vẻ như là nhóm thích hợp nhất để mở công ty. Nhóm này có tầm nhìn, có sự nhạy bén, có chuyên môn, có một ước mơ cháy bỏng về kinh doanh và khẳng định mình. Nhưng nhóm này vẫn chỉ mới có điều kiện cần chứ chưa có điều kiện đủ. Nhóm này nếu nhìn ra được mọi thứ nhưng không có khả năng biến những cái tầm nhìn ấy thành hiện thực (tố chất của nhóm 5) thì ngoại trừ trường hợp bỏ tiền về thuê nhóm (5) làm việc cho mình, còn không thì cũng rất khó thành công.
Đọc đến đây bạn sẽ hỏi: Này, cái nào cũng không, vậy khi nào thì mới đủ điều kiện để thành lập công ty?
Câu trả lời là khi có đủ tất cả những yếu tố trên (trừ cái số 2, cái đó không quan trọng).
Nghe có vẻ ba phải nhưng thật ra điều đó chính xác. Khi bạn thấy được một hướng kinh doanh mà bạn tin là sẽ hiệu quả (6), bạn có năng lực về quản lý, đam mê kinh doanh (5) bạn có một đầu ra căn bản ban đầu (3), bạn có ước mơ làm giàu chính đáng, tạo công ăn việc làm cho mình và những xung quanh (4), bạn có thật nhiều đam mê (với kinh doanh và với lĩnh vực mà mình kinh doanh) và bạn cũng có một chút máu liều (1). Khi tất cả những câu trả lời cho các câu hỏi trên đều là thì đó là thời điểm chúng ta sẵn sàng cho việc bắt đầu một doanh nghiệp riêng của mình.
Và hãy luôn luôn chuẩn bị tinh thần rằng đây không phải là con đường nhàn hạ, bạn sẽ cày mười mấy tiếng mỗi ngày, lảo đảo bước ra khỏi công ty bạn sẽ đi ăn vất vưởng đâu đó, trong lúc ăn bạn vẫn tiếp tục suy nghĩ về những việc còn dang dở, về nhà bạn tiếp tục làm việc và bạn đi ngủ với giấc ngủ chập chờn với những vấn đề về chi phí, khách hàng, dự án… Tất cả những điều đó để đổi lấy một thu nhập rẻ bèo hàng tháng (thường là thấp hơn nhiều so với khi ta làm tất cả những việc đó lúc đi làm thuê), tệ hơn bạn có thể chẳng có đồng thu nhập nào hoặc thậm chí phải vay mượn để bù vào chi phí.

Thế chúng ta được gì khi thành lập công ty?

Tất cả những cái “bị” bên trên cũng chính là cái chúng ta “được” và nếu chúng ta may mắn đứng về phía % những công ty vượt qua được thời gian khó khăn ban đầu, thì sẽ đến một ngày nào đó chúng ta xây dựng được một doanh nghiệp ổn định, thu nhập chúng ta dần cao lên, công việc chúng ta dần đi vào quỹ đạo. Và khi về già chúng ta tự hào kể với con cháu rằng chúng ta đã dám tách ra khỏi đám đông để bước đi con đường chông gai.
Đơn giản chỉ có thế, chúng ta sẽ mất rất nhiều để được những cái giản dị như vậy. Giàu có, danh vọng vẫn là những khái niệm không nên nằm trong kế hoạch của những cái “được”. Vì vậy một lần nữa, các bạn nhóm (2) thích danh thiếp: đừng thành lập công ty. Hoặc nếu có thì nhớ xác định rõ ràng: chi phí 5 triệu nhờ dịch vụ thành lập công ty + mỗi tháng một ít tiền để thuê kế toán + mỗi năm ít tiền để đóng vài loại thuế (nhớ đừng bán hóa đơn, cái đó phạm pháp). Các bạn nhóm (3) thích giàu: nên mua vé số hoặc lấy chồng (phải đẹp, nếu không đẹp thì cũng đừng tuyệt vọng, vẫn còn cơ hội lấy chồng nước ngoài vì đôi khi quan điểm thẩm mỹ của bọn Tây rất khác).
PS: Nếu bạn thắc mắc thế tui là kiểu gì: Tui có thời từng ở nhóm 1 (nhóm điếc không sợ súng) và thật may mắn và hạnh phúc cho tui, tui được thất bại. Thất bại đó giúp tui bây giờ biết sợ súng, lựu đạn và các loại bom mìn. Còn hiện tại thì tui vẫn đang tham tiền, nhát gan chưa dám bước chân vào chông gai, nên đến giờ tui vẫn đang chỉ đi làm thuê, kiếm tiền về cho tư bản.
Nguồn: Apo Blog

Xây dựng kế hoạch kinh doanh – Phần 1

Bạn tui làm cho một công ty truyền thông, chẳng biết không may ăn ở thế nào nên năm nay phải cưới vợ. Nhìn hắn chạy đôn chạy đáo đến tội nghiệp, nào đi đặt tiệc, nào in thiệp, nào lên lịch chụp hình cưới – mà chụp gần không chịu, đi tận Côn Đảo chụp (chắc có dụng ý gì), xong rồi “đú đởn” không thích đám cưới giống người khác, thế là phải xây dựng kịch bản cho chương trình đêm tiệc… ôi thôi không biết bao nhiêu là việc. Rồi hôm rồi đi uống cà phê với người bạn, nói chuyện chưa được dăm ba câu thì hắn rủ đi mua… mỹ phẩm!!! Hỏi mua làm gì thì nó bảo mua để tặng cô bạn đang muốn nâng cấp lên thành người yêu, chẳng hiểu sao thấy thằng bên trên chết rồi mà thằng này vẫn lao đầu theo???
Nhưng vấn đề ở đây tui không muốn bàn sâu đến những việc dại dột ấy, mà là tui muốn nêu bật cái sự quan trọng của việc lên kế hoạch. Mọi người thấy rõ là đến cả những việc vớ vẩn như lấy vợ hay hẹn hò nhăng nhít với phụ nữ mà người ta còn phải lên kế hoạch thì tôi thật không hiểu vì sao vẫn có một số người hăng hái xách tiền lập công ty TNHH nhưng khi tui hỏi thế kế hoạch kinh doanh thế nào thì vô tư bảo “làm thủ tục xong rồi mấy anh em sẽ họp lại với nhau để bàn”, hoặc khi hỏi định vị khách hàng ra sao thì bảo “tất cả phụ nữ”, hoặc hôm nào may mắn đẹp trời thì có người “phụ nữ văn phòng có thu nhập ổn định” (vẫn còn rất chung chung). Chả trách vì sao mà số lượng công ty đăng “cáo phó” giải thể công ty cũng đông không kém số lượng đăng “cáo phó” thành lập công ty.
Hôm nay sáng cuối tuần đẹp trời, tui xách laptop vô một ngôi chùa rất mát ở quận 9 – nơi này ngày xưa tui thường hay đạp xe đến để học bài thi. Cảnh chùa thanh tịnh, tâm hồn chùng xuống làm tôi thấy thương xót cho những kẻ bên trên, những kẻ cưới vợ và cả những kẻ lập công ty không có kế hoạch kinh doanh. Nên quyết định lấy laptop ra viết bài này, chia sẻ đôi chút kinh nghiệm về cơ bản của một kế hoạch kinh doanh. Hy vọng giúp ích được chi đó cho nước nhà giảm thiểu số lượng “cáo phó” giải thể công ty trên báo.
Bài này tui viết tập trung nói về việc xây dựng một kế hoạch kinh doanh cơ bản nhất, không phải là xây dựng một doanh nghiệp hoành tráng, với những trường hợp cần hoành tráng thì tốt nhất lên tìm một bạn CEO tốt nghiệp MBA ở Tây Tàu gì đó (hay Việt Nam cũng được, nhưng nơi nào học phí cao cao tí), thuê về để các bạn ấy làm, chúng ta làm chủ đầu tư đi đánh “gốp” cho sướng thân.
Kế hoạch kinh doanh nôm na giống như bản hiến pháp của một nước, nó quy định khái quát nhưng rõ ràng, cụ thể hướng đi của doanh nghiệp. Mọi cái kế hoạch sau này đều sẽ dựa trên cái kim chỉ nan này mà phát triển ra. Vì là cơ bản nên tui chia KHKD ra làm 2 loại, lại đầu là dành cho những bạn có ý tưởng về một sản phẩm hay ho nào đó, nhưng không đủ tiền để làm, cần có nhà đầu tư, kế hoạch này đòi hỏi phải chứng minh thêm cái phần về năng lực của đội ngũ quản trị, chia sẻ lợi nhuận và những phương án rút vốn đầu tư… Loại 2 là loại dành cho những người muốn tự mình làm, không cần xin xỏ ai, có bao nhiêu xài bấy nhiêu. KHKD loại này có thể rút tỉa bớt những phần bên trên, tất nhiên nếu có điều kiện thì nên làm đầy đủ, đừng tỉa. Trong bài này tui nói trước về loại kế hoạch đã tỉa bớt, nếu thấy mọi người hứng thú muốn viết cho đủ luôn thì tui sẽ viết tiếp những phần sau.

Khung sườn

Làm gì cũng vậy, chúng ta cần cái khung sườn, rồi từ đó triển khai rộng ra, chi tiết dần. Làm như vầy sẽ giúp chúng ta không bị lạc hướng và bao quát được đầy đủ nhiều mặt của vấn đề. Về cơ bản, một kế hoạch kinh doanh cần có những phần sau:
  1. Giới thiệu tổng quát.
  2. Phân tích thị trường.
  3. Sản phẩm/dịch vụ cung cấp.
  4. Định vị khách hàng.
  5. Phân tích đối thủ.
  6. Chiến lược Sales/Marketing.
  7. Chiến lược giá.
  8. Nguồn nhân lực.
  9. Kế hoạch tài chính.
  10. Phân tích rủi ro.
  11. Kế hoạch triển khai.
Bài này tui phân tích khái quát mục đích từng phần về từng phần, trong những bài sau tui sẽ nói chi tiết hơn từng cái.
1. Giới thiệu tổng quát: phần này để giúp người đọc có cái nhìn tổng quát về toàn bộ kế hoạch kinh doanh.
2. Phân tích thị trường: thị trường là ở đâu, đang cần gì, tiềm năng của thị trường thế nào, vì sao chúng ta cho rằng đó là một thị trường có thể mang lại lợi nhuận.
3. Sản phẩm/dịch vụ: chi tiết về những gì chúng ta đưa cho khách hàng, cấu tạo sản phẩm thế nào, làm thế nào để chế tạo, có điểm độc đáo gì…
4. Định vị khách hàng: cái này khá quan trọng, khách hàng là ai, mối quan tâm của họ thế nào, thu nhập ra sao, vì sao họ lại là khách hàng mục tiêu…
5. Phân tích đối thủ: hên thì chúng ta chui vô cái đại dương xanh, nhưng giờ mấy cái đó hơi bị hiếm, nên rủi chui vào đại dương đỏ thì đối thủ chính là ai, vì sao họ lại thành công, điểm yếu là gì, đối thủ gián tiếp là gì…
6. Chiến lược sales và marketing: cái này chắc không phải giải thích rồi, tui sẽ nói chi tiết hơn khi phân tích tới phần này.
7. Chiến lược giá: một trong 4 cái P, cách định giá thế nào, vì sao định giá như vậy, giá sẽ được thay đổi ra sao, trong tình huống nào…
8. Nguồn nhân lực: không ai làm việc gì một mình cả, nên phải tính tới việc cần những ai, tìm người ở đâu, đào tạo người thế nào, chính sách với người thế nào để người không bỏ ta…
9. Kế hoạch tài chính: tiền, tiền tiền! Xài tiền thế nào, mượn tiền ở đâu,… đại khái là kiếm tiền thế nào và dùng tiền ra sao.
10. Phân tích rủi ro: không ai làm gì mà không có rủi ro cả, phân tích cái này càng kỹ thì càng giúp ta dễ dàng tránh được mấy cái rủi ro này, hoặc ít nhất cũng giúp ta đỡ bị… shock :-D
11. Kế hoạch triển khai: đại khái là khi nào thì làm cái nào, sẽ đạt được cái nào…
Như đã nói, đây là kế hoạch viết chủ yếu tập trung dùng cho trường hợp tự có vốn đầu tư, kế hoạch dùng để đi dụ kêu gọi nhà đầu tư góp vốn sẽ được viết sau nếu người đọc hứng thú. Kế hoạch của tui là sẽ phân tích khái quát 11 điểm trên, tuy nhiên nói gì thì nói, cho đến nay tui vẫn đi làm mọi cho tư bản, vẫn chưa dám dũng cảm nộp đơn xin nghỉ việc để xách tiền đi đầu tư làm riêng. Do đó hy vọng sẽ nhận được sự đóng góp của bạn bè gần xa.
Một lần nữa cũng xin phép nhắc lại, vì tui làm cho tư bản nên dùng tiếng tư bản là đa số, và những dự án mà tui lập cho tư bản cũng viết bằng tiếng tư bản. Nên trong một số trường hợp tui sẽ dùng từ tiếng Anh, không dịch ra tiếng Việt vì đôi khi dịch ra rất buồn cười hoặc không dịch được. Và như tinh thần từ đầu, tui sẽ viết theo kiểu phong cách tưng tửng, hy vọng không gây khó chịu cho người đọc nghiêm túc.
Nguồn: Apo Blog