SOLID architecture principles using simple C# examples

Introduction

I know there are 1000’s of articles on this subject and every month 10 new articles around SOLID would be injected more. My goal of writing this article is to understand SOLID with simple C# examples.

Any improvements on this article comment box is open below.

What is SOLID?

SOLID are five basic principles whichhelp to create good software architecture. SOLID is an acronym where:-

  • S stands for SRP (Single responsibility principle
  • O stands for OCP (Open closed principle)
  • L stands for LSP (Liskov substitution principle)
  • I stands for ISP ( Interface segregation principle)
  • D stands for DIP ( Dependency inversion principle)

So let’s start understanding each principle with simple c# examples.

Understanding “S”- SRP (Single responsibility principle)

The best way to understand SOLID is by understanding what problem it tries to solve. Have a look at the code below, can you guess what the problem is ?( You are not going to get BEER to guess it J , because it’s too simple).

OK, let me give a HINT look at the catch block code.

class Customer
    {
        public void Add()
        {
            try
            {
                // Database code goes here
            }
            catch (Exception ex)
            {
                System.IO.File.WriteAllText(@"c:\Error.txt", ex.ToString());
            }
        }
    }

The above customer class is doing things WHICH HE IS NOT SUPPOSED TO DO. Customer class should do customer datavalidations, call the customer data access layer etc , but if you see the catch block closely it also doing LOGGING activity. In simple words its over loaded with lot of responsibility.

So tomorrow if add a new logger like event viewer I need to go and change the “Customer”class, that’s very ODD.

It’s like if “JOHN” has a problem why do I need to check “BOB”.

This also reminds me of the famous swiss knife. If one of them needs to be changed the whole set needs to be disturbed. No offense I am great fan of swiss knifes.

But if we can have each of those items separated its simple, easy to maintain and one change does not affect the other. The same principle also applies to classes and objects in software architecture.

So SRP says that a class should have only one responsibility and not multiple.So if we apply SRP we can move that logging activity to some other class who will only look after logging activities.

class FileLogger
    {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\Error.txt", error);
        }
    }

Now customer class can happily delegate the logging activity to the “FileLogger” class and he can concentrate on customer related activities.

class Customer
    {
        private FileLogger obj = new FileLogger();
        publicvirtual void Add()
        {
            try
            {
                // Database code goes here
            }
            catch (Exception ex)
            {
                obj.Handle(ex.ToString());
            }
        }
    }

Now architecture thought process is an evolution. For some people who are seniors looking at above SRP example can contradict that even the try catch should not be handled by the customer class because that is not his work.

Yes, we can create a global error handler must be in theGlobal.asax file , assuming you are using ASP.NET and handle the errors in those section and make the customer class completely free.

So I will leave how far you can go and make this solution better but for now I want to keep this simple and let your thoughts have the freedom to take it to a great level.

Below is a great comment which talks about how we can take this SRP example to the next level.
http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp?msg=4729987#xx4729987xx

Understanding “O” – Open closed principle

Let’s continue with our same customer class example. I have added a simple customer type property to the class. This property decided if this is a “Gold” ora “Silver” customer.

Depending on the same it calculates discount. Have a look at the “getDiscount” function which returns discount accordingly. 1 for Gold customer and 2 for Silver customer.

Guess, what’s the problem with the below code. Hahaha, looks like this article will make you a GUESS championWink | ;-) .

Ok, also let me add a HINT, look at the “IF” condition in the “getDiscount” function.

class Customer
{
        private int _CustType;

        public int CustType
        {
            get { return _CustType; }
            set { _CustType = value; }
        }

        public double getDiscount(double TotalSales)
        {
                if (_CustType == 1)
                {
                    return TotalSales - 100;
                }
                else
                {
                    return TotalSales - 50;
                }
        }
}

The problem is if we add a new customer type we need to go and add one more “IF” condition in the “getDiscount” function, in other words we need to change the customer class.

If we are changing the customer class again and again, we need to ensure that the previous conditions with new one’s are tested again , existing client’s which are referencing this class are working properly as before.

In other words we are “MODIFYING” the current customer code for every change and every time we modify we need to ensure that all the previous functionalities and connected client are working as before.

How about rather than “MODIFYING” we go for “EXTENSION”. In other words every time a new customer type needs to be added we create a new class as shown in the below. So whatever is the current code they are untouched and we just need to test and check the new classes.

class Customer
{
        public virtual double getDiscount(double TotalSales)
        {
            return TotalSales;
        }
}

  class SilverCustomer : Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 50;
        }
    }
class goldCustomer : SilverCustomer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 100;
        }
    }

Putting in simple words the “Customer” class is now closed for any new modification but it’s open for extensions when new customer types are added to the project.

Understanding “L”- LSP (Liskov substitution principle)

Let’s continue with the same customer. Let’s say our system wants to calculate discounts for Enquiries. Now Enquiries are not actual customer’s they are just leads. Because they are just leads we do not want to save them to database for now.

So we create a new class called as Enquiry which inherits from the “Customer” class. We provide some discounts to the enquiry so that they can be converted to actual customers and we override the “Add’ method with an exception so that no one can add an Enquiry to the database.

class Enquiry : Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 5;
        }

        public override void Add()
        {
            throw new Exception("Not allowed");
        }
    }

If you visualize the current customer inheritance hierarchy it looks something as shown below. In other word “Customer” is the parent class with “Gold” , “Silver” and “Enquiry” as child classes.

So as per polymorphism rule my parent “Customer” class object can point to any of it child class objects i.e. “Gold”, “Silver” or “Enquiry” during runtime without any issues.

So for instance in the below code you can see I have created a list collection of “Customer” and thanks to polymorphism I can add “Silver” , “Gold” and “Enquiry” customer to the “Customer” collection without any issues.

Thanks to polymorphism I can also browse the “Customer” list using the parent customer object and invoke the “Add” method as shown in the below code.

Now again let me tickle your brains, there is a slight problem here, THINK, THINK THINK.

HINT: -Watch when the Enquiry object is browsed and invoked in the “FOR EACH” loop.

 

List<Customer> Customers = new List<Customer>();
Customers.Add(new SilverCustomer());
Customers.Add(new goldCustomer());
Customers.Add(new Enquiry());

 foreach (Customer o in Customers)
 {
                o.Add();
 }
}

As per the inheritance hierarchy the “Customer” object can point to any one of its child objects and we do not expect any unusual behavior.

But when “Add” method of the “Enquiry” object is invoked it leads to below error because our “Equiry” object does save enquiries to database as they are not actual customers.

Now read the below paragraph properly to understand the problem. If you do not understand the below paragraph read it twiceJ..

In other words the “Enquiry” has discount calculation , it looks like a “Customer” but IT IS NOT A CUSTOMER. So the parent cannot replace the child object seamlessly. In other words “Customer” is not the actual parent for the “Enquiry”class. “Enquiry” is a different entity altogether.

So LISKOV principle says the parent should easily replace the child object. So to implement LISKOV we need to create two interfaces one is for discount and other for database as shown below.

interface IDiscount
{
        double getDiscount(double TotalSales);
}


interface IDatabase
{
        void Add();
}

Now the “Enquiry” class will only implement “IDiscount” as he not interested in the “Add” method.

class Enquiry : IDiscount
    {
        public  double getDiscount(double TotalSales)
        {
            return TotalSales - 5;
        }
    }

While the “Customer” class will implement both “IDiscount” as well as “IDatabase” as it also wants to persist the customer to the database.

class Customer : IDiscount, IDatabase
   {


       private MyException obj = new MyException();
       public virtual void Add()
       {
           try
           {
               // Database code goes here
           }
           catch (Exception ex)
           {
               obj.Handle(ex.Message.ToString());
           }
       }

       public virtual double getDiscount(double TotalSales)
       {
           return TotalSales;
       }
   }

Now there is no confusion, we can create a list of “Idatabase” interface and add the relevant classes to it. In case we make a mistake of adding “Enquiry” class to the list compiler would complain as shown in the below code snippet.

Understanding “I” – ISP (Interface Segregation principle)

Now assume that our customer class has become a SUPER HIT component and it’s consumed across 1000 clients and they are very happy using the customer class.

Now let’s say some new clients come up with a demand saying that we also want a method which will help us to “Read” customer data. So developers who are highly enthusiastic would like to change the “IDatabase” interfaceas shown below.

But by doing so we have done something terrible, can you guess ?

HINT: – Think about the effect of this change on the above image.

interface IDatabase
{
        void Add(); // old client are happy with these.
voidRead(); // Added for new clients.
}

If you visualize the new requirement which has come up, you have two kinds of client’s: –

  • Who want’s just use “Add” method.
  • The other who wants to use “Add” + “Read”.

Now by changing the current interface you are doing an awful thing, disturbing the 1000 satisfied current client’s , even when they are not interested in the “Read” method. You are forcing them to use the “Read” method.

So a better approach would be to keep existing clients in their own sweet world and the serve the new client’s separately.

So the better solution would be to create a new interface rather than updating the current interface. So we can keep the current interface “IDatabase” as it is and add a new interface “IDatabaseV1” with the “Read” method the “V1” stands for version 1.

interface IDatabaseV1 : IDatabase // Gets the Add method
{
Void Read();
}

You can now create fresh classes which implement “Read” method and satisfy demands of your new clients and your old clients stay untouched and happy with the old interface which does not have “Read” method.

class CustomerwithRead : IDatabase, IDatabaseV1
    {

public void Add()
{
	Customer obj = new Customer();
Obj.Add();
}
	Public void Read()
	{
	// Implements  logic for read
}
    }

So the old clients will continue using the “IDatabase” interface while new client can use “IDatabaseV1” interface.

IDatabase i = new Customer(); // 1000 happy old clients not touched
i.Add();

IDatabaseV1 iv1 = new CustomerWithread(); // new clients
Iv1.Read();

Understanding “D”- Dependency inversion principle

In our customer class if you remember we had created a logger class to satisfy SRP. Down the line let’s say new Logger flavor classes are created.

class Customer
    {
        private FileLogger obj = new FileLogger();
        public virtual void Add()
        {
            try
            {
                // Database code goes here
            }
            catch (Exception ex)
            {
                obj.Handle(ex.ToString());
            }
        }
    }

Just to control things we create a common interface and using this common interface new logger flavors will be created.

interface ILogger
{
        void Handle(string error);
}

Below are three logger flavors and more can be added down the line.

class FileLogger : ILogger
    {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\Error.txt", error);
        }
    }
class EverViewerLogger : ILogger
    {
        public void Handle(string error)
        {
            // log errors to event viewer
        }
    }
class EmailLogger : ILogger
  {
      public void Handle(string error)
      {
          // send errors in email
      }
  }

Now depending on configuration settings different logger classes will used at given moment. So to achieve the same we have kept a simple IF condition which decides which logger class to be used, see the below code.

QUIZ time, what is the problem here.

HINT: – Watch the CATCH block code.

class Customer : IDiscount, IDatabase
    {
        private IException obj; 

public virtual void Add(int Exhandle)
        {
            try
            {
                // Database code goes here
            }
            catch (Exception ex)
            {
                if (Exhandle == 1)
                {
                    obj = new MyException();
                }
                else
                {
                    obj = new EmailException();
                }
                obj.Handle(ex.Message.ToString());
            }
        }

The above code is again violating SRP but this time the aspect is different ,its about deciding which objects should be created. Now it’s not the work of “Customer” object to decide which instances to be created , he should be concentrating only on Customer class related functionalities.

If you watch closely the biggest problem is the “NEW” keyword. He is taking extra responsibilities of which object needs to be created.

So if we INVERT / DELEGATE this responsibility to someone else rather the customer class doing it that would really solve the problem to a certain extent.

So here’s the modified code with INVERSION implemented. We have opened the constructor mouth and we expect someone else to pass the object rather than the customer class doing it. So now it’s the responsibility of the client who is consuming the customer object to decide which Logger class to inject.

class Customer : IDiscount, IDatabase
 {
        private Ilogger obj;
        public Customer(ILogger i)
        {
            obj = i;
        }
}

So now the client will inject the Logger object and the customer object is now free from those IF condition which decide which logger class to inject. This is the Last principle in SOLID Dependency Inversion principle.

Customer class has delegated the dependent object creation to client consuming it thus making the customer class concentrate on his work.

IDatabase i = new Customer(new EmailLogger());

Revising SOLID principles

S stands for SRP (Single responsibility principle):- A class should take care of only one responsibility.

O stands for OCP (Open closed principle):- Extension should be preferred over modification.

L stands for LSP (Liskov substitution principle):- A parent class object should be able to refer child objects seamlessly during runtime polymorphism.

I stands for ISP (Interface segregation principle):- Client should not be forced to use a interface if it does not need it.

D stands for DIP (Dependency inversion principle) :- High level modules should not depend on low level modules but should depend on abstraction.

If you are already done with this article the next logical steps would be going through GOF Design Patterns, here’s an article for the same, Hope you enjoy it.

Once you understand SOLID the next step is to learn design patterns. Below is a nice video which teaches you Design Pattern with a project in 8 hours.

 

Source http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp

SOLID LÀ GÌ – ÁP DỤNG CÁC NGUYÊN LÝ SOLID ĐỂ TRỞ THÀNH LẬP TRÌNH VIÊN CODE “CỨNG”

Trong quá trình học, hầu như các bạn sinh viên đều được học một số khái niệm OOP cơ bản như sau:

  • Abstraction (Tính trừu tượng)
  • Encapsulation (Tính bao đóng)
  • Inheritance (Tính kế thừa)
  • Polymophirsm (Tính đa hình)

Những khái niệm này đã được dạy khá rõ ràng, và hầu như những buổi phỏng vấn nào cũng có những câu hỏi liên quan đến khái niệm này. Vì 4 khái niệm này khá cơ bản, bạn nào chưa vũng có thể google để tìm hiểu thêm.

Những nguyên lý mình giới thiệu hôm nay là những nguyên lý thiết kế trong OOP. Đây là những nguyên lý được đúc kết bởi máu xương vô số developer, rút ra từ hàng ngàn dự án thành công và thất bại. Một project áp dụng những nguyên lý này sẽ có code dễ đọc, dễ test, rõ ràng hơn. Và việc quan trọng nhất là việc maintainace code sẽ dễ hơn rất nhiều (Ai có kinh nghiệm trong ngành IT đều biết thời gian code chỉ chiếm 20-40%, còn lại là thời gian để maintainance: thêm bớt chức năng và sửa lỗi).  Nắm vững những nguyên lý này, đồng thời áp dụng chúng trong việc thiết kế + viết code sẽ giúp bạn tiến thêm 1 bước trên con đường thành senior nhé (1 ông senior bên FPT Software từng bảo mình thế).

keepcalm

Ok, 10 phút quảng cáo đã qua, bây giờ đến phần giới thiệu. SOLID tức là “cứng”, áp dụng nhiều thì bạn sẽ code “cứng”. Đùa thôi, nó là tập hợp 5 nguyên tắc sau đây:

  1. Single responsibility principle
  2. Open/closed principle
  3. Liskov substitution principle
  4. Interface segregation principle
  5. Dependency inversion principle

Trong nội dung bài viết này, mình chỉ giới thiệu tổng quát để các bạn có cái nhìn tổng quan về các nguyên lý này.

1. Single responsibility principle

single_responsibility_principle_thumb

Nguyên lý đầu tiên, tương ứng với chữ S trong SOLID. Nội dung nguyên lý:

Một class chỉ nên giữ 1 trách nhiệm duy nhất 
(Chỉ có thể sửa đổi class với 1 lý do duy nhất)

Để hiểu nguyên lý này, ta hãy lấy ví dụ với 1 class vi phạm nguyên lý. Ta có 1 class như sau

1
2
3
4
5
6
public class ReportManager()
{
   public void ReadDataFromDB();
   public void ProcessData();
   public void PrintReport();
}

Class này giữ tới 3 trách nhiệm: Đọc dữ liệu từ DB, xử lý dữ liệu, in kết quả. Do đó, chỉ cần ta thay đổi DB, thay đổi cách xuất kết quả, … ta sẽ phải sửa đổi class này. Càng về sau class sẽ càng phình to ra. Theo đúng nguyên lý, ta phải tách class này ra làm 3 class riêng. Tuy số lượng class nhiều hơn những việc sửa chữa sẽ đơn giản hơn, class ngắn hơn nên cũng ít bug hơn.

2. Open/closed principle

openclosed_principle_thumb

Nguyên lý thứ hai, tương ứng với chữ O trong SOLID. Nội dung nguyên lý:

Có thể thoải mái mở rộng 1 class, nhưng không được sửa đổi bên trong class đó 
(open for extension but closed for modification).

Theo nguyên lý này, mỗi khi ta muốn thêm chức năng,.. cho chương trình, chúng ta nên viết class mới mở rộng class cũ ( bằng cách kế thừa hoặc sở hữu class cũ) không nên sửa đổi class cũ.

3. Liskov Substitution Principle

liskov_substitution_principle_thumb

Nguyên lý thứ ba, tương ứng với chữ L trong SOLID. Nội dung nguyên lý:

Trong một chương trình, các object của class con có thể thay thế class cha mà không làm thay đổi tính đúng đắn của chương trình

Hơi khó hiểu? Không sao, lúc mới đọc mình cũng vậy. Hãy tưởng tượng bạn có 1 class cha tên Vịt. Các class VịtBầu, VịtXiêm có thể kế thừa class này, chương trình chạy bình thường. Tuy nhiên nếu ta viết class VịtChạyPin, cần pin mới chạy được. Khi class này kế thừa class Vịt, vìkhông có pin không chạy được, sẽ gây lỗi. Đó là 1 trường hợp vi phạm nguyên lý này.

4. Interface Segregation Principle

interface_segregation_principle_thumb

Nguyên lý thứ tư, tương ứng với chữ I trong SOLID. Nội dung nguyên lý:

Thay vì dùng 1 interface lớn, ta nên tách thành nhiều interface nhỏ, với nhiều mục đích cụ thể

Nguyên lý này khá dễ hiểu. Hãy tưởng tượng chúng ta có 1 interface lớn, khoảng 100 methods. Việc implements sẽ khá cực khổ, ngoài ra còn có thể dư thừa vì 1 class không cần dùng hết 100 method. Khi tách interface ra thành nhiều interface nhỏ, gồm các method liên quan tới nhau, việc implement + quản lý sẽ dễ hơn.

5. Dependency inversion principle

dependency_inversion_principle_thumb

Nguyên lý cuối cùng, tương ứng với chữ D trong SOLID. Nội dung nguyên lý:

1. Các module cấp cao không nên phụ thuộc vào các modules cấp thấp. 
   Cả 2 nên phụ thuộc vào abstraction.
2. Interface (abstraction) không nên phụ thuộc vào chi tiết, mà ngược lại.
( Các class giao tiếp với nhau thông qua interface, 
không phải thông qua implementation.)

Nguyên lý này khá lắt léo, mình sẽ lấy ví dụ thực tế. Chúng ta đều biết 2 loại đèn: đèn tròn và đèn huỳnh quang. Chúng cùng có đuôi tròn, do đó ta có thể thay thế đèn tròn bằng đèn huỳnh quanh cho nhau 1 cách dễ dàng.

20817695_images1672955_bong

Ở đây, interface chính là đuôi tròn, implementation là bóng đèn trònbóng đèn huỳnh quang. Ta có thể swap dễ dàng giữa 2 loại bóng vì ổ điện chỉ quan tâm tới interface (đuôi tròn), không quan tâm tới implementation.

Trong code cũng vậy, khi áp dụng Dependency Inverse, ta chỉ cần quan tâm tới interface. Để kết nối tới database, ta chỉ cần gọi hàm Get, Save … của Interface IDataAccess. Khi thay database, ta chỉ cần thay implementation của interface này.

Mình nói khá kĩ về nguyên lí này vì nó khá quan trọng. Về sau mình sẽ viết 1 bài riêng về Dependency Injection (Dependency Injection chỉ là 1 trong những pattern để hiện thực Dependency Inversion, Dependency Injection != Dependency Inversion nhé các bạn), cùng với 1 số Dependency Injection Framework cơ bản.

Bài viết khá dài, xin có lời khen với các bạn đã kiên nhẫn đọc hết. Ở những bài viết sau mình sẽ giải thích rõ hơn về từng nguyên lý SOLID này, cùng với code mình họa + cách áp dụng nguyên lí vào quá trình code.

Nguồn toidicodedao.wordpress.com

5 truyện tiếng Anh hài hước về phụ nữ

 

5-truyen-tieng-anh-hai-huoc-ve-phu-nu

Question: Why are hurricanes sometimes named after women?

Answer: When they come they’re wild and wet, but when they go they take your house and car with them.

Hỏi: Vì sao những cơn bão thường được đặt tên phụ nữ?

Đáp: Vì họ đến một cách hoang dã và đầy nước/ ủy mị nhưng lúc đi lại lấy theo cả nhà cửa, ô tô

5-truyen-tieng-anh-hai-huoc-ve-phu-nu-1

Question: If your wife is shouting at the front door and your dog is barking at the back door, who do you let in first?

Answer: The dog, of course. At least he’ll shut up after you let him in.

Hỏi: Nếu vợ anh đứng mắng mỏ ở cửa trước và chó sủa ở cửa sau, anh sẽ mở cửa cho ai vào trước 

Đáp: Tất nhiên là con chó rồi. Ít nhất nó cũng im lặng sau khi tôi cho nó vào nhà

5-truyen-tieng-anh-hai-huoc-ve-phu-nu-2

An alien walked into a shop and told the owner that he came from Mars and wanted to buy a brain for research.

”How much is this one?” he asked.

”That one is a monkey brain, and it’s $20,” the owner explained.

”How much is that one?” the alien asked.

“That one is a female brain, and it’s $100,” the owner replied.

”And how much is that one?” the alien asked.

”That one is a male’s brain and it is $500” the owner explained.

‘Why so expensive?” the alien asked. The owner answered,

”Well, it’s hardly been used!”

Xem bản dịch

5-truyen-tieng-anh-hai-huoc-ve-phu-nu-3

Question: What does a blonde do when it gets cold?

Answer: She sits by a candle.

Question: What does she do when it gets really cold?

Answer: She lights it.

Hỏi: Tóc vàng hoe làm gì khi trời lạnh?

Đáp: Cô ấy ngồi cạnh một cây nến?

Hỏi: Thế cô ấy làm gì khi trời rất lạnh

Đáp: Cô ấy thắp ngọn nến lên

5-truyen-tieng-anh-hai-huoc-ve-phu-nu-4

A woman is driving for 1st time on the highway. Her husband calls says: “Be careful love. It’s just been on the radio, that someone is driving opposite to the traffic on the highway..”

She replies: “Someone…? These rascals are in hundreds!”

Một người phụ nữ lần đầu tiên lái xe trên đường cao tốc. Chồng cô ấy gọi điện: “Em cẩn thận nhé. Đài vừa thông báo rằng có ai đó đang lái xe ngược đường trên đường cao tốc”. Người vợ trả lời: “Ai đó ư? Có cả trăm đứa nhãi ranH đang lái ngược đường ấy!”

Y Vân tổng hợp

Những câu nói tiếng Anh hài hước về phụ nữ

Một người phụ nữ chỉ có hai vấn đề: thứ nhất, không có gì để mặc; thứ hai, không có chỗ chứa quần áo..

Cùng học tiếng Anh và giải trí với những câu hỏi hài hước về phụ nữ dưới đây.

Women: scientifically proven to be right even when they’re wrong. Phụ nữ được khoa học chứng minh là luôn đúng ngay cả khi họ sai.

Here’s all you have to know about men and women: women are crazy, men are stupid. And the main reason women are crazy is that men are stupid. Tất cả những gì chúng ta biết về đàn ông và phụ nữ là: phụ nữ điên rồ, đàn ông ngốc nghếch. Và lý do phụ nữ phát điên là vì đàn ông ngốc nghếch.

A jealous woman does better research than the FBI.

A jealous woman does better research than the FBI.

A jealous woman does better research than the FBI. Một người phụ nữ ghen tuông điều tra còn giỏi hơn FBI.

When a woman says “What?”, it’s not because she didn’t hear you. She’s giving you a chance to change what you said. Khi người phụ nữ nói “Cái gì”, không phải vì cô ấy không nghe rõ bạn nói gì. Cô ấy đang cho bạn cơ hội thay đổi điều vừa nói.

A woman gets the last word in every argument. Anything a man says after that is the beginning of a new argument. Phụ nữ là người nói cuối cùng trong mọi cuộc tranh cãi. Bất cứ điều gì người đàn ông nói sau đó sẽ là khởi đầu cho một cuộc tranh cãi mới.

A woman gets the last word in every argument. Anything a man says after that is the beginning of a new argument.

A woman gets the last word in every argument. Anything a man says after that is the beginning of a new argument.

Women are like police, they can have all the evidence in the world but they still want a confession. Phụ nữ chẳng khác gì cảnh sát, họ có mọi bằng chứng trên đời nhưng vẫn mong muốn một lời thú tội.

I am the boss in this house, my wife told me so. Tôi là chủ của ngôi nhà, vợ tôi bảo vậy.

Women are like banks, they take every cent you got and give you very little interest. Phụ nữ giống như các ngân hàng, họ cầm đi từng cent bạn có và trả lại một tí lãi suất.

Thứ ba, 8/3/2016 | 00:33 GMT+7
Chia sẻ bài viết lên facebookChia sẻ bài viết lên twitterChia sẻ bài viết lên google+|

Những câu nói tiếng Anh hài hước về phụ nữ

There are two ways to rule a woman and no body knows them.

There are two ways to rule a woman and no body knows them.

There are two ways to rule a woman and no body knows them. Có hai cách để chế ngự một người phụ nữ và chẳng ai biết những cách đó cả.

You tell a man something, it goes in one ear and out the other. Tell a woman something, it goes in both ears and comes out through the mouth. Nói với đàn ông điều gì, nó đi vào tai này và ra ở tai kia. Nói với phụ nữ điều gì, nó đi vào cả hai tai và đi ra ở miệng.

A woman may be misinformed, mislead, unclear, misguided, and even downright stupid. But she is never ever wrong. Một người phụ nữ có thể bị ai đó báo tin sai, bị dẫn lối sai, chưa rõ điều gì, bị lạc đường và thậm chí hết sức ngốc nghếch. Nhưng cô ấy không bao giờ sai.

A woman has only 2 problems. 1, Nothing to wear; 2, No room for all the clothes.

A woman has only 2 problems. 1, Nothing to wear; 2, No room for all the clothes.

A woman has only 2 problems. 1, Nothing to wear; 2, No room for all the clothes. Một người phụ nữ chỉ có hai vấn đề: thứ nhất, không có gì để mặc; thứ hai, không có chỗ chứa quần áo.

Fake hair, fake nails, fake eye lash, artificial face and sometimes fake behavior, yet a woman will say she needs a real man. Tóc giả, móng tay giả, lông mi giả, khuôn mặt giả tạo và thỉnh thoảng cư xử giả tạo nhưng phụ nữ sẽ luôn nói là cô ta cần một người đàn ông thật lòng.

What would be men without women? – Rich. Đàn ông sẽ trở nên như thế nào nếu không có phụ nữ – Giàu có

What would be men without women?

What would be men without women?

Only a woman can make a man feel wrong, when he does good. Chỉ có một người phụ nữ mới khiến một người đàn ông cảm thấy mình đã sai, dù anh ta đúng.

Women don’t want to hear what you think. Women want to hear what they think – in a deeper voice.  Phụ nữ không muốn nghe điều bạn nghĩ đâu. Họ muốn nghe điều họ nghĩ – bằng một chất giọng trầm hơn. 

Y Vân tổng hợp

Từ vựng tiếng Anh về thời trang

Những từ vựng dưới đây có thể giúp bạn tự tin gọi tên trang phục trên người mình từ đầu xuống chân bằng tiếng Anh.
tu-vung-tieng-anh-ve-thoi-trang

Những từ vựng trên sẽ giúp bạn dễ dàng miêu tả các loại trang phục hơn. Xem phiên âm và nghĩa tiếng Việt ở các bảng dưới. Ảnh: The English Student.

Accessory /əkˈses.ər.i/: phụ kiện

hat /hæt/ mũ đội đầu
cap /kæp/ mũ lưỡi trai
sunglasses /ˈsʌŋˌɡlɑː.sɪz/ kính râm
tie /taɪ/ cà vạt
bow tie /ˌboʊ ˈtaɪ/ nơ con bướm
scarf /skɑːrf/ khăn quàng
belt /belt/ thắt lưng
socks /sɒks/ tất

Outerwear /ˈaʊtəwɛː/: quần áo mặc ngoài

jacket /ˈdʒæk.ɪt/ áo khoác ngắn
coat /koʊt/ áo khoác
trench coat /ˈtrentʃ ˌkoʊt/ áo khoác dáng dài, rộng, có thắt lưng
vest /vest/ áo khoác không tay
suit /suːt/ comple
blazer /ˈbleɪ.zɚ/ áo khoác blazer

Top /tɑːp/: các loại áo

sweater /ˈswet.ər/ áo dài tay, thường bằng len
sweatshirt /ˈswet.ʃɝːt/ áo dài tay, thường bằng vải cotton
cardigan /ˈkɑːr.dɪ.ɡən/ áo khoác cardigan
tank top /ˈtæŋk ˌtɑːp/ áo ba lỗ
t-shirt /ˈtiː.ʃɜːt/ áo phông
shirt /ʃɜːt/ áo sơ mi, có cổ, hàng cúc phía trước

Bottom /ˈbɑː.t̬əm/: quần, váy

jeans /dʒiːnz/ quần bò
cargo pants /ˈkɑː.ɡəʊ ˌpænts/ quần có túi hộp
dress pants /dress pænts/ quần âu
shorts /ʃɔːts/ quần đùi
sweatpants /ˈswet.pænts/ quần vải mỏng, nhẹ
skirt /skɝːt/ chân váy

Shoes /ʃuːs/: các loại giày

sandals /ˈsæn.dəl/ dép sandal
sneaker /ˈsniː.kər/ giày sneakers
flats /flæts/ giày bệt
(high) heels /hiːlz/ giày cao gót
slippers /ˈslɪp.ɚz/ dép đi trong nhà
boots /buːts/ giày boots
rain boots /reɪn buːts/ ủng đi mưa

Y Vân

Continue reading Từ vựng tiếng Anh về thời trang

Phương pháp quản lý tài chính cá nhân hiệu quả

Nhiều bạn trẻ hiện hay tâm sự cuộc sống của họ khá khó khăn dù làm việc chăm chỉ nhưng tiền lương vẫn không đủ trang trải những nhu cầu thiết yếu hàng ngày. Trong khi đó một số khác tuy cũng cùng mức lương như họ nhưng lại có cuộc sống khá thoải mái. Vậy vấn đề ở đây có thể là do cách chi tiêu chưa hợp lí, các bạn chưa có cách quản lý tài chính của mình một cách hiêu quả? Nếu bạn đã và đang gặp những tình huống này thì cũng là lúc bạn nên ngồi lại để tìm kiếm các giải pháp cho mình.

quan_li_tai_chinh_ca_nhan_3

Continue reading Phương pháp quản lý tài chính cá nhân hiệu quả

Âm giai

Scale (Âm giai)

âm giai = thang âm = gamme (tiếng Pháp) = scale (tiếng Anh)

—- 

Nốt nhạc không phải chỉ có 7 nốt  – Nốt nhạc chuẩn có 12 nốt

C | C# | D | D# | E | F | F# | G | G# | A | A# |  B | C

Âm Giai (Scale) là một chuỗi những nhóm nốt nhạc được “nhặt” ra từ 12 nốt chính này.

Các âm giai khác nhau tạo ra các chất nhạc khác nhau.

Continue reading Âm giai

14 Small Differences Between Ordinary People And Successful People

Successful people are the icing on the cake of any hot discussion. Success is inspiring and interesting to talk about.

The truth is, any successful individual is flesh and blood just like you. They are not born miracles, but it’s the small differences that help them stick out from the rest.

So, what are the key aspects that differentiate them from the crowd?

1. Ordinary people talk about other people, successful people talk about ideas.

Gossiping and bagging others are popular among ordinary folks. They just can’t help but talk about people, often with a vein of jealousy. What successful people do is discuss various ideas that could improve their lives.

Plans, goals, aspirations and innovations — these are all the aspects of discussions between successful individuals.

Continue reading 14 Small Differences Between Ordinary People And Successful People

Chúng tôi không quan tâm

Tổng thống Mỹ và thủ tướng Việt Nam nói chuyện với nhau:

maxresdefault

– Ở Mỹ công nhân làm được mỗi tháng khoảng 1500 $ nhưng chỉ cần chi 500 $ là bảo đảm cuộc sống.

– Trời, vậy họ làm gì với số tiền còn lại?

– À đó là việc riêng của họ, chúng tôi không quan tâm, thế ở Việt Nam thì sao?

– Ở VN chúng tôi lương công chức khoảng 800 ngàn VND và mỗi tháng cần khoảng 3 triệu VND thì mới đủ chi.

– Trời, vậy họ kiếm đâu ra phần còn lại?

– À đó là việc riêng của họ, chúng tôi không quan tâm.

 Sưu tầm