Javascript: Học Javascript cơ bản – Kiến thức chung về lập trình.

Series hiện tại có 2 bài viết:

  1. Học Javascript cơ bản – Kiến thức chung về lập trình.
  2. Học Javascript cơ bản – Các khái niệm cần nắm trong JS.

Phần này sẽ giúp bạn hiểu hơn về lập trình trên máy tính. Với những kiến thức cơ bản nhất về máy tính và lập trình nói chung.

Một khi bạn cảm thấy thoải mái về nền tảng trong lập trình, phần sau sẽ giúp bạn đi nhanh hơn và hiệu quả hơn.

Code

Hãy cùng bắt đầu. Nhiều người hỏi code là gì?

Trong một ứng dụng, nó thường là những mã nguồn(source code) là tập hợp những chỉ dẫn đặc biệt để nói cho máy tính làm những điều chúng ta muốn. Thông thường, code được lưu với dạng file text, mặc dù với Javascript chúng ta có thể gõ code trực tiếp trên console của trình duyệt. Phân này sẽ được đề cập ở những phần sau.

Những qui định về định dạng, cú pháp, những chỉ hẫn dẫn được kết hợp với nhau gọi là ngôn ngữ của máy tính(computer language). Nó cũng giống như cách làm sao chúng ta phát âm từ ngữ, tạo nên những câu văn bằng cách sử dụng những từ đơn và giống câu trong tiếng anh.

Statements

Trong ngôn ngữ máy tính, một nhóm các từ ngữ, con số, phương thức hay toán tử mà chúng thực hiện một nhiệm vụ cụ thể nào đó được gọi là statement(câu lệnh). Trong Javascritp, một statement trông như sau:

a = a * 2

Ký tự a b được gọi là biến(variables). Nó giống như cái hộp mà bạn có thể chứa những gì mình thích. Trong lập trình biến giữ giá trị(values)- như số 42.

Ngược lại, 2 được chỉ là một giá trị(value), gọi là literal value, bởi vì nó đứng một mình và ko được biến nào quản lý.

Dấu = và * là những toán tử(operators). Chúng tạo nên những hành động với sự tham gia của biến(variables) và giá trị(values) như gán giá trị cho biến hay nhân hai số với nhau, …

Hầu hết những câu lệnh trong Javascript có dấu (;) ở cuối câu.

Câu lệnh a = b * 2 nói với máy tính rằng lấy giá từ biến b nhân với giá trị 2, sau đó lưu kết quả ngược lại một biến mới là a.

Một chương trình đơn giản là tập hợp nhiều câu lệnh để làm một nhiệm vụ gì đó như tính toán diện tích hình chữ nhật, tìm nghiệm phương trình, tìm số lớn nhất trong mảng, …

Expressions

Những câu lệnh thường được cấu thành từ những biểu thức(expressions). Một biểu thức là sự kết hợp giữa các biến, giá trị và toán tử như cộng, trừ, nhân, chia, …

Ví dụ:

a = b * 2;

Câu lệnh trên gồm 4 biểu thức là:

  • 2 là một literal value expression
  • b là một biến expression
  • b*2 là một tính toán expression
  • a = b * 2 là một phép gán, có nghĩa là kết quả của b * 2 sẽ được lưu lại vào biến a

Ngoài ra, còn có một số expression gọi call expression(nó giống như một function và được gọi để thực thi), ví dụ như:

alert(a);

Executing a Program

Máy tính sẽ hiểu và thực thi những câu lệnh như thế nào? Một chương trình cần được thực thi(executed) hay là chạy một chương trình.

Câu lệnh như a = b * 2 thì khá dễ để các developer đọc và viết. Nhưng đối với máy tính nó không hiểu những chỉ dẫn như vậy, máy tính chỉ đọc và thực thi được câu lệnh sau khi được mã hóa thành dãy nhị phân. Quá trình đó gọi là thông dịch(interpretor) hay biên dịch(compiler).

Ở một số ngôn ngữ lập trình, quá trình dịch từ ngôn ngữ tự nhiên(ví dụ: a = b *2) thành ngôn ngữ để máy tính hiểu( ví dụ a = b * 2 được dịch thành 000111000) – mã nhị phân. Quá trình này được diễn ra từ trên xuống dưới, và đoạn code của chúng ta sẽ được máy tính thực thi từng dòng. Đó gọi là thông dịch. Bạn hãy tưởng tượng giống như những thông dịch viên. Quá trình thông dich từ tiếng Anh sang tiếng Việt cũng diễn ra tương tự. Thông dịch viên sẽ dịch từng câu. Sau khi người nói nói xong một câu, thì sẽ được dịch câu đó và cứ thế tiếp tục cho đến hết bài nói.

Ở môt số ngôn ngữ khác, quá trình dịch code được diễn ra một lần. Máy tính chỉ thực thi đoạn code khi mà nó được dịch toàn bộ sang ngôn ngữ máy.

Với Javascript thì nó thường được biết đến là một ngôn ngữ thông dịch, bởi vì nó được thực thi khi chúng ta mở trang web lên. Nhưng điều đó không thực sự chính xác. Một cách nhanh chóng, Javascript thưc sự sẽ biên dịch(compile) code trước và ngay lập tức thực thi code đã được biên dịch.

Try Javascript Code

Bạn có thể mở developer console của trình duyệt và bắt đầu code thử một số câu lệnh, operator đơn giản như sau nhé:

const a = 21;

const b = a * 2;

console.log( b );

Để xuống dòng trong console bạn có thể sử dụng <shift> + <enter>. Sau khi hoàn tất đoạn code, bạn có thể nhấn <enter> thì code của bạn sẽ được thực thi.

Có một vài cách khác để bắt đầu code với JS là sử dụng một số playground như: JS Bin, JS Complete, JS Fiddle,…

Hãy bắt đầu với chính đoạn code bạn viết ra. Bởi vì cách tốt nhất để học lập trình là xoắn tay áo lên và lao vào code.

Output

Output là những gì đượ xuất ra cho người dùng thấy ví dụ như lệnh print, echo, log, … Trong Javascript bạn có thể print một output bằng console.logalert.

console.log(b);
alert(b);

Input

Input là cách để máy tính thu thập dữ liệu từ người dùng. Một trong những cách phổ biến đó là trong HTML, chúng ta có thể dùng một <form> để tạo nên những thẻ <input> sau đó lấy thông tin từ người dùng.

Nhưng có một cách đơn giản hơn trong JS là dùng hàm prompt()

const age = prompt( "Please tell me your age:" );

console.log( age );

Sau khi chạy đoạn code trên, trình duyệt sẽ xuất hiện một popup để cho chúng ta nhập thông tin vô như sau:

Và sau khi nhập giá trị 35, console sẽ in ra giá trị là 35.

Operators

Toán tử(operators) là những hành động mà máy tính thực hiện dựa treen các biến và các giá trị. Hiện tại chúng ta có thể biết đến các toán tử như =(phép gán), *(phép nhân).

Ví dụ, chúng ta có một số toán tử như sau:

var a = 20;

a = a + 1;
a = a * 2;

console.log( a );	// 42

Trong Javascript có một số toán tử thông dụng như sau:

  • Phép gán: = ví dụ a = 2.
  • Tính toán: + (cộng), - (trừ), * (nhân), and / (chia), ví dụa * 3.
  • Phép gán kết hợp: +=-=*=, and /= ví dụa += 2 (tương đương với a = a + 2).
  • Tăng/Giảm: ++ (tăng lên 1), -- (giảm xuống 1), ví dụ a++ (tương đương với a = a + 1).
  • Truy cấp thuộc tính của đối tượng: . ví dụ console.log() hay obj.a nghĩa là đối tượng obj có một thuộc tính là a. Hay có thể dùng cách này obj["a"]. Sẽ được nói chi tiết ở phần sau
  • So sánh bằng: == (chỉ so sánh giá trị), === (so sánh cả gía trị và kiểu dữ liệu), != , !== ví dụa == b.
  • So sánh khác: < , > , <= , >=, ví dụa <= b.
  • Logic: && (và), || (hoặc), ví dụ a || b chọn a hoặc b.

Values & Types

Giá trị và kiểu giá trị(Values & Types) là những con số, chuỗi, mảng dữ liệu mà chúng ta thao tác trên đó. Ví dụ như:

  • Khi tính toán với những con số( số 5, 6) chúng ta cần kiểu dữ liệu number
  • String là kiểu dữ liệu chuỗi, như : “Hello World”, “Tôi tên là A” là những kiểu(types) dữ liệu dạng chuỗi.
  • Ngoài ra còn có giá trị đúng hay sai gọi là boolean.
"I am a string";
'I am also a string';

42;

true;
false;

Ngoài những dữ liệu quen thuộc như string/number/boolean chúng ta còn phải biết đến những kiểu phức tạp hơn như arrays, objects, functions,

Chuyển đổi giữa các type(Converting types)

Trong một số trường hợp chúng ta cần chuyển đổi từ string sang number và từ number sang string. Trong Javascript quá trình đó được gọi là ép kiểu(coercison).

Javascript cung cấp một số cách để ép kiểu như sau:

var a = "42";
var b = Number( a );

console.log( a );	// "42"
console.log( b );	// 42

Sử dụng Number(…) để chuyển đổi kiểu string sang kiểu số thường được gọi là chuyển đổi kiểu rõ ràng(explicit coercion). Một cách dễ dàng chúng ta có thể hiểu rằng nó sẽ chuyển đổi string hay một number.

Một trong những tranh cãi khác về chuyển đổi kiểu là Javascript trong một số trường hợp sẽ tự động chuyển đổi kiểu dùm chúng ta. Mọi người thường nói đây là kiểu implicit coercion. Bởi vì nó không minh bạch và được tự động bên trong nên có khi chúng ta không nhận biết về chúng gây nên sự hiểm nhầm và sai sót trong khi lập trình.

Ví dụ như khi so sanh hai giá trị “99.98”99.99. Rõ ràng đây là hai kiểu dữ liệu khác nhau, một là type string, hai là type number.

console.log("99.98" == 99.99)
console.log("99.98" === 99.99)

Bạn có thể dự đoán được kết quả hai phép so sánh trên đây không?

Nếu bạn sử dụng == để so sánh thì Javascript sẽ tự động bên trong nó chuyển đổi bên trái “99.98” thành số number là 99.99. Và kết quả dĩ nhiên sẽ là true.

Với cách so sánh dùng === thì mọi chuyện sẽ khác. Bởi vì Javascript sẽ không tự động chuyển type nữa nên kết quả sẽ là false.

Với Javascript thì tự động chuyển type(implicit corercion) có thể gây nhiều sự khó khăn và bối rối cho developer. Cho nên mọi người nói đây là lỗ hỏng của ngôn ngữ và nó nên được tránh.

Tuy nhiên, implicit coercion nếu được tìm hiểu kỹ nó sẽ không gây hiểu lầm mà còn là một công cụ để chúng ta lập trình tốt hơn và yêu Javascript hơn.

Code Comments

Comments là cách để chúng ta giải thích code chúng ta như thế nào. Trong một số trường hợp chúng ta cần comments để cho người đọc hiểu rõ hơn về code. Nhưng việc lạm dụng comments lại bị người nhiều chê trách.

Khi sử dụng comments chúng ta cần lưu ý:

  • Code không comment là code tôi ưu vì code của bạn đã quá rõ ràng đến mức người đọc đã hiểu và không cần nói gì thêm
  • Quá nhiều code cho một đoạn code, có thể code của bạn ko được tổ chức tốt và quá phức tạp cho nên bạn phải dùng nhiều comments để giải thích
  • Comments nên sử dụng để giải thích why, chứ không phải what.

Trong Javascript có hai loại comments là: một dòng và nhiều dòng.

//This is a single-line comment
/* But this is
       a multiline
             comment.
                      */

Variables

Hầu hết chương trình đều cần để theo dõi những giá trị bởi vì chúng sẽ thay đổi theo thời gian bằng những phương pháp gồm những toán tử, phép gán.

Cách dễ dàng nhất để làm điều đó là gán những giá trị đó vào một cái thùng chứa hay gọi là các variables. Trong tiếng anh, variables xuất phát từ vary, có nghĩa là chúng sẽ bị thay đổi theo thời gian.

Trong một số ngôn ngữ, bạn sẽ khai báo một biến để lưu một kiểu dữ liệu cụ thể như number hoặc string. Đó được gọi là static typing. Nó bắt buộc chúng ta truyền đúng kiểu dữ liệu và ngăn chặn sự sai sót khi chúng ta truyền dữ liệu lung tung.

Một số ngôn ngữ khác như Javascript sử dụng weak typing(dynamic typing). Nó cho phép một biến có thể lưu nhiều kiểu giá trị khác nhau qua những thời điểm khác nhau. Javasctipt được thiết kế như một dynamic type, chúng ta có thể dễ dàng khai báo một biến, lưu bất kỳ number, string, object mà chúng ta thích.

var amount = 99.99;

amount = amount * 2;

console.log( amount );		// 199.98

// convert `amount` to a string, and
// add "$" on the beginning
amount = "$" + String( amount );

console.log( amount );		// "$199.98"

Biến amount ban đầu giữ giá trị 99.99 như một number. Sau đó với câu lệnh
amount = “$” + String(amount) đã chuyển biến amount về như một string để lưu giá trị “$199.98”.

Các lập trình viên Javascript có thể linh hoạt sử dụng biến amount cho những giá trị khác nhau như 99.99, 199.88, hay “$199.98”. Với những ngôn ngữ static typing như C#, Typesccript, Java chúng ta phải sử dụng một biến khác như amountStr để lưu giá trị “$199.88”. Bạn không thể biên dịch chương trình khi bạn dùng sai type cho một biến.

Hơn nữa, bạn có thể nhận thấy rằng biến amount đang giữ một giá trị biến đổi theo thời gian trong một chương trình phân mềm. Nó mô tả một cách đúng đắn rằng chức năng của biến là: quản lí sự thay đổi giá trị(state).

State là những giá trị mà bạn phải theo dõi trong khi chương trình của bạn được khởi chạy.

Ngoài ra, chúng ta còn có các biến constants. Nó thường được khai báo đầu tiên cho mỗi chương trình và giá trị của chúng sẽ không thay đổi theo thời gian. Trong Javascript qui tắc đặt tên những hằng số thường được viết hoa và được ngăn cách nhau bởi dấu _.

Ví dụ như sau:

const TAX_RATE = 0.08;	// 8% sales tax

let amount = 99.99;

amount = amount * 2;

amount = amount + (amount * TAX_RATE);

console.log( amount );				// 215.9784
console.log( amount.toFixed( 2 ) );	// "215.98"

Với cú pháp ES6, chúng ta phải dùng từ khóa const cho một hằng số. Bởi vì khi sử dụng const trình biên dịch sẽ bảo vệ biến đó không bị thay đổi.

Blocks

Một block là một nhóm những câu lệnh đi cùng nhau thực hiện một nhiệm vụ gì đó. Trong Javascript, một block được khai báo bên trong dấu ngoặc nhọn { … }

let amount = 99.99;

// a general block
{
	amount = amount * 2;
	console.log( amount );	// 199.98
}

Một block độc lâp như ví dụ trên là đúng cú pháp nhưng liệu nó có được dùng nhiều. Có lẽ không, vì block được dùng kết hợp với một số từ khóa như if, for, while, function , …

let amount = 99.99;

// is amount big enough?
if (amount > 10) {			// <-- block attached to `if`
	amount = amount * 2;
	console.log( amount );	// 199.98
}

Conditionals

Có một số cách để thể hiện điều kiện(hay quyết định) trong Javascript. Trong đó sử dụng câu lệnh if là cách thông dụng nhất. Nó cũng gần giống nhất với ngôn ngữ tự nhiên: “Nếu điều kiện này đúng thì sẽ làm cái gì đó...”

Ví dụ:

const bank_balance = 302.13;
const amount = 99.99;

if (amount < bank_balance) {
  console.log( "I want to buy this phone!" );
}

Trong code trên nếu điều kiện amount < bank_balancetrue thì những lệnh trong block {…} sẽ được thực hiện.

Hoặc chúng ta có thể sử dụng kết hợp với else như sau:

const ACCESSORY_PRICE = 9.99;

let bank_balance = 302.13;
let amount = 99.99;

amount = amount * 2;

// can we afford the extra purchase?
if ( amount < bank_balance ) {
   console.log( "I'll take the accessory!" );
   amount = amount + ACCESSORY_PRICE;
}
// otherwise:
else {
  console.log( "No, thanks." );
}

Có thể bạn đã hiểu đoạn code trên được thực thi như thế nào đúng không? Nếu if đúng(true) thì làm gì đó, ngược lại(else) thì làm việc khác.

Loops

Việc lặp đi lặp lại một vài hành động gì đó khi điều kiện đúng được gọi là loops(vòng lặp) trong Javascript.

Một vòng lặp thường bao gồm một điều kiện nào đó. Miễn là điều kiện đúng thì hành động được lặp lại mãi mãi. Ví dụ chúng ta có đoạn code sau:

while (numOfCustomers > 0) {
	console.log( "How may I help you?" );

	// help the customer...

	numOfCustomers = numOfCustomers - 1;
}

// versus:

do {
	console.log( "How may I help you?" );

	// help the customer...

	numOfCustomers = numOfCustomers - 1;
} while (numOfCustomers > 0);

Trên đây chúng ta có vòng lặp kiểu while(kiểm tra điều kiện cho lần đầu tiên của vòng lặp) và vòng lặp do…while(bỏ qua lần kiểm tra đầu tiên).

Theo như ví dụ thì, nếu điều kiện là false trong lần chạy đầu tiên thì:

  • Với while nó sẽ không thực thi đoạn code trong dấu ngoặc { … }
  • Ngược lại với do … while sẽ thực thi đoạn code này.

Ngoài ra, Javascript còn nhiều cú pháp khác cho vòng lặp như: for, for/in for/of, forEach. Các bạn cùng tìm hiểu thêm ở đây nhe.

Với những thuật toán phưc tạp, đôi khi chúng ta còn cần dùng đến breakcontinue.

  • Break dùng để thoát khỏi vòng lặp khi thỏa mãn một điều kiện gì đó.
  • Continue dùng để bỏ qua một lần trong vòng lặp

Bạn có thể xem chi tiết cách sử dụng tại đây.

Functions

Một nhân viên bán hàng ở siêu thị thường sẽ không mang theo bên mình một chiếc máy tính cầm tay để tính tiền cho khách. Điều đó có lẽ bất tiện bởi vì cô ta phải luôn nhớ công thức toán học trong đầu như giá, thuế, … Cho nên, cửa hàng này đã trang bị một máy tính để checkout cho khách hàng. Trong đó, chiếc máy tính đã có sẵn chức năng (function) thanh toán tiền cho khách hàng và chức năng này sẽ được sử dụng lại nhiều lần mà thu ngân sẽ không quan tâm quá nhiều về cách tính toán nữa. Cô ta chỉ việc nhập số lương và function sẽ tự động tính toán thay cô.

Tương tự trong lập trình cũng vậy, chúng ta có nhu cầu sử dụng lại những chức năng gì đó. Và khi mà chúng ta gọi nó sẽ trả về kết quả cuối cùng. Lập trình viên sẽ không cần quan tâm nhiều quá về cách thức function đó hoạt động thế nào.

Một function đơn giản như một biến có tên và phần code để thực thi khi chúng ta gọi nó. Ví dụ ta có:

function printAmount() {
  console.log( amount.toFixed( 2 ) );
}

let amount = 99.99;

printAmount(); // "99.99"

amount = amount * 2;

printAmount(); // "199.98"

Một khi bạn muốn in một giá trị gì đó chỉ cần việc gọi hàm printAmout và nó khá dễ để chúng ta sử dụng lại.

Một function thường có tham sốgiá trị trả về. Chúng ta có thể viết lại hàm trên khi có sử dụng tham số như sau:

function printAmount(amt) {
	console.log( amt.toFixed( 2 ) );
}

function formatAmount() {
	return "$" + amount.toFixed( 2 );
}

let amount = 99.99;

printAmount( amount * 2 );		// "199.98"

amount = formatAmount();
console.log( amount );			// "$99.99"

Hàm printAmount giờ đây trở nên linh hoạt hơn khi mà chúng ta chỉ việc truyền một tham số amt vào. Sau đó nó sẽ in ra đúng giá trị bạn muốn. 🙂

Scope

Scope là phạm vi truy cập những biến trong một hàm. Mỗi function sẽ có một scope riêng và chúng ta chỉ truy xuất được những biến trong scope của function đó. Khi ra khỏi một function, những biến của nó sẽ ko được truy cập.

Một biến là duy nhất trong một hàm nhưng chúng ta có thể khai báo hai biến giống nhau ở hai scope khác nhau.

function one() {
	// this `a` only belongs to the `one()` function
	var a = 1;
	console.log( a );
}

function two() {
	// this `a` only belongs to the `two()` function
	var a = 2;
	console.log( a );
}

one();		// 1
two();		// 2

Có một khái niệm khác về scope nữa là lexical scope, nghĩa là có khi một function có thể truy xuất một biến của function khác nếu hai function đó được lồng nhau như ví dụ sau:

function outer() {
	var a = 1;

	function inner() {
		var b = 2;

		// we can access both `a` and `b` here
		console.log( a + b );	// 3
	}

	inner();

	// we can only access `a` here
	console.log( a );			// 1
}

outer();

Scope của function inner nằm trong scope của function outer cho nên nó có thể đọc và ghi được biến a. 🙂

Practice – cách tốt nhất để học lập trình

Quả thật không có một sự thay thế nào cho việc học code bằng cách xoắn tay áo lên và bắt tay vào code.

Sau đây là một số yêu cầu nho nhỏ bạn có thể bắt đầu code:

  • Viết một chương trình tính toán tổng giá của tất cả Iphone mà bạn mua. Bạn cứ tiếp tục mua cho đến khi bạn hết tiền. Và sau đó bạn mua thêm một số phụ kiện theo kinh phí dự định trước.
  • Sau khi bạn tính toán xong giá, bạn phải cộng thêm thuế và in ra theo một format như VND.
  • Cuối cùng, bạn viết một hàm trả về có lượng Iphone mà bạn có thể mua dựa vào số tiền bạn có.
  • Bạn nên tạo những hằng số như “giá thuế”, “số tiền bạn có”, “giá mỗi điện thoại”, “giá phụ kiện”

Sau đây là một solution đơn giản:

const SPENDING_THRESHOLD = 200;
const TAX_RATE = 0.08;
const PHONE_PRICE = 99.99;
const ACCESSORY_PRICE = 9.99;

var bank_balance = 303.91;
var amount = 0;

function calculateTax(amount) {
	return amount * TAX_RATE;
}

function formatAmount(amount) {
	return "$" + amount.toFixed( 2 );
}

// keep buying phones while you still have money
while (amount < bank_balance) {
	// buy a new phone!
	amount = amount + PHONE_PRICE;

	// can we afford the accessory?
	if (amount < SPENDING_THRESHOLD) {
		amount = amount + ACCESSORY_PRICE;
	}
}

// don't forget to pay the government, too
amount = amount + calculateTax( amount );

console.log(
	"Your purchase: " + formatAmount( amount )
);
// Your purchase: $334.76

// can you actually afford this purchase?
if (amount > bank_balance) {
	console.log(
		"You can't afford this purchase. :("
	);
}
// You can't afford this purchase. :(

Review

Học lập trình không phải là một quá trình quá là gian khổ và khó khăn. Để bắt đầu, chúng ta nên làm quen dần với các khái niệm cơ bản và nắm chắc chúng.

Những hành động nhỏ này giống như từng viên gạch nhỏ. Để xây dựng nên một tòa Landmark 81 hùng vĩ, chúng ta cần những viên gạch rất nhỏ như vậy. Nó cũng giống như việc học lập lập trình.

Thành công không phải là bạn làm gì đó to tát trong một ngày mà là bạn phải làm những việc rất nhỏ mỗi ngày. Sau một thời gian dài sự tích lũy về lượng sẽ thay đổi thành chất. Hãy ghi nhớ công thức: làm việc nhỏ + thời gian dài= thành công.

Thâu Nguyễn

Sau đây là một số khái niệm nhỏ bạn cần ôn luyện lại:

  • Bạn cần những toán tử(operators) để thực hiện một hành động trên các giá trị.
  • Bạn cần những giá trị và kiểu dữ liệu(values & types) để thao tác trên nhiều dữ liệu khác nhau.
  • Bạn cần những biến(variables) để lưu trữ dữ liệu.
  • Bạn cần những điều kiện(conditionals) để ra một quyết định.
  • Bạn cần những vòng lặp(loops) để làm những task lặp đi lặp lại.
  • Bạn cần những hàm(functions) để tổ chức code cho logic và để sử dụng lại.

Và cuối cùng đừng bỏ qua việc luyện tập và hãy thực hành.

Phương pháp tốt nhất để học code là viết code.

Tham khảo: You don’t know JS

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *