NỘI DUNG I) LỚI GIỚI THIỆU II ) HỆ THỐNG TIỀN TỆ 1. CÔNG CỤ TÀI CHÍNH 2. CÁC THIẾT CHẾ CỦA HỆ THỐNG TIỀN TỆ QUỐC TẾ 3. HỆ THỐNG ĐIỀU CHỈNH III) CÁC HÌNH THỨC CHUYỂN DỊCH TÀI CHÍNH QUỐC TẾ 1. ĐẦU TƯ LIÊN QUỐC GIA 2. CHUYỂN DỊCH QUA HỆ THỐNG THANH TOÁN VÀ MUA BÁN NGOẠI HỐI 3. CHUYỂN DỊCH TÀI CHÍNH LIÊN NGÂN HÀNG IV) NỢ TÀI CHÍNH QUỐC TẾ VÀ VAI TRÒ CỦA CÂU LẠC BỘ LONDON-PARIS V) KẾT LUẬN VI) TÀI LIỆU THAM KHẢO
=========================================
I. GIỚI THIỆU Khi nghiên cứu về tài chính và tiền tệ, người nghiên cứu bắt buộc phải tìm hiểu Tài Chính Quốc Tế, hệ thống tiền tệ và hình thức chuyển dịch tài chính quốc tế là những căn bản trong nghiên cứu tài chính quốc tế, nó cung cấp cho người đọc về hệ thống các công cụ về tài chính quốc tế để các tổ chức, chính quyền thực hiện chuyển dịch và trao đổi tài chính quốc tế. Hệ thống tiền tệ và tài chính quốc tế cho ta thấy các công cụ tài chính, các thiết chế, và hệ thống điều chỉnh sự vận động và sử dụng luồng tài chính quốc tế. Ngày nay chuyển dịch tài chính cấp quốc tế không còn đơn thuần thể hiện bởi sự di chuyển công cụ tài chính như ngoại tệ, trái phiếu, SDR ….Từ chủ thể nầy sang chủ thể khác mà dần sang hình thức không công cụ. Ví dụ như kết toán bù trừ liên ngân hàng quốc tế, vay mượn và thanh toán qua mạng, cho vay dự trữ hoặc cho vay ngoại tệ qua đêm giữa các tổ chức tài chính quốc tế… Nếu phân loại theo chủ thể tham gia ta thấy có ba hình thức chuyển dịch tài chính quốc tế đó là: chuyển dịch đa phương, chuyển dịch song phương, chuyển dịch không đối tác (chuyển dịch nội bộ). Nếu phân loại theo cách thức duy chuyển ta có bốn hình thức chuyển dịch phổ biến đó là:
II. HỆ THỐNG TIỀN TỆ Hệ thống tiền tệ và tài chính quốc tế là hệ thống các công cụ về tài chính quốc tế để các tổ chức chuyển dịch và trao đổi tài chính quốc tế. Hệ thống nầy có những thành tố sau
Có 2 dạng Tiền tệ và công cụ khác tiền: Tiền Quốc tế có thể là vàng, kim loại quý và các hình thức trái phiếu a/ Vàng:
Hệ thống tỉ giá trao đổi cố định (Bretton Woods)
Sau hệ thống tỉ giá cố định sụp đổ mỗi quốc gia đều có quyền chọn một chế độ tỉ giá riêng thích hợp cho mình, Nhằm thúc đẩy hỗ trợ những thanh toán quốc tế IMF đã tạo ra thêm một loại trái phiếu của nó như một loại tiền tệ bổ sung cho hệ thống tiền tệ với hệ thống thả nổi SDR Là một công cụ tài chính toàn cầu, loại trái phiếu nầy có giá trị được tạo thành từ giá trị đóng góp của 5 đồng tiền (theo nguyên lý rổ tiền tệ) USD, Mark,Yen, Pound, Franc. Giá trị của SDR được IMF tính hàng ngày theo nguyên tắc rổ tiền giữa giá trị USD với 4 đơn vị tiền còn lại theo tỷ giá tại thời điểm tính. ECU
Đồng USD: là một công cụ tài chính quốc tế và dự trữ quan trọng nhất vì
Các đơn vị tiền của các nước phát triển: Trong khối OECD là các nước có nền kinh tế mạnh, thương mại các nước này chiếm 80% giao dịch toàn cầu do vậy phần còn lại của thế giới vẫn có nhu cầu sử dụng đồng tiền nầy để thực hiện một số giao dịch quốc tế, ngoài ra một số nước có lãnh thổ và tỉ trọng thương mại lớn như Trung Quốc, Ấn Độ, Đài Loan cũng có cũng có đóng góp vào công cụ tài chính quốc tế. 2) Các thiết chế của hệ thống tiền tệ thế giới Nếu ta phân loại có 2 nhóm là: Các thiết chế tài chính thông thường và các tổ chức tài chính quốc tế đầu não. a/ Các thiết chế tài chính thông thường gồm:
Thị trường tiền tệ Châu Âu: Thị trường nầy phát triển nhanh do các nguyên nhân sau đây
Là một tổ chức tài chính điển hình, tổ chức nầy là một tập đòan gồm 3 thiết chế khác phụ thuộc là:
Hoạt động chính của ngân hàng thế giới là:
Là thành viên của ngân hàng thế giới nhưng cung cấp các khỏan vay mềm là các khoản vay có thời gian đáo hạn 40 năm và gia hạn nợ là 10 năm. Tính chất của tổ chức nầy là nó huy động tài chính từ các nước phát triển cho các nướ kém phat triển vay rồi chấp nhận thanh toán bằng tiền chuyển đổi kém do vây nó làm quốc tế hoá đồng tiền, tạo dòng chảy tài chính từ nước giàu sang nước nghèo và ngược lại. IMF (Quỹ Tiền tệ Quốc tế)
Ngân hàng phát triển châu A (ADB). 3) Hệ thống điều chỉnh: a) Hệ thống điều chỉnh nó điều chỉnh luồng vận động của tài chính quốc tế nó bao gồm
Những thoả thuận và điều khỏan ràng buộc là hệ thống điều chỉnh hoạt động tài chính quốc tế, tạo thị trường tài chí`nh quốc tế hoạt động trong luật, tạo khung cho hoạt động thống nhất của thị trường toàn cầu. d) IBF Không những là một ngân hàng mà còn là một cơ chế quản lý điều tiết và theo dõi của Fed đối với các khỏan cho vay và chuyển dịch tài chính ra nước ngoài của các ngân hàng thương mại Mỹ. Giữa những năm 1980 IBF quản lý quỹ viện trợ kỹ thuật của Hoa-Kỳ cho các nước phát triển, những ràng buộc của IBF là bộ lọc làm tăng giảm tốc độ chuyển dịch tài chính ở phạm vịquốc tế dưới nhiều hình thức khác nhau. e) Điều chỉnh bằng lãi suất thả nổi và hợp tác quốc tế về chính sách tiền tệ
III. CÁC HÌNH THỨC CHUYỂN DỊCH TÀI CHÍNH QUỐC TẾ; Nếu phân loại theo chủ thể tham gia ta có: chuyển dịch đa phương, chuyển dịch song phương và chuyển dịch không đối tác. Phân loại theo cách thức di chuyển ta có đầu tư lien quốc gia, Thanh toán và mua bán ngoại hối, tài chính thương mại quốc tế và chuyển dịch tài chính của khu vực chính quyền. 1. Đầu tư liên Quốc gia: Đầu tư trực tiếp, đầu tư trực tiếp bởi xuất khẩu lao động và đầu tư gián tiếp a) Đầu tư trực tiếp: FDI
Ảnh hưởng của FDI: ta phân tích giữa hai nước có quan hệ đầu tư và không có quan hệ đầu tư: (theo hình vẽ sau) Giả sử nước đầu tư là A nước chủ nhà là B Tổng tư bản 2 nước là đường O O1 Tử bản của nước A là OZ, tư bản của nước chủ nhà B là O1 Z. Trường hợp 1: chưa đầu tư Tại quốc gia A ứng cới mức lợi tức R.a nội địa, nước A sử dũng hết nguồnvốn mức lợi tức sẽ ltại E1 , tức là R.a, đường Ka cho biêế nó là đường giá trị cận biên của vốn tại nước A. Tại B ở mức lợi tức rb cao hơn vì vốn khan hiếm, đướng giá trị sản phẩm biên của vốn là Kb đi qua điểm E2
Trường hợp 2: khi tư bản tự do duy chuyển tài chính từ A sang B tìm lợi nhuận cao hơn (dưới hình thức FDI). Quá trình chuyển vốn từ A sang B làm cho vốn của nướa lùi dần về O, ngược lại vốn của nước B tăng dần qua mức O1.Z. Giảm vốn nước A làm lãi súât tăng và tăng vốn ờ B làm lãi suất giảm cho đến khi lãi suất 2 nước bằng nhau, lượng vốn từ A qua B là đoạn VZ.Cả 2 nước sản xuất tại E và mức lợi tức R1.R2. Sản lượng thế giới tăng E. E1. E2 trong đó nước nhận đầu tư (B) là E .E2.U và nước đầu tư (A) là E. E1 U Từ mô hình trên ta kết luận rằng Tự do di chuyển tài chính quốc tế làm tăng sản lượng và thu nhập cho tất cả các bên tham gia. b) Đầu tư theo danh mục: Là đầu tư thuần tuý vào tài sản tài chính như cổ phiếu trái phiếu, loại đầu tư nầy có thể thực hiện qua nhiều loại tiền tệ khác nhau.Với trái phiếu nhà đầu tư chỉ thuần tuý chỉ cho vay và nhận một khỏan lợi tức. cổ phiếu nhà đầu tư bỏ vốn ngoài kỳ vọng kiếm lời còn có quyền sở hữu công ty. Đầu tư theo danh mục có đặc điểm là dòng tài chính quốc tế chảy về những khu vực có lợi ích kinh tế cao. 2.. chuyển dịch tài chính quốc tế qua thanh toán và mua bán ngoại hối. a. Thị trường ngoại hối:
Thị trường ngoại hối cố định tỉ giá: (ta có 2 sơ đồ sau) Trong thế giới thị trường ngoại hối cố định về tỉ giá (1944-1973) cơ chế vận nành của nó có những nét đặt trung riêng, Giả sử tỉ giá được cố định tại E. Nếu cầu tăng lên D1 (đồ thị a) để ổn định lãi suất tại E các tổ chức quản lý tài chính nội địa sẽ phải tăng cung lên q2 theo nhu cầu. Ngược lại lương cung tăng S1 (đồ thị b). Để tỉ giá ổn định tại E các tổ chức tài chính phải làm ngược lại là mua hết lương cung tăng Q0.Q2. Thị trường tỉ giá hoấi đoái thả nổi: tỉ giá sẽ do thị trường quyết định B. Chuyển dịch tài chính qua thị trường ngoại hối: Ta có: Y = C + I + G + X - M Hay Y – C = I + G +X - M Mà Y – T= Yd và Yd = C + S Suy ra Y-T = C + S hay Y –C = S + T Như vậy I + G +X – M = S + T Suy ra I – S – (T-G) =M –X Ta đặt (T-G) là tiết kiệm trong khu vực chính quyền ta viết tắc là Sg Ta có I – (S + Sg) = M-X Ta đặt M-X là tiết kiệm từ giao dịch với nước ngoài ta viết tắc là Sf Ta có I – (S + Sg) = Sf Công thức trên cho chúng ta thấy khi thiếu hụt về tiết kiệm trong nước sẽ tạo ra nhu cầu bồi đắp bởi các luồng chảy vào của tiết kiệm nước ngoài và ngược lại. Chuyển dịch tài chính qua thị trường ngoại hối nằm dưới một trong các hình thức sau
a) Khái niệm: Nợ tài chính quốc tế là sự xuất hiện và gia tăng của các khỏan phải trả định kỳ cho nước ngoài bao gồm chi phí phát sinh b) Vai trò của câu lạc bộ các nhà tài chính London và Paris Câu lạc bộ các nhà tài chính London và Paris là những đạo diễn chính trong việc tái cấu trúc lại nợ tài chính nhằm chống khủng hoảng. Câu lạc bộ Pari là một nhóm các nước chủ nợ trong đó chủ yếu là Mỹ và các nước G7, nó là một tổ chức không chính thức, không có luật lệ hay cơ cấu vật chất. Bộ ngân khố cung cấp một số nhân viên, Thư ký…. Những người nầy sẽ triệu tập các nước chủ nợ lien quan khi mà một nước con nợ thông báo rằng đang ở tình trạng nguy kịch. Mục đích của mỗi kỳ họp Paris Club không hoàn toàn nhằm ban tăng tặng một ân hạn cho con nợ mà nhằm xây dựng một cơ sở mà trên đó chủ nợ huy vọng rằng có thể thu hồi được công nợ bằng cách kéo dài thời gian hoàn trả và cắt giảm các khỏan thanh toán hàng năm xuống tới míưc mà con nợ thanh toán được và thanh toán từ từ. Các nước con nợ trước mắt được giảm các khoản phải trả hàng năm, có khả năng thanh toán trong năm nhưng tổng số nợ tăng lên cả lãi lẫn gốc. IV. KẾT LUẬN:
ĐẠI HỌC MỞ TP HCM Lớp MBA5. Bài viết nhóm 5. MÔN : CÁC TỔ CHỨC TÀI CHÍNH QUỐC TẾ Thành viên nhóm5: 1. Võ Văn Tùng 2. Nguyễn Minh Tân 3. Đào Minh Tuyến 4. Phan Bích Lê 5. Võ Văn Cần |
Bài viết bản quyền "© SAGA, www.saga.vn," đề nghị ghi nhận rõ khi trích đăng sử dụng lại một phần hay toàn bộ bài viết |
Tuesday, June 26, 2012
Hệ thống tiền tệ và hình thức chuyển dịch tài chính quốc tế
Saturday, May 5, 2012
Khái Niệm Về Vốn Xã Hội
Trần Kiêm Đoàn
Khi nói về vốn liếng, người ta thường nghĩ ngay đến những giá trị vật chất cụ thể mà người sở hữu có thể nhìn thấy, cất giữ hay cân, đo, đong, đếm được. Những giá trị phi vật thể, đặc biệt là những giá trị tinh thần tạo nên bản sắc đặc thù của một quốc gia, một xã hội, một dòng họ hay một con người được coi như những “bẩm tính trời sinh”, bị chìm khuất sau biên cương và hào lũy truyền đời của lịch sử và văn hóa.
Từ trong nếp nghĩ theo thói quen và cảm tính, VXH thường bị xem hay được xem là một hệ thống giá trị mặc nhiên (taking for granted value system), mỗi người sinh ra là đã có nó như khí trời, thiên nhiên cây cỏ. Thật ra, nguồn vốn to lớn và quan trọng bậc nhất là Vốn Xã Hội (VXH). Trong cụm từ “Vốn Xã Hội” đã ngầm chứa hai thành tố là: Vốn (capital) + Xã Hội (social).
Vậy thì Vốn Xã Hội là gì và ai là sở hữu chủ của nguồn vốn đã bén rễ, đâm chồi nẩy lộc lâu dài và phong phú đó?
Vốn Xã Hội là một thực tại đã có chung dòng lịch sử với đất nước và con người từ thuở sơ khai. Nhưng người ta đã gọi nguồn vốn nầy theo những khái niệm và từ ngữ khác nhau.
Khái niệm về “Vốn Xã Hội” xưa nhất của người Việt Nam xuất hiện trong câu chuyện dân gian là chuyện Thằng Bờm. Giá trị của “có” (thằng Bờm) và “đổi” (phú ông) trong câu chuyện nầy căn cứ trên nguồn “vốn” thì mờ nhạt mà đậm nét nhất chính là cuộc trao đổi nặng tính chất tâm lý và xã hội giữa hai nhân vật có quan hệ mua bán và trao đổi là Phú Ông và Thằng Bờm. Cái quạt mo chỉ là biểu tượng của vật chất. Thằng Bờm mới chính là biểu tượng của xã hội và khát vọng cụ thể của con người trong xã hội đó.
Với phương Tây, khái niệm “vốn xã hội” (social capital) được Lyda Judson Hanifan, một nhà giáo dục Mỹ, nói đến lần đầu tiên năm 1916 khi ông ta bàn đến vấn đề quan hệ trong các trường ốc ở vùng thôn dã tại Bắc Mỹ. Để nói về vốn xã hội, ông xác định rằng: “ những giá trị hiện thực đó có tác dụng lên hầu hết cuộc sống hàng ngày của con người” (those tangible substance [that] count for most in the daily lives of people).
Từ đó, vấn đề vốn xã hội đã được nhắc nhở, nghiên cứu, phát triển và áp dụng một cách có hệ thống và rộng khắp trong các lĩnh vực kinh tế, giáo dục, xã hội, tâm lý… tại Mỹ, các nước phương Tây và các quốc gia kỹ nghệ trên toàn thế giới. Năm 1961, Jane Jacob phân tích và thảo luận về vốn xã hội trong mối tương quan của đời sống ở thành phố. Năm 1983, Pierre Bourdieu soạn hẳn ra một lý thuyết riêng về VXH. James S. Coleman phát triển lý thuyết thành một nội dung giáo dục về nguồn vốn xã hội. Ý tưởng nầy đã được một tổ chức tài chính lớn nhất hành tinh là Ngân Hàng Thế Giới sử dụng như một ý kiến rất hữu ích về mặt tổ chức. Ngân Hàng Thế Giới xác định rằng: “ bằng chứng mỗi ngày một nhiều chỉ rõ rằng, sự liên kết xã hội là rất thiết yếu cho các xã hội trong việc làm giàu mạnh kinh tế và cho việc phát triển tiến lên không ngừng”. (Increasing evidence shows that social cohesion is critical for societies to prosper economically and for development to be sustainable (World Bank 1999) ”.
Trong khi vốn vật chất (physical capital) nói đến các vật thể hiện hữu và vốn nhân sinh (human capital) nói đến tài sản cá nhân thì vốn xã hội nói đến liên hệ nối kết giữa những con người. Đấy là mạng lưới xã hội với những tiêu chuẩn giao dịch qua lại trong sự tin tưởng lẫn nhau và đồng thời đó cũng là đạo lý cư xử giữa người và người trong xã hội. Theo định nghĩa của Ngân Hàng Thế Giới thì vốn xã hội là những gì liên quan đến các cơ sở, các mối quan hệ và những giá trị truyền thống. Tất cả cùng hợp sức tạo nên chất lượng và số lượng của thành phẩm làm nên bởi sự tương giao hợp tác trong xã hội… Vốn xã hội không phải chỉ đơn thuần là sự tổng hợp những khối lượng vật chất của xã hội mà là chất keo làm dính chặt những khối lượng tài sản xã hội nầy lại với nhau.
Nói một cách cụ thể hơn về vốn xã hội, Cohen và Prusak (2001) định nghĩa: “Vốn xã hội bao gồm phần lớn sự hợp tác xây dựng giữa những con người với nhau: Sự tin tưởng, sự hiểu biết lẫn nhau, và sự chia sẻ những giá trị đạo đức, phong cách nối kết những thành viên trong các tập đoàn, các cộng đồng lại với nhau làm cho việc phối hợp hành động có khả năng thực hiện được”.
Như vậy, vốn xã hội chính là con người. Trong khi con người lại chính là sản phẩm của một hoàn cảnh xã hội hiện hữu và phát triển trong một hoàn cảnh kinh tế, một bối cảnh lịch sử, một truyền thống văn hóa cụ thể nào đó.
Nhìn về Vốn Xã Hội Việt Nam
Ngày 24 tháng 4 năm 2006 vừa qua, Bill Gates, chủ nhân công ty Microsoft và cũng là người giàu nhất thế giới với gia tài xấp xỉ 53 tỷ đô la Mỹ, đến thăm Việt Nam. Nhân vật nầy đã được giới trẻ Việt Nam cả nước đặc biệt quan tâm theo dõi. Đã có người tự hỏi: “Nếu Bill Gates sinh ra tại Việt Nam hay một nơi nào đó không phải là Mỹ thì liệu một ‘Bill Gates hạt giống’ có khả năng trở thành một Bill Gates thành công lẫy lừng như hôm nay không? Tuy đây chỉ là câu hỏi giả định, nhưng câu trả lời dĩ nhiên là “không!” và câu hỏi tiếp sẽ là “Tại sao?” Câu trả lời đơn giản nhất sẽ là: “Vì Mỹ khác, ta khác. Mỹ có nhiều phương tiện kinh doanh và điều kiện thuận lợi nghiên cứu kỹ thuật và tham khảo thị trường mà ta không có...” Thế thì có người lại hỏi, một nhân vật Mỹ nổi tiếng khác cũng đã đến thăm Việt Nam, cựu tổng thống Mỹ Bill Clinton, có một người em trai cùng cha khác mẹ, lớn lên trong cùng một mái ấm gia đình, suýt soát tuổi nhau là Roger Clinton lại trở thành một tay lêu lổng, bị tù tội vì ghiền xì ke, ma túy. Như vậy có hai Clintons trái ngược nhau trong cùng một hoàn cảnh. Clinton anh là vốn xã hội đáng quý và Clinton em là cục nợ xã hội đáng thương hại.
Trên đây là thí dụ cụ thể về mối tương quan và sự tác động qua lại giữa con người và hoàn cảnh. Đây là cả một sự tương tác về cả ba mặt: Vật chất, tinh thần, hoàn cảnh riêng, chung. Bởi vậy, phương pháp luận cũng như dữ kiện về các mặt nhân sinh và môi trường xã hội thường là những đối tượng rất phức tạp trong việc đo lường hay phân tích nguồn vốn xã hội.
Các nhà nghiên cứu phải lưu ý đến ba định mức của vốn xã hội: (1) Mức độ vốn xã hội vi mô (micro-level social capital), (2) mức độ vốn xã hội trung mô (Meso-level social capital), và (3) mức độ vốn xã hội vĩ mô (macro-level social capital). Ba định mức nầy liên quan đến: (1) Cá nhân, (2) gia đình, trường học, cơ quan, đoàn thể, xí nghiệp, và (3) xã hội, đất nước và toàn cầu. Mối liên hệ hữu cơ là: (1) Nếu cá nhân không được chuẩn bị kỹ càng; (2) nếu nghiệp vụ không được đào tạo, huấn luyện nghiêm túc; (3) kết quả sẽ tạo ra là những thành viên xã hội có chất lượng nghèo nàn và hệ quả tất yếu là sẽ làm cho nguồn vốn xã hội suy thoái hay khánh tận.
Công trình nghiên cứu về vốn xã hội gần đây nhất của Robert D. Putnam (1993; 2000) nhấn mạnh về sự hợp tác hai chiều và nhiều chiều của các thành viên trong xã hội. Ông cho rằng sự hợp tác và chia sẻ giữa các thành viên xã hội với nhau là yếu tố quan trọng hàng đầu trong việc xây dựng vốn xã hội. Từ đó, Putnam cũng báo động nguy cơ về sự xuống dốc của nguồn vốn xã hội tại Mỹ. Nguyên nhân chính là vì chủ nghĩa cá nhân (individualism) ngày một chiếm thế mạnh và trẻ em chỉ sống với cha hay mẹ một mình do tình trạng ly dị gia tăng làm cho tinh thần hợp tác xã hội yếu dần.
Nhìn lại vốn xã hội Việt Nam, cảm nhận tức thời trước khi đưa lên bàn cân tính toán là nước ta và dân ta có một nguồn vốn xã hội phong phú được tích lũy qua “bốn nghìn năm văn hiến”. Nếu đem các tiêu chí điển hình nhất của khái niệm vốn xã hội cơ bản như truyền thống đạo lý, phong cách xử sự hợp tác làm ăn nghiêm túc, đáng tin cậy, giàu tinh thần hợp tác và chia sẻ, có tay nghề vững vàng trong lĩnh vực chuyên môn… thì đất nước và con người Việt Nam xưa nay không thiếu. Nguồn vốn xã hội Việt Nam, do đó, sẽ rất nhiều. Nếu không có nguồn vốn xã hội giàu có làm căn bản cho sự sống còn và vươn lên của đất nước và con người Việt Nam thì có lẽ nước Việt Nam đã bị đồng hóa hay biến mất giữa những thế lực xâm lăng cường bạo đến từ mọi phía trong những nghìn năm qua. Nhưng nếu xin tạm gác lại niềm tự hào dân tộc để nhìn vào thực tiễn cuộc sống của dân ta trong dòng sinh mệnh của đất nước và trong bối cảnh lịch sử thế giới thì ta thấy được những gì?
Phải chăng nguồn vốn xã hội của Việt Nam trong bao nhiêu năm qua đã được tận dụng đem làm vũ khí chống xâm lăng? Nguồn vốn quan trọng đó bây giờ đang cạn kiệt hay vẫn còn dự trữ tràn đầy dưới dạng tiềm năng?
Căn bản để tạo ra nguồn vốn xã hội là con người. Phẩm chất của con người Việt Nam không thua sút bất cứ dân tộc nào trong cùng hoàn cảnh địa dư và lịch sử. Trong những trường đại học Mỹ mà người viết bài nầy có dịp giảng dạy, sự thể hiện rất rõ ràng là sinh viên Việt Nam, thuộc cả hai thế hệ trẻ từ quê nhà sang du học hay sinh ra và lớn lên tại Mỹ đều không thua kém mảy may sinh viên của bất cứ nước nào, nhất là đối với sinh viên châu Á như Nhật, Trung Quốc, Đại Hàn, Singapore… Thế nhưng trong thực tế đất nước, về mặt chuyên môn và khả năng khai phá, sáng tạo trong khoa học, kỹ thuật để tạo ra những sản phẩm kỹ nghệ hiện đại, chúng ta vẫn còn bị giới hạn và tụt hậu so với họ? Vốn xã hội hiện nay của đất nước ta có đủ phẩm chất và lượng dự trữ để đáp ứng được nhu cầu phát triển của nền kinh tế thị trường hay không? Đấy vẫn còn là những vấn đề cần được nghiên cứu một cách khách quan và khoa học mới có thể tìm ra câu trả lời thích đáng.
Kết Luận
Vốn xã hội là một khái niệm tương đối còn mới mẽ trong sinh hoạt kinh tế đậm tính truyền thống và kế thừa của người Việt chúng ta. Khi nói về nguồn vốn, người ta quen nói đến nguồn vốn vật chất hữu hình và cụ thể (tangible). Còn nguồn vốn xã hội là một giá trị phi vật thể (intangible) nên người ta mơ hồ thấy nó “ở đâu đó” qua những biểu hiện “tài năng” cá nhân có tính chất tiểu xảo và tiểu thương theo kiểu: “nói dẽo quẹo như mẹo con buôn…”! Lenkowsky (2000) đã chứng minh rằng xã hội càng kém phát triển, sức mạnh kinh tế càng yếu thì nguồn vốn xã hội càng dễ bị quên lãng. Nguồn vốn xã hội là một tiến trình hình thành và đầu tư lâu dài chứ không xuất hiện cụ thể và nhanh chóng trong đời sống như “mì ăn liền”. Tuy nhiên, Putnam cũng đưa ra một “kính chiếu yêu” để nhìn vào và nhận biết những vùng đang có nguồn vốn xã hội cao hơn… khi “những nơi công cộng sạch sẽ hơn, con người thân thiện, đáng tin cậy hơn, và đường sá an toàn hơn.
Sự phát triển kinh tế thường đi song song với sự cải thiện đời sống về mặt vật chất. Nhưng một vùng đất nào đó rất giàu có về vật chất thuần túy mà thiếu vắng vốn xã hội. Nghĩa là thiếu đi chiều sâu văn hóa và chiều cao nhân văn thì đấy cũng chỉ là một hình thức phồn vinh thô thiển mà người xưa gọi là “trọc phú” (thanh bần hơn trọc phú) hay theo mắt nhìn của quần chúng bình dân là “giàu mà không sang”. Hình ảnh của những vùng đất giàu vốn vật chất mà nghèo vốn xã hội thường xuất hiện trong những vùng kinh tế “nước nổi”. Nếu có dịp ghé đến những vùng kinh tế quanh các khu quân sự, hầm mõ hay hảng xưởng khai thác kinh doanh tạm thời ở Phi Luật Tân, Panama, Trung đông, Nam Phi… sẽ thấy rõ hình ảnh “giàu mà không sang” nầy xuất hiện nhan nhản. Theo Sennett, R. (1998) thì “Dấu hiệu báo động đầu tiên của sự suy thoái nguồn vốn xã hội là số người phát giàu mà không làm gì cả hay kiếm lợi bất chính một cách công khai càng lúc càng đông và khoảng cách giữa những người nghèo lương thiện và những người giàu gian manh mỗi ngày một lớn”.
Các nhà nghiên cứu về nguồn vốn xã hội trong tương quan kinh tế đều đồng ý với nhau rằng, một nền kinh tế lành mạnh trong một đất nước có kỷ cương và văn hiến không thể nào thiếu vắng nguồn vốn xã hội. Friedland (2003) đã nêu dẫn trường hợp các nước châu Mỹ La Tinh và sự èo uột của vốn xã hội. Giới lãnh đạo và thân hào nhân sĩ trong vùng thường vinh danh tinh thần địa phương và lòng tự hào nhân chủng một cách quá bảo thủ và cực đoan đến độ lơ là không quan tâm đúng mức đến sự un đúc, nuôi dưỡng và phát triển nguồn vốn xã hội. Hậu quả là sự thiếu hợp tác giữa những thành viên xã hội và các thế lực đầu tư đã đưa đến quan hệ một chiều và dẫn đến chỗ vốn xã hội bị phá sản. Các nhà kinh doanh đầu tư nản lòng lui bước. Thay vì hợp tác song phương trong tinh thần ngay thẳng, bình đẳng và danh dự thì lại biến tướng thành quan hệ “đút” (bribe) và “đớp” (being bribed) trong mối quan hệ bệnh hoạn của hối lộ và tham nhũng. Kết quả là hơn một thế kỷ qua, các nước nghèo vẫn nghèo. Dân chúng vẫn lầm than; nền kinh tế các nước trong vùng rất giàu tài nguyên nhưng vẫn kiệt quệ vì giới tài phiệt sử dụng nhân lực và tài nguyên đất nước để làm giàu cho riêng cá nhân, gia đình và dòng họ của mình rồi tìm cách chuyển tiền của và gửi con cháu của mình ra nước ngoài du học và lập nghiệp.
Kẻ thù dai dẳng nhất của quá trình tích lũy, phát triển nguồn vốn xã hội là tham nhũng. Bởi vậy, vốn xã hội và tham nhũng có mối quan hệ nghịch chiều với nhau: Nạn tham nhũng càng bành trướng, vốn xã hội càng co lại. Khi tham nhũng trở thành “đạo hành xử” hàng ngày thì cũng là lúc vốn xã hội đang trên đà phá sản.
Nếu chỉ có ánh sáng mới có khả năng quét sạch hay đuổi dần bóng tối thì cũng Tương tự như thế, vốn xã hội được tích lũy càng cao, nạn tham nhũng càng có hy vọng bị đẩy lùi dần vào quá khứ.
Thử nhìn lại vốn xã hội Việt Nam trong tương quan nguồn vốn xã hội của thế giới, chúng ta mới thấy rõ được đâu là thế mạnh và thế yếu của mình. Nhìn rõ mình không phải để thỏa mãn hay nản lòng dễ dãi nhất thời mà để cầu tiến bộ; để sửa đổi và điều chỉnh kịp thời trước sự đòi hỏi như một xu thế tất yếu của thời đại toàn cầu hóa. Sẽ không bao giờ muộn màng, cũng như chẳng bao giờ quá sớm để gây vốn xã hội, vì vốn xã hội là xương sống của đời sống kinh tế và nhân văn cho đất nước hôm nay và cho thế hệ đàn em mai sau.
Sacramento, Xuân 2006
Website: Trankiemdoan.net
Email: Doantran@sbcglobal.net
Wednesday, May 2, 2012
- Những bức ảnh cuộc đời của Steve Jobs
06/10/2011 13:52
Người đời sẽ mãi nhớ đến Steve Jobs với những sản phẩm “thần kỳ” mà ông mang lại như iPhone, iPod hay MacBook Air.
Ngôi nhà nơi Steve Jobs đã sống thời thơ ấu. Ông sinh ngày 24/2/1955 tại San Francisco, là con nuôi của ông Paul và bà Clara Jobs. Nơi ông lớn lên sau này trở thành một trong những địa danh nổi tiếng nhất thế giới - thung lũng Silicon.
|
Gặp gỡ Steve Wozniak khi còn đang học Trung học. Cả hai chàng Steve đều có niềm đam mê cháy bỏng với máy tính. Sau đó, Jobs vào đại học Reed và bị đuổi học ngay sau kỳ học đầu tiên và quyết tâm sang Ấn Độ "tu nghiệp"...
|
...và trở về với phong cách của một tài tử điện ảnh. |
Để thành lập ra Apple, hai chàng Steve đã phải bán đi toàn bộ những tài sản quý giá nhất của mình. Jobs bán đi chiếc Volkswagen, còn Wozniak bán đi chiếc máy tính bỏ túi HP để mang về 1.300 USD làm vốn "khởi nghiệp". |
"Think" là slogan của Apple những ngày đầu tiên. Sau đó, khẩu hiệu này được đổi thành "Think different". Cho đến nay, slogan này vẫn là kim chỉ nam cho những thành công của Apple. |
Năm 1984, Steve Jobs giới thiệu chiếc máy Mac đầu tiên. Đây cũng là chiếc máy tính đầu tiên trên thế giới sử dụng giao diện đồ họa. |
Năm 1985, sau khi bị đẩy khỏi Apple, Jobs sáng lập ra công ty có tên NeXT. Các sản phẩm của NeXt không có gì đặc biệt về phần cứng nhưng phần mềm của chúng chính là tiền thân của MacOS và iOS hiện đang được sử dụng trên máy Mac và iPhone hay iPad hiện tại. |
Năm 1991, Jobs và Laurene Powell cưới nhau tại khách sạn Ahwahnee thuộc Công viên Quốc gia Yosemite dưới sự chứng giám của một vị Thiền sư. Họ có 3 người con là Reed Paul, Erin Sienna và Eve. |
Ít ai biết được rằng khối tài sản khổng lồ trị giá 7 tỉ USD của Jobs hiện tại phần lớn đến từ phim hoạt hình. Năm 1986, Jobs mua lại xưởng sản xuất phim hoạt hình Pixar. Năm 1995, bộ phim hoạt hình "Toy Story" trở thành phim bom tấn, mang lại doanh thu 191 triệu USD tại Mỹ và Canada. |
Năm 1998, sau khi Apple mua lại NeXT, Steve Jobs trở lại cương vị điều hành Apple và cho ra đời máy tính iMac. Ông nói vui rằng: "có vẻ như nó đến từ một hành tinh khác, và tất nhiên đó là một hành tinh tuyệt vời". |
iPod ra đời năm 2001 làm thay đổi toàn bộ thị trường thiết bị nghe nhạc. Và cũng từ đó, vị thế của Apple bước lên một tầm cao mới. |
Tháng 6/2007, sản phẩm vĩ đại nhất đưa thương hiệu Apple lên một tầm cao mới là iPhone ra đời và lập tức gây sốt khi 6 triệu chiếc được mua hết veo chỉ sau một thời gian ngắn. |
Năm 2009, Jobs trải qua một cuộc phẫu thuật ghép gan. Bộ dạng tiều tụy của ông sau đó đã làm nhiều người yêu mến cảm thấy lo ngại về tình hình sức khỏe của ông. |
Năm 2010, Steve Jobs tiếp tục đăng đàn giới thiệu một sản phẩm "bom tấn" khác là iPad. Hiện iPad vẫn chiếm thế thượng phong so với hàng tá những máy tính bảng Android trên thị trường. |
Một trong những hoạt động cuối cùng của Steve Jobs dưới cương vị điều hành Apple là giới thiệu trụ sở hình đĩa bay đẹp như mơ của hãng này. |
Cách đây gần 2 tháng, ông giao lại quyền điều hành Apple cho Tim Cook, và hôm qua (5/10/2011), chỉ một ngày sau khi Apple ra mắt thế hệ iPhone thứ 5 mang tên iPhone 4S, Steve Jobs đã mãi mãi ra đi. |
Báo điện tử VTC News. Giấy phép số 993/GP-BTTTT ngày 07/07/2008. Tổng biên tập: Trần Duy Phương, P.Tổng biên tập: Lê Đức Sảo.
Tòa soạn và Trị sự: Tầng 6 - Số 18 Tam Trinh - Hai Bà Trưng - Hà Nội. E-mail: toasoan@vtc.vn
© Ghi rõ nguồn "VTC.VN" khi phát hành lại thông tin từ website này.
Tòa soạn và Trị sự: Tầng 6 - Số 18 Tam Trinh - Hai Bà Trưng - Hà Nội. E-mail: toasoan@vtc.vn
© Ghi rõ nguồn "VTC.VN" khi phát hành lại thông tin từ website này.
Tuesday, April 3, 2012
Đầu tư giá trị, văn hóa doanh nghiệp: Trò chuyện cùng CEO 8X
Đầu tư giá trị, văn hóa doanh nghiệp: Trò chuyện cùng CEO 8X: Là người xây dựng mô hình "bác sĩ gia đình" đầu tiên ở VN, có lúc, Tạ Minh Tuấn chán nản, tưởng chừng bỏ cuộc. Qua chông gai ấy, giờ anh đư...
Friday, March 9, 2012
Factors influencing investment decision
Capital investment decisions are not governed by one or two factors, because the investment problem is not simply one of replacing old equipment by a new one, but is concerned with replacing an existing process in a system with another process which makes the entire system more effective. We discuss below some of the relevant factors that affects investment decisions:
(i) Management Outlook: lf the management is progressive and has an aggressively marketing and growth outlook, it will encourage innovation and favor capital proposals which ensure better productivity on quality or both. In some industries where the product being manufactured is a simple standardized one, innovation is difficult and management would be extremely cost conscious. In contrast, in industries such as chemicals and electronics, a firm cannot survive, if it follows a policy of 'make-do' with its existing equipment. The management has to be progressive and innovation must be encouraged in such cases.
(ii) Competitor’s Strategy: Competitors' strategy regarding capital investment exerts significant influence on the investment decision of a company. If competitors continue to install more equipment and succeed in turning out better products, the existence of the company not following suit would be seriously threatened. This reaction to a rival's policy regarding capital investment often forces decision on a company'
(iii) Opportunities created by technological change: Technological changes create new equipment which may represent a major change in process, so that there emerges the need for re-evaluation of existing capital equipment in a company. Some changes may justify new investments. Sometimes the old equipment which has to be replaced by new equipment as a result of technical innovation may be downgraded to some other applications, A proper evaluation of this aspect is necessary, but is often not given due consideration. In this connection, we may note that the cost of new equipment is a major factor in investment decisions. However the management should think in terms of incremental cost, not the full accounting cost of the new equipment because cost of new equipment is partly offset by the salvage value of the replaced equipment. In such analysis an index called the disposal ratio becomes relevant.
Disposal ratio = (Salvage value, Alternative use value) / Installed cost
(iv) Market forecast: Both short and long run market forecasts are influential factors in capital investment decisions. In order to participate in long-run forecast for market potential critical decisions on capital investment have to be taken.
(v) Fiscal Incentives: Tax concessions either on new investment incomes or investment allowance allowed on new investment decisions, the method for allowing depreciation deduction allowance also influence new investment decisions.
(vi) Cash flow Budget: The analysis of cash-flow budget which shows the flow of funds into and out of the company may affect capital investment decision in two ways. 'First, the analysis may indicate that a company may acquire necessary cash to purchase the equipment not immediately but after say, one year, or it may show that the purchase of capital assets now may generate the demand for major capital additions after two years and such expenditure might clash with anticipated other expenditures which cannot be postponed. Secondly, the cash flow budget shows the timing of cash flows for alternative investments and thus helps management in selecting the desired investment project.
(vii) Non-economic factors: new equipment may make the workshop a pleasant place and permit more socializing on the job. The effect would be reduced absenteeism and increased productivity. It may be difficult to evaluate the benefits in monetary terms and as such we call this as non-economic factor. Let us take one more example. Suppose the installation of a new machine ensures greater safety in operation. It is difficult to measure the resulting monetary saving through avoidance of an unknown number of injuries. Even then, these factors give tangible results and do influence investment decisions.
(i) Management Outlook: lf the management is progressive and has an aggressively marketing and growth outlook, it will encourage innovation and favor capital proposals which ensure better productivity on quality or both. In some industries where the product being manufactured is a simple standardized one, innovation is difficult and management would be extremely cost conscious. In contrast, in industries such as chemicals and electronics, a firm cannot survive, if it follows a policy of 'make-do' with its existing equipment. The management has to be progressive and innovation must be encouraged in such cases.
(ii) Competitor’s Strategy: Competitors' strategy regarding capital investment exerts significant influence on the investment decision of a company. If competitors continue to install more equipment and succeed in turning out better products, the existence of the company not following suit would be seriously threatened. This reaction to a rival's policy regarding capital investment often forces decision on a company'
(iii) Opportunities created by technological change: Technological changes create new equipment which may represent a major change in process, so that there emerges the need for re-evaluation of existing capital equipment in a company. Some changes may justify new investments. Sometimes the old equipment which has to be replaced by new equipment as a result of technical innovation may be downgraded to some other applications, A proper evaluation of this aspect is necessary, but is often not given due consideration. In this connection, we may note that the cost of new equipment is a major factor in investment decisions. However the management should think in terms of incremental cost, not the full accounting cost of the new equipment because cost of new equipment is partly offset by the salvage value of the replaced equipment. In such analysis an index called the disposal ratio becomes relevant.
Disposal ratio = (Salvage value, Alternative use value) / Installed cost
(iv) Market forecast: Both short and long run market forecasts are influential factors in capital investment decisions. In order to participate in long-run forecast for market potential critical decisions on capital investment have to be taken.
(v) Fiscal Incentives: Tax concessions either on new investment incomes or investment allowance allowed on new investment decisions, the method for allowing depreciation deduction allowance also influence new investment decisions.
(vi) Cash flow Budget: The analysis of cash-flow budget which shows the flow of funds into and out of the company may affect capital investment decision in two ways. 'First, the analysis may indicate that a company may acquire necessary cash to purchase the equipment not immediately but after say, one year, or it may show that the purchase of capital assets now may generate the demand for major capital additions after two years and such expenditure might clash with anticipated other expenditures which cannot be postponed. Secondly, the cash flow budget shows the timing of cash flows for alternative investments and thus helps management in selecting the desired investment project.
(vii) Non-economic factors: new equipment may make the workshop a pleasant place and permit more socializing on the job. The effect would be reduced absenteeism and increased productivity. It may be difficult to evaluate the benefits in monetary terms and as such we call this as non-economic factor. Let us take one more example. Suppose the installation of a new machine ensures greater safety in operation. It is difficult to measure the resulting monetary saving through avoidance of an unknown number of injuries. Even then, these factors give tangible results and do influence investment decisions.
Thursday, March 8, 2012
Three Factors That Affect Purchase Decisions
Why do people decide to buy? Some consumers use an intense system of thorough investigation before they decide to purchase, while others are basic impulse shoppers. Either way, three factors affect all purchasing decisions. Retailers should be familiar with the impact each factor has on the minds of consumers. A thorough understanding of the interdependency of each factor will help you market your inventory better, attract more customers and close more deals.
Apple, Inc. was flawless in their execution when they rolled out the new iPhone and iTouch because they knew what made consumers act. They knew the emotional hot buttons. They knew how to create enough excitement about a new line of entertainment gear that for many, a simple “want” transformed into a self-justified, immediate need. The iPhone and iTouch hit the market with a fury like the Running of the Bulls and Apple’s stock skyrocketed. So did the net worth of Steve Jobs, a hard-charging and creative businessman who understands the consumer.
If you want a better understanding of how consumers act, implement these three factors into your marketing and sales plans:
The Economic Factor – This is the foundation of a purchasing decision. People can’t buy what they can’t afford no matter how badly they need it or want it. However, affordability is often a matter of perspective, which would explain why so many consumers use “creative” budgeting to get the things they really want. This practice has led to the special finance market and a struggling mortgage industry, and it has you reading this article.
In our business, the economic factor is represented in the terms of down payments and monthly payments. You will be better served to hold your considerations of this most basic of the three factors to the end, long after you’ve gained the attention and interest of your prospects. Otherwise, you will run into the common scenario of “these customers have no money” problems. To stay off that road, focus on the other two factors first.
The Functional Factor – The functional factor is all about needs. It’s about logic, what makes sense and the best interest of the customer. Although it too plays an important role in the decision to buy, it is the boring factor and typically doesn’t affect emotional appeal.
That being said, the functional factor is perhaps the most important of all three when it comes to special finance. A dealer must set the customer up for success and not for failure. It is much too easy to get a customer excited about a vehicle that is out of their price range and/or does not meet their needs. A dealer with a strong special finance program is able to weave logic into the equation and convince the customer to do what is in their best interest by taking time to learn and understand their needs first.
If you take the time to uncover the needs with a thorough analysis, you will build more rapport and be much more likely to earn the customer’s trust in the process. Then, when you introduce the logical choice later in the sale, your customer will be more apt to follow your advice and direction rather than seeing you as just another fast-talking salesperson.
The Psychological Factor – All effective advertising appeals to emotion, or the psychological side of the sale. The psychological factor is all about what the customer wants. To divert the customer from the “wrong” vehicle and effectively bypass price, a special finance salesperson must introduce the psychological elements of the sale early in the process. One effective method that I recommend is to show the customer the merits of establishing or re-establishing a positive credit score. To be effective, you have to build the vision of an easier life for them with good credit, and then, get their buy in.
Personal image is also an important emotional hot button. Having an iPhone is a social statement. Likewise are having a nice car and home. People want the best they can afford and, more often than not, the best they can’t afford. That’s why the most powerful commercials focus on image and not price. Image, fear, wants and dreams are all powerful emotional forces that drive the decision to buy. If used in a timely fashion, they will be the forces behind higher down payments and profit.
Apple, Inc. was flawless in their execution when they rolled out the new iPhone and iTouch because they knew what made consumers act. They knew the emotional hot buttons. They knew how to create enough excitement about a new line of entertainment gear that for many, a simple “want” transformed into a self-justified, immediate need. The iPhone and iTouch hit the market with a fury like the Running of the Bulls and Apple’s stock skyrocketed. So did the net worth of Steve Jobs, a hard-charging and creative businessman who understands the consumer.
If you want a better understanding of how consumers act, implement these three factors into your marketing and sales plans:
The Economic Factor – This is the foundation of a purchasing decision. People can’t buy what they can’t afford no matter how badly they need it or want it. However, affordability is often a matter of perspective, which would explain why so many consumers use “creative” budgeting to get the things they really want. This practice has led to the special finance market and a struggling mortgage industry, and it has you reading this article.
In our business, the economic factor is represented in the terms of down payments and monthly payments. You will be better served to hold your considerations of this most basic of the three factors to the end, long after you’ve gained the attention and interest of your prospects. Otherwise, you will run into the common scenario of “these customers have no money” problems. To stay off that road, focus on the other two factors first.
The Functional Factor – The functional factor is all about needs. It’s about logic, what makes sense and the best interest of the customer. Although it too plays an important role in the decision to buy, it is the boring factor and typically doesn’t affect emotional appeal.
That being said, the functional factor is perhaps the most important of all three when it comes to special finance. A dealer must set the customer up for success and not for failure. It is much too easy to get a customer excited about a vehicle that is out of their price range and/or does not meet their needs. A dealer with a strong special finance program is able to weave logic into the equation and convince the customer to do what is in their best interest by taking time to learn and understand their needs first.
If you take the time to uncover the needs with a thorough analysis, you will build more rapport and be much more likely to earn the customer’s trust in the process. Then, when you introduce the logical choice later in the sale, your customer will be more apt to follow your advice and direction rather than seeing you as just another fast-talking salesperson.
The Psychological Factor – All effective advertising appeals to emotion, or the psychological side of the sale. The psychological factor is all about what the customer wants. To divert the customer from the “wrong” vehicle and effectively bypass price, a special finance salesperson must introduce the psychological elements of the sale early in the process. One effective method that I recommend is to show the customer the merits of establishing or re-establishing a positive credit score. To be effective, you have to build the vision of an easier life for them with good credit, and then, get their buy in.
Personal image is also an important emotional hot button. Having an iPhone is a social statement. Likewise are having a nice car and home. People want the best they can afford and, more often than not, the best they can’t afford. That’s why the most powerful commercials focus on image and not price. Image, fear, wants and dreams are all powerful emotional forces that drive the decision to buy. If used in a timely fashion, they will be the forces behind higher down payments and profit.
Trước khi mua cổ phiếu bạn phải tính đến...
Details
Category: FUNDAMENTAL ANALYST
Published on Wednesday, 30 November -0001 07:06
Hits: 622
Sách dạy về chứng khoán có bán khá nhiều, song đại đa số khuyên bảo giống nhau, chỉ cho nhà đầu tư các công thức, song ít khi chỉ bảo cách nhìn nhận, đánh giá, những ranh giới được và không được để giúp nhà đầu tư "hành tẩu” đúng trên sàn và ngoài sàn. Bài viết này đưa ra một số tri thức để giúp các nhà đầu tư nhìn nhận những cơ hội thực sự cho mình.
1- Đừng chú ý đến cổ tức ngay, hãy xem Công ty đó ở trong ngành nào trước
Chính vấn đề tưởng trừng không liên quan trực tiếp đến giá cổ phiếu này lại là một trong những nhân tố quan trọng nhất quyết định cổ phiếu đó có tăng giá nhiều hày không trong tương lai. Nếu một Công ty chuyên tư vấn du học niêm yết trên thị trường chứng khoán, giá của nó đương nhiên khó có thể cao được bởi đa số các Công ty du học là các Công ty loại OMS tức chỉ hoạt động quy mô nhỏ, phụ thuộc vào tài năng và sự chăm chỉ của một hay vài người, giống như cây bonsai, khó có thể lớn lên và nhân rộng được quy mô. Trong khi đó, nếu các Công ty trong ngành tài chính, các Ngân hàng, Công ty xây dựng, bất động sản (đúng nghĩa chứ không phải là “cò nhà”), Công ty hàng tiêu dùng nhanh, Công ty truyền thông… thì khả năng mở rộng quy mô hoạt động, tăng cường kinh doanh là rất lớn. Vinamilk, Kinh Đô, REE, Sacombank, Ngân hàng ACB, Sudico... giá cao điều đầu tiên đều do họ thuộc các ngành đầy triển vọng này.
2- Có hay không khả năng mở rộng kinh doanh?
Vấn đề này chính là vấn đề phải xem xét tiếp theo. Nếu một Công ty có khả năng mở rộng liên tục quy mô sán xuất kinh doanh của mình thì giá của chúng sẽ tăng, đó là điều đương nhiên. Dẫn chứng sắc nét có thể đưa ra ngay là giả định có 2 Công ty cùng có cụm từ thủy điện trên tên giao dịch như "Công ty Thủy điện ABC" và "Công ty Đầu tư Thủy điện XYZ" thì giá của Công ty thứ hai đương nhiên sẽ cao, còn Công ty thứ nhất sẽ khó lòng lên đến đầu 4x, trong khi đó, nếu Công ty thứ hai có thể lên đến trên 10x, thậm chí 20x là bình thưởng. Giá chênh như vậy là dễ hiểu bởi Công ty thứ nhất chỉ có 1 nhà máy thủy điện duy nhất. Nhà máy này xây một lần rồi thôi, không có khả năng mở rộng sản xuất, không đắp cao đập lên được, không lắp thêm máy, không tăng công suất phát điện được, nhà đầu tư chí có thể trông vào cố tức mà thôi. Trong khi đó, ở Công ty thứ hai, vốn điêu lệ ban đầu có thể chỉ là 50 tỷ, song Công ty lại có khả năng tham gia đầu tư vào rất nhiều: 10, 100 và hơn nữa các Nhà máy thủy điện nên vốn đầu tư có thể tăng tương ứng và quyền lợi của nhà đầu tư tăng theo đà đó.
3- Nhìn vào cả quá trình thay vì chỉ vào một thời điểm
Lịch sử một Công ty nói lên nhiều điều. Trước hết nếu Công ty đó có cả một lịch sử rất dài nhưng các "chỉ số cơ thể" hiện đều nhàng nhàng thì khó có đột biến đáng mừng cho nhà đầu ra bởi thời gian đã chứng minh Công ty đó không có gì xuất sắc. Nếu 5 năm trước, các chỉ số tài chính của Công ty tốt, song vào thời điểm nhà đầu tư xem xét, chỉ số đó đang tụt dần thì hãy cẩn thận: dù chí số đó, vào thời điểm đó đã tốt song có gì đám bảo nó sẽ không tụt dốc tiếp?
4- Nhìn vào đội ngũ, hơn là chỉ nhìn vào chỉ số tài chính
Lịch sử các Công ty hay ngân hàng Việt Nam đã chứng minh là vấn đề đội ngũ nói chung và đội ngũ quản lý là vô cùng quan trọng với một Công ty. Nếu các nhân tố nói trên căn bản tốt, có đội ngũ tốt, Công ty đó sẽ ăn nên làm ra và trong trường hợp đó, lợi nhuận của nhà đầu tư sẽ cao hơn nhiều. Thậm chí lịch sử đã chứng minh nếu một doanh nghiệp đang kém nhưng xuất hiện một đội ngũ tất thì doanh nghiệp đó vẫn có thể lội ngược dòng. VP Bank là một trường bị hợp điển hình. Vào năm 2002, VP Bank vẫn đang trong tình trạngkiểm soát đặc biệt. Nhưng sau đó, với sự thay đổi nhân sự, với quyết tâm cao và định hướng đúng, ngân hàng này không những ra khỏi tình trạng bị kiểm soát đặc biệt mà còn có nhiều bước phát triển ngoạn mục, trở thành một trong những ngân hàng lớn nhất và tất nhất. Giá cổ phiếu vào thời điểm đó thường được mua bán dưới mệnh giá (thậm chí lúc thấp nhất chỉ còn 0,25 lần mệnh giá) đã nhanh chóng lên đến cao nhất khoảng 7,4 lần mệnh giá.
5- Hãy lưu ý đến các cổ đông là pháp nhân
Các cổ đông pháp nhân có vai trò khá quan trọng với cổ phiếu của một Công ty. Nếu trong số cổ đông đó, có nhiều ngân hàng, Công ty tài chính, các Công ty có tên tuổi, đó chắc chắn là một điểm căn cứ để "lên điểm” của cổ phiếu đó. Điểm của Công ty càng lên nếu đó là các Công ty hay ngân hàng nước ngoài, Công ty cổ phần, ngân hàng thương mại cổ phần.
6- Chú ý đến động thái của các quỹ đầu tư
Ở Việt Nam hiện tại, còn quá ít các quỹ đầu tư song nhà đầu tư cũng nên chú ý đến động thải của các quỹ này. Các quỹ thường có "giác quan" rất nhạy nên họ sẽ quyết định đầu tư vào những nơi nào có triển vọng nhất. Tuy nhiên, ngược lại, cũng có nhiều Công ty tốt song không muốn bán cho các quỹ này bởi nhiều quỹ chỉ muốn gặt hái lợi nhuận đơn thuần và thường đầu tư theo kiểu ngắn hạn, nếu có lời là có thể bán ngay.
7- Cần có thông tin rõ ràng
Tất nhiên, đây là một việc quan trọng khi xem xét đầu tư vào cổ phiếu của một Công ty nào đó. Không nên mua cổ phiếu khi không có đầy đủ thông tin cần thiết về Công ty đó. Hệ thống thông tin và các quy định về công bố thông tin của các Công ty khi phát hành cổ phiếu ở nước ta còn rất sơ sài. Với Công ty lên sàn niêm yết, mọi việc đơn giản hơn vì ít nhất Công ty đó phải có cáo bạch. Đối với Công ty mới có cổ phiếu OTC, bạn cũng nên đòi người bán phải cung cấp thông tin như báo cáo tài chính hàng năm, báo cáo kiểm toán.
8- Chú ý đến các chỉ số tài chính và P/E của Công ty
Có nhiều cách tính chỉ số P/E, nhà đầu tư có thể tham khảo trên các cuốn sách về chứng khoán được bán rất nhiều ở các hiệu sách khắp cả nước. Nhưng quan trọng hơn, chỉ số thế nào thì mua, chỉ số nào thì không mua?
Theo các chuyên gia chứng khoán, nếu P/E của một Công ty ở mức dưới 12, bạn có thể mua cổ phiếu đó mà không cần cân nhắc gì nhiều. Nếu P/E ở mức 12 - 18 nên cân nhắc và hỏi ý kiến chuyên gia xem có nên đầu tư hay không. Còn nếu P/E ở mức trên 18, thường chỉ nên bán. Đây là các cột mốc song chi có tính tương đối và luôn phải xem xét đến các nhân tố tương lai (nhất là các quyền lợi sắp phát sinh, yếu tố ngành nghề… để "tính lại" P/E trong tương lai gần là bao nhiêu rồi mới nên kết luận là mua hay bán.
9- Không thể thiếu các “nhân tố vô hình”
Một điều các chuyên gia của chúng ta thường không nhắc đền nhiều nhưng lại là câu hỏi mà các nhà đầu tư khôn ngoan bao giờ cũng hỏi khi tìm hiểu về một cổ phiếu, đó là các giá trị mô hình của doanh nghiệp đã được tính đến chưa và nếu tính thì giá là bao nhiêu. Giá đó là đắt hay rẻ? Giá trị mô hình này có thể là lợi thế thương mại. Thí dụ như PV Driuing có lợi thế độc tôn trong ngành dầu khí là một nhân tố phải tính đến của Công ty này. Cavico Mining có một hợp đồng khai mỏ lớn và lâu dài đến khoảng 15 năm liền đảm bảo công ăn việc làm trong một thời gian dài cũng là lợi thế. Vinamilk có thương hiệu và một loạt nhãn hiệu nổi tiếng, đã ăn vào tâm trí người tiêu dùng cũng là lợi thế lớn trên thị trường.
Nhìn chung, khi nhìn nhận một cổ phiếu phải xét đến rất nhiều nhân tố. Đó chính là điểm khởi phát cho những thành công khi nhà đầu tư bước chân vào thị trường cổ phiếu. Chúng tôi sẽ còn một số bài viết sâu hơn cho bạn đọc về những vấn đề này trong các số báo tới.
Một trong những yếu tố quan trọng nhất khi bước chân vào sân chơi chứng khoán đó là tìm kiếm công ty để bạn có thể mua cổ phiếu. Và một khi bạn đã tìm hiểu và nghiên cứu về loại cổ phiếu mà bạn quan tâm và có một nhà môi giới để giúp bạn mua thì việc mua cổ phiếu lại là một việc tương đối dễ dàng.
Tìm cổ phiếu như thế nào?
Bước 1: Hãy tìm hiểu những báo cáo tài chính công khai của các doanh nghiệp mà có những thông tin liên quan đến chứng khoán.
Bước 2: Hãy phân tích những bản báo cáo hàng quý của công ty đó trong vòng hai hoặc ba năm trở lại đây, và đặc biệt chú ý đến xu hướng lợi nhuận tính theo cổ phiếu và doanh thu của công ty.
Bước 3: Hãy tìm cho mình một công ty có xu thế tăng trưởng ổn định nhất về lợi nhuận tính trên cổ phiếu.
Bước 4: Hãy tính tỉ lệ giá cả - lợi nhuận (tỉ lệ PE) của công ty đó, vì đây là một thước đo giá trị của cổ phiếu. (Tính tỉ lệ này bằng cách chia giá cổ phiếu cho lợi nhuận hàng năm tính theo cổ phiếu.)
Bước 5: Hãy so sánh tỉ lệ PE đó với các quy chuẩn của ngành và với tỉ lệ của chỉ số S&P 500. Tỉ lệ này càng thấp thì giá cổ phiếu càng rẻ so với lợi nhuận.
Bước 6: Hãy chú ý đến cả các món nợ của công ty đó. Vì vậy phải kiểm tra bảng cân đối kế toán của công ty và tìm đến phần thông tin về các món nợ dài hạn.
Bước 7: Ngoài ra cũng cần phải chú ý đến bảng lưu chuyển tiền tệ trong các báo cáo tài chính đó để xem tiền được lưu chuyển như thế nào trong hoạt động kinh doanh của công ty. Bởi vì chắc hẳn rằng bạn sẽ muốn nhìn thấy một bảng lưu chuyển tiền tệ có lãi chứ không phải là thua lỗ.
Mua cổ phiếu như thế nào?
Bước 1: Hãy trang bị cho bản thân đầy đủ những kiến thức về loại cổ phiếu trước khi bạn quyết định mua.
Bước 2: Hãy quyết định xem mình cần những gì từ người môi giới chứng khoán. Liệu mình có cần phải gặp trực tiếp người đó không? Liệu chỉ liên lạc với người đó qua điện thoại thôi có được không? Có phải giá cả là mối quan tâm duy nhất của bạn không? Có phải bạn chỉ muốn mua hoặc bán cổ phiếu hay là bạn còn muốn đầu tư cả vào những loại khác như quỹ tương hỗ, trái phiếu hay thậm chí cả cổ phiếu của nước ngoài.
Bước 3: Hãy chọn một nhà môi giới hoặc một công ty môi giới để thay bạn mua những cổ phiếu bạn muốn. Bạn có cần thật nhiều lời khuyên hay không? Nếu câu trả lời là có thì hãy tìm đến một hãng môi giới với dịch vụ trọn gói. Các nhà môi giới càng rẻ tiền sẽ càng cung cấp cho bạn ít lời khuyên mà bạn muốn. Nếu bạn khá tự tin vào khả năng của mình rồi và muốn mua các cổ phiếu giá rẻ? Vậy thì hãy thử tìm đến những lời khuyên và môi giới trên mạng Internet xem sao.
Bước 4: Hãy liên lạc với người môi giới hoặc công ty môi giới chứng khoán để xin một lá đơn, và yêu cầu mở một tài khoản giao dịch chứng khoán.
Bước 5: Khi tài khoản đã được mở bạn có thể bắt đầu ngay việc mua hay bán cổ phiếu của mình.
Bước 6: Hãy rà soát lại các bản báo cáo bạn nhận được và đánh giá lại những gì đang diễn ra trên danh mục đầu tư của mình để xem bạn có đang đi đúng hướng để đạt được những mục tiêu trong đầu tư của bạn không?
Các mẹo vặt và vài lời nhắc nhở
Hãy hỏi bạn bè và đồng nghiệp để tìm cho mình được người môi giới chứng khoán hay công ty môi giới tốt và có uy tín. Nếu bạn không có được những lời khuyên từ một cá nhân nào, thì hãy tìm trên báo chí về tài chính để có những thông tin bạn cần.
Đầu tư chứng khoán không phải là một trò chơi, nó đòi hỏi bạn phải có những kiến thức thực sự và phải có trí thông minh nhất định. Phải nhớ là bạn luôn theo dõi chặt chẽ mọi diễn biến trên thị trường và đưa ra những quyết định sáng suốt kịp thời để bảo vệ chính bản thân mình.
vào cổ phiếu của hãng Chamber Lych, một công ty công nghệ đang nổi tại miền trung nước Mỹ mà không đầu tư vào một công ty lâu năm cũng trong lĩnh vực công nghệ là TechTech vì cho rằng công ty đang thất thế.
Trong hai tháng đầu tiên đầu tư, cổ phiếu của Lych liên tục tăng giá và cổ phiếu của TechTech thì hạ giá dần. Nhưng chỉ sau thời gian đó, đột nhiên cổ phiếu của TechTech lại tăng giá rất cao, trong khi cổ phiếu của Chamber lại đứng yên thậm chí có tin đồn là sẽ xuống giá nên không ai dám mua nữa. Kết quả, số tiền của hai người bạn Lane Jack và Peter Huge đã không phát sinh lợi nhuận, thậm chí có nguy cơ mất sạch. Cả Lane Jack và Peter Huge đều tiếc nuối vì đã không đầu tư vào cổ phiếu của TechTech.
Trong đầu tư chứng khoán việc lựa chọn cổ phiếu sẽ là rất quan trọng. Nó sẽ quyết định việc thành bại của cả quá trình đầu tư. Nhiều khi nhà đầu tư không nên nghe theo những gì nhà môi giới chứng khoán nói mà hãy dựa vào chính sự phân tích và suy xét của mình.
Mua loại cổ phiếu nào
Khi đã quyết định đầu tư vào cổ phiếu thường phải nghiên cứu xem loại cổ phiếu nào là hiệu quả nhất. Đây chính là lúc cần những thông tin về phân tích chứng khoán và tình hình công ty vì ít có cách nào mất tiền nhanh hơn là mua phải chứng khoán không tốt.
Một số tiêu thức để so sánh và lựa chọn:
- Chọn ngành cổ phiếu: ngành công nghiệp, nông nghiệp, giao thông vận tải, tài chính hay dịch vụ công cộng... Có thể đi vào nhiều ngành chi tiết hơn, ví dụ trong công nghiệp có thể là công nghiệp khai thác, công nghiệp chế biến hoặc công nghiệp sản xuất. Phân tích từng ngành kinh tế về tính chất, thị trường, khả năng phát triển, tăng trưởng bình quân, khả năng cạnh tranh, ảnh hưởng có tính chất chu kỳ;
- Chọn bất cứ công ty nào trong ngành nào thì cũng nên phân tích tình hình công ty đó trên các mặt: tình hình tài chính, lợi nhuận, lợi tức cổ phần, nhu cầu vốn, tình hình huy động vốn và những loại chứng khoán chủ yếu của công ty, đánh giá tình hình cổ phiếu của công ty về mặt tài chính, vị trí của công ty trong ngành, trình độ ban quản trị, ban điều hành và chính sách quản trị của công ty, địa điểm, vận tải, lao động, nguyên liệu, bằng sáng chế phát minh, v.v...
Muốn phân tích thấu đáo giá trị cổ phiếu của một công ty thì phải xem xét những nhân tố kể trên, đồng thời phải tham khảo sự đánh giá của các Trung tâm phân tích chứng khoán, các tổ chức xếp loại doanh nghiệp. Ngoài ra, cần chú ý đến việc đa dạng hóa cổ phiếu đầu tư để tránh được sự vận động của chu kỳ kinh doanh, sự thay đổi vị trí của một doanh nghiệp... Có thể đa dạng hóa theo nhiều cách như: mua cổ phiếu của nhiều ngành khác nhau; mua cổ phiếu của các công ty khác nhau; mua cổ phiếu của nhiều khu vực khác nhau; mua cổ phiếu của các công ty có những thành phẩm khác nhau; mua ở những thời điểm khác nhau... Tuy nhiên, nếu đa dạng hóa đầu tư quá mức cũng sẽ có những nhược điểm như: làm cho việc quản lý khó khăn, tốn nhiều công sức điều tra và phân tích, làm tăng chi phí mua bán, làm giảm bớt cơ hội đạt lợi nhuận cao.
Khi nào mua?
Một câu trả lời rất đơn giản là “khi nào cần thấy được thì mua”. Bởi vì một số không ít những nhà kinh doanh chứng khoán cho rằng họ thường sai lầm trong việc đánh giá về thị trường nói chung và một số cổ phiếu nói riêng. Nói theo một nghĩa nào đó thì những người kinh doanh chứng khoán là những người đầu tư giá trị, do vậy có những người khi thấy công ty trong giai đoạn hưng thịnh thì mua cổ phiếu và thậm chí có nhiều người thích mua cổ phiếu của những công ty đang ở giai đoạn thất thế.
Từ đầu thế kỷ XVIII ở thị trưưòng chứng khoán Tây Âu và thị trường chứng khoán Mỹ sau này đã đưa ra học thuyết “Đầu tư ngược dòng”. Thuyết này đã đưa ra lời khuyên rằng “vẫn có thể lội ngược dòng sông”. Thực tế cho thấy, đầu tư ngược dòng có khả năng rủi ro rất cao nhưng cũng có cơ may đưa đến lợi nhuận khổng lồ bởi vì rất có thể thời gian thất thế của một công ty sẽ được khôi phục trong tương lai. Có nhiều người có cùng dự đoán lạc quan đó nên số người đầu tư ngược dòng tăng lên. Chính hành động có nhiều người có cùng nhận định, cùng mua cổ phiếu đã làm cho giá trị cổ phiếu được phục hồi uy tín ngay khi công ty này còn thất thế. Do vậy, không nhất thiết cứ phải mua cổ phiếu khi công ty đang có uy tín tốt mà vẫn có thể mua cổ phiếu khi công ty đang thất thế.
Sưu tầm
Trang thông tin tổng hợp Phố Chứng Khoán
Category: FUNDAMENTAL ANALYST
Published on Wednesday, 30 November -0001 07:06
Hits: 622
Sách dạy về chứng khoán có bán khá nhiều, song đại đa số khuyên bảo giống nhau, chỉ cho nhà đầu tư các công thức, song ít khi chỉ bảo cách nhìn nhận, đánh giá, những ranh giới được và không được để giúp nhà đầu tư "hành tẩu” đúng trên sàn và ngoài sàn. Bài viết này đưa ra một số tri thức để giúp các nhà đầu tư nhìn nhận những cơ hội thực sự cho mình.
1- Đừng chú ý đến cổ tức ngay, hãy xem Công ty đó ở trong ngành nào trước
Chính vấn đề tưởng trừng không liên quan trực tiếp đến giá cổ phiếu này lại là một trong những nhân tố quan trọng nhất quyết định cổ phiếu đó có tăng giá nhiều hày không trong tương lai. Nếu một Công ty chuyên tư vấn du học niêm yết trên thị trường chứng khoán, giá của nó đương nhiên khó có thể cao được bởi đa số các Công ty du học là các Công ty loại OMS tức chỉ hoạt động quy mô nhỏ, phụ thuộc vào tài năng và sự chăm chỉ của một hay vài người, giống như cây bonsai, khó có thể lớn lên và nhân rộng được quy mô. Trong khi đó, nếu các Công ty trong ngành tài chính, các Ngân hàng, Công ty xây dựng, bất động sản (đúng nghĩa chứ không phải là “cò nhà”), Công ty hàng tiêu dùng nhanh, Công ty truyền thông… thì khả năng mở rộng quy mô hoạt động, tăng cường kinh doanh là rất lớn. Vinamilk, Kinh Đô, REE, Sacombank, Ngân hàng ACB, Sudico... giá cao điều đầu tiên đều do họ thuộc các ngành đầy triển vọng này.
2- Có hay không khả năng mở rộng kinh doanh?
Vấn đề này chính là vấn đề phải xem xét tiếp theo. Nếu một Công ty có khả năng mở rộng liên tục quy mô sán xuất kinh doanh của mình thì giá của chúng sẽ tăng, đó là điều đương nhiên. Dẫn chứng sắc nét có thể đưa ra ngay là giả định có 2 Công ty cùng có cụm từ thủy điện trên tên giao dịch như "Công ty Thủy điện ABC" và "Công ty Đầu tư Thủy điện XYZ" thì giá của Công ty thứ hai đương nhiên sẽ cao, còn Công ty thứ nhất sẽ khó lòng lên đến đầu 4x, trong khi đó, nếu Công ty thứ hai có thể lên đến trên 10x, thậm chí 20x là bình thưởng. Giá chênh như vậy là dễ hiểu bởi Công ty thứ nhất chỉ có 1 nhà máy thủy điện duy nhất. Nhà máy này xây một lần rồi thôi, không có khả năng mở rộng sản xuất, không đắp cao đập lên được, không lắp thêm máy, không tăng công suất phát điện được, nhà đầu tư chí có thể trông vào cố tức mà thôi. Trong khi đó, ở Công ty thứ hai, vốn điêu lệ ban đầu có thể chỉ là 50 tỷ, song Công ty lại có khả năng tham gia đầu tư vào rất nhiều: 10, 100 và hơn nữa các Nhà máy thủy điện nên vốn đầu tư có thể tăng tương ứng và quyền lợi của nhà đầu tư tăng theo đà đó.
3- Nhìn vào cả quá trình thay vì chỉ vào một thời điểm
Lịch sử một Công ty nói lên nhiều điều. Trước hết nếu Công ty đó có cả một lịch sử rất dài nhưng các "chỉ số cơ thể" hiện đều nhàng nhàng thì khó có đột biến đáng mừng cho nhà đầu ra bởi thời gian đã chứng minh Công ty đó không có gì xuất sắc. Nếu 5 năm trước, các chỉ số tài chính của Công ty tốt, song vào thời điểm nhà đầu tư xem xét, chỉ số đó đang tụt dần thì hãy cẩn thận: dù chí số đó, vào thời điểm đó đã tốt song có gì đám bảo nó sẽ không tụt dốc tiếp?
4- Nhìn vào đội ngũ, hơn là chỉ nhìn vào chỉ số tài chính
Lịch sử các Công ty hay ngân hàng Việt Nam đã chứng minh là vấn đề đội ngũ nói chung và đội ngũ quản lý là vô cùng quan trọng với một Công ty. Nếu các nhân tố nói trên căn bản tốt, có đội ngũ tốt, Công ty đó sẽ ăn nên làm ra và trong trường hợp đó, lợi nhuận của nhà đầu tư sẽ cao hơn nhiều. Thậm chí lịch sử đã chứng minh nếu một doanh nghiệp đang kém nhưng xuất hiện một đội ngũ tất thì doanh nghiệp đó vẫn có thể lội ngược dòng. VP Bank là một trường bị hợp điển hình. Vào năm 2002, VP Bank vẫn đang trong tình trạngkiểm soát đặc biệt. Nhưng sau đó, với sự thay đổi nhân sự, với quyết tâm cao và định hướng đúng, ngân hàng này không những ra khỏi tình trạng bị kiểm soát đặc biệt mà còn có nhiều bước phát triển ngoạn mục, trở thành một trong những ngân hàng lớn nhất và tất nhất. Giá cổ phiếu vào thời điểm đó thường được mua bán dưới mệnh giá (thậm chí lúc thấp nhất chỉ còn 0,25 lần mệnh giá) đã nhanh chóng lên đến cao nhất khoảng 7,4 lần mệnh giá.
5- Hãy lưu ý đến các cổ đông là pháp nhân
Các cổ đông pháp nhân có vai trò khá quan trọng với cổ phiếu của một Công ty. Nếu trong số cổ đông đó, có nhiều ngân hàng, Công ty tài chính, các Công ty có tên tuổi, đó chắc chắn là một điểm căn cứ để "lên điểm” của cổ phiếu đó. Điểm của Công ty càng lên nếu đó là các Công ty hay ngân hàng nước ngoài, Công ty cổ phần, ngân hàng thương mại cổ phần.
6- Chú ý đến động thái của các quỹ đầu tư
Ở Việt Nam hiện tại, còn quá ít các quỹ đầu tư song nhà đầu tư cũng nên chú ý đến động thải của các quỹ này. Các quỹ thường có "giác quan" rất nhạy nên họ sẽ quyết định đầu tư vào những nơi nào có triển vọng nhất. Tuy nhiên, ngược lại, cũng có nhiều Công ty tốt song không muốn bán cho các quỹ này bởi nhiều quỹ chỉ muốn gặt hái lợi nhuận đơn thuần và thường đầu tư theo kiểu ngắn hạn, nếu có lời là có thể bán ngay.
7- Cần có thông tin rõ ràng
Tất nhiên, đây là một việc quan trọng khi xem xét đầu tư vào cổ phiếu của một Công ty nào đó. Không nên mua cổ phiếu khi không có đầy đủ thông tin cần thiết về Công ty đó. Hệ thống thông tin và các quy định về công bố thông tin của các Công ty khi phát hành cổ phiếu ở nước ta còn rất sơ sài. Với Công ty lên sàn niêm yết, mọi việc đơn giản hơn vì ít nhất Công ty đó phải có cáo bạch. Đối với Công ty mới có cổ phiếu OTC, bạn cũng nên đòi người bán phải cung cấp thông tin như báo cáo tài chính hàng năm, báo cáo kiểm toán.
8- Chú ý đến các chỉ số tài chính và P/E của Công ty
Có nhiều cách tính chỉ số P/E, nhà đầu tư có thể tham khảo trên các cuốn sách về chứng khoán được bán rất nhiều ở các hiệu sách khắp cả nước. Nhưng quan trọng hơn, chỉ số thế nào thì mua, chỉ số nào thì không mua?
Theo các chuyên gia chứng khoán, nếu P/E của một Công ty ở mức dưới 12, bạn có thể mua cổ phiếu đó mà không cần cân nhắc gì nhiều. Nếu P/E ở mức 12 - 18 nên cân nhắc và hỏi ý kiến chuyên gia xem có nên đầu tư hay không. Còn nếu P/E ở mức trên 18, thường chỉ nên bán. Đây là các cột mốc song chi có tính tương đối và luôn phải xem xét đến các nhân tố tương lai (nhất là các quyền lợi sắp phát sinh, yếu tố ngành nghề… để "tính lại" P/E trong tương lai gần là bao nhiêu rồi mới nên kết luận là mua hay bán.
9- Không thể thiếu các “nhân tố vô hình”
Một điều các chuyên gia của chúng ta thường không nhắc đền nhiều nhưng lại là câu hỏi mà các nhà đầu tư khôn ngoan bao giờ cũng hỏi khi tìm hiểu về một cổ phiếu, đó là các giá trị mô hình của doanh nghiệp đã được tính đến chưa và nếu tính thì giá là bao nhiêu. Giá đó là đắt hay rẻ? Giá trị mô hình này có thể là lợi thế thương mại. Thí dụ như PV Driuing có lợi thế độc tôn trong ngành dầu khí là một nhân tố phải tính đến của Công ty này. Cavico Mining có một hợp đồng khai mỏ lớn và lâu dài đến khoảng 15 năm liền đảm bảo công ăn việc làm trong một thời gian dài cũng là lợi thế. Vinamilk có thương hiệu và một loạt nhãn hiệu nổi tiếng, đã ăn vào tâm trí người tiêu dùng cũng là lợi thế lớn trên thị trường.
Nhìn chung, khi nhìn nhận một cổ phiếu phải xét đến rất nhiều nhân tố. Đó chính là điểm khởi phát cho những thành công khi nhà đầu tư bước chân vào thị trường cổ phiếu. Chúng tôi sẽ còn một số bài viết sâu hơn cho bạn đọc về những vấn đề này trong các số báo tới.
Một trong những yếu tố quan trọng nhất khi bước chân vào sân chơi chứng khoán đó là tìm kiếm công ty để bạn có thể mua cổ phiếu. Và một khi bạn đã tìm hiểu và nghiên cứu về loại cổ phiếu mà bạn quan tâm và có một nhà môi giới để giúp bạn mua thì việc mua cổ phiếu lại là một việc tương đối dễ dàng.
Tìm cổ phiếu như thế nào?
Bước 1: Hãy tìm hiểu những báo cáo tài chính công khai của các doanh nghiệp mà có những thông tin liên quan đến chứng khoán.
Bước 2: Hãy phân tích những bản báo cáo hàng quý của công ty đó trong vòng hai hoặc ba năm trở lại đây, và đặc biệt chú ý đến xu hướng lợi nhuận tính theo cổ phiếu và doanh thu của công ty.
Bước 3: Hãy tìm cho mình một công ty có xu thế tăng trưởng ổn định nhất về lợi nhuận tính trên cổ phiếu.
Bước 4: Hãy tính tỉ lệ giá cả - lợi nhuận (tỉ lệ PE) của công ty đó, vì đây là một thước đo giá trị của cổ phiếu. (Tính tỉ lệ này bằng cách chia giá cổ phiếu cho lợi nhuận hàng năm tính theo cổ phiếu.)
Bước 5: Hãy so sánh tỉ lệ PE đó với các quy chuẩn của ngành và với tỉ lệ của chỉ số S&P 500. Tỉ lệ này càng thấp thì giá cổ phiếu càng rẻ so với lợi nhuận.
Bước 6: Hãy chú ý đến cả các món nợ của công ty đó. Vì vậy phải kiểm tra bảng cân đối kế toán của công ty và tìm đến phần thông tin về các món nợ dài hạn.
Bước 7: Ngoài ra cũng cần phải chú ý đến bảng lưu chuyển tiền tệ trong các báo cáo tài chính đó để xem tiền được lưu chuyển như thế nào trong hoạt động kinh doanh của công ty. Bởi vì chắc hẳn rằng bạn sẽ muốn nhìn thấy một bảng lưu chuyển tiền tệ có lãi chứ không phải là thua lỗ.
Mua cổ phiếu như thế nào?
Bước 1: Hãy trang bị cho bản thân đầy đủ những kiến thức về loại cổ phiếu trước khi bạn quyết định mua.
Bước 2: Hãy quyết định xem mình cần những gì từ người môi giới chứng khoán. Liệu mình có cần phải gặp trực tiếp người đó không? Liệu chỉ liên lạc với người đó qua điện thoại thôi có được không? Có phải giá cả là mối quan tâm duy nhất của bạn không? Có phải bạn chỉ muốn mua hoặc bán cổ phiếu hay là bạn còn muốn đầu tư cả vào những loại khác như quỹ tương hỗ, trái phiếu hay thậm chí cả cổ phiếu của nước ngoài.
Bước 3: Hãy chọn một nhà môi giới hoặc một công ty môi giới để thay bạn mua những cổ phiếu bạn muốn. Bạn có cần thật nhiều lời khuyên hay không? Nếu câu trả lời là có thì hãy tìm đến một hãng môi giới với dịch vụ trọn gói. Các nhà môi giới càng rẻ tiền sẽ càng cung cấp cho bạn ít lời khuyên mà bạn muốn. Nếu bạn khá tự tin vào khả năng của mình rồi và muốn mua các cổ phiếu giá rẻ? Vậy thì hãy thử tìm đến những lời khuyên và môi giới trên mạng Internet xem sao.
Bước 4: Hãy liên lạc với người môi giới hoặc công ty môi giới chứng khoán để xin một lá đơn, và yêu cầu mở một tài khoản giao dịch chứng khoán.
Bước 5: Khi tài khoản đã được mở bạn có thể bắt đầu ngay việc mua hay bán cổ phiếu của mình.
Bước 6: Hãy rà soát lại các bản báo cáo bạn nhận được và đánh giá lại những gì đang diễn ra trên danh mục đầu tư của mình để xem bạn có đang đi đúng hướng để đạt được những mục tiêu trong đầu tư của bạn không?
Các mẹo vặt và vài lời nhắc nhở
Hãy hỏi bạn bè và đồng nghiệp để tìm cho mình được người môi giới chứng khoán hay công ty môi giới tốt và có uy tín. Nếu bạn không có được những lời khuyên từ một cá nhân nào, thì hãy tìm trên báo chí về tài chính để có những thông tin bạn cần.
Đầu tư chứng khoán không phải là một trò chơi, nó đòi hỏi bạn phải có những kiến thức thực sự và phải có trí thông minh nhất định. Phải nhớ là bạn luôn theo dõi chặt chẽ mọi diễn biến trên thị trường và đưa ra những quyết định sáng suốt kịp thời để bảo vệ chính bản thân mình.
vào cổ phiếu của hãng Chamber Lych, một công ty công nghệ đang nổi tại miền trung nước Mỹ mà không đầu tư vào một công ty lâu năm cũng trong lĩnh vực công nghệ là TechTech vì cho rằng công ty đang thất thế.
Trong hai tháng đầu tiên đầu tư, cổ phiếu của Lych liên tục tăng giá và cổ phiếu của TechTech thì hạ giá dần. Nhưng chỉ sau thời gian đó, đột nhiên cổ phiếu của TechTech lại tăng giá rất cao, trong khi cổ phiếu của Chamber lại đứng yên thậm chí có tin đồn là sẽ xuống giá nên không ai dám mua nữa. Kết quả, số tiền của hai người bạn Lane Jack và Peter Huge đã không phát sinh lợi nhuận, thậm chí có nguy cơ mất sạch. Cả Lane Jack và Peter Huge đều tiếc nuối vì đã không đầu tư vào cổ phiếu của TechTech.
Trong đầu tư chứng khoán việc lựa chọn cổ phiếu sẽ là rất quan trọng. Nó sẽ quyết định việc thành bại của cả quá trình đầu tư. Nhiều khi nhà đầu tư không nên nghe theo những gì nhà môi giới chứng khoán nói mà hãy dựa vào chính sự phân tích và suy xét của mình.
Mua loại cổ phiếu nào
Khi đã quyết định đầu tư vào cổ phiếu thường phải nghiên cứu xem loại cổ phiếu nào là hiệu quả nhất. Đây chính là lúc cần những thông tin về phân tích chứng khoán và tình hình công ty vì ít có cách nào mất tiền nhanh hơn là mua phải chứng khoán không tốt.
Một số tiêu thức để so sánh và lựa chọn:
- Chọn ngành cổ phiếu: ngành công nghiệp, nông nghiệp, giao thông vận tải, tài chính hay dịch vụ công cộng... Có thể đi vào nhiều ngành chi tiết hơn, ví dụ trong công nghiệp có thể là công nghiệp khai thác, công nghiệp chế biến hoặc công nghiệp sản xuất. Phân tích từng ngành kinh tế về tính chất, thị trường, khả năng phát triển, tăng trưởng bình quân, khả năng cạnh tranh, ảnh hưởng có tính chất chu kỳ;
- Chọn bất cứ công ty nào trong ngành nào thì cũng nên phân tích tình hình công ty đó trên các mặt: tình hình tài chính, lợi nhuận, lợi tức cổ phần, nhu cầu vốn, tình hình huy động vốn và những loại chứng khoán chủ yếu của công ty, đánh giá tình hình cổ phiếu của công ty về mặt tài chính, vị trí của công ty trong ngành, trình độ ban quản trị, ban điều hành và chính sách quản trị của công ty, địa điểm, vận tải, lao động, nguyên liệu, bằng sáng chế phát minh, v.v...
Muốn phân tích thấu đáo giá trị cổ phiếu của một công ty thì phải xem xét những nhân tố kể trên, đồng thời phải tham khảo sự đánh giá của các Trung tâm phân tích chứng khoán, các tổ chức xếp loại doanh nghiệp. Ngoài ra, cần chú ý đến việc đa dạng hóa cổ phiếu đầu tư để tránh được sự vận động của chu kỳ kinh doanh, sự thay đổi vị trí của một doanh nghiệp... Có thể đa dạng hóa theo nhiều cách như: mua cổ phiếu của nhiều ngành khác nhau; mua cổ phiếu của các công ty khác nhau; mua cổ phiếu của nhiều khu vực khác nhau; mua cổ phiếu của các công ty có những thành phẩm khác nhau; mua ở những thời điểm khác nhau... Tuy nhiên, nếu đa dạng hóa đầu tư quá mức cũng sẽ có những nhược điểm như: làm cho việc quản lý khó khăn, tốn nhiều công sức điều tra và phân tích, làm tăng chi phí mua bán, làm giảm bớt cơ hội đạt lợi nhuận cao.
Khi nào mua?
Một câu trả lời rất đơn giản là “khi nào cần thấy được thì mua”. Bởi vì một số không ít những nhà kinh doanh chứng khoán cho rằng họ thường sai lầm trong việc đánh giá về thị trường nói chung và một số cổ phiếu nói riêng. Nói theo một nghĩa nào đó thì những người kinh doanh chứng khoán là những người đầu tư giá trị, do vậy có những người khi thấy công ty trong giai đoạn hưng thịnh thì mua cổ phiếu và thậm chí có nhiều người thích mua cổ phiếu của những công ty đang ở giai đoạn thất thế.
Từ đầu thế kỷ XVIII ở thị trưưòng chứng khoán Tây Âu và thị trường chứng khoán Mỹ sau này đã đưa ra học thuyết “Đầu tư ngược dòng”. Thuyết này đã đưa ra lời khuyên rằng “vẫn có thể lội ngược dòng sông”. Thực tế cho thấy, đầu tư ngược dòng có khả năng rủi ro rất cao nhưng cũng có cơ may đưa đến lợi nhuận khổng lồ bởi vì rất có thể thời gian thất thế của một công ty sẽ được khôi phục trong tương lai. Có nhiều người có cùng dự đoán lạc quan đó nên số người đầu tư ngược dòng tăng lên. Chính hành động có nhiều người có cùng nhận định, cùng mua cổ phiếu đã làm cho giá trị cổ phiếu được phục hồi uy tín ngay khi công ty này còn thất thế. Do vậy, không nhất thiết cứ phải mua cổ phiếu khi công ty đang có uy tín tốt mà vẫn có thể mua cổ phiếu khi công ty đang thất thế.
Sưu tầm
Trang thông tin tổng hợp Phố Chứng Khoán
Thursday, January 5, 2012
Domain Logic and SQL
Domain Logic and SQL
Over the last couple of decades we've seen a growing gap between database-oriented software developers and in-memory application software developers. This leads to many disputes about how to use database features such as SQL and stored procedures. In this article I look at the question of whether to place business logic in SQL queries or in-memory code, considering primarily performance and maintainability based on an example of a simple, but rich SQL query.
February 2003
Martin Fowler
Translations: Japanese
Tags: database
Contents
Complex Queries
Transaction Script
Domain Model
Logic in SQL
Looking at Performance
Modifiability
Understandability
Avoiding Duplication
Encapsulation
Database Portability
Testability
Summing Up
Look at any recent book on building enterprise applications (such as my recent P of EAA) and you'll find a breakdown of logic into multiple layers which separate out different parts of an enterprise application. Different authors use different layers, but a common theme is a separation between domain logic (business rules) and data source logic (where data comes from). Since a large part of enterprise application data is stored on relational databases, this layering scheme seeks to separate business logic from the relational database
Many application developers, particularly strong OO developers like myself, tend to treat relational databases as a storage mechanism that is best hidden away. Frameworks exist who tout the advantages of shielding application developers from the complexities of SQL.
Yet SQL is much more than a simple data update and retrieval mechanism. SQL's query processing can perform many tasks. By hiding SQL, application developers are excluding a powerful tool.
In this article I want to explore the pros and cons of using rich SQL queries that may contain domain logic. I have to declare that I bring a OO bias to the discussion, but I've lived on the other side too. (One former client's OO expert group ran me out of the company because I was a "data modeler".)
Complex Queries
Relational databases all support a standard query language - SQL. Fundamentally I believe that SQL is the primary reason why relational databases have succeeded to the extent they have. A standard way of interacting with databases has provided a strong degree of vendor independence, which both helped the rise of relational databases, and helped see off the OO challenge.
SQL has many strengths, but a particular one is extremely powerful capabilities for querying the database, allowing clients to filter and summarize large amounts of data with very few lines of SQL code. Yet using powerful SQL queries often embed domain logic, which goes against the basic principles of a layered enterprise application architecture.
To explore this topic further, let's play with a simple example. We'll begin with a data model along the lines of Figure 1. Imagine our company has a special discount, which we'll call the Cuillen. Customers qualify for the Cuillen discount if they make at least one order in the month which includes more than $5000 worth of Talisker. Note that two orders in the same month of $3000 each doesn't count, there must be a single order for more than $5000. Let's imagine a you want to look at a particular customer and determine which months in the last year they qualified for a Cuillen discount. I'll ignore the user interface and just assume that what we want is a list of numbers corresponding to their qualifying months.
Figure 1: The database schema for the example (UML notation)
There are many ways we can answer this question. I'll begin with three crude alternatives: transaction script, domain model, and complex SQL.
For all these examples, I'm going to illustrate them using the Ruby programming language. I'm going out on a bit of a limb here: usually I use Java and/or C# to illustrate these things as most application developers can read C-based languages. I'm picking Ruby somewhat as an experiment. I like the language because it encourages compact yet well-structured code and makes it easy to write in an OO style. It's my language of choice for scripting. I've added a quick ruby syntax guide based on the ruby I'm using here.
Transaction Script
Transaction script is the pattern name I coined for a procedural style of handling a request in P of EAA. In this case the procedure reads in all the data it might need and then does the selection and manipulation in-memory to figure out which months are needed.
def cuillen_months name
customerID = find_customerID_named(name)
result = []
find_orders(customerID).each do |row|
result << row['date'].month if cuillen?(row['orderID'])
end
return result.uniq
end
def cuillen? orderID
talisker_total = 0.dollars
find_line_items_for_orderID(orderID).each do |row|
talisker_total += row['cost'].dollars if 'Talisker' == row['product']
end
return (talisker_total > 5000.dollars)
end
The two methods, cuillen_months and cuillen?, contain the domain logic. They use a number of "finder" methods that issue queries to the database.
def find_customerID_named name
sql = 'SELECT * from customers where name = ?'
return $dbh.select_one(sql, name)['customerID']
end
def find_orders customerID
result = []
sql = 'SELECT * FROM orders WHERE customerID = ?'
$dbh.execute(sql, customerID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end
def find_line_items_for_orderID orderID
result = []
sql = 'SELECT * FROM lineItems l WHERE orderID = ?'
$dbh.execute(sql, orderID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end
In many ways this is a very simple minded approach, in particular it's very inefficient in its use of SQL - requiring multiple queries to pull back the data (2 + N where N is the number of orders). Don't worry about that too much at the moment, I'll talk about how to improve that later. Concentrate instead on essence of the approach: read in all the data you have to consider, then loop through and select what you need.
(As an aside, the domain logic above is done that way to make it easy to read - but it isn't what I feel is idiomatic Ruby. I'd prefer the method below which makes more use of Ruby's powerful blocks and collection methods. This code will look odd to many people, but Smalltalkers should enjoy it.)
def cuillen_months2 name
customerID = find_customerID_named(name)
qualifying_orders = find_orders(customerID).select {|row| cuillen?(row['orderID'])}
return (qualifying_orders.collect {|row| row['date'].month}).uniq
end
Domain Model
For the second starting point, we'll consider a classical object-oriented domain model. In this case we create in-memory objects, which in this case mirror the database tables (in real systems they usually aren't exact mirrors.) A set of finder objects loads these objects from the database, once we have the objects in memory, we then run the logic on them.
We'll start with the finders. They slam queries against the database and create the objects.
class CustomerMapper
def find name
result = nil
sql = 'SELECT * FROM customers WHERE name = ?'
return load($dbh.select_one(sql, name))
end
def load row
result = Customer.new(row['customerID'], row['NAME'])
result.orders = OrderMapper.new.find_for_customer result
return result
end
end
class OrderMapper
def find_for_customer aCustomer
result = []
sql = "SELECT * FROM orders WHERE customerID = ?"
$dbh.select_all(sql, aCustomer.db_id) {|row| result << load(row)}
load_line_items result
return result
end
def load row
result = Order.new(row['orderID'], row['date'])
return result
end
def load_line_items orders
#Cannot load with load(row) as connection gets busy
orders.each do
|anOrder| anOrder.line_items = LineItemMapper.new.find_for_order anOrder
end
end
end
class LineItemMapper
def find_for_order order
result = []
sql = "select * from lineItems where orderID = ?"
$dbh.select_all(sql, order.db_id) {|row| result << load(row)}
return result
end
def load row
return LineItem.new(row['lineNumber'], row['product'], row['cost'].to_i.dollars)
end
end
These load methods load the following classes
class Customer...
attr_accessor :name, :db_id, :orders
def initialize db_id, name
@db_id, @name = db_id, name
end
class Order...
attr_accessor :date, :db_id, :line_items
def initialize (id, date)
@db_id, @date, @line_items = id, date, []
end
class LineItem...
attr_reader :line_number, :product, :cost
def initialize line_number, product, cost
@line_number, @product, @cost = line_number, product, cost
end
The logic of determining the cuillen months can be described in a couple of methods.
class Customer...
def cuillenMonths
result = []
orders.each do |o|
result << o.date.month if o.cuillen?
end
return result.uniq
end
class Order...
def cuillen?
discountableAmount = 0.dollars
line_items.each do |line|
discountableAmount += line.cost if 'Talisker' == line.product
end
return discountableAmount > 5000.dollars
end
This solution is longer than the transaction script version. However it's worth pointing out that the logic to load the objects and the actual domain logic are more separated. Any other processing on this set of domain objects would use the same load logic. So if we were doing a lot of different bits of domain logic the effort of the load logic would be amortized across all the domain logic, which would make it less of an issue. That cost can be even further reduced by techniques such as Metadata Mapping.
Again there's a lot of SQL queries (2 + number of orders).
Logic in SQL
With both of the first two, the database is used pretty much as a storage mechanism. All we've done is asked for all the records from a particular table with some very simple filtering. SQL is a very powerful query language and can do much more than the simple filtering that these examples use.
Using SQL to its full extent we can do all the work in SQL
def discount_months customerID
sql = <<-END_SQL
SELECT DISTINCT MONTH(o.date) AS month
FROM lineItems l
INNER JOIN orders o ON l.orderID = o.orderID
INNER JOIN customers c ON o.customerID = c.customerID
WHERE (c.name = ?) AND (l.product = 'Talisker')
GROUP BY o.orderID, o.date, c.NAME
HAVING (SUM(l.cost) > 5000)
END_SQL
result = []
$dbh.select_all(sql, customerID) {|row| result << row['month']}
return result
end
Although I've referred to this as a complex query, it's only complex in comparison to the simple select and where clause queries of the earlier examples. SQL queries can get far more complicated than this one, although many application developers would shy away from even a query as minimally complex as this.
Looking at Performance
One of the first questions people consider with this kind of thing is performance. Personally I don't think performance should be the first question. My philosophy is that most of the time you should focus on writing maintainable code. Then use a profiler to identify hot spots and then replace only those hot spots with faster but less clear code. The main reason I do this is because in most systems only a very small proportion of the code is actually performance critical, and it's much easier to improve the performance of well factored maintainable code.
But in any case, let's consider the performance trade-offs first. On my little laptop the complex SQL query performs twenty times faster than the other two approaches. Now you cannot form any conclusions about the the performance of a data center server from an svelte but elderly laptop, but I would be surprised if the complex query would be less than an order of magnitude faster than the in memory approaches.
Part of the reason for this is that the in-memory approaches are written in a way that is very inefficient in terms of SQL queries. As I've pointed out in their descriptions, each one issues a SQL query for every order that a customer has - and my test database has a thousand orders for each customer.
We can reduce this load considerably by rewriting the in-memory programs to use a single SQL query. I'll start with the transaction script.
SQL = <<-END_SQL
SELECT * from orders o
INNER JOIN lineItems li ON li.orderID = o.orderID
INNER JOIN customers c ON c.customerID = o.customerID
WHERE c.name = ?
END_SQL
def cuillen_months customer_name
orders = {}
$dbh.select_all(SQL, customer_name) do |row|
process_row(row, orders)
end
result = []
orders.each_value do |o|
result << o.date.month if o.talisker_cost > 5000.dollars
end
return result.uniq
end
def process_row row, orders
orderID = row['orderID']
orders[orderID] = Order.new(row['date']) unless orders[orderID]
if 'Talisker' == row['product']
orders[orderID].talisker_cost += row['cost'].dollars
end
end
class Order
attr_accessor :date, :talisker_cost
def initialize date
@date, @talisker_cost = date, 0.dollars
end
end
This is a pretty big change to the transaction script, but it speeds things up by a factor of three.
I can do a similar trick with the domain model. Here we see an advantage of the domain model's more complex structure. I only need to modify the loading method, the business logic in the domain objects themselves does not need to change.
class CustomerMapper
SQL = <<-END_SQL
SELECT c.customerID,
c.NAME as NAME,
o.orderID,
o.date as date,
li.lineNumber as lineNumber,
li.product as product,
li.cost as cost
FROM customers c
INNER JOIN orders o ON o.customerID = c.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE c.name = ?
END_SQL
def find name
result = nil
om = OrderMapper.new
lm = LineItemMapper.new
$dbh.execute (SQL, name) do |sth|
sth.each do |row|
result = load(row) if result == nil
unless result.order(row['orderID'])
result.add_order(om.load(row))
end
result.order(row['orderID']).add_line_item(lm.load(row))
end
end
return result
end
(I'm telling a little lie when I say that I don't need to modify the domain objects. In order to get decent performance I needed to change the data structure of customer so that the orders were held in a hash rather than an array. But again, it was a very self-contained change, and didn't impact the code for determining the discount.)
There's a few points here. Firstly it's worth remembering that in-memory code can often by boosted by more intelligent queries. It's always worth looking to see if you are calling the database multiple times, and if there's a way to do it with a single call instead. This is particularly easy to overlook when you have a domain model because people usually think of class at a time access. (I've even seen cases where people load a single row at a time, but that pathological behavior is relatively rare.)
One of the biggest differences between the transaction script and the domain model is the impact of changing the query structure. For the transaction script, it pretty much means altering the entire script. Furthermore if there were many domain logic scripts using similar data, each one would have to be changed. With the domain model you alter a nicely separated section of the code and the domain logic itself doesn't have to change. This is a big deal if you have a lot of domain logic. This is the general trade off between transaction scripts and domain logic - there's an initial cost in complexity of database access for a domain logic which pays off iff you have a lot of domain logic.
But even with the multi-table query, the in-memory approaches are still not as fast as the complex SQL - by a factor of 6 in my case. This makes sense: the complex SQL does the selection and summing of costs in the database and only has to schlep a handful of values back to the client, while the in-memory approach needs to schlep five thousand rows of data back to the client.
Performance isn't the only factor in deciding what route to go, but it's often a concluding one. If you have a hot spot that you absolutely need to improve, then other factors come second. As a result many fans of domain models follow the system of doing things in-memory as a default, and using things like complex queries for hot spots only when they have to.
It's also worth pointing out that this example is one that plays to a database's strengths. Many queries don't have the strong elements of selection and aggregation that this one does, and won't show such a performance change. In addition multi-user scenarios often cause surprising changes to the way queries behave, so real profiling has to be done under a realistic multi-user load. You may find that locking issues outweigh anything you can get by faster individual queries.
Modifiability
For any long-lived enterprise application, you can be sure of one thing - it's going to change a lot. As a result you have to ensure that the system is organized in such a way that's easy to change. Modifiability is probably the main reason why people put business logic in memory.
SQL can do many things, but there limits to its capabilities. Some things that it can do require quite clever coding, as a browse of algorithms for the median of a dataset displays. Others are impossible to make without resorting to non-standard extensions, which is a problem if you want portability.
Often you want to run business logic before you write data into the database, particularly if you working on some pending information. Loading into a database can be problematic because often you want pending session data to be isolated from fully accepted data. This session data often shouldn't be subject to the same validation rules as fully accepted data.
Understandability
SQL is often seen as a special language, one that's not something that application developers should need to deal with. Indeed many database frameworks like to say how by using them you avoid needing to deal with SQL. I've always found that a somewhat strange argument, since I've always been fairly comfortable with moderately complex SQL. However many developers find SQL harder to deal with than traditional languages, and a number of SQL idioms are hard to fathom to all but SQL experts.
A good test for you is to look at the three solutions, and see which makes the domain logic easiest to follow and thus modify. I find the domain model version, which is just a couple of methods, the easiest to follow; in large part because the data access is separated out. Next I prefer the SQL version over the in-memory transaction script. But I'm sure other readers would have other preferences.
If most of a team is less comfortable with SQL, then that's a reason to keep domain logic away from SQL. (It's also a reason to consider training more people in SQL - at least to an intermediate level.) This is one of those situations where you have to take into account the make up of your team - people do affect architectural decisions.
Avoiding Duplication
One of the simplest, yet most powerful, design principles I've come across is avoiding duplication - formulated by the Pragmatic Programmers as the DRY (Don't Repeat Yourself) principle.
To think about the DRY principle for this case, let's consider another requirement for this application - a list of orders for a customer on a particular month showing the orderID, date, total cost and whether this order is a qualifying order for the Cuillen plan. All of this sorted by the total cost.
Using the domain object approach to handling this query we need to add a method to the order to calculate the total cost.
class Order...
def total_cost
result = 0.dollars
line_items.each {|line| result += line.cost}
return result
end
With that in place then it's easy to print the order list
class Customer
def order_list month
result = ''
selected_orders = orders.select {|o| month == o.date.month}
selected_orders.sort! {|o1, o2| o2.total_cost <=> o1.total_cost}
selected_orders.each do |o|
result << sprintf("%10d %20s %10s %3s\n",
o.db_id, o.date, o.total_cost, o.discount?)
end
return result
end
Defining the same query using a single SQL statement requires a correlated sub-query - which some people find daunting.
def order_list customerName, month
sql = <<-END_SQL
SELECT o.orderID, o.date, sum(li.cost) as totalCost,
CASE WHEN
(SELECT SUM(li.cost)
FROM lineitems li
WHERE li.product = 'Talisker'
AND o.orderID = li.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE (c.name = ?)
AND (MONTH(o.date) = ?)
GROUP by o.orderID, o.date
ORDER BY totalCost desc
END_SQL
result = ""
$dbh.select_all(sql, customerName, month) do |row|
result << sprintf("%10d %20s %10s %3s\n",
row['orderID'],
row['date'],
row['totalCost'],
row['isCuillen'])
end
return result
end
Different people will differ about which of these two is the easiest to understand. But the issue I'm chewing on here is that of duplication. This query duplicates logic from the original query that just gives the months. The domain object approach does not have this duplication - should I wish to change the definition for the cuillen plan, all I have to do is to alter the definition of cuillen? and all uses are updated.
Now it isn't fair to trash SQL on the duplication issue - because you can avoid duplication in the rich SQL approach as well. The trick, as database aficionados must be gasping to point out, is to use a view.
I can define a view, for simplicity called Orders2 based on the following query.
SELECT TOP 100 PERCENT
o.orderID, c.name, c.customerID, o.date,
SUM(li.cost) AS totalCost,
CASE WHEN
(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker'
AND o.orderID = li2.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.orders o
INNER JOIN dbo.lineItems li ON o.orderID = li.orderID
INNER JOIN dbo.CUSTOMERS c ON o.customerID = c.customerID
GROUP BY o.orderID, c.name, c.customerID, o.date
ORDER BY totalCost DESC
I can now use this view for both getting the months and for producing the order list
def cuillen_months_view customerID
sql = "SELECT DISTINCT month(date) FROM orders2 WHERE name = ? AND isCuillen = 'Y'"
result = []
$dbh.select_all(sql, customerID) {|row| result << row[0]}
return result
end
def order_list_from_view customerName, month
result = ''
sql = "SELECT * FROM Orders2 WHERE name = ? AND month(date) = ?"
$dbh.select_all(SQL, customerName, month) do |row|
result << sprintf("%10d %10s %10s\n",
row['orderID'],
row['date'],
row['isCuillen'])
end
return result
end
The view simplifies both the queries and puts the key business logic into a single place.
It seems that people rarely discuss using views like this to avoid duplication. Books I've seen on SQL don't seem to discuss doing this kind of thing. In some environments this is difficult because of the organizational and cultural splits between database and application developers. Often application developers aren't allowed to define views and database developers form a bottleneck that discourages application developers from getting views like this done. DBAs may even refuse to build views that are only needed by a single application. But my opinion is that SQL deserves as much care to design as anything else.
Encapsulation
Encapsulation is a well known principle of object-oriented design, and it's one that I think applies well to general software design. Essentially it says that a program should be divided into modules that hide data structures behind an interface of procedure calls. The purpose of this is to allow you to change the underlying data structure without causing a large ripple effect across the system.
In this case, the question is how can we encapsulate the database? A good encapsulation scheme would allow us to alter the database schema without causing a painful round of editing across an application.
For enterprise applications, a common form of encapsulation is a layering, where we strive to separate domain logic from data source logic. That way the code that works on business logic isn't affected when we alter the database design.
The domain model version is a good example of this kind of encapsulation. The business logic works only on in-memory objects. How the data gets there is completely separated. The transaction script approach has some database encapsulation through the find methods, although the database structure is more revealed through the returning result sets.
In an application world, you achieve encapsulation through an API of procedures and objects. The SQL equivalent is to use views. If you change a table you can create a view which supports the old table. The biggest issue here is with updates, which often can't be done properly with views. This is why many shops wrap all DML with stored procedures.
Encapsulation is about more than just supporting changes to views. It's also about the difference between accessing data and defining business logic. With SQL the two can easily be blurred, yet you can still make some form of separation.
For an example, consider the view I defined above to avoid duplication in queries. That view is a single view which could be split along the lines of a data source and business logic separation. A data source view would look something like this
SELECT o.orderID, o.date, c.customerID, c.name,
SUM(li.cost) AS total_cost,
(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker' AND o.orderID =li2.orderID
) AS taliskerCost
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN dbo.lineItems li ON li.orderID = o.orderID
GROUP BY o.orderID, o.date, c.customerID, c.name
We can then use this view in other views that focus more on domain logic. Here's one that indicates the Cuillen eligibility
SELECT orderID, date, customerID, name, total_cost,
CASE WHEN taliskerCost > 5000 THEN 'Y' ELSE 'N' END AS isCuillen
FROM dbo.OrdersTal
This kind of thinking can also be applied to cases where we're loading data into a domain model. Earlier on I talked about how performance issues with a domain model could be dealt with by taking the entire query for cuillen months and substituting it with a single SQL query. Another approach would be to use the above data source view. This would allow us to keep a higher performance while still keeping the domain logic in a domain model. The line items would only be loaded in if necessary using a Lazy Load, but suitable summary information could be brought in via the view.
Using views, or indeed stored procedures, provides encapsulation only up to a point. In many enterprise applications data comes from multiple sources, not just multiple relational databases, but also legacy systems, other applications, and files. Indeed the growth of XML will probably see more data coming from flat files shared via networks. In this case full encapsulation really can only be done by a layer within the application code, which further implies that domain logic should also sit in memory.
Database Portability
One reason why many developers shy away from complex SQL is the issue of database portability. After all the promise of SQL is that it allows you to use the same standard SQL on a bevy of database platforms, allowing to change database vendors easily
In reality that's always been a bit of a fudge. In practice SQL is mostly standard but with all sort of little places to trip you up. With care, however, you can create SQL that isn't too painful to shift between database servers. But to do this you lose a lot of capabilities.
The decision about database portability ends up being particular to your project. These days it's much less of an issue than it used to be. The database market has shaken out so most places fall into one of the three major camps. Corporations often have strong commitments to whichever camp they are in. If you consider that changing databases is very unlikely due to this kind of investment, you might as well start taking advantage of the special features your database provides.
Some people still need portability, such as people who provide products that can be installed and interfaced with multiple databases. In this case there is a stronger argument against putting logic into SQL since you have to be so careful about which parts of SQL you can safely use.
Testability
Testability isn't a topic that's tended to come up enough in discussions about design. One of the benefits of Test Driven Development (TDD) is that it's rekindled the notion that testability is a vital part of design.
Common practice in SQL seems to not test. Indeed it's not uncommon to find essential views and stored procedures not even held in configuration management tools. Yet it's certainly possible to have testable SQL. The popular xunit family has a number of tools that can be used for testing within a database environment. Evolutionary database techniques such as test databases can be used to provide a testable environment very similar to what TDD programmers enjoy.
The main area that can make a difference is performance. While direct SQL is often faster in production, it can be much faster to run tests on business logic in memory if the database interface is designed in such a way that you can replace the actual database connection with a Service Stub.
Summing Up
So far I've talked about the issues. Now it's time to draw conclusions. Fundamentally what you have to do is to consider the various issues I've talked about here, judge them by your biases, and decide which policy to take to using rich queries and putting domain logic in there.
The way I look at the picture, one of the most critical elements is whether your data comes from a single logical relational database, or is scattered across a mass of different, often non-SQL, sources. If it's scattered then you should build a data source layer in memory to encapsulate your data sources and keep your domain logic in memory. In this case the strengths of SQL as a language isn't an issue, because not all of your data is in SQL.
The situation becomes interesting when the vast majority of your data sits in a single logical database. In this case you have two primary issues to consider. One is the choice of programming language: SQL versus your application language. The other is where the code runs, SQL at the database, or in memory.
SQL makes some things easy, but other things more difficult. Some people find SQL easy to work with, others find it horribly cryptic. The teams personal comfort is a big issue here. I would suggest that if you go the route of putting a lot of logic in SQL, don't expect to be portable - use all of your vendors extensions and cheerfully bind yourself to their technology. If you want portability keep logic out of SQL.
So far I've talked about modifiability issues. I think these concerns should come first, but be trumped by any critical performance issues. If you use an in-memory approach and have hot-spots that can be solved by more powerful queries, then do that. I would suggest looking to see how much you can organize performance enhancing queries as data source queries, as I outlined above. That way you can minimize putting domain logic into the SQL.
Over the last couple of decades we've seen a growing gap between database-oriented software developers and in-memory application software developers. This leads to many disputes about how to use database features such as SQL and stored procedures. In this article I look at the question of whether to place business logic in SQL queries or in-memory code, considering primarily performance and maintainability based on an example of a simple, but rich SQL query.
February 2003
Martin Fowler
Translations: Japanese
Tags: database
Contents
Complex Queries
Transaction Script
Domain Model
Logic in SQL
Looking at Performance
Modifiability
Understandability
Avoiding Duplication
Encapsulation
Database Portability
Testability
Summing Up
Look at any recent book on building enterprise applications (such as my recent P of EAA) and you'll find a breakdown of logic into multiple layers which separate out different parts of an enterprise application. Different authors use different layers, but a common theme is a separation between domain logic (business rules) and data source logic (where data comes from). Since a large part of enterprise application data is stored on relational databases, this layering scheme seeks to separate business logic from the relational database
Many application developers, particularly strong OO developers like myself, tend to treat relational databases as a storage mechanism that is best hidden away. Frameworks exist who tout the advantages of shielding application developers from the complexities of SQL.
Yet SQL is much more than a simple data update and retrieval mechanism. SQL's query processing can perform many tasks. By hiding SQL, application developers are excluding a powerful tool.
In this article I want to explore the pros and cons of using rich SQL queries that may contain domain logic. I have to declare that I bring a OO bias to the discussion, but I've lived on the other side too. (One former client's OO expert group ran me out of the company because I was a "data modeler".)
Complex Queries
Relational databases all support a standard query language - SQL. Fundamentally I believe that SQL is the primary reason why relational databases have succeeded to the extent they have. A standard way of interacting with databases has provided a strong degree of vendor independence, which both helped the rise of relational databases, and helped see off the OO challenge.
SQL has many strengths, but a particular one is extremely powerful capabilities for querying the database, allowing clients to filter and summarize large amounts of data with very few lines of SQL code. Yet using powerful SQL queries often embed domain logic, which goes against the basic principles of a layered enterprise application architecture.
To explore this topic further, let's play with a simple example. We'll begin with a data model along the lines of Figure 1. Imagine our company has a special discount, which we'll call the Cuillen. Customers qualify for the Cuillen discount if they make at least one order in the month which includes more than $5000 worth of Talisker. Note that two orders in the same month of $3000 each doesn't count, there must be a single order for more than $5000. Let's imagine a you want to look at a particular customer and determine which months in the last year they qualified for a Cuillen discount. I'll ignore the user interface and just assume that what we want is a list of numbers corresponding to their qualifying months.
Figure 1: The database schema for the example (UML notation)
There are many ways we can answer this question. I'll begin with three crude alternatives: transaction script, domain model, and complex SQL.
For all these examples, I'm going to illustrate them using the Ruby programming language. I'm going out on a bit of a limb here: usually I use Java and/or C# to illustrate these things as most application developers can read C-based languages. I'm picking Ruby somewhat as an experiment. I like the language because it encourages compact yet well-structured code and makes it easy to write in an OO style. It's my language of choice for scripting. I've added a quick ruby syntax guide based on the ruby I'm using here.
Transaction Script
Transaction script is the pattern name I coined for a procedural style of handling a request in P of EAA. In this case the procedure reads in all the data it might need and then does the selection and manipulation in-memory to figure out which months are needed.
def cuillen_months name
customerID = find_customerID_named(name)
result = []
find_orders(customerID).each do |row|
result << row['date'].month if cuillen?(row['orderID'])
end
return result.uniq
end
def cuillen? orderID
talisker_total = 0.dollars
find_line_items_for_orderID(orderID).each do |row|
talisker_total += row['cost'].dollars if 'Talisker' == row['product']
end
return (talisker_total > 5000.dollars)
end
The two methods, cuillen_months and cuillen?, contain the domain logic. They use a number of "finder" methods that issue queries to the database.
def find_customerID_named name
sql = 'SELECT * from customers where name = ?'
return $dbh.select_one(sql, name)['customerID']
end
def find_orders customerID
result = []
sql = 'SELECT * FROM orders WHERE customerID = ?'
$dbh.execute(sql, customerID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end
def find_line_items_for_orderID orderID
result = []
sql = 'SELECT * FROM lineItems l WHERE orderID = ?'
$dbh.execute(sql, orderID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end
In many ways this is a very simple minded approach, in particular it's very inefficient in its use of SQL - requiring multiple queries to pull back the data (2 + N where N is the number of orders). Don't worry about that too much at the moment, I'll talk about how to improve that later. Concentrate instead on essence of the approach: read in all the data you have to consider, then loop through and select what you need.
(As an aside, the domain logic above is done that way to make it easy to read - but it isn't what I feel is idiomatic Ruby. I'd prefer the method below which makes more use of Ruby's powerful blocks and collection methods. This code will look odd to many people, but Smalltalkers should enjoy it.)
def cuillen_months2 name
customerID = find_customerID_named(name)
qualifying_orders = find_orders(customerID).select {|row| cuillen?(row['orderID'])}
return (qualifying_orders.collect {|row| row['date'].month}).uniq
end
Domain Model
For the second starting point, we'll consider a classical object-oriented domain model. In this case we create in-memory objects, which in this case mirror the database tables (in real systems they usually aren't exact mirrors.) A set of finder objects loads these objects from the database, once we have the objects in memory, we then run the logic on them.
We'll start with the finders. They slam queries against the database and create the objects.
class CustomerMapper
def find name
result = nil
sql = 'SELECT * FROM customers WHERE name = ?'
return load($dbh.select_one(sql, name))
end
def load row
result = Customer.new(row['customerID'], row['NAME'])
result.orders = OrderMapper.new.find_for_customer result
return result
end
end
class OrderMapper
def find_for_customer aCustomer
result = []
sql = "SELECT * FROM orders WHERE customerID = ?"
$dbh.select_all(sql, aCustomer.db_id) {|row| result << load(row)}
load_line_items result
return result
end
def load row
result = Order.new(row['orderID'], row['date'])
return result
end
def load_line_items orders
#Cannot load with load(row) as connection gets busy
orders.each do
|anOrder| anOrder.line_items = LineItemMapper.new.find_for_order anOrder
end
end
end
class LineItemMapper
def find_for_order order
result = []
sql = "select * from lineItems where orderID = ?"
$dbh.select_all(sql, order.db_id) {|row| result << load(row)}
return result
end
def load row
return LineItem.new(row['lineNumber'], row['product'], row['cost'].to_i.dollars)
end
end
These load methods load the following classes
class Customer...
attr_accessor :name, :db_id, :orders
def initialize db_id, name
@db_id, @name = db_id, name
end
class Order...
attr_accessor :date, :db_id, :line_items
def initialize (id, date)
@db_id, @date, @line_items = id, date, []
end
class LineItem...
attr_reader :line_number, :product, :cost
def initialize line_number, product, cost
@line_number, @product, @cost = line_number, product, cost
end
The logic of determining the cuillen months can be described in a couple of methods.
class Customer...
def cuillenMonths
result = []
orders.each do |o|
result << o.date.month if o.cuillen?
end
return result.uniq
end
class Order...
def cuillen?
discountableAmount = 0.dollars
line_items.each do |line|
discountableAmount += line.cost if 'Talisker' == line.product
end
return discountableAmount > 5000.dollars
end
This solution is longer than the transaction script version. However it's worth pointing out that the logic to load the objects and the actual domain logic are more separated. Any other processing on this set of domain objects would use the same load logic. So if we were doing a lot of different bits of domain logic the effort of the load logic would be amortized across all the domain logic, which would make it less of an issue. That cost can be even further reduced by techniques such as Metadata Mapping.
Again there's a lot of SQL queries (2 + number of orders).
Logic in SQL
With both of the first two, the database is used pretty much as a storage mechanism. All we've done is asked for all the records from a particular table with some very simple filtering. SQL is a very powerful query language and can do much more than the simple filtering that these examples use.
Using SQL to its full extent we can do all the work in SQL
def discount_months customerID
sql = <<-END_SQL
SELECT DISTINCT MONTH(o.date) AS month
FROM lineItems l
INNER JOIN orders o ON l.orderID = o.orderID
INNER JOIN customers c ON o.customerID = c.customerID
WHERE (c.name = ?) AND (l.product = 'Talisker')
GROUP BY o.orderID, o.date, c.NAME
HAVING (SUM(l.cost) > 5000)
END_SQL
result = []
$dbh.select_all(sql, customerID) {|row| result << row['month']}
return result
end
Although I've referred to this as a complex query, it's only complex in comparison to the simple select and where clause queries of the earlier examples. SQL queries can get far more complicated than this one, although many application developers would shy away from even a query as minimally complex as this.
Looking at Performance
One of the first questions people consider with this kind of thing is performance. Personally I don't think performance should be the first question. My philosophy is that most of the time you should focus on writing maintainable code. Then use a profiler to identify hot spots and then replace only those hot spots with faster but less clear code. The main reason I do this is because in most systems only a very small proportion of the code is actually performance critical, and it's much easier to improve the performance of well factored maintainable code.
But in any case, let's consider the performance trade-offs first. On my little laptop the complex SQL query performs twenty times faster than the other two approaches. Now you cannot form any conclusions about the the performance of a data center server from an svelte but elderly laptop, but I would be surprised if the complex query would be less than an order of magnitude faster than the in memory approaches.
Part of the reason for this is that the in-memory approaches are written in a way that is very inefficient in terms of SQL queries. As I've pointed out in their descriptions, each one issues a SQL query for every order that a customer has - and my test database has a thousand orders for each customer.
We can reduce this load considerably by rewriting the in-memory programs to use a single SQL query. I'll start with the transaction script.
SQL = <<-END_SQL
SELECT * from orders o
INNER JOIN lineItems li ON li.orderID = o.orderID
INNER JOIN customers c ON c.customerID = o.customerID
WHERE c.name = ?
END_SQL
def cuillen_months customer_name
orders = {}
$dbh.select_all(SQL, customer_name) do |row|
process_row(row, orders)
end
result = []
orders.each_value do |o|
result << o.date.month if o.talisker_cost > 5000.dollars
end
return result.uniq
end
def process_row row, orders
orderID = row['orderID']
orders[orderID] = Order.new(row['date']) unless orders[orderID]
if 'Talisker' == row['product']
orders[orderID].talisker_cost += row['cost'].dollars
end
end
class Order
attr_accessor :date, :talisker_cost
def initialize date
@date, @talisker_cost = date, 0.dollars
end
end
This is a pretty big change to the transaction script, but it speeds things up by a factor of three.
I can do a similar trick with the domain model. Here we see an advantage of the domain model's more complex structure. I only need to modify the loading method, the business logic in the domain objects themselves does not need to change.
class CustomerMapper
SQL = <<-END_SQL
SELECT c.customerID,
c.NAME as NAME,
o.orderID,
o.date as date,
li.lineNumber as lineNumber,
li.product as product,
li.cost as cost
FROM customers c
INNER JOIN orders o ON o.customerID = c.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE c.name = ?
END_SQL
def find name
result = nil
om = OrderMapper.new
lm = LineItemMapper.new
$dbh.execute (SQL, name) do |sth|
sth.each do |row|
result = load(row) if result == nil
unless result.order(row['orderID'])
result.add_order(om.load(row))
end
result.order(row['orderID']).add_line_item(lm.load(row))
end
end
return result
end
(I'm telling a little lie when I say that I don't need to modify the domain objects. In order to get decent performance I needed to change the data structure of customer so that the orders were held in a hash rather than an array. But again, it was a very self-contained change, and didn't impact the code for determining the discount.)
There's a few points here. Firstly it's worth remembering that in-memory code can often by boosted by more intelligent queries. It's always worth looking to see if you are calling the database multiple times, and if there's a way to do it with a single call instead. This is particularly easy to overlook when you have a domain model because people usually think of class at a time access. (I've even seen cases where people load a single row at a time, but that pathological behavior is relatively rare.)
One of the biggest differences between the transaction script and the domain model is the impact of changing the query structure. For the transaction script, it pretty much means altering the entire script. Furthermore if there were many domain logic scripts using similar data, each one would have to be changed. With the domain model you alter a nicely separated section of the code and the domain logic itself doesn't have to change. This is a big deal if you have a lot of domain logic. This is the general trade off between transaction scripts and domain logic - there's an initial cost in complexity of database access for a domain logic which pays off iff you have a lot of domain logic.
But even with the multi-table query, the in-memory approaches are still not as fast as the complex SQL - by a factor of 6 in my case. This makes sense: the complex SQL does the selection and summing of costs in the database and only has to schlep a handful of values back to the client, while the in-memory approach needs to schlep five thousand rows of data back to the client.
Performance isn't the only factor in deciding what route to go, but it's often a concluding one. If you have a hot spot that you absolutely need to improve, then other factors come second. As a result many fans of domain models follow the system of doing things in-memory as a default, and using things like complex queries for hot spots only when they have to.
It's also worth pointing out that this example is one that plays to a database's strengths. Many queries don't have the strong elements of selection and aggregation that this one does, and won't show such a performance change. In addition multi-user scenarios often cause surprising changes to the way queries behave, so real profiling has to be done under a realistic multi-user load. You may find that locking issues outweigh anything you can get by faster individual queries.
Modifiability
For any long-lived enterprise application, you can be sure of one thing - it's going to change a lot. As a result you have to ensure that the system is organized in such a way that's easy to change. Modifiability is probably the main reason why people put business logic in memory.
SQL can do many things, but there limits to its capabilities. Some things that it can do require quite clever coding, as a browse of algorithms for the median of a dataset displays. Others are impossible to make without resorting to non-standard extensions, which is a problem if you want portability.
Often you want to run business logic before you write data into the database, particularly if you working on some pending information. Loading into a database can be problematic because often you want pending session data to be isolated from fully accepted data. This session data often shouldn't be subject to the same validation rules as fully accepted data.
Understandability
SQL is often seen as a special language, one that's not something that application developers should need to deal with. Indeed many database frameworks like to say how by using them you avoid needing to deal with SQL. I've always found that a somewhat strange argument, since I've always been fairly comfortable with moderately complex SQL. However many developers find SQL harder to deal with than traditional languages, and a number of SQL idioms are hard to fathom to all but SQL experts.
A good test for you is to look at the three solutions, and see which makes the domain logic easiest to follow and thus modify. I find the domain model version, which is just a couple of methods, the easiest to follow; in large part because the data access is separated out. Next I prefer the SQL version over the in-memory transaction script. But I'm sure other readers would have other preferences.
If most of a team is less comfortable with SQL, then that's a reason to keep domain logic away from SQL. (It's also a reason to consider training more people in SQL - at least to an intermediate level.) This is one of those situations where you have to take into account the make up of your team - people do affect architectural decisions.
Avoiding Duplication
One of the simplest, yet most powerful, design principles I've come across is avoiding duplication - formulated by the Pragmatic Programmers as the DRY (Don't Repeat Yourself) principle.
To think about the DRY principle for this case, let's consider another requirement for this application - a list of orders for a customer on a particular month showing the orderID, date, total cost and whether this order is a qualifying order for the Cuillen plan. All of this sorted by the total cost.
Using the domain object approach to handling this query we need to add a method to the order to calculate the total cost.
class Order...
def total_cost
result = 0.dollars
line_items.each {|line| result += line.cost}
return result
end
With that in place then it's easy to print the order list
class Customer
def order_list month
result = ''
selected_orders = orders.select {|o| month == o.date.month}
selected_orders.sort! {|o1, o2| o2.total_cost <=> o1.total_cost}
selected_orders.each do |o|
result << sprintf("%10d %20s %10s %3s\n",
o.db_id, o.date, o.total_cost, o.discount?)
end
return result
end
Defining the same query using a single SQL statement requires a correlated sub-query - which some people find daunting.
def order_list customerName, month
sql = <<-END_SQL
SELECT o.orderID, o.date, sum(li.cost) as totalCost,
CASE WHEN
(SELECT SUM(li.cost)
FROM lineitems li
WHERE li.product = 'Talisker'
AND o.orderID = li.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE (c.name = ?)
AND (MONTH(o.date) = ?)
GROUP by o.orderID, o.date
ORDER BY totalCost desc
END_SQL
result = ""
$dbh.select_all(sql, customerName, month) do |row|
result << sprintf("%10d %20s %10s %3s\n",
row['orderID'],
row['date'],
row['totalCost'],
row['isCuillen'])
end
return result
end
Different people will differ about which of these two is the easiest to understand. But the issue I'm chewing on here is that of duplication. This query duplicates logic from the original query that just gives the months. The domain object approach does not have this duplication - should I wish to change the definition for the cuillen plan, all I have to do is to alter the definition of cuillen? and all uses are updated.
Now it isn't fair to trash SQL on the duplication issue - because you can avoid duplication in the rich SQL approach as well. The trick, as database aficionados must be gasping to point out, is to use a view.
I can define a view, for simplicity called Orders2 based on the following query.
SELECT TOP 100 PERCENT
o.orderID, c.name, c.customerID, o.date,
SUM(li.cost) AS totalCost,
CASE WHEN
(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker'
AND o.orderID = li2.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.orders o
INNER JOIN dbo.lineItems li ON o.orderID = li.orderID
INNER JOIN dbo.CUSTOMERS c ON o.customerID = c.customerID
GROUP BY o.orderID, c.name, c.customerID, o.date
ORDER BY totalCost DESC
I can now use this view for both getting the months and for producing the order list
def cuillen_months_view customerID
sql = "SELECT DISTINCT month(date) FROM orders2 WHERE name = ? AND isCuillen = 'Y'"
result = []
$dbh.select_all(sql, customerID) {|row| result << row[0]}
return result
end
def order_list_from_view customerName, month
result = ''
sql = "SELECT * FROM Orders2 WHERE name = ? AND month(date) = ?"
$dbh.select_all(SQL, customerName, month) do |row|
result << sprintf("%10d %10s %10s\n",
row['orderID'],
row['date'],
row['isCuillen'])
end
return result
end
The view simplifies both the queries and puts the key business logic into a single place.
It seems that people rarely discuss using views like this to avoid duplication. Books I've seen on SQL don't seem to discuss doing this kind of thing. In some environments this is difficult because of the organizational and cultural splits between database and application developers. Often application developers aren't allowed to define views and database developers form a bottleneck that discourages application developers from getting views like this done. DBAs may even refuse to build views that are only needed by a single application. But my opinion is that SQL deserves as much care to design as anything else.
Encapsulation
Encapsulation is a well known principle of object-oriented design, and it's one that I think applies well to general software design. Essentially it says that a program should be divided into modules that hide data structures behind an interface of procedure calls. The purpose of this is to allow you to change the underlying data structure without causing a large ripple effect across the system.
In this case, the question is how can we encapsulate the database? A good encapsulation scheme would allow us to alter the database schema without causing a painful round of editing across an application.
For enterprise applications, a common form of encapsulation is a layering, where we strive to separate domain logic from data source logic. That way the code that works on business logic isn't affected when we alter the database design.
The domain model version is a good example of this kind of encapsulation. The business logic works only on in-memory objects. How the data gets there is completely separated. The transaction script approach has some database encapsulation through the find methods, although the database structure is more revealed through the returning result sets.
In an application world, you achieve encapsulation through an API of procedures and objects. The SQL equivalent is to use views. If you change a table you can create a view which supports the old table. The biggest issue here is with updates, which often can't be done properly with views. This is why many shops wrap all DML with stored procedures.
Encapsulation is about more than just supporting changes to views. It's also about the difference between accessing data and defining business logic. With SQL the two can easily be blurred, yet you can still make some form of separation.
For an example, consider the view I defined above to avoid duplication in queries. That view is a single view which could be split along the lines of a data source and business logic separation. A data source view would look something like this
SELECT o.orderID, o.date, c.customerID, c.name,
SUM(li.cost) AS total_cost,
(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker' AND o.orderID =li2.orderID
) AS taliskerCost
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN dbo.lineItems li ON li.orderID = o.orderID
GROUP BY o.orderID, o.date, c.customerID, c.name
We can then use this view in other views that focus more on domain logic. Here's one that indicates the Cuillen eligibility
SELECT orderID, date, customerID, name, total_cost,
CASE WHEN taliskerCost > 5000 THEN 'Y' ELSE 'N' END AS isCuillen
FROM dbo.OrdersTal
This kind of thinking can also be applied to cases where we're loading data into a domain model. Earlier on I talked about how performance issues with a domain model could be dealt with by taking the entire query for cuillen months and substituting it with a single SQL query. Another approach would be to use the above data source view. This would allow us to keep a higher performance while still keeping the domain logic in a domain model. The line items would only be loaded in if necessary using a Lazy Load, but suitable summary information could be brought in via the view.
Using views, or indeed stored procedures, provides encapsulation only up to a point. In many enterprise applications data comes from multiple sources, not just multiple relational databases, but also legacy systems, other applications, and files. Indeed the growth of XML will probably see more data coming from flat files shared via networks. In this case full encapsulation really can only be done by a layer within the application code, which further implies that domain logic should also sit in memory.
Database Portability
One reason why many developers shy away from complex SQL is the issue of database portability. After all the promise of SQL is that it allows you to use the same standard SQL on a bevy of database platforms, allowing to change database vendors easily
In reality that's always been a bit of a fudge. In practice SQL is mostly standard but with all sort of little places to trip you up. With care, however, you can create SQL that isn't too painful to shift between database servers. But to do this you lose a lot of capabilities.
The decision about database portability ends up being particular to your project. These days it's much less of an issue than it used to be. The database market has shaken out so most places fall into one of the three major camps. Corporations often have strong commitments to whichever camp they are in. If you consider that changing databases is very unlikely due to this kind of investment, you might as well start taking advantage of the special features your database provides.
Some people still need portability, such as people who provide products that can be installed and interfaced with multiple databases. In this case there is a stronger argument against putting logic into SQL since you have to be so careful about which parts of SQL you can safely use.
Testability
Testability isn't a topic that's tended to come up enough in discussions about design. One of the benefits of Test Driven Development (TDD) is that it's rekindled the notion that testability is a vital part of design.
Common practice in SQL seems to not test. Indeed it's not uncommon to find essential views and stored procedures not even held in configuration management tools. Yet it's certainly possible to have testable SQL. The popular xunit family has a number of tools that can be used for testing within a database environment. Evolutionary database techniques such as test databases can be used to provide a testable environment very similar to what TDD programmers enjoy.
The main area that can make a difference is performance. While direct SQL is often faster in production, it can be much faster to run tests on business logic in memory if the database interface is designed in such a way that you can replace the actual database connection with a Service Stub.
Summing Up
So far I've talked about the issues. Now it's time to draw conclusions. Fundamentally what you have to do is to consider the various issues I've talked about here, judge them by your biases, and decide which policy to take to using rich queries and putting domain logic in there.
The way I look at the picture, one of the most critical elements is whether your data comes from a single logical relational database, or is scattered across a mass of different, often non-SQL, sources. If it's scattered then you should build a data source layer in memory to encapsulate your data sources and keep your domain logic in memory. In this case the strengths of SQL as a language isn't an issue, because not all of your data is in SQL.
The situation becomes interesting when the vast majority of your data sits in a single logical database. In this case you have two primary issues to consider. One is the choice of programming language: SQL versus your application language. The other is where the code runs, SQL at the database, or in memory.
SQL makes some things easy, but other things more difficult. Some people find SQL easy to work with, others find it horribly cryptic. The teams personal comfort is a big issue here. I would suggest that if you go the route of putting a lot of logic in SQL, don't expect to be portable - use all of your vendors extensions and cheerfully bind yourself to their technology. If you want portability keep logic out of SQL.
So far I've talked about modifiability issues. I think these concerns should come first, but be trumped by any critical performance issues. If you use an in-memory approach and have hot-spots that can be solved by more powerful queries, then do that. I would suggest looking to see how much you can organize performance enhancing queries as data source queries, as I outlined above. That way you can minimize putting domain logic into the SQL.
Subscribe to:
Posts (Atom)