huge boobs pictures hd. 3gp desi glamcore perfect goddesses in oral.

https://eporner.monster destiny blonde has a sweet teen pussy.

Kỹ thuật

Giới thiệu thư viện MvpPattern dùng xây dựng mô hình ứng dụng dựa trên kiến trúc MVP


bởi Nguyễn Thành Mãn vào 8 tháng 1 2013 lúc 17:20 ·

Giới thiệu thư viện MvpPattern dùng để xây dựng mô hình ứng dụng dựa trên kiến trúc Model – View – Presenter 

 

1         Giới thiệu

Trong quá trình thực hiện dự án Phần mềm quản lý tư liệu và Website Nhã nhạc cung đình Huế, từ kinh nghiệm của các dự án trước và qua tìm hiểu tham khảo trên Internet, nhóm thực hiện dự án đã học hỏi, cải tiến và tổ chức lại thành thư viện MvpPattern chạy trên nền tảng .NET, với mục tiêu nâng cao tính tái sử dụng, giảm bớt khối lượng mã cần viết cho các thao tác thường gặp khi xây dựng phần mềm áp dụng theo mô hình Model-View-Presenter (MVP). Mô hình MVP đã khá quen thuộc với giới lập trình nên việc giới thiệu nằm ngoài phạm vi bài viết này. Đây là phiên bản đầu tiên, bước đầu chỉ mới khái quát hóa vấn đề ở mức độ cơ bản, nên có một số điểm vẫn chưa được hoàn thiện, chưa được như mong muốn. Trong quá trình ứng dụng thực tiễn, thư viện sẽ tiếp tục được cải tiến cho phù hợp và tiện lợi hơn. Chúng tôi chia sẻ một số kinh nghiệm và mong nhận được ý kiến đóng góp.

Các ví dụ sử dụng theo cách lập trình truyền thống, chưa đáp ứng hoàn toàn nguyên lý đảo ngược phụ thuộc (Dependency Inversion Principle – DIP[*], cách gọi khác là Inversion of Control – IoC), việc áp dụng nguyên lý này làm giảm bớt sự kết nối (decoupling) chặt chẽ giữa các đối tượng trong phần mềm, tăng độ linh hoạt và giúp phần mềm có tính module hóa cao. Trong khuôn khổ bài viết không thể trình bày đầy đủ, xin tham khảo mã nguồn ví dụ áp dụng thư viện Unity Application Block (phiên bản 2.1) để cài đặt mẫu thiết kế (design pattern) dependency injection.

 

2         Cấu trúc gói

2.1      Biểu đồ gói

Các giao diện và lớp của thư viện.

Vị trí của thư viện trong mô hình MVP.

Ghi chú: Các giao diện và lớp có màu đen là mã ví dụ, không thuộc thành phần của thư viện.

2.2      Tổng quan

Áp dụng thư viện MvpPattern cho phát triển mô hình phần mềm dựa theo kiến trúc ba tầng Model – View – Presenter(MVP). MvpPattern theo cơ chế Passive View, tất cả các tương tác từ tầng giao diện (View) đi xuống và tầng dữ liệu (Model) trở lên đều thông qua tầng trung gian nghiệp vụ (Presenter).

Tầng dữ liệu sử dụng LINQ (LINQ được Microsoft tích hợp vào Visual Studio từ phiên bản 2008. tuy nhiên vẫn có thể dùng trong phiên bản 2005, lưu ý là LINQ chỉ dùng được cho hệ quản trị cơ sở dữ liệu MS SQL Server) và kết hợp với thư viện Dynamic LINQ để tạo các câu truy vấn có điều kiện tương tự câu lệnh truy vấn SQL quen thuộc.

2.2.1      Tầng Business

2.2.1.1  Giao diện IGenericView

Giao diện gốc, với mục đích cho các giao diện khác kế thừa.

public interface IGenericView

{

}

2.2.1.2  Giao diện IListManipulationView

Định nghĩa các thuộc tính và sự kiện thao tác cơ bản là thêm mới, chỉnh sửa, xóa bỏ và lựa chọn khi xử lý dữ liệu trên một danh sách, dẫn xuất từ IGenericView.

public interface IListManipulationView : IGenericView

{

// Trả về hoặc thiết lập danh sách các đối tượng của view

IList ListItem { set; get; }

 

// Trả về đối tượng được tạo mới trên view

TEntity NewItem { get; }

 

// Trả về đối tượng hiện hành trên danh sách của view

TEntity CurrentItem { get; }

 

// Trả về danh sách các đối tượng được lựa chọn trên view

IList SelectedItems { get; }

 

// Sự kiện phát sinh khi thêm một hạng mục dữ liệu mới

event EventHandler OnAddEventHandler;

 

// Sự kiện phát sinh khi lưu trữ thông tin của hạng mục dữ liệu

event EventHandler OnSaveEventHandler;

 

// Sự kiện phát sinh khi xóa bỏ các hạng mục dữ liệu

event EventHandler OnDeleteEventHandler;

 

// Sự kiện phát sinh khi các hạng mục dữ liệu được lựa chọn

event EventHandler OnSelectEventHandler;

}

Ví dụ: Form danh sách người dùng có các thao tác thêm mới, cập nhật và  xóa bỏ. Định nghĩa giao diện IUserView kế thừa từ giao diện IListManipulationView, định nghĩa thêm một số thuộc tính cần thiết khác và thi hành giao diện này cho form.

public interface IUserView : IListManipulationView

Thi hành  giao diện mới cho form:

public partial class frmUser : Form, IUserView

2.2.1.3  Giao diện IListSelectionView

Định nghĩa các thuộc tính và sự kiện khi lựa chọn các hạng mục dữ liệu trên một danh sách, dẫn xuất từ IGenericView.

public interface IListSelectionView : IGenericView

{

// Trả về hoặc thiết lập danh sách các đối tượng của view

IList ListItem { set; get; }

 

// Trả về danh sách các đối tượng được lựa chọn trên view

IList SelectedItems { get; }

 

// Sự kiện phát sinh khi các hạng mục dữ liệu được lựa chọn

event EventHandler OnSelectEventHandler;

}

Người phát triển có thể định nghĩa ra các giao diện mới tùy theo nhu cầu hoặc kế thừa từ các giao diện trên.

Ví dụ: Có một form danh sách người dùng và sử dụng để lựa chọn ra một số người dùng từ danh sách đó, ta định nghĩa giao diện IUserSelectionView kế thừa từ giao diện IListSelectionView, định nghĩa thêm một số thuộc tính cần thiết khác và thi hành giao diện này cho form.

public interface IUserSelectionView : IListSelectionView

Thi hành giao diện cho form:

public partial class dlgUser : Form, IUserSelectionView

2.2.1.4  Lớp tổng quát GenericPresenter

Lớp chứa các phương thức phổ biến khi thực hiện các thao tác xử lý trên danh sách. Người phát triển có thể override các phương thức này tùy theo nhu cầu sử dụng.

Ví dụ tạo presenter kế thừa từ GenericPresenter, mỗi presenter gắn với view mà nó điều khiển:

public class UserPresenter : GenericPresenter

Khởi tạo đối tượng UserPresenter từ view như sau:

public partial class frmUser : Form, IUserView

{

private UserPresenter presenter;

 

private void frmUser_Load(object sender, EventArgs e)

{

// Khởi tạo đối tượng presenter

presenter = new UserPresenter();

// Gắn tham chiếu của form thực thi giao diện cho presenter

presenter.View = this;

2.2.1.4.1   Thuộc tính View

Mô tả: Trả về hoặc thiết lập tham chiếu đến view gắn với presenter. Thao tác gán giá trị cho thuộc tính View gọi phương thức OnViewSet.

Cú pháp:

TView View { get; set; }

Ví dụ: Thiết lập giá trị View cho presenter.

presenter = new UserSelectionPresenter();

presenter.View = this;

2.2.1.4.2   Phương thức OnViewSet

Mô tả: Phương thức được gọi khi thuộc tính view của presenter được gán giá trị (xem 2.2.1.4.1).

Cú pháp: public abstract void OnViewSet();

Ví dụ:

public override void OnViewSet()

{

// Khởi tạo dịch vụ xử lý dữ liệu

service = UserGroupService.Instance;

// Đăng ký hàm nhận thông báo mỗi khi dữ liệu có sự thay đổi

service.DataChanged += new DataChangeHandler(FillData);

// Đăng ký các hàm xử lý sự kiện

RegisterEvents();

// Điền thông tin vào giao diện trong lần đầu chạy ứng dụng

FillData();

}

2.2.1.4.3   Phương thức RegisterEvents

Mô tả: Đăng ký các phương thức xử lý sự kiện xảy ra trên view. Có sẵn bốn  sự kiện thường gặp là tạo mới, chỉnh sửa, xóa bỏ và lựa chọn hạng mục dữ liệu, thông thường với view dẫn xuất từ IListManipulationView thì sử dụng cả bốn sự kiện trên, còn view dẫn xuất từ IListSelectiontionView thì chỉ đăng ký sự kiện OnSelectEventHandler.

Cú pháp: public virtual void RegisterEvents();

Ví dụ:

public override void RegisterEvents()

{

View.OnAddEventHandler += new EventHandler(OnAddEventHandler);

View.OnSaveEventHandler += new EventHandler(OnSaveEventHandler);

View.OnDeleteEventHandler += new EventHandler(OnDeleteEventHandler);

View.OnSelectEventHandler += new EventHandler(OnSelectEventHandler);

}

2.2.1.4.4   Phương thức OnAddEventHandler

Mô tả: Xử lý sự kiện tạo hạng mục dữ liệu mới trên view.

Cú pháp: public virtual void OnAddEventHandler;

Ví dụ:

public override void OnAddEventHandler(object sender, EventArgs e)

{

userService.Insert(View.NewItem);

}

2.2.1.4.5   Phương thức OnSaveEventHandler

Mô tả: Xử lý sự kiện lưu thông tin hạng mục trên view.

Cú pháp: public virtual void OnSaveEventHandler;

Ví dụ:

public override void OnSaveEventHandler(object sender, EventArgs e)

{

userService.Update(View.CurrentItem, “UserID=” + View.CurrentItem.UserID);

}

2.2.1.4.6   Phương thức OnDeleteEventHandler

Mô tả: Xử lý sự kiện xóa bỏ hạng mục dữ liệu trên view.

Cú pháp: public virtual void OnDeleteEventHandler;

Ví dụ:

public override void OnDeleteEventHandler(object sender, EventArgs e)

{

userService.Delete(View.SelectedItems);

}

2.2.1.4.7   Phương thức OnSelectEventHandler

Mô tả: Xử lý sự kiện lựa chọn hạng mục dữ liệu trên view

Cú pháp: public virtual void OnSelectEventHandler;

Ví dụ:

public override void OnSelectEventHandler(object sender, EventArgs e)

{

userService.AddToGroup(View.CurrentGroup, View.SelectedItems);

}

2.2.2      Tầng Data

2.2.2.1       Giao diện IGenericService

Giao diện gốc, với mục đích cho các giao diện khác dẫn xuất.

public interface IGenericService

{

}

2.2.2.2       Giao diện IGenericDataAccessService

Định nghĩa các phương thức xử lý dữ liệu thông dụng, dẫn xuất từ IGenericService. Gồm các phương thức cơ bản như truy vấn, các thao tác thêm mới, cập nhật, xóa bỏ đối tượng và gửi thông báo mỗi khi dữ liệu có sự thay đổi.

2.2.2.3       Lớp tổng quát GenericDataAccessService

Lớp tổng quát này thi hành  từ giao diện IGenericDataAccessService.

2.2.2.3.1   Phương thức khởi tạo đối tượng GenericDataAccessService

Mô tả: Phương thức khởi tạo đối tượng (constructor).

Cú pháp: GenericDataAccessService(System.Data.Linq.DataContext dataContext)

Tham số: Đối tượng Linq.LINQ.DataContext. Thông báo biệt lệ ArgumentNullException nếu tham số bằng Null. Tham số của đối tượng LINQ.DataContext là chuỗi kết nối tới cơ sở dữ liệu.

Trả về: Đối tượng GenericDataAccessService

Ví dụ:

public class UserService : GenericDataAccessService, IUserService

{

// Constructor (strConnectionString là chuỗi kết nối tới cơ sở dữ liệu)

public UserService() : base(new MvpExampleDataContext(strConnectionString)) { }

2.2.2.3.2   Thuộc tính DataContext

Mô tả: Trả về tham chiếu DataContext của đối tượng GenericDataAccessService.

Trả về: Đối tượng LINQ.DataContext

Ví dụ:

// Viết ra chuỗi kết nối đến cơ sở dữ liệu

Console.WriteLine(DataContext.Connection.ConnectionString);

2.2.2.3.3   Phương thức SelectAll

Mô tả: Trả về tất cả đối tượng của một lớp.

Cú pháp: virtual IList SelectAll(string orderByExpression)

Tham số:

orderByExpression: Thứ tự sắp xếp kết quả truy vấn, gồm tên trường và thứ tự sắp xếp ASC hoặc DESC, hoặc để chuỗi rỗng nếu không cần sắp xếp.

Trả về: Danh sách các đối tượng.

Ví dụ: IList users = SelectAll(“UserName ASC”);

2.2.2.3.4   Phương thức SelectBy

Mô tả: Truy vấn đối tượng theo điều kiện lọc.

Cú pháp: 

virtual IList SelectBy(string searchCondition, string orderByExpression)

Tham số:

–         searchCondition: Điều kiện lọc.

–         orderByExpression: Thứ tự sắp xếp kết quả truy vấn, gồm tên trường và thứ tự sắp xếp ASC hoặc DESC, hoặc để chuỗi rỗng nếu không cần sắp xếp.

Ví dụ: userService.SelectBy(“GroupID = 1″, “UserName ASC”);

2.2.2.3.5   Phương thức SelectBy

Mô tả: Truy vấn đối tượng theo điều kiện lọc.

Cú pháp: 

IList SelectBy(int fromItemNumber, int numberOfItems, string searchCondition, string orderByExpression)

Tham số:

–         fromItemNumber: Bắt đầu chọn từ đối tượng thứ fromItemNumber.

–         numberOfItems: Trả về số lượng numberOfItems đối tượng.

–         searchCondition: Điều kiện lọc.

–         orderByExpression: Thứ tự sắp xếp kết quả truy vấn, gồm tên trường và thứ tự sắp xếp ASC hoặc DESC, hoặc để chuỗi rỗng nếu không cần sắp xếp.

Ví dụ: userService.SelectBy(1, 20, “GroupID Null”, “UserName DESC”);

2.2.2.3.6   Phương thức Delete

Mô tả: Xóa bỏ đối tượng theo điều kiện lọc.

Cú pháp:  virtual void Delete(string searchCondition)

Tham số:

searchCondition: Điều kiện lọc.

Ví dụ: userService.Delete(“GroupID = Null”);

2.2.2.3.7   Phương thức Delete

Mô tả: Xóa bỏ một tập các đối tượng.

Cú pháp:  virtual void Delete(IList entities)

Tham số:

entities: Danh sách các đối tượng cần xóa bỏ.

Ví dụ: userService.Delete(View.SelectedItems);

2.2.2.3.8   Phương thức DeleteAll

Mô tả: Xóa bỏ toàn bộ các đối tượng của một lớp.

Cú pháp:  virtual void DeleteAll()

Ví dụ: userService.DeleteAll();

2.2.2.3.9   Phương thức Insert

Mô tả: Thêm mới một đối tượng.

Cú pháp: virtual TEntity Insert(TEntity entity)

Tham số:

entity: Đối tượng mới.

Ví dụ:

User user = new User() { UserName = “X” };

userService.Insert(user);

2.2.2.3.10             Phương thức Update

Mô tả: Override phương thức này để thực hiện cập nhật thông tin một đối tượng.

Cú pháp: virtual void Update(TEntity entity, string searchCondition)

Tham số:

–         entity: Đối tượng chứa thông tin cập nhật.

–         searchCondition: Điều kiện lọc.

Ví dụ:

user.UserName = “Y”;

userService.Update(user, “UserID = 1″);

2.2.2.3.11             Phương thức NotifyDataChanged

Mô tả: Gọi phương thức này để thông báo mỗi khi dữ liệu vừa có sự thay đổi. Phương thức này kích hoạt sự kiện DataChanged trên các presenter và gọi phương thức FillData cập nhật lại dữ liệu trên toàn bộ các presenter có thi hành giao diện IObserver.

Cú pháp:  void NotifyDataChanged()

Ví dụ:

UserGroup group = DataContext.GetTable().Where(obj => obj.GroupID == entity.GroupID).SingleOrDefault();

IList users = SelectBy(searchCondition, “”);

foreach (User user in users)

{

user.UserName = entity.UserName;

user.UserGroup = group;

}

DataContext.SubmitChanges();

NotifyDataChanged();

2.2.2.3.12             Phương thức ClearCache

Mô tả: Xóa bộ đệm dữ liệu.

Cú pháp:  static void ClearCache()

2.2.2.3.13             Hàm delegate DataChangeHandler

Mô tả: Đăng ký nhận sự kiện mỗi khi dữ liệu có sự thay đổi.

Ví dụ: Đăng ký một hàm có tên FillData, phương thức này được kích hoạt mỗi khi dữ liệu có sự thay đổi.

public override void OnViewSet()

{

service = new UserGroupService();

service.DataChanged += new DataChangeHandler(FillData);

 

// Phương thức này thực hiện cập nhật lại thông tin trên view

private void FillData()

{

View.ListItem = service.SelectAll(“GroupName ASC”);

}

 

Có hai cách chặn bắt sự kiện dữ liệu có sự thay đổi, dùng hàm delegate DataChangeHandler hoặc dùng phương thức AttachObserver.  Sự khác biệt của hai phương cách thức này là:

–         Dùng hàm delegate: Chỉ presenter nào đăng ký mới nhận được thông báo.

–         Dùng AttachObserver: Tất cả các presenter nào có đăng ký sẽ cùng nhận được thông báo.

2.2.2.4       Giao diện IObserver

Giao diện IObserver chỉ định nghĩa một phương thức duy nhất là FillData, phương thức được gọi mỗi khi lớp đối tượng Subject có sự thay đổi dữ liệu,  dùng để thực hiện các thao tác cập nhật lại giao diện người dùng.

public interface IObserver

{

void FillData();

}

2.2.2.5       Giao diện ISubject

Định nghĩa các phương thức cho lớp Subject thi hành  (dựa theo Observer pattern).

2.2.2.6       Lớp tổng quát Subject

Lớp đối tượng thi hành  giao tiếp ISubject.

2.2.2.6.1   Phương thức AttachObserver

Mô tả: Đăng ký làm một observer, lớp đăng ký sẽ nhận được thông báo mỗi khi có sự thay đổi dữ liệu từ data service (xem mục 2.2.2.3.14).

Cú pháp: void AttachObserver(IObserver observer)

Tham số:

observer: Tên lớp đối tượng thi hành giao tiếp IObserver.

Ví dụ:

public class UserPresenter : GenericPresenter, IObserver

{

private IUserService userService;

 

public override void OnViewSet()

{

// Lấy single instance của UserService

userService = UserService.Instance;

// Dăng ký presenter này là observer nhận thông báo từ data service.

// Hàm FillData tự động được gọi mỗi khi dữ liệu có sự thay đổi.

userService.AttachObserver(this);

2.2.2.6.2   Phương thức DetachObserver

Mô tả: Hủy đăng ký một observer.

Cú pháp:  void DetachObserver(IObserver observer)

Tham số:

observer: Tên lớp đối tượng thi hành giao tiếp IObserver.

Ví dụ: userService.DetachObserver(this);

2.2.2.6.3   Phương thức DetachAll

Mô tả: Hủy đăng ký toàn bộ observer.

Cú pháp:  void DetachAll()

2.2.2.6.4   Phương thức NotifyObservers

Mô tả: Thông báo dữ liệu có sự thay đổi tới các observer đã đăng ký

Cú pháp:  void NotifyObservers()

Ví dụ: userService.NotifyObservers();

2.2.2.6.5   Thuộc tính Observers

Mô tả: Trả về danh sách các observer đã đăng ký

Trả về:  IList

Ví dụ:

// Tổng số các observer được đăng ký

Console.WriteLine(Observers.Count);

 

3         Nguồn thông tin tham khảo

–         Kiến trúc Model-View-Presenter trong .NET (http://www.fpt.edu.vn/story/kien-truc-model-view-presenter-trong-net)

–         Creating a generic Model-View-Presenter framework (https://dotnetchris.wordpress.com/2009/02/16/creating-a-generic-model-view-presenter-framework)

–         Smart Client Software Factory (http://msdn.microsoft.com/en-us/library/ff648753.aspx)

–         Tài liệu LINQ bản tiếng Việt (http://congthuong.googlecode.com/files/LINQ%20tieng%20viet.pdf)

–         Dynamic LINQ (http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx)

–         Unity Application Block (http://msdn.microsoft.com/en-us/library/hh237493.aspx)

 

4         Ví dụ sử dụng

Tạo hai lớp User và UserGroup với các thuộc tính và quan hệ như sau:

Thiết kế các form cho đối tượng User và UserGroup với các thao tác thêm mới, cập nhật và xóa bỏ. Form UserGroup có thêm chức năng chọn thêm các thành viên vào nhóm chỉ định. Cụ thể có ba form như sau:

–         frmUser quản lý danh sách người dùng.

–         frmUserGroup quản lý danh sách nhóm người dùng.

–         dlgUser để lựa chọn ra một số người dùng từ danh sách người dùng.

1          Tạo một solution với ba project tên là UI, BussinessData (tên project tùy chọn) tương ứng với ba tầng View, Presenter và Model.

–         Project UI chứa các form, là lớp giao diện tương tác với người phát triển (view).

–         Project Business chứa các lớp xử lý nghiệp vụ (business).

–         Project Data chứa các lớp đối tượng dữ liệu và các lớp dịch vụ truy cập dữ liệu (model).

Thêm tham chiếu tới thư viện MvpPattern vào References của ba project trên.

2          Trong project Data sử dụng LINQ để ánh xạ các bảng từ cơ sở dữ liệu quan hệ ra các đối tượng và để truy xuất cơ sở dữ liệu.

  1. Right click vào thư mục Data, chọn Add New Item, LINQ to SQL Classes, đặt tên cho file DBML.
  2. Vào menu View, chọn Server Explorer.
  3. Right click vào Data Connections, chọn Add Connection, chọn tên máy chủ và cơ sở dữ liệu.
  4. Kéo hai bảng Users và UserGroups thả vào file DBML.
  5. Lưu file DBML, các lớp đối tượng được tự động sinh mã trong file MvpExample.designer.cs, người phát triển có thể chỉnh sửa, bổ sung thêm mã bằng cách right click vào file DBML, chọn View Code.

3          Trong project Data, định nghĩa các giao diện và viết mã xử lý cho tầng dữ liệu.

Giao diện cho lớp UserService định nghĩa các phương thức thao tác với lớp User.

public interface IUserService : IGenericDataAccessService

{

// Thêm các thành viên vào nhóm người dùng

void AddToGroup(UserGroup group, IList users);

}

Thi hành giao diện IUserService và viết mã cho lớp UserService.

public class UserService : GenericDataAccessService, IUserService

{

// Constructor

public UserService() : base(new MvpExampleDataContext(LocalConfig.ConnectionString)) { }

Override các phương thức Insert, Update tương ứng.

Giao diện cho lớp UserGroupService định nghĩa các phương thức thao tác với lớp UserGroup.

public interface IUserGroupService : IGenericDataAccessService

{

}

Thực hiện các bước tương tự như với lớp UserService.

4          Trong project Bussiness, tạo các giao diện tương ứng cho các form trên.

Định nghĩa giao diện cho form frmUser và viết mã cho presenter:

public interface IUserView : IListManipulationView

{

IList GroupList { set; }

UserGroup CurrentGroup { get; }

}

UserPresenter quản lý giao diện IUserView.

public class UserPresenter : GenericPresenter, IObserver

{

private IUserService userService;

 

public override void OnViewSet()

{

userService = new UserService.Instance;

userService.AttachObserver(this);

 

groupService = UserGroupService.Instance;

}

 

public void FillData()

{

// Cập nhật thông tin của view ở đây

}

Định nghĩa giao diện cho hộp thoại dlgUser và viết mã cho presenter:

public interface IUserSelectionView : IListSelectionView

{

UserGroup CurrentGroup { get; set; }

}

UserSelectionPresenter quản lý giao diện IUserSelectionView.

 

public class UserSelectionPresenter : GenericPresenter

{

private IUserService userService;

 

public override void OnViewSet()

{

userService = UserService.Instance;

Định nghĩa giao diện cho form frmUserGroup và viết mã cho presenter:

public interface IUserGroupView : IListManipulationView

{

}

UserGroupPresenter quản lý giao diện IUserGroupView. Ngoài cách đăng ký làm một observer, còn cách khác là đăng ký một hàm nhận sự kiện. Trong ví dụ dưới đây hàm có tên là FillData.

public class UserGroupPresenter : GenericPresenter

{

private IUserGroupService groupService;

 

public override void OnViewSet()

{

groupService = new UserGroupService();

groupService.DataChanged += new DataChangeHandler(FillData);

}

 

private void FillData()

{

// Cập nhật thông tin của view ở đây

}

5          Trong project UI, tạo các form fmrUser, frmUserGroup và dlgUser.

Tạo form frmUser và thi hành giao diện IUserView

public partial class frmUser : Form, IUserView

Tạo hộp thoại dlgUser và thi hành giao diện IUserSelectionView

public partial class dlgUser : Form, IUserSelectionView

Tạo form frmUserGroup và thi hành giao diện IUserGroupView

public partial class frmUserGroup : Form, IUserGroupView

6. Tương tác giữa các tầng với nhau:

Khi người dùng cập nhật thông tin của một đối tượng, ấn nút Lưu, tầng UI sẽ gửi thông tin tới tầng như sau:

private void btnSave_Click(object sender, EventArgs e)

{

// CurrentItem là đối tượng hiện hành được cập nhật dữ liệu

CurrentItem.UserName = tbxName.Text.Trim();

CurrentItem.UserGroup = CurrentGroup;

// Phát sinh sự kiện lưu trữ gửi tới presenter

if (OnSaveEventHandler != null)

OnSaveEventHandler(this, e);

Tầng presenter lấy đối tượng vừa rồi, gọi phương thức Update của userService để cập nhật vào cơ sở dữ liệu:

public override void OnSaveEventHandler(object sender, EventArgs e)

{

userService.Update(View.CurrentItem, “UserID=” + View.CurrentItem.UserID);

}

 

Tải mã nguồn ví dụ:

–         MvpPatternExample.rar (http://www.mediafire.com/?fqcznsk5s4euvu4)

–         MvpPatternDIPExample.rar (http://www.mediafire.com/?u91e7keg8qr8mv5)

 

ManNT – R&D, HueCIT (bài cho HW) 

09/01/2013

 

 

[*] Nguyên lý đảo ngược phụ thuộc (Dependency Injection): Lớp cấp cao không nên phụ thuộc vào lớp cấp thấp, cả hai nên phụ thuộc vào một lớp tổng quát (abstract class/interface); và, lớp tổng quát (abstract) không nên phụ thuộc vào lớp cụ thể (concrete), ngược lại lớp cụ thể nên phụ thuộc vào lớp trừu tượng. Do lớp tổng quát ít có sự thay đổi, ổn định hơn so với lớp cụ thể thường xuyên có sự thay đổi, chỉnh sửa nâng cấp; và khi phụ thuộc vào các lớp tổng quát, hệ thống vẫn hoạt động bình thường nếu có sự thay đổi diễn ra tại một lớp cụ thể nào đó. Bởi vậy, cần đảo ngược sự phụ thuộc đó thành lớp cụ thể phụ thuộc vào lớp tổng quát.

 

Phiếm đàm về “òa” và “oà”

Thứ Hai, 10/01/2011 14:14 (GMT+7)
Người viết vừa “Google” vài từ để kiểm tra kết quả cuộc cải cách chữ viết nho nhỏ, hình như do nhóm nào đó khởi xướng khoảng 20 năm trước, về dấu trên các vần oa, oe, uy…

Và đây là kết quả:

Khoảng 23.500.000 kết quả (0,22 giây) cho “hòa bình”
Khoảng 8.780.000 kết quả (0,27 giây) cho “hoà bình”

Khoảng 6.970.000 kết quả (0,21 giây) cho “thỏa mãn”
Khoảng 2.860.000 kết quả (0,23 giây) cho “thoả mãn”

Khoảng 1.400.000 kết quả (0,15 giây) cho “giải tỏa”
Khoảng 1.440.000 kết quả (0,22 giây) cho “giải toả”

Khoảng 1.770.000 kết quả (0,27 giây) cho “khỏe mạnh”
Khoảng 1.990.000 kết quả (0,28 giây) cho “khoẻ mạnh”

Khoảng 576.000 kết quả (0,33 giây) cho “tung tóe”
Khoảng 224.000 kết quả (0,36 giây) cho “tung toé”

Khoảng 565.000 kết quả (0,34 giây) cho “mánh khóe”
Khoảng 135.000 kết quả (0,27 giây) cho “mánh khoé”

Khoảng 1.890.000 kết quả (0,16 giây) cho “tùy ý”
Khoảng 452.000 kết quả (0,40 giây) cho “tuỳ ý”

Khoảng 165.000 kết quả (0,27 giây) cho “thành lũy”
Khoảng 92.800 kết quả (0,34 giây) cho “thành luỹ”

Khoảng 437.000 kết quả (0,32 giây) cho “tiều tụy”
Khoảng 94.800 kết quả (0,32 giây) cho “tiều tuỵ”

Khoảng 80.700 kết quả (0,22 giây) cho “túy lúy”
Khoảng 26.000 kết quả (0,29 giây) cho “tuý luý”

Khoảng 246.000 kết quả (0,22 giây) cho “lũy kế”
Khoảng 386.000 kết quả (0,36 giây) cho “luỹ kế”

Chịu khó phân tích thấy cũng có nhiều thông tin từ các con số khô khan của Google:

1. Các từ càng phổ thông, càng có xu hướng viết kiểu cũ như “hòa bình”, “thỏa mãn”… Các từ ít phổ thông có lẽ khiến người viết phải cân nhắc lại chính tả khi viết nên xu hướng viết kiểu mới lại thắng thế như “giải toả”…

Tuy nhiên, cũng có người đưa ra ý kiến cho rằng “Không phải vậy, người ta quen viết kiểu cũ, viết kiểu mới là vì từ thời máy tính được dùng phổ biến thay máy chữ soạn thảo văn bản, thì các bộ gõ bị đặt mặc định kiểu gõ mới, nên họ buộc phải theo thôi, quay lui sửa mệt chứ không phải thích kiểu bỏ dấu mới! Chẳng hạn nếu không bật về kiểu gõ cũ thì khi muốn gõ “hòa” sẽ phải gõ “hò a” có dấu cách ở giữa, rồi quay lui 1, xóa dấu cách, rồi lại tiến lên 1, tính ra phải thêm đến 4 lần bấm phím”

2. Chịu khó xem viết trong văn bản nào, có thể thấy các tác phẩm văn học thường in theo kiểu cũ

3. Các từ thuộc nhóm KHXH thiên về kiểu cũ (75% cho túy lúy)

4. Các từ nhóm KHKT lại nghiêng theo kiểu mới (61% cho luỹ kế)

5. Xu hướng viết cân đối mỹ thuật vẫn còn nhiều người ủng hộ: kết quả về tiều tụy/tiều tuỵ ở trên cho thấy rõ là khi kiểu viết mới mất cân đối rõ rệt thì tỷ lệ ủng hộ rất thấp (chỉ có 18% cho tiều tuỵ). Khi cắt khẩu hiệu, băng rôn treo ngoài đường phố thì chữ rất to, vấn đề cân đối cũng thấy rõ nên xu hướng chọn kiểu viết cũ cũng thắng thế, xem dạng font cỡ lớn ở dưới sẽ hiểu:

HÒA , HOÀ

Với tình hình khảo sát thống kê ở trên, người viết trộm nghĩ giá hồi xưa người ta đừng đứng ra phát động cuộc cải cách về dấu trên các vần oa, oe, uy thì biết đâu chính tả tiếng Việt bây giờ sẽ đỡ lộn xộn hơn? Người viết từng có dịp trao đổi với cụ Nguyễn Tài Cẩn, GS đầu ngành ngôn ngữ học của Việt Nam. Khi  nhắc tới vấn đề này, thì thấy GS có vẻ không quan tâm và không bình luận đúng sai gì cả. Cá nhân người viết cho rằng đặt dấu trên nguyên âm chính có vẻ “khoa học” hơn, nhưng những người đặt dấu trên âm đệm -o-, -u- cũng có cái lý của họ (mà không cần viện dẫn lý do “cân đối”, “mỹ thuật” đâu nhé).

Vấn đề là, thanh điệu vốn là thuộc tính của cả từ chứ không phải là “độc quyền” của nguyên âm chính. Do quán tính vật lý của bộ máy phát âm nên khó có thể ngay lập tức thay đổi cao độ của từ chỉ trong khoảng thời gian ngắn của âm chính, nên các âm đệm trước (-o-,-u-) và sau âm chính (như -i ở vần -ai, -oi) ít nhiều cũng tham gia vào việc thể hiện thanh điệu. Ngay cả phát âm các phụ âm cuối cũng có thể biến đổi ít nhiều phụ thuộc vào thanh điệu cả từ.

Có lẽ những người phát minh dấu điện tín tiếng Việt (telex) cũng đã nắm khá rõ vấn đề này nên quy tắc điện tín chuẩn thời xưa là bỏ dấu (f,j,r,s,x) ở cuối từ, chứ không phải đính sau một nguyên âm nào cả. Người viết nhớ, khi nhóm cải cách muốn “giác ngộ” quần chúng, họ đã yêu cầu thử đọc tách rời hò-a và ho-à để xem cách nào sát âm “hòa” hơn… Quả thực ho-à sát hơn, nhưng cách làm đó chưa công bằng, vì tách âm đúng hơn nữa phải là hò-à, dấu không thuộc riêng một nguyên âm nào.

Như vậy viết “hòa” theo kiểu cũ, cho dấu nằm ngay giữa từ, chính là để nhắc người đọc rằng dấu thanh vốn thuộc về cả từ, cũng có logic lắm chứ? Nếu thực sự cần phát động một cuộc “cách mạng chữ viết” thì còn rất nhiều cái đáng phải sửa chữa hơn là quy tắc bỏ dấu trên 3 vần đó. Chẳng hạn:

  • Trong các vần -ay, -au thì “a” là nguyên âm a ngắn, chính tả thông thường viết là “ă”. Như vậy tau, say, mày, mau… phải viết tău, săy, mằy, mău… Khi đọc thấy điều “nằy” trong cuốn giáo trình lịch sử ngữ âm tiếng Việt của GS Cẩn, người viết rất bất ngờ, té ra lâu “năy” mình dốt.
  • Trong các vần -ay, -au khó nhận ra nguyên âm nào là âm chính, nhưng dựa vào các ví dụ như ni = nay, thu = thâu thì lại có thể cho rằng âm chính là -y và -u? Như vậy, nếu theo logic dấu phải đặt trên âm chính thì lại phải sửa thêm rất nhiều trường hợp như mày => măỳ, máu => măú…
  • Tiếng Việt còn nhiều cặp nguyên âm kép khá cân bằng về độ dài và cường độ tương đối, rất khó nhận ra âm nào là chính. Như vậy, nếu yêu cầu phải đặt dấu trên âm chính thì sẽ rất khó cho người bình thường không có máy móc kỹ thuật đo đạc chính xác trường độ, cường độ, tần số âm thanh…?
  • Phụ âm “Ph” có bật hơi thời Alexandre De Rhodes hầu như đã biến mất khỏi tiếng Việt, chuyển thành “F”, nên chính tả hiện đại phải là “F”.
  • Âm đệm -o-, -u- thực chất chỉ là một, có thể viết là -w- . Nhưng trong một số vần như -oi , -ui thì -o-, -u- lại là âm chính chứ không phải âm đệm, nên nếu cải cách thì có lẽ vấn đề sẽ rất phức tạp, bởi tùy địa phương và thời đại mà có thể nguyên âm thứ nhất mạnh hơn (là âm chính) hay suy giảm (trở thành âm đệm).
  • “Q” nên viết là “K”?
  • “Gi” có thể viết là “j”, “d” là “z”, “đ” là “d” .v.v…
  • So với các vấn đề “nằy” thì chuyện “òa”, “oà” là chuyện nhỏ, nhưng nói ra cũng dễ bị… “chọi đá”. Đã làm cách mạng thì phải triệt để. Cuộc cải cách nửa vời nói trên đã gây ra tình trạng hỗn loạn không đáng có cho chính tả tiếng Việt thời @!

Nhân tiện bàn thêm: Vấn đề truyền thống văn hóa cũng rất quan trọng. Chữ quốc ngữ đã có lịch sử gần 500 năm, văn học viết bằng chữ quốc ngữ cũng đã có hơn một thế kỷ, nếu vứt bỏ để theo hệ thống chính tả mới, các tiểu thuyết, thi ca thời tiền chiến sẽ phải đem ra phiên dịch lại? Có lẽ lý do tương tự mới giải thích được vì sao người Anh, Mỹ không cải tiến chính tả tiếng Anh dù chính tả tiếng Anh đã nổi tiếng thế giới về lối viết một đằng, đọc một nẻo?

Phân tích kỹ thuật các kiểu gõ tiếng Việt

Bài đã đăng tạp chí PCWorld Vietnam, January 8, 2009. See .

Xử lý tiếng Việt là vấn đề rất cũ, nhưng không phải là nhỏ vì ảnh hưởng tới rất nhiều người dùng. Đa phần các bộ gõ tiếng Việt lâu nay là tự phát, không có tài liệu phân tích kỹ thuật chi tiết. Nhân hợp tác với nhóm m17n thuộc AIST (Viện Khoa Học và Công Nghệ Công Nghiệp Tiên Tiến Nhật Bản) để cải tiến và phát triển các bộ gõ tiếng Việt, Chăm, Thái… trên môi trường Linux mã mở, chúng tôi đã thực hiện một số tài liệu phân tích kỹ thuật một cách bài bản, sau đây xin giới thiệu một số vấn đề rút từ những tài liệu đó.

I. Vài số liệu thống kê về hệ thống âm-vần-chữ cái tiếng Việt

Đây không phải là các thống kê ngôn ngữ học mà chỉ tập trung vào các dữ liệu liên quan tới việc xây dựng bộ bàn phím tiếng Việt.

1. Tổng số đơn âm tiếng Việt theo thống kê chưa đầy đủ của chúng tôi là: 7432.

Số này cũng xấp xỉ số liệu của GS Hoàng Phê, chủ biên từ điển Chính Tả Tiếng Việt. Số tuyệt đối không quan trọng vì dưới đây chỉ để ý tỉ lệ so sánh tương đối.

2. Số âm có dấu thanh: 6050, tỉ lệ: 81,4%

3. Số đơn âm viết có ít nhất một dấu thanh hoặc dấu phụ: 6761, tỉ lệ: 91%

4. Thanh sắc: 1861, tỉ lệ: 25%

5. Thanh nặng: 1474, tỉ lệ: 19,8%

6. Không dấu: 1382, tỉ lệ: 18,6%

7. Thanh huyền: 1177, tỉ lệ: 15,8%

8. Thanh hỏi: 980, tỉ lệ: 13,2%

9. Thanh ngã: 558, tỉ lệ: 7,5%

10. Số âm có phụ âm đầu: 7110, tỉ lệ: 95,7%

11. Số âm không phụ âm đầu: 322, tỉ lệ: 4,3%

12. Số dạng tổ hợp nguyên âm (không tính phụ âm cuối): 64

a. Số nguyên âm đơn: 12 (a, e, o, i, u, y, â, ê, ô, ơ, ă, ư)

b. Tổ hợp kép 2 nguyên âm: 32

c. Tổ hợp kép 3 nguyên âm: 20

13. Số vần (tổ hợp nguyên âm + phụ âm cuối): 228

14. Có 8 phụ âm cuối: M, N, C, T, P, CH, NG, NH

15. Và có 8 phụ âm đầu kép: CH, KH, NG, NGH, NH, TR, TH, PH.

II. Tần suất sử dụng phím

Chúng tôi thực hiện thống kê trên một văn bản thuần Việt và đủ lớn là Truyện Kiều, vì Truyện Kiều là một thể hiện điển hình của tiếng Việt. Chúng tôi đã chọn bản Nôm Liễu Văn Đường (1871), gồm 3244 câu, 22708 chữ.

Bảng 1: Dùng kiểu gõ Telex

Trung bình: 4,68 lần gõ phím trên 1 chữ

Phím dùng Số lần gõ Tỉ lệ %
A 12411 11,69
N 10327 9,727
O 9427 8,879
H 6347 5,978
F 6205 5,844
W 6087 5,733
I 5774 5,438
G 5384 5,071
E 5161 4,861
T 5029 4,737
S 4844 4,563
D 4531 4,268
U 4271 4,023
C 3555 3,348
R 2978 2,805
M 2573 2,423
J 2525 2,378
X 1748 1,646
Y 1685 1,587
L 1606 1,513
B 1065 1,003
V 907 0,854
K 719 0,677
P 700 0.659
Q 310 0,292
Tính theo hàng
home row 44572 41,982
qwer row 41422 39,015
zxcv row 20175 19,003
num row 0 0
Tổng số lượt gõ 106169

Bảng 2: Dùng kiểu gõ VNI

Trung bình: 4,72 lần gõ phím trên 1 chữ

Phím dùng Số lần gõ Tỉ lệ %
N 10327 9,621
A 10141 9,448
O 7523 7,009
6 6384 5,948
H 6347 5,913
2 6205 5,781
I 5774 5,379
U 5438 5,066
G 5384 5,016
T 5029 4,685
7 4938 4,601
1 4006 3,732
C 3555 3,312
E 2951 2,749
D 2653 2,472
M 2573 2,397
5 2525 2,352
9 1878 1,75
Y 1685 1,57
L 1606 1,496
R 1602 1,493
3 1376 1,282
4 1252 1,166
8 1149 1,07
B 1065 0,992
V 907 0,845
S 838 0,781
K 719 0,67
0,67 700 0,652
X 496 0,462
Q 310 0,289
Tính theo hàng
home row 27688 25,796
qwer row 29327 27,323
zxcv row 20608 19,201
num row 29713 27,682
Tổng số lượt gõ 107336

Bảng 3: Tần suất sử dụng các vần

(chỉ kê ra 32 vần thông dụng nhất)

Vần Số lần Tỉ lệ %
a 140 1 6,153
ai 781 3,430
ơi 697 3,061
ang 679 2,982
ay 654 2,872
i 644 2,828
ên 603 2,648
ao 581 2,552
ong 568 2,495
ây 566 2,486
o 561 2,464
inh 544 2,389
ương 510 2,240
ôi 509 2,235
ăng 491 2,156
ơ 473 2,077
ưa 443 1,946
âu 439 1,928
ông 436 1,915
ê 408 1,792
ung 386 1,695
ư 385 1,691
anh 384 1,686
ôt 346 1,520
ươi 330 1,449
ên 308 1,353
on 295 1,296
iêu 294 1,291
e 274 1,203
an 271 1,190
ươc 267 1,173
âm 245 1,076
u 230 1,010

Nhận xét chung

– Nhìn chung nếu chia bình quân thì tần suất sử dụng các phím dấu thanh gần bằng các phím nguyên âm và lớn hơn tần suất dùng các phím phụ âm. Đây là một chi tiết rất quan trọng mà chúng ta sẽ cần dùng trong phần so sánh các kiểu gõ Telex, VNI dưới đây.

– Nhưng xét trị tuyệt đối thì phụ âm n và hai phím nguyên âm a, o đứng đầu bảng tức là dùng nhiều nhất, trong cả 2 kiểu gõ.

III. Các luật gõ tiếng Việt

Mô hình cấu trúc một từ tiếng Việt, dấu ngoặc tròn là thành phần luôn phải có, ngoặc vuông có thể có hoặc không:

[C] ((V1) [V2] [V3] [T]) [C]

C: phụ âm đầu

V1: nguyên âm 1, luôn có ít nhất một nguyên âm

V2: nguyên âm 2

V3: nguyên âm 3

T: dấu thanh

C: phụ âm cuối

Các luật gõ chính thức của các kiểu gõ Telex, VNI, TCVN 6064 chỉ là một bảng các quy tắc ánh xạ phím, khá quen thuộc nên chúng tôi xin lược bỏ để giới thiệu sang quy luật về vị trí dấu thanh, thiết thực hơn. Quy luật vị trí dấu thanh trên các tổ hợp nguyên âm, theo GS Hoàng Phê, như sau:

1. Khi chỉ có 1 nguyên âm thì dấu đặt trên nguyên âm đó

2. Khi có phụ âm cuối thì dấu nằm ở nguyên âm sát phụ âm cuối

3. Vần có nguyên âm đệm oa, oe, uê, uơ, uy thì dấu nằm ở nguyên âm chính (sau)

4. Các vần tận cùng là nguyên âm (có thể 2 hay 3 nguyên âm) và khác oa, oe, uê, uơ, uy thì dấu nằm trên nguyên âm đứng trước nguyên âm tận cùng.

Tuy nhiên qua thực tiễn ở VN thì các vần bất định oa, oe, uy phần nhiều vẫn theo kiểu bỏ dấu cũ, dấu thanh đặt trên nguyên âm đệm. Vì vậy các bộ gõ đều cung cấp khóa chuyển cho phép chọn kiểu bỏ dấu mới hay cũ cho chúng – bộ gõ m17n cũng thế.

IV. Phân tích ưu điểm của kiểu gõ Telex so với VNI, TCVN

Nhiều người khẳng định kiểu gõ Telex là tiện lợi nhất khi gõ thuần tiếng Việt, nhưng thuận lợi ở điểm nào thì lại không nói, ở đây chúng tôi thử phân tích:

1. Kiểu gõ Telex hoàn toàn chỉ sử dụng 3 hàng phím tiếng Anh cơ bản (QWER … ASDF … ZXCV..). Trong đó hàng phím ASDF… tiếng Anh là “home row” chính là hàng phím cơ sở, trong kiểu gõ 10 ngón tay thì hai ngón trỏ được định vị trên hai phím F&J trên hàng phím này (hai phím này có gờ nhỏ để đánh dấu), các ngón khác xếp tự nhiên ở các phím bên cạnh trên home row. Khi gõ 10 ngón tay, dễ dàng nhận thấy là ngón tay càng phải dời xa hàng phím cơ sở thì càng khó gõ đồng thời càng dễ gõ sai hơn. Kiểu gõ Telex có lợi thế hơn VNI và TCVN chính ở điểm này, do không dùng đến hàng phím số ở xa home row.

2. Trong kiểu gõ Telex, hàng phím cơ sở dễ gõ nhất đồng thời lại là hàng phím có tần suất sử dụng lớn nhất, tần suất của hai hàng còn lại cũng khá cân đối (xem bảng thống kê ở phần II).

3. Khi dùng kiểu gõ VNI tất cả các dấu phụ đều bị đẩy lên hàng phím số, phần lớn dấu phụ của kiểu gõ TCVN cũng thế, cho nên hàng phím khó gõ nhất này lại có tần suất sử dụng lớn nhất (xem bảng thống kê tần suất ở trên, hoặc có thể đoán qua con số 91% các từ tiếng Việt có dấu phụ).

4. Kiểu gõ VNI & TCVN bỏ phí không dùng đến 4 phím w,f,j,z ở khu vực dễ gõ. Trong khi Telex nguyên thủy chỉ bỏ phí một phím z thôi. Chú ý thêm là hai phím định vị quan trọng F&J trong kiểu gõ Telex được dùng với tần suất khá lớn thì VNI/TCVN lại bỏ phí.

5. Cơ chế gõ lặp phím để tạo dấu cho đ-â-ô-ê (các cải tiến hiện nay còn cho phép hủy dấu, mở rộng sang cả dấu thanh) của kiểu gõ Telex là rất tiết kiệm. Tuy cũng phải gõ 2 lượt phím như VNI nhưng thực chất ngón tay chỉ di chuyển lên xuống thêm chừng 5mm, đồng thời rất khó gõ sai. Chính các điện thoại di động cũng dùng cơ chế gõ lặp phím để sinh ra nhiều chữ, nên cơ chế này tạo cảm giác khá thân thuộc cho người dùng.

V. Phân tích nhược điểm của kiểu gõ Telex so với VNI, TCVN và định hướng giải quyết

Cho đến nay chúng tôi chỉ xác định được một nhược điểm của kiểu gõ Telex so với VNI và TCVN là khó gõ hỗn hợp Anh-Việt. Tiếc thay, đây lại là một nhược điểm chí mạng trong điều kiện giao lưu quốc tế rộng rãi ngày nay, nhất là với những người làm chuyên về KHKT, CNTT…

Tuy các phần mềm đều có phím nóng để chuyển qua lại giữa trạng thái gõ Anh và Việt, nhưng nhiều người lại không thích dùng mà muốn các bộ gõ tự động xử lý vấn đề này.

Để xử lý được việc gõ hỗn hợp thì trước hết bộ gõ phải được cung cấp các tiêu chí phân biệt từ Anh/Việt để quyết định xử lý từ đang đánh như tiếng Việt hay tiếng Anh, đây chính là chỗ mà mục này sẽ phân tích.

Giải quyết trọn vẹn nhất là gắn vào bộ gõ một modul kiểm tra chính tả và một từ điển chính tả tiếng Việt, tuy không khó nhưng cũng khá phiền phức. Nếu không thì phải tìm kiếm một số tiêu chí để chuyển tự động về tiếng Anh dựa trên phân tích, tổng hợp các quy luật chính tả, ngữ âm tiếng Việt. Sau đây xin giới thiệu một vài tiêu chí mà bộ gõ vi-telex mã nguồn mở chạy trên môi trường Linux của nhóm m17n (Viện AIST, Nhật Bản) đã ứng dụng (xem www.m17n.org):

1. Sau nguyên âm mà gặp các phụ âm cuối không có trong tiếng Việt thì cho chuyển sang tiếng Anh đến hết từ, sau đây sẽ gọi là “temp-escape”, cụ thể là các phụ âm sau: q,d,g,h,k,l,z,v,b.

2. Với các phụ âm đã mượn làm dấu tiếng Việt s,f,j,r,x thì không thể temp-escape như thế mà phải dùng kiểu gõ lặp lại. Nhấn lần đầu là tạo dấu, nhấn lần nữa là hủy dấu đồng thời temp-escape luôn, người dùng phải chủ động trong quyết định này.

3. Tiếng Việt là đơn âm nên với các từ có hơn 1 âm cũng cho temp-escape khi phát hiện âm thứ 2, như từ “changes” khi gõ đến “e” sẽ temp-escape cho nên “s” không bị biến thành dấu sắc nữa.

4. DD/dd chỉ là Đ/đ khi đứng đầu từ, còn lại cho temp-escape, ví dụ từ address.

5. w chỉ là ư khi đi ngay sau phụ âm, hoặc sau u/a/o để tạo dấu, còn lại vẫn là w, ví dụ từ view sẽ không bị biến ra vieư.

6. z chỉ xóa dấu khi trước đó đã có nguyên âm được bỏ dấu, còn lại cho temp-escape.

Dự kiến có thể đưa ra môt tiêu chí nữa là nhận dạng các tổ hợp phụ âm đầu kép của tiếng Việt, nhưng có lẽ hiệu quả không cao vì các phụ âm đó (ch, kh, ng, ngh, nh, tr, th, ph) cũng có trong các ngôn ngữ Latinh… Đưa vào quá nhiều tiêu chí sẽ làm code lộn xộn thiếu sáng sủa, nhiều hơn nữa thì quay về phương án kiểm tra qua từ điển chính tả lại hợp lý hơn.

VI. Các xu hướng cải tiến bộ gõ tiếng Việt

Xu hướng phát triển chung là gắn thêm vào bộ gõ các phần kiểm tra chính tả và hỗ trợ tốc ký, hoặc mở rộng cho các thứ tiếng dân tộc ở VN như chữ Nôm, Tày, Thái, Chăm… đó là những cải tiến nên có, có dịp chúng tôi sẽ giới thiệu ở một bài khác.

Ở đây chỉ bàn tới những cải tiến còn gây tranh cãi, ví dụ một số người dùng muốn có kiểu bỏ dấu tự do (cả dấu thanh lẫn dấu mũ, dấu móc), nhưng phân tích kĩ thì thấy kiểu bỏ dấu tự do này chỉ phù hợp với VNI, chứ với Telex thì sẽ làm trầm trọng thêm nhược điểm khó gõ hỗn hợp Anh Việt. Vấn đề là do các phím dấu trong kiểu gõ Telex có hai chức năng tạo dấu và chữ cái nên dễ bị lẫn lộn, còn trong VNI chỉ có một chức năng tạo dấu thôi. Các từ như data, Japan, common, receive khi gõ Telex kiểu bỏ dấu tự do thì hóa ra dât, Jâpn, cômmn, rêcive… Phải sáng suốt trong vấn đề này, không nên vì những nhận xét kiểu gõ này “thông minh”, kiểu gõ kia không mà sa vào những cái phức tạp, ít hiệu quả thực tiễn. VNI thêm các cải tiến này cũng không hiệu quả đến mức áp đảo được các ưu điểm của Telex đã phân tích trên. Còn Telex “học” theo VNI cải tiến này cũng không có hiệu quả gì hơn nếu không nói là ngược lại. Ví dụ Telex tự do gõ chữ ôm = omo, đầu tiên là tên bột giặt “OMO” sẽ biến ra ÔM, làm nặng thêm khuyết điểm khó gõ hỗn hợp Anh Việt, sau nữa là rất nhiều người chỉ quen gõ một tay thì cự ly di chuyển sẽ xa thêm: từ phím O sang M rồi về O cự li di chuyển gần gấp đôi so với gõ đúp O rồi chuyển sang gõ M. Gõ “thông minh” chưa rõ có lợi gì, nhưng tốc độ thì đã thua kiểu gõ “chân quê”.

Phan Anh Dũng
R&D Department
Thua Thien Hue Center of Information Technology (Huesoft).