Skip to content

Instantly share code, notes, and snippets.

@tuannguyenssu
Created July 14, 2019 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tuannguyenssu/6b1be46e96110945b96a5f7645579880 to your computer and use it in GitHub Desktop.
Save tuannguyenssu/6b1be46e96110945b96a5f7645579880 to your computer and use it in GitHub Desktop.
//--------------------------------------------------------------------------------------
// 7. SOLID
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// 7.1 Single Responsibility
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Bad
class UserSettings
{
private User User;
public UserSettings(User user)
{
User = user;
}
public void ChangeSettings(Settings settings)
{
if (verifyCredentials())
{
// ...
}
}
private bool VerifyCredentials()
{
// ...
}
}
// Good
class UserAuth
{
private User User;
public UserAuth(User user)
{
User = user;
}
public bool VerifyCredentials()
{
// ...
}
}
class UserSettings
{
private User User;
private UserAuth Auth;
public UserSettings(User user)
{
User = user;
Auth = new UserAuth(user);
}
public void ChangeSettings(Settings settings)
{
if (Auth.VerifyCredentials())
{
// ...
}
}
}
//--------------------------------------------------------------------------------------
// 7.2 Open Closed
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Bad
abstract class AdapterBase
{
protected string Name;
public string GetName()
{
return Name;
}
}
class AjaxAdapter : AdapterBase
{
public AjaxAdapter()
{
Name = "ajaxAdapter";
}
}
class NodeAdapter : AdapterBase
{
public NodeAdapter()
{
Name = "nodeAdapter";
}
}
class HttpRequester : AdapterBase
{
private readonly AdapterBase Adapter;
public HttpRequester(AdapterBase adapter)
{
Adapter = adapter;
}
public bool Fetch(string url)
{
var adapterName = Adapter.GetName();
if (adapterName == "ajaxAdapter")
{
return MakeAjaxCall(url);
}
else if (adapterName == "httpNodeAdapter")
{
return MakeHttpCall(url);
}
}
private bool MakeAjaxCall(string url)
{
// request and return promise
}
private bool MakeHttpCall(string url)
{
// request and return promise
}
}
// Good
interface IAdapter
{
bool Request(string url);
}
class AjaxAdapter : IAdapter
{
public bool Request(string url)
{
// request and return promise
}
}
class NodeAdapter : IAdapter
{
public bool Request(string url)
{
// request and return promise
}
}
class HttpRequester
{
private readonly IAdapter Adapter;
public HttpRequester(IAdapter adapter)
{
Adapter = adapter;
}
public bool Fetch(string url)
{
return Adapter.Request(url);
}
}
//--------------------------------------------------------------------------------------
// 7.3 Liskov Substitution
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Bad
class Rectangle
{
protected double Width = 0;
protected double Height = 0;
public Drawable Render(double area)
{
// ...
}
public void SetWidth(double width)
{
Width = width;
}
public void SetHeight(double height)
{
Height = height;
}
public double GetArea()
{
return Width * Height;
}
}
class Square : Rectangle
{
public double SetWidth(double width)
{
Width = Height = width;
}
public double SetHeight(double height)
{
Width = Height = height;
}
}
Drawable RenderLargeRectangles(Rectangle rectangles)
{
foreach (rectangle in rectangles)
{
rectangle.SetWidth(4);
rectangle.SetHeight(5);
var area = rectangle.GetArea(); // BAD: Will return 25 for Square. Should be 20.
rectangle.Render(area);
}
}
var rectangles = new[] { new Rectangle(), new Rectangle(), new Square() };
RenderLargeRectangles(rectangles);
// Good
abstract class ShapeBase
{
protected double Width = 0;
protected double Height = 0;
abstract public double GetArea();
public Drawable Render(double area)
{
// ...
}
}
class Rectangle : ShapeBase
{
public void SetWidth(double width)
{
Width = width;
}
public void SetHeight(double height)
{
Height = height;
}
public double GetArea()
{
return Width * Height;
}
}
class Square : ShapeBase
{
private double Length = 0;
public double SetLength(double length)
{
Length = length;
}
public double GetArea()
{
return Math.Pow(Length, 2);
}
}
Drawable RenderLargeRectangles(Rectangle rectangles)
{
foreach (rectangle in rectangles)
{
if (rectangle is Square)
{
rectangle.SetLength(5);
}
else if (rectangle is Rectangle)
{
rectangle.SetWidth(4);
rectangle.SetHeight(5);
}
var area = rectangle.GetArea();
rectangle.Render(area);
}
}
var shapes = new[] { new Rectangle(), new Rectangle(), new Square() };
RenderLargeRectangles(shapes);
//--------------------------------------------------------------------------------------
// 7.4 Interface Segregation
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Bad
public interface IEmployee
{
void Work();
void Eat();
}
public class Human : IEmployee
{
public void Work()
{
// ....working
}
public void Eat()
{
// ...... eating in lunch break
}
}
public class Robot : IEmployee
{
public void Work()
{
//.... working much more
}
public void Eat()
{
//.... robot can't eat, but it must implement this method
}
}
// Good
public interface IWorkable
{
void Work();
}
public interface IFeedable
{
void Eat();
}
public interface IEmployee : IFeedable, IWorkable
{
}
public class Human : IEmployee
{
public void Work()
{
// ....working
}
public void Eat()
{
//.... eating in lunch break
}
}
// robot can only work
public class Robot : IWorkable
{
public void Work()
{
// ....working
}
}
//--------------------------------------------------------------------------------------
// 7.4 Dependency Inversion
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Bad
public abstract class EmployeeBase
{
protected virtual void Work()
{
// ....working
}
}
public class Human : EmployeeBase
{
public override void Work()
{
//.... working much more
}
}
public class Robot : EmployeeBase
{
public override void Work()
{
//.... working much, much more
}
}
public class Manager
{
private readonly Robot _robot;
private readonly Human _human;
public Manager(Robot robot, Human human)
{
_robot = robot;
_human = human;
}
public void Manage()
{
_robot.Work();
_human.Work();
}
}
// Good
public interface IEmployee
{
void Work();
}
public class Human : IEmployee
{
public void Work()
{
// ....working
}
}
public class Robot : IEmployee
{
public void Work()
{
//.... working much more
}
}
public class Manager
{
private readonly IEnumerable<IEmployee> _employees;
public Manager(IEnumerable<IEmployee> employees)
{
_employees = employees;
}
public void Manage()
{
foreach (var employee in _employees)
{
_employee.Work();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment