Truyện chưa có tên

Chương 1: Gặp gỡ

Đã là tháng thứ hai Gia Hân đi làm ở công ty mới. Vì chưa bỏ được thói quen ngủ muộn, nên hôm nay cô suýt đến công ty trễ. Chạy được đến thang máy, nhìn đồng hồ, “Còn 3 phút nữa “. Trong thang máy lúc này chỉ có cô và một thanh niên nữa. Đến tầng 20, cô bước ra, chàng trai cũng bước ra. Khuôn mặt chàng trai ngơ ngác, đuổi theo Gia Hân.

-Chị ơi, cho em hỏi với, công ty HNS ở đâu vậy chị ?.

Nhưng Gia Hân đã vụt mất, bỏ mặc chàng trai lại. “May quá vừa kịp giờ”. Điểm danh vân tay xong, cô vội vã bước vào bàn làm việc của mình. Cô nhìn ra phía cửa, có một thanh niên mà cô gặp ở thang máy đi vào. Hình như người này đến phỏng vấn. Cô cũng chả bận tâm, không phải việc của mình.

Hôm nay công việc cũng không có gì nhiều. “Để tí làm” - Gia Hân tự nhủ. Ngồi lướt facebook một lúc, chả có tin tức gì mới. Được một lúc, người thanh niên đi ra, khuôn mặt thất thần. Đến lúc này cô mới chú ý bộ dạng của anh. Khá điển trai, mặc một chiếc áo sơ mi xanh da trời, trên tay cầm bộ hồ sơ. Cô nghĩ “Chắc trượt phỏng vấn rồi, trai đẹp đến mầy mà vô dụng thì cũng bỏ đi “.

Gió điều hòa hơi se lạnh, cô đứng dậy vươn vai, uể oải tiến đến bàn pha Cafe.

-Hôm nay sao mặt buồn thế em ? - Phát hỏi.

-Cũng không có gì, điều hòa lạnh quá thôi. - Gia Hân đáp.

Phát - dáng hơi đậm, trên mắt là cặp kính cận, làm ở phòng Marketing. Luôn tốt với mọi người, đặc biệt là phụ nữ. Hắn crush Gia Hân từ lần đầu tiên gặp mặt. Cô có nhan sắc khá bình thường, nhưng có đôi mắt biết nói. Chỉ cần đôi mắt ấy năn nỉ thôi, hắn có thể làm bất cứ điều gì. Tiếc là, hẵn còn chưa là bạn với cố, chỉ là đồng nghiệp thôi, còn khác bộ phận nữa, nên ánh mắt năn nỉ ấy chắc sẽ chẳng bao giờ xuất hiện.

Kết thúc giờ làm, mọi người lần lượt checkout ra về. Gia Hân mặc bộ áo chống nắng, thứ giúp cô gia nhập làng nhẫn giả lead. Phóng xe vèo vèo trên đường, bóp còi, leo vỉa, chả việc gì cô không làm cả. Về đến nhà, lại tất bật nhảy vào để nấu ăn. Hôm nay là ngày cuối tuần, ăn xong lại dán mặt vào màn hình điện thoại. Mệt quá, cô ngủ thiếp đi lúc nào không hay.

“Reng reng”. Tiếng chuông cửa làm Gia Hân tỉnh giấc, cô bước ra mở cửa. Thì ra là người giao hàng, mấy hôm trước cô đặt mua một chiếc váy. “Mình mua cái này làm gì không biết ?” - Gia Hân nhìn vào chiếc váy. Một cái váy hết sức sặc sỡ và sang trọng. Đi chơi với lũ bạn cờ hó ư ? Với bọn nó thì quá sỉ nhục chiếc váy ? Đi chơi với người yêu ? Hang này chưa ai thám hiểm. “Thôi kệ đi, tính sau” - Cô nghĩ. Mặc nguyên bộ quần áo ngủ ( không phải mấy kiểu sexy đâu), Gia Hân đi mang Laptop ra cửa hàng tiện lợi bên đường ngồi. Ăn mặc như này mà ra ngồi Cafe không ổn lắm. Cô thích ngồi ở đây. Điều hòa có, wifi có. Cô mở phimmoi ra, xem vài bộ phim yêu thích, ăn snack.

Đến gần trưa, xem phim cũng quá chán rồi, Gia Hân về nhà, tranh thủ tạt qua chợ để mua vài thứ. Đi đến cổng chợ, bỗng cô khựng lại. Chàng trai đến phỏng vấn hôm qua. Anh đang mặc bộ đồng phục GoViet và ngồi cạnh chiếc xe wave cũ. Hình như anh cũng nhận ra cô. Cô bước qua với ánh mắt có chút bối rối. Đứng ở quầy thịt, đang mặc cả với bà bán hàng, thì có tiếng điện thoại. “Hân về ngay đi con, mẹ con mất rồi”. Như sét đánh bên tai, cô đứng như trời chồng mặc cho người bán hàng đang giục. Được vài phút, cô chạy nhanh ra chỗ người lái xe ôm, nói “Anh chở tôi nhanh với, tôi có việc gấp”. Về đến phòng, cô bảo anh đứng đợi mình một lúc. Cô thay quần áo và quay ra. “Anh trở tôi ra bến xe”.

Nhân, tên của anh. Nhân là sinh viên mới ra trường, đang đi tìm việc. Tranh thủ chạy xe ôm để kiếm thêm thu nhập. Nghe thấy tiếng khóc sụt sùi, anh hỏi:

-Cô có ổn không?

-Tôi ổn, chỉ là đang có chuyện buồn - Gia Hân.

Nhân cảm thấy không nên hỏi nữa và tiếp tục chạy xe. Vừa xuống xe, anh thấy Gia Hân sờ túi. “Chết rồi, mình để quên ví ở phòng rồi, làm sao bây giờ” - Cô nghĩ. Như hiểu chuyện, anh nói:

-Khi nào gặp trả cũng được, cho tôi xin số điện thoại của cô. Quê cô ở đâu ?

-Sao anh lại hỏi thế ? Thái Bắc- Cô đáp

Anh rút ví ra đưa cô tờ 100 nghìn. “Cô cầm lấy mà đi xe này, về nhanh, người nhà mong”. Cô nở một nụ cười, đôi mắt như phát sáng. “Cảm ơn anh, nhất định tôi sẽ gặp lại anh”. Ánh mắt như có ma lực ấy làm thôi miên Nhân. Anh chưa bao giờ có cảm giác nào như thế này. “Uống nhầm ánh mắt say cả đời” - câu hát chợt lóe lên trong đầu Nhân. Một lúc sau, khi cô đã lên xe rồi, anh mới bừng tỉnh.

“Nhất định phải gặp lại cô ấy” - Nhân nghĩ.

…còn tiếp

Soạn thảo văn bản với Typora

Reduce và reducer

Hôm nay mình sẽ nói về reduce và reducer, một hàm rất hay trong lập trình. Mình sẽ trình bày những ứng dụng của nó vào việc lập trình

Khái niệm

Reducers là những hàm nhận vào một giá trị, sau đó trả về giá trị khác dựa trên giá trị nhập vào

Đây là một khái niệm trong lập trình hàm, trong đó các hàm số là những pure function (không có side-effect). Reducer vì vậy ( khi áp dụng trong những ngôn ngữ tự do như javascript) cũng nên là pure function

Ví dụ :

1
const increase = val => val+1;

Khái niệm reducer rất đơn giản, nhưng khi ứng dụng nó với hàm reduce, sẽ mang lại một hiệu quả cao.

Tính tổng một mảng

Dưới đây mình sẽ dùng 2 cách

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Mang ban dau
const arr = [2,4,6,9,2];

// Sử dụng for loop
let sum = 0;
for (let index = 0; index < arr.length; index++)
{
sum+= arr[index];
}
console.log(sum);

// Su dung reduce
const initial = 0;
const reducer = (prev,current)=>pre+current;
const sum2 = arr.reduce(reducer,initial);
console.log(sum2);

Cụ thể hơn, nếu như sử dụng for loop, bạn sử dụng một biến để lưu tổng của mảng, và biến này sẽ thay đổi trong chương trình

1
2
3
4
5
6
0
2
6
12
21
23

Tuy nhiên với cách dùng reduce lại không thế, tổng tạm thời sau mỗi lần lặp đều được tạo mới và được truyền đến lần lặp sau (truyền giá trị ). Tổng cuối cùng chỉ được tạo ra sau lần lặp cuối cùng. Xem hình dưới đây.

Đệ quy

Hình dung dễ nhất về reduce, đó là sử dụng đệ quy. Bạn có thể thấy rõ hơn cách hoạt động của reduce.

1
2
3
4
5
6
7
8
9
const len = arr.length;
const recursi= (sum,val, index)=>{
if(index < len)
{
return recursi(sum + val,arr[index], index+1);
}
return sum;
}
console.log(recursi(0,arr[0],0))

Máy rút tiền

Vì hướng đối tượng của javascript chưa hỗ trợ biến private, nên mình sẽ viết ví dụ này trên C#

Lớp tài khoản. Ta có thể mở rộng bằng việc truyền những hàm khác nhau vào phương thức dispatch. Trong dispatch, ta có thể hoàn toàn kiểm soát việc thay đổi các trường ( giới hạn những trường được phép sửa). Dispatch giống như một setter, nhưng sẽ mạnh hơn.

1
2
3
4
5
6
7
8
9
10
11
12
13
class TaiKhoan
{
private int SoDu;
public TaiKhoan()
{
SoDu = 0;
}
public void dispatch(Func<int,int, int> reducer, int payLoad)
{
int soDuSau = reducer(SoDu,payLoad);
this.SoDu = soDuSau;
}
}

Chương trình chính

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Program
{
static void Main(string[] args)
{
var taiKhoan = new TaiKhoan();
//Rút
int Rut(int goc, int payload)
{
if (goc > payload)
{
return goc - payload;
}
Console.Write("Rút không thành công");
return goc;
};
//Nạp
int Nap(int goc, int payload) => goc + payload;
//Kiểm tra
int Check(int goc, int payload)
{
Console.Write("So tien :" + goc);
return goc;
}
taiKhoan.dispatch(Nap, 1000);
taiKhoan.dispatch(Check, 0);// 1000;
Console.WriteLine();
taiKhoan.dispatch(Rut, 100);
taiKhoan.dispatch(Check, 1000); // 900;
Console.Read();
}
}

Khi muốn sửa đổi một class, ta chỉ cần sửa đổi các reducer. Các reducer nên được viết càng dễ hiểu càng tốt, và nó thậm chí còn không biết được các bên trong class có gì.

Điểm yếu:

Kết

Với kiến thức hạn hẹp của mình, reduce, reducer là một cái gì đó rất cool và thú vị, nó mang lại những cách nghĩ mới, cách code mới. Hiện tại thì với reduce, nó chậm hơn đáng kể so với vòng lặp thông thường, nhưng nó khiễn code dễ đọc hơn rất nhiều và khiến cho việc kiểm soát lỗi tốt hơn.

Tạo một thư viện JS

Viết một thư viện, dù chỉ vài chục dòng, mang lại rất nhiều kiến thức hữu ích. Mình sẽ viết theo những hiểu biết của mình. Hi vọng các bạn sẽ có cho mình nhiều kinh nghiệm. Thư viện mình viết có chức năng rất đơn giản: Một db đơn giản với lưu FILE dạng Blob.

Tạo thư mục git

Đầu tiên các bạn tạo remote repostory trên git server yêu thích của bạn, trong tuts này mình sẽ dùng github

Tạo git folder ở local:

1
git init [Tên dụ án git]

Thêm remote cho git folder:

1
git remote add origin [Địa chỉ git remote của bạn]

Cấu trúc thư mục

Thư mục src sẽ chứa code nguồn, thư mục tests để chạy test, thư mục dist sẽ chứa code release.

Cài các depedencies

Cấu hình webpack

Tạo file webpack.config.js:

1
2
npm i webpack-cli @webpack-cli/init
npx webpack-cli init

Sau đó sửa lại như sau:

1
2
3
4
5
6
7
8
9
10
11
12

var libraryName = 'mamaDB'; // Hoặc tên thư viện của bạn
var outputFile = libraryName + '.js';

...
output: {
path: __dirname+'/dist',
filename: outputFile,
library: libraryName,
libraryTarget: 'umd',
umdNamedDefine: true
},

Module hóa code

Đầu tiên ta có code ban đầu:

Nếu các hàm có liên quan đến nhau, hoặc chỉ được gọi ở ngay tại scope đó thì nên để chung. Còn không, chia các hàm thành các file riêng. Khi import sẽ dễ đọc hơn. Một cách khác nữa để import, export nhiều từ một file là sử dụng destructuring:

Test với mocha và chai

Test là một công việc rất quan trọng và cần thiết trong lập trình. Hiện tại chúng ta ít còn phải test bằng tay do việc ra đời của các công cụ test rất mạnh mẽ. Ở đây mình sử dụng Mocha để test và Chai để assert.
Vì thư viện trên trình duyệt nên test trên môi trường trình duyệt (vì js trên server với trên browser có nhiều khác biệt về các API). Code test trình duyệt:

  • HTML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!DOCTYPE html>
    <html>
    <head>
    <title>Mocha Tests</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/6.1.2/mocha.min.css">
    </head>
    <body>
    <div id="mocha"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/6.1.2/mocha.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js"></script>
    <script>mocha.setup('bdd')</script>

    <!-- load code you want to test here -->
    <script src="../dist/mamaDB.js"></script>
    <script>
    let expect = chai.expect;
    </script>
    <!-- load your test files here -->
    <script src="./test.js"></script>
    <script>
    mocha.run();
    </script>
    </body>
    </html>
  • JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
describe('mamaDB',()=>{
let db = null;
beforeEach(() => {
db = new mamaDB();
});
describe('after initization',()=>{
it('should return an error after getItem(anykey)', ()=>{
expect(db.getItem("key").message).to.equal("Unable to get item");
});
it('should return an error after getItem(anykey) with anykey is not string',()=>{
expect(db.getItem(1).message).to.equal("Key is not a string");
})
})
describe('Test putItem function',()=>{
it('should return an err if "key" is not string',()=>{
expect(db.putItem(null,"key").message).to.equal("invalid type")
})
it('should return an err if "key" is null',()=>{
expect(db.putItem(null,null).message).to.equal("invalid type")
})
it('should return an err if "file" is not a FILE',()=>{
expect(db.putItem("D","key").message).to.equal("invalid type")
})
it('should return an err if "file" is null',()=>{
expect(db.putItem(null,"key").message).to.equal("invalid type")
})
it('should return key if succes add to db',()=>{
expect(db.putItem(new File([JSON.stringify("Text")],"ex.json"),"key")).to.equal("key")
})
})
describe('Test getItem function',()=>{
beforeEach(()=>{
db.putItem(db.putItem(new File([JSON.stringify("Text")],"ex.json"),"key"));
})
it('Should return item if valid key');
it('Should return error if key is not string');
it('Should return error item if key is null');
it('Should not return item if not valid key');
})
});

Mình sử dụng liveserver ngay trong visual studio code để tự cập nhập lại code:

Hàm descbrice dùng để mô tả đoạn test. Hàm it để định nghĩa code cho các đoạn code.

Build code

Kết