Thứ Bảy, 24 tháng 11, 2012

Tổng quan kiến trúc của Entity Framework

ADO.NET Entity Framework là một nền tảng được sử dụng để làm việc với database thông qua cơ chế ánh xạ Object/Relational Mapping (ORM). Nhờ đó, bạn có thể truy vấn, thao tác với database gián tiếp thông qua các đối tượng lập trình.

Kiến trúc của Entity Framework được minh họa như sau:
Entity Framework architecture
Các nội dung dưới đây sẽ đi vào giải thích từng phần trong sơ đồ trên. Trong giới hạn của bài viết, tôi chỉ đi khái quát để bạn nắm được nội dung chính. Trong thực tế, bạn cũng không cần biết sâu hơn về kiến trúc bên dưới trừ những mục đích đặc biệt.

Object Services

Đây là các class tự động sinh ra tương ứng với mô hình dữ liệu. Các class này bao gồm:
-      ObjectContext đại diện cho một database. ObjectContext có chức năng quản lý các kết nối, định nghĩa mô hình dữ liệu với metadata và thao tác với database. Lớp này cũng có thể thêm vào các phương thức đại diện cho các stored procedure trong database.
-      ObjectSet là một  một tập hợp các entity. Mỗi đối tượng này tương ứng với một table. Có thể lấy được các đối tượng này thông qua các property tương ứng của ObjectContext.
-      EntityObject, ComplexObject là các lớp tương ứng cho một dòng dữ liệu của table trong database. Khác biệt chính giữa hai loại này là ComplexObject không chứa primary key.
-      EntityCollectionEntityReference: là các đối tượng thể hiện mối quan hệ (relationship) giữa hai entity class. Mỗi đối tượng này có thể được truy xuất thông qua các property của entity class.
Ta có bảng ánh xạ tương đương sau giữa các đối tượng trong database và EF:
Database Object Entity Framework Object
Database ObjectContext
Table, View EntityObject, ComplexObject
Column Property
Relationship EntityCollection, EntityReference
Ví dụ sau cho thấy cách tạo một đối tượng ObjectContext từ mô hình dữ liệu NorthwindEntities (tên của connection string được lưu trong app.config), sau đó sử dụng LINQ to Entities để lấy ra các sản phẩm (trong bảng Products) có tên bắt đầu bằng “G” và in ra màn:
01// …
02ObjectContext context = new ObjectContext("name=NorthwindEntities");
03 
04ObjectSet products = context.CreateObjectSet();
05 
06var query = from p in products
07            where p.ProductName.StartsWith("g")
08            select p;
09 
10foreach (var item in query)
11{
12    Console.WriteLine("{0,-4}{1}",item.ProductID, item.ProductName);
13}
14// …
Output:
6   Grandma's Boysenberry Spread
15  Genen Shouyu
22  Gustaf's Knäckebröd
24  Guaraná Fantástica
26  Gumbär Gummibärchen
31  Gorgonzola Telino
33  Geitost
37  Gravad lax
44  Gula Malacca
56  Gnocchi di nonna Alice
69  Gudbrandsdalsost

Entity Data Model

Entity Data Model (EDM) là mô hình dữ liệu được mô tả thông qua các ngôn ngữ theo chuẩn XML. EDM được chia làm 3 lớp là: Conceptual, Mapping và Logical. Mỗi lớp này được định nghĩa bởi ngôn ngữ riêng theo định dạng XML:
-      Conceptual – Conceptual Schema Definition Language (CSDL): là ngôn ngữ định nghĩa các entity, relationship, hàm trong tập tin với phần mở rộng .csdl. Có thể tạo được các entity class (object layer).
-      Mapping – Mapping specification language (MSL): định nghĩa các ánh xạ giữa lớp conceptual và logical, nội dung này được lưu trong tập tin .msl.
-      Logical – Store Schema Definition Language (SSDL): định nghĩa mô hình lưu trữ của dữ liệu, lưu trữ trong tập tin .ssdl.
Entity Mapping Model
Tham khảo thêm: CSDL, SSDL, and MSL Specifications
Các nội dung của ba tập tin .csdl, .msl và .ssdl được lưu trữ trong cùng tập tin .edmx trong Visual Studio. Tập tin này có thể được tạo ra tự động từ database và công cụ Entity Framework Model Wizard của Visual Studio. Trong quá trình biên dịch, các tập tin .csdl, .msl và .ssdl sẽ được tạo ra dựa vào tập tin .edmx này.
Note: Khi mở tập tin .edmx này, VS tự động hiển thị giao diện trực quan của nó bằng công cụ mặc định là ADO.NET Entity Data Model Designer. Để xem nội dung của tập tin này, bạn nhấn chuột phải, nhấn Open with… và chọn mục XML Editor hoặc một trình xem dưới dạng văn bản bất kì.

EntityClient Data Provider

EntityClient là một data provider mới của ADO.NET dùng để truy xuất đến database. Được xây dựng bên trên các ADO.NET data provider cơ bản, EntityClient không truy xuất trực tiếp dữ liệu mà thông qua các data provider khác dựa vào các thông tin dữ liệu từ Entity Data Model.
EntityClient cũng bao gồm các lớp giống như các ADO.NET data provider khác và tên lớp được đặt với tiền tố Entity. Ví dụ bạn có thể tạo kết nối bằng EntityConnection, tạo các câu truy vấn bằng EntityCommand và đọc kết quả bằng EntityDataReader.
Một điểm khác biệt với các data provider khác là EntityClient sử dụng Entity SQL để truy vấn dữ liệu. Các lệnh Entity SQL sẽ được chuyển thành một cấu trúc lệnh dạng cây (command tree) và chuyển xuống cho các data provider khác.
Ví dụ sau sử dụng EntityClient để tạo kết nối, tạo đối tượng EntityCommand và sử dụng tham số để lấy các sản phẩm có CategoryID là 1:
01int categoryID = 1;
02using (EntityConnection con = new EntityConnection("Name=NorthwindEntities"))
03{
04    con.Open();
05    EntityCommand cmd = con.CreateCommand();
06    cmd.CommandText = "SELECT VALUE p FROM NorthwindEntities.Products AS p WHERE p.CategoryID = @catId";
07    cmd.Parameters.AddWithValue("catId", categoryID);
08    EntityDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
09    while (reader.Read())
10    {
11        var name = reader["ProductName"];
12        var catId=reader["CategoryID"];
13        Console.WriteLine("{0,-3}{1}",catId,name);
14    }
15    reader.Close();
16}
17// ...
Output:
CategoryID ProductName
1          Chai
1          Chang
1          Guaraná Fantástica
1          Sasquatch Ale
1          Steeleye Stout
1          Côte de Blaye
1          Chartreuse verte
1          Ipoh Coffee
1          Laughing Lumberjack Lager
1          Outback Lager
1          Rhönbräu Klosterbier
1          Lakkalikööri

yinyangit.wordpress.com
(http://yinyangit.wordpress.com/2011/11/24/tong-quan-ve-kien-truc-entity-framework/)

CSS3 – Media Query và Responsive Web Design

Tính năng Media Query của CSS3 dự định sẽ mang lại một “kỉ nguyên” mới của kĩ thuật thiết kế web mới trong năm 2012. Nhờ tính năng, các trang web sẽ hiển thị linh hoạt hơn trên các loại thiết bị, độ phân giải màn hình, kích thước trình duyệt khác nhau mà không cần phải sử dụng bất kì mã xử lý javascript nào. Kĩ thuật thiết kế này được gọi là Responsive Web Design và được ứng dụng rất phổ biến trên thế giới.

CSS2: Media Type

Phiên bản CSS 2 mặc dù chưa hỗ trợ  Media Query nhưng cũng đã hỗ trợ các Media Type. Tính năng này cho phép xác định các định dạng cho mỗi loại thiết bị nhưng không linh hoạt và rất hạn chế.
Media Type Description
All Used for all media type devices
Aural Used for speech and sound synthesizers
Braille Used for braille tactile feedback devices
Embossed Used for paged braille printers
Handheld Used for small or handheld devices
Print Used for printers
Projection Used for projected presentations, like slides
Screen Used for computer screens
Tty Used for media using a fixed-pitch character grid, like teletypes and terminals
Tv Used for television-type devices
Trong cùng một style sheet, bạn có thể sử dụng các luật (hoặc chỉ thị) @media để quy định loại thiết bị nào sẽ được áp dụng bởi các khối định dạng CSS bên trong mỗi luật đó.
Ví dụ như đoạn style sheet sau sẽ thiết lập chiều rộng của trang web là 800px khi được xem trên máy tính và 300px khi xem trên các thiết bị cầm tay.  Cả hai loại thiết bị này đều hiển thị font-weight của các thẻ là bold.
01

CSS3 : Media Query

Media Query là một bước cải tiến của luật @media bằng cách kết hợp Media Type và các thông số khác như độ phân giải, kích thước, màu sắc,… để tăng thêm tính chặt chẽ và linh hoạt của các luật này. Mỗi luật của Media Query là một biểu thức logic và chỉ được áp dụng khi nó có giá trị true.
Các Media Query có thể được sử dụng bằng các cách dùng thẻ trong HTML hoặc thẻ trong XML, ngoài ra thì trong HTML bạn có thể dùng các luật @import và @media. Các ví dụ sau sẽ áp dụng style css cho các loại máy vi tính và hỗ trợ màu:
1"stylesheet" type="text/css" href=" example.css" media="screen and (color)">
2 
3"screen and (color)" rel="stylesheet" href="example.css" ?>
4 
5@import url(style.css) screen and (color);
6 
7@media screen and (color) and (min-width:400px) {
8 
9}
Một Media Query được tạo thành từ một Media Type  và không hoặc nhiều expression (biểu thức) nối với nhau bằng toán tử and. Cấu trúc của một Media Query có dạng:
-          Media Feature: bao gồm các thuộc tính như width, height, device-width, device-height, color, resolution, … Các thuộc tính này thường được thêm các tiếp đầu ngữ min- hoặc max- để xác định phạm vi ảnh hưởng của thuộc tính trong Media Query.
Media Features (http://reference.sitepoint.com/css/mediaqueries)
Feature Value Min/Max Description
color integer yes number of bits per color component
color-index integer yes number of entries in the color lookup table
device-aspect-ratio integer/integer yes aspect ratio
device-height length yes height of the output device
device-width length yes width of the output device
grid integer no true for a grid-based device
height length yes height of the rendering surface
monochrome integer yes number of bits per pixel in a monochrome frame buffer
resolution resolution (“dpi” or”dpcm”) yes resolution
scan “progressive”or”interlaced” no scanning process of ”tv”media types
width length yes width of the rendering surface
-          Expression: bao gồm một Media Feature và không hoặc một giá trị của nó được ngăn cách bởi dấu hai chấm “:”. Mỗi Expression được bao trong cặp ngoặc đơn.
Ví dụ: (color) và (min-width : 200px).
Nhiều expression nối với nhau bằng toán tử and: (color) and (min-width : 200px)
-          Media Type: Tham khảo bảng ở phần trên.
-          Media Query: Bắt đầu bằng một Media Type và theo sau là một chuỗi Expression cũng được nối với nhau bằng toán tử and.
-          Các Media Query có thể được nối với nhau bằng dấu phẩy “,”, tương tự như khi dùng selector của css.
Media Query Structure
Ngoài ra bạn có thể sử dụng thêm hai toán tử là notonly vào đầu Media Query. Công dụng của hai toán tử này:
-Toán tử not giúp đảo ngược giá trị của Media Query. Toán tử này có độ ưu tiên thấp nhất nên sẽ được tính cuối cùng.
-Toán tử only giúp ẩn các style sheet trên các trình duyệt không hỗ trợ Media Query.

Demo: Thiết kế một trang web theo Responsive Design

Trình duyệt với kích thước >800px:
Responsive Web Design Demo Wide ScreenKhi thu nhỏ width lại bạn sẽ thấy vị trí sidebar thay đổi và biến mất nếu như nhỏ hơn 400px:
Responsive Web Design Demo 2
Mã nguồn hoàn chỉnh:
01<html>
02<head>
03<title>Responsive Design Demo</title>
04 
05<style type="text/css">
06header, section, aside, footer {
07    background: wheat;
08    border: 1px solid gray;
09    margin: 2px;
10    font-family: Sans-serif;
11    font-size: 1.6em;
12    font-style: bold;
13}
14aside, section {
15    height: 300px;
16}
17footer{
18    clear: both;
19}
20 
21/* Media queries */
22 
23@media screen {
24    section {
25        width: auto;
26        float: none;
27    }
28    aside {
29        display: none;
30    }
31}
32@media screen and (min-width: 400px) {
33    section {
34        width: auto;
35        float: none;
36    }
37    aside {
38        width: auto;
39        height: 200px;
40        float: none;
41        display: block;
42    }
43 
44}
45 
46@media screen and (min-width: 800px) {
47    section {
48        width: 78%;
49        float: left;
50    }
51    aside {
52        width: 20%;
53        height: 300px;
54        float: right;
55        display: block;
56    }
57}
58</style>
59</head>
60 
61<body>
62    <header>
63        Header
64    </header>
65 
66    <section>
67        Main Content
68    </section>
69 
70    <aside>
71    Sidebar
72    </aside>
73 
74    <footer>
75        Footer
76    </footer>
77</body>
78</html>
Tham khảo cú pháp hoàn chỉnh của Media Query tại: https://developer.mozilla.org/en/CSS/media_queries
YinYang’s Programming.
(http://yinyangit.wordpress.com/2012/02/18/css3-media-query-va-responsive-web-design/)

CSS – Tìm hiểu về Grid System

Grid System là một thuật ngữ được dùng để chỉ phương pháp sắp đặt các thành phần HTML theo dạng lưới dựa trên CSS. Một Grid System rất quen thuộc và được áp dụng phổ biến là 960 Grid. 960 Grid hỗ trợ hai loại là 12 và 16 cột. Ngoài ra, bạn có thể sử dụng một Grid System tương tự cho phép bạn xác định số cột tùy ý, đó là Variable Grid System.

960 Grid System

Xem Demo: http://960.gs/demo.html
Download: http://github.com/nathansmith/960-Grid-System/zipball/master
Cái tên bắt đầu với con số 960 là do Grid System này cố định chiều rộng của trang web là 960px. Với loại 12 cột thì mỗi cột sẽ có chiều rộng là 60px và tương tự là 40px cho loại 16 cột. Ở đây tôi chỉ đề cập đến loại 12 cột (16 cột cũng tương tự).
Bạn có thể thắc mắc tại sao chỉ là 60px với 12 cột (bởi vì 12 * 60px = 720px)? Câu trả lời là bởi vì các cột không nằm sát nhau mà chúng cách nhau 20px, hay nói cách khác, một cột sẽ có margin trái và phải là 10px.
12 * 60px + 12 * 20px = 960px
Mỗi ô của Grid System thường là một thẻ div (hoặc bất kì thẻ nào bạn muốn) được gắn class là grid_x. Trong đó là x là một số xác định chiều rộng của ô (từ 1 đến 12). Ví dụ chiều rộng của thẻ div tương ứng với mỗi class là (xem hình minh họa):
grid_1: 60px
grid_2: 140px
grid_3: 220px

960 Grid System - 12 Columns
Để chứa một Grid System, bạn cần tạo một thẻ div “container” với class có dạng container_x. Giá trị x ở đây là số lượng cột tối đa mà Grid System hỗ trợ, nghĩa là container_12 đối với loại 12 cột. Các ô bên trong sẽ tự động xuống hàng mới khi vượt quá số lượng cột của container.
Để bắt buộc tạo hàng mới, bạn có thể thêm vào các thẻ div có class=”clear”.
Ví dụ sao tạo ra một lưới với ba hàng. Bạn sẽ thấy hàng thứ hai mặc dù chỉ có một thẻ div rộng 140px nhưng nó vẫn xuống hàng mới.
960 Grid System demo

01<div class="container_12">
02    <div class="grid_12">
03        <p> 940 </p>
04    </div>
05    <div class="grid_2">
06        <p> 140 </p>
07    </div>
08    <div class="clear"></div>
09    <div class="grid_1">
10        <p> 60 </p>
11    </div>
12    <div class="grid_11">
13        <p> 860 </p>
14    </div>
15</div>

Các thuật ngữ

Push và Pull:
- Mặc định các ô trong lưới sẽ nằm cách nhau theo chiều ngang một khoảng cố định là 20px. Tuy nhiên bạn có thể muốn “đẩy” (push) hoặc “kéo” (pull) một ô nào đó để nó nằm đè lên ô khác nhằm tạo ra một layout linh hoạt. Grid System cung cấp cho bạn các class có tên là push_x và pull_x (x là số cột). Ví dụ:
push_2: đẩy về bên phải 2 cột.
pull_2: kéo sang bên trái 2 cột.
960 Grid System - Pulling Demo
Prefix và Suffix:
- Quy định khoảng cách trước và sau giữa các ô. Ví dụ: prefix_1, suffix_2
Alpha và Omega
- alpha: loại bỏ margin phía trước.
- omege: loại bỏ margin phía sau.

Variable Grid System

Dựa trên 960 Grid System, bạn có thể dễ dàng tạo ra một Grid System với số lượng, kích thước của cột, gutter tại http://grids.heroku.com/:
Variable Grid System
Tóm lại, trong khi chờ đợi Flexbox của CSS3 được hỗ trợ đầy đủ, bạn nên sử dụng Grid System cho các dự án của mình để đơn giản hóa việc tạo các giao diện.
YinYangIt’s Blog
(http://yinyangit.wordpress.com/2012/07/19/css-tim-hieu-ve-grid-system/)

Javascript – Unit Test với QUnit

Unit test là công việc quen thuộc của các lập trình viên để kiểm tra một đơn vị mã nguồn có hoạt động chính xác hay không. Nếu bạn là một javascript coder và đang tìm kiếm một phương pháp thực hiện unit test, hãy thử sử dụng QUnit – một framework được tạo jQuery team và được sử dụng cho dự án jQuery.

Trang chủ và tài liệu: http://docs.jquery.com/Qunit
Mã nguồn dự án: https://github.com/jquery/qunit

Chuẩn bị

Để sử dụng, bạn chỉ cần download hai tập tin sau: qunit.jsqunit.js
Và tạo một file HTML đơn giản có dạng như sau:
01<html>
02<head>
03    <title>QUnit Test Example</title>
04 
05    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" />
06    <script src="http://code.jquery.com/qunit/qunit-git.js"></script>
07</head>
08<body>
09    <div id="qunit"></div>
10 
11    <script>
12    (function(){
13 
14        // your sourcecode goes here
15 
16    })();
17    </script>
18</body>
19</html>
File HTML trên tôi tạo một hàm vô danh (anonymous function) tự động thực thi để chứa các đoạn mã sẽ viết. Phương pháp này được áp dụng phổ biến trong lập trình javascript vì giúp tránh việc tạo ra các định danh không cần thiết, và do đó hạn chế được các trường hợp xung đột (conflict) định danh.
Đừng quên thêm vào thẻ div có id là “qunit”, đây sẽ là nơi để QUnit hiển thị các thông tin và kết quả test lên trên trình duyệt. Nếu bạn mở file này bên trong trình duyệt, bạn sẽ thấy giao diện như sau:
QUnit Test Example - 1

Các tùy chọn

Giao diện QUnit tạo ra có 3 checkbox tùy chọn. Công dụng của chúng là:
- Hide passed tests: ẩn các test chạy đúng. Việc sử dụng tùy chọn có thể khiến bạn khó xác định được test nào fail.
- Check for Globals: test sẽ là fail nếu như một biến global (hay một thuộc tính của đối tượng window) được tạo ra khi thực thi. Việc này nhằm phát hiện và hạn chế việc tạo ra các biến global một cách không cần thiết và có thể gây ảnh hưởng đến toàn bộ trang web.
- No try-catch: Chạy các test mà không sử dụng khối try catch. Tùy chọn này giúp bạn có thể phát hiện các vị trí lỗi và debug (thường kết hợp với tool như Firebug).

Tạo các Unit Test

Trước tiên, tôi tạo một test unit, ở đây là một function add(x, y) đơn giản có chức năng trả về tổng của hai tham số. Sau đó sử dụng hàm test() của QUnit để bắt đầu một unit test mới với hai tham số là tên và đoạn code chứa các mã test:
test( name, expected, test )
Ở đây tôi sử dụng assertion là equal() để so sánh hai giá trị bằng nhau:
equal( actual, expected, message )
01(function(){
02    // test unit
03    function add(x, y){
04        return x + y;
05    }
06 
07    test('add()', function() {
08        equal(add(1, 2), 3, "Passed: 1 + 2 = 3");
09        equal(add(2, null), 3);
10        equal(add_numbers(2, 2), 3);
11 
12    });
13 
14})();
Kết quả:
QUnit Test Example 2
Bạn thấy kết quả hiển thị có thông báo “1 tests of 3 passed, 2 failed“. Bên dưới liệt kê các test có đánh số thứ tự cùng với kết quả của chúng:
1. Passed: 1 + 2 = 3
2. failed (Do giá trị Expected và Result khác nhau)
3. Died (add_numbers không được định nghĩa)
Một test có trạng thái “died” tức là mọi test bên dưới nó sẽ không được thực hiện. Điều này xảy ra khi một lỗi nghiêm trọng có thể ảnh hưởng đến toàn bộ test bên dưới. Bạn cũng có thể tạo ra các test dạng này bằng cách dùng assertion ok():
ok( state, message )
Ví dụ các test unit của bạn cần đối tượng jQuery để chạy, vậy bạn có thể viết như sau:
1test('ok() assertion', function() {
2    ok(jQuery);
3 
4    // assertion calls
5 
6});

Test bất đồng bộ (Asynchronous)

Phương pháp test thông thường sẽ chạy lần lượt từ trên xuống dưới các lời gọi assertion (test đồng bộ – Synchronous). Trong trường hợp muốn test một cách bất đồng bộ, bạn có thể sử dụng hai hàm stop() và start() kết hợp với setTimeout()/setInterval().
- start( decrement ) : Chạy lại test khi nó bị dừng bởi stop().
- stop( increment ) : Dừng test cho đến khi start() được gọi.
Ví dụ:
1test('asynchronous test', function() {
2    stop();
3 
4    equal(1,1);
5    setTimeout(start,1000);
6 
7});
Sẽ có kết quả là:
Tests completed in 1045 milliseconds.
1 tests of 1 passed, 0 failed.
Như bạn thấy, chỉ một lời gọi assertion đơn giản nhưng lại chiếm hơn 1000 milisecond để thực thi. Đó là do dòng lệnh equal(1,1) chỉ được thực hiện sau khi hàm start() được gọi.
YinYangIt’s Blog
(http://yinyangit.wordpress.com/2012/07/11/javascript-unit-test-voi-qunit/)

OOP – Interface vs Abstract class

Hiện nay mặc dù OOP đã rất phổ biến nhưng đa số vẫn còn khá mơ hồ trong việc phân biệt và định nghĩa hai khái niệm Interface và Abstract class. Có vẻ vấn đề này không được dạy rõ ràng ở trường, hoặc có thể các người dạy cũng chưa nắm rõ về nó. Ngoài ra, đây còn là một vấn đề cần giải quyết mà xác suất bạn nhận được khi đi phỏng vấn là khá cao.

Is-a và Can-do

Bỏ qua tất cả những phần về lý thuyết của việc tạo một abstract class và interface. Bạn không cần quan tâm nhiều đến việc abstract có thể khai báo những gì, hay interface có được phép định nghĩa nội dung phương thức hay không. Điểm cơ bản khi bạn được hỏi về sự khác biệt giữa chúng là gì? Đó chính là mục đích mà chúng được sử dụng:
-          Abstract class: là một class cha cho tất cả các class có cùng bản chất. Bản chất ở đây được hiểu là kiểu, loại, nhiệm vụ của class. Hai class cùng hiện thực một interface có thể hoàn toàn khác nhau về bản chất.
-          Interface: là một chức năng mà bạn có thể thêm và bất kì class nào. Từ chức năng ở đây không đồng nghĩa với phương thức (hoặc hàm). Interface có thể bao gồm nhiều hàm/phương thức và tất cả chúng cùng phục vụ cho một chức năng.
Vậy, bạn không nên nhầm lẫn khi nói về việc một class được implement hay extend. Nhiều người thường hay đồng nhất là không phân biệt hai từ này, nhưng chính chúng đã nói lên sự khác biệt giữa interface và abstract class. Bạn chỉ có thể thừa kế (extend) từ một class và chỉ có thể hiện thực (implement) các chức năng (interface) cho class của mình.
Theo cách ngắn gọn, quan hệ giữa một class khi thừa kế một abstract class được gọi là is-a, và một class khi hiện thực một interface được gọi là can-do (hoặc –able).
Hãy xem ví dụ sau, tôi có:
-          Interface: Barkable, Runable, Flyable, Swimable.
-          Abstract class Animal và các sub class: Bolt, AngryBird và Nemo.
-          Abstract class Machine và các sub class: McQueen, Siddeley.
Abstract class - interface - OOP
Như bạn thấy, mặc dù cả McQueen và Bolt đều được hiện thực interface Runable, nhưng chúng hoàn toàn thuộc hai loại khác nhau. Và tất nhiên một class có thể can-do nhiều thứ, ví dụ như Bolt có thể chạy và “bow wow”.
Angry bird fly

Dùng Interface như một “bản thiết kế” của class?

Đây là một điều thường được dùng để trả lời cho hai câu hỏi:
-          Interface được dùng để làm gì?
-          Tại sao không thể định nghĩa phần thân cho các phương thức của interface.
Xét ở một mức độ nào đó điều này là hợp lý, nhưng như đã nói ở phần trên, nó chỉ được dùng để mô tả một “bản thiết kế” cho một chức năng của class. Nếu muốn tạo một bản thiết kế, hãy sử dụng abstract class. Một bản thiết kế tất nhiên sẽ có những thứ đã được dựng sẵn và có những thứ là abstract.
Một câu trả lời có thể lý giải phần nào câu hỏi thứ hai là việc cho phép định nghĩa thân phương thức trong các interface có thể khiến cho hiệu suất bị giảm sút. Nguyên nhân là việc tìm kiếm các phương thức sẽ diễn ra lâu hơn vì phải duyệt qua các interface, thay vì chỉ cần phải tìm trong class cha của nó.
Angry bird
Về công dụng của interface, xét ở mức ứng dụng, các interface có thể được hiểu như các plugin hoặc thư viện/phần mềm third-party. Việc hiện thực một interface cho class cũng giống như cài thêm plugin cho một phần mềm vậy.

Bảng so sánh

Cuối cùng, cũng nên liệt kê các điểm khác biệt giữa hai khái niệm này để bạn có thể sử dụng được khi cần thiết. Các điểm khác biệt này có thể khác nhau tùy vào ngôn ngữ mà bạn sử dụng. Vì vậy bạn chỉ cần nhớ các điểm căn bản sau:

Interface Abstract class
Multiple inheritance Một class có thể hiện thực nhiều interface.(tạm coi là thừa kế) Không hỗ trợ đa thừa kế
Default implementation Không thể định nghĩa code xử lý, chỉ có thể khai báo. Có thể định nghĩa thân phương thức, property.
Access Modifiers Mọi phương thức, property đều mặc định là public. Có thể xác định modifier.
Adding functionality Mọi phương thức, property của interface cần được hiện thực trong class. Không cần thiết.
Fields and Constants Không
YinYang’s Programming Blog