Template Method

Template Method là một design pattern trong đó một khuôn mẫu được định nghĩa, chứa một số bước cơ bản của một thuật toán, trong khi các bước cụ thể được định nghĩa bởi các lớp con. Khuôn mẫu này đảm bảo rằng các bước cơ bản của thuật toán được thực hiện theo cùng một cách, nhưng cách thức cụ thể của từng bước có thể được thay đổi bởi các lớp con.

abstract class Report {
    public function generate() {
        $this->setData();
        $this->formatData();
        $this->generateOutput();
    }
    
    abstract protected function setData();
    
    protected function formatData() {
        // default implementation
    }
    
    abstract protected function generateOutput();
}

class PdfReport extends Report {
    protected function setData() {
        // set data for pdf report
    }
    
    protected function generateOutput() {
        // generate pdf output
    }
}

class ExcelReport extends Report {
    protected function setData() {
        // set data for excel report
    }
    
    protected function generateOutput() {
        // generate excel output
    }
}

Trong đoạn code này, Report là một abstract class định nghĩa khuôn mẫu cho việc tạo ra báo cáo. Phương thức generate() định nghĩa các bước cơ bản trong việc tạo ra báo cáo, bao gồm setData(), formatData()generateOutput(). Trong đó, setData()generateOutput() là các phương thức trừu tượng và phải được định nghĩa bởi các lớp con. Trong khi đó, formatData() có một implementation mặc định, nhưng có thể được ghi đè bởi các lớp con nếu cần thiết.

Các lớp con, như PdfReportExcelReport, kế thừa từ Report và định nghĩa các phương thức trừu tượng để thực hiện các bước cụ thể trong việc tạo ra báo cáo. Ví dụ, PdfReport định nghĩa setData() để thiết lập dữ liệu cho báo cáo PDF, và generateOutput() để tạo ra đầu ra PDF. Tương tự, ExcelReport định nghĩa setData()generateOutput() để tạo ra báo cáo Excel.

Khi chúng ta muốn tạo ra một báo cáo, chúng ta có thể tạo một đối tượng của lớp con và gọi phương thức generate(). Phương thức này sẽ thực hiện các bước cơ bản của thuật toán và gọi các phương thức cụ thể của lớp con để thực hiện các bước cụ

SOLID

SOLID là một nguyên tắc lập trình hướng đối tượng được đặt tên theo chữ cái đầu của các từ trong các nguyên tắc này: Single Responsibility Principle (SRP), Open/Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP), và Dependency Inversion Principle (DIP).

Các nguyên tắc SOLID đề cao việc thiết kế các lớp và đối tượng trong hệ thống phần mềm, nhằm tăng tính linh hoạt, dễ bảo trì, mở rộng và tái sử dụng của hệ thống.

Dưới đây là một số định nghĩa cho từng nguyên tắc SOLID:

  1. Single Responsibility Principle (SRP): Một lớp nên chỉ có một trách nhiệm duy nhất và không nên bị phân tán với nhiều trách nhiệm khác.
  2. Open/Closed Principle (OCP): Một lớp nên được thiết kế để dễ dàng mở rộng mà không cần sửa đổi mã nguồn hiện tại.
  3. Liskov Substitution Principle (LSP): Các lớp con phải có thể thay thế được cho các lớp cha của chúng mà không làm thay đổi tính năng của hệ thống.
  4. Interface Segregation Principle (ISP): Các giao diện nên được thiết kế theo những chức năng cụ thể và không nên yêu cầu các phương thức không cần thiết.
  5. Dependency Inversion Principle (DIP): Mã nguồn nên phụ thuộc vào các giao diện và không phải các lớp cụ thể, để tạo tính linh hoạt và dễ bảo trì.

1 chút mở rộng với Interface Segregation Principle

interface PaymentGatewayInterface {
    public function processPayment(float $amount, string $paymentMethod): bool;
    public function refundPayment(float $amount, string $paymentMethod): bool;
    public function savePaymentInfo(array $paymentInfo): bool;
}

Trong ví dụ này, PaymentGatewayInterface định nghĩa các phương thức không cần thiết như refundPayment() và savePaymentInfo(). Nếu PaymentGateway không sử dụng chúng, nó vẫn phải triển khai các phương thức này và sẽ phụ thuộc vào chúng. Việc này có thể dẫn đến các vấn đề về độ phức tạp và hiệu suất của ứng dụng, đồng thời cũng làm cho việc thay đổi PaymentGateway khó khăn hơn nếu chúng ta muốn loại bỏ các phương thức không cần thi

Còn đối với Dependency Inversion Principle (DIP) là một trong những nguyên tắc trong SOLID và nhấn mạnh rằng “Các module cấp cao không nên phụ thuộc vào các module cấp thấp. Cả hai nên phụ thuộc vào abstraction”. Nguyên tắc này khuyến khích chúng ta thiết kế các module để chúng phụ thuộc vào abstraction chung hơn là phụ thuộc vào các chi tiết cụ thể.

DIP có thể được áp dụng bằng cách sử dụng các design pattern như Dependency Injection (DI), Inversion of Control (IoC) và Service Locator.

Ví dụ, giả sử bạn đang phát triển một ứng dụng quản lý đơn hàng. Trong ứng dụng của bạn, bạn có một lớp OrderService để xử lý các thao tác liên quan đến đơn hàng, ví dụ như tạo đơn hàng, cập nhật đơn hàng, hoàn tất đơn hàng, v.v.

Trong trường hợp này, nếu OrderService phụ thuộc vào các lớp cấp thấp như OrderRepository, ProductRepository và CustomerRepository, nó sẽ phải biết chi tiết cụ thể của các lớp này, gây ra sự phụ thuộc chặt chẽ và làm cho việc bảo trì, mở rộng và thay đổi khó khăn hơn.

Thay vào đó, nếu chúng ta áp dụng DIP, chúng ta sẽ tạo ra các abstraction (interface hoặc abstract class) để mô tả các chức năng của các lớp cấp thấp như OrderRepository, ProductRepository và CustomerRepository. Sau đó, chúng ta sẽ thiết kế OrderService để phụ thuộc vào các abstraction này thay vì các lớp cụ thể. Ví dụ:

interface OrderRepositoryInterface {
    public function createOrder(array $orderData): int;
    public function updateOrder(int $orderId, array $orderData): bool;
    public function completeOrder(int $orderId): bool;
}

interface ProductRepositoryInterface {
    public function getProductById(int $productId): array;
}

interface CustomerRepositoryInterface {
    public function getCustomerById(int $customerId): array;
}

class OrderService {
    private $orderRepository;
    private $productRepository;
    private $customerRepository;

    public function __construct(OrderRepositoryInterface $orderRepository, ProductRepositoryInterface $productRepository, CustomerRepositoryInterface $customerRepository) {
        $this->orderRepository = $orderRepository;
        $this->productRepository = $productRepository;
        $this->customerRepository = $customerRepository;
    }

    public function createOrder(array $orderData): int {
        // Use the injected order repository to create the order
        $orderId = $this->orderRepository->createOrder($orderData);

        // Use the injected product repository to get the product information
        $product = $this->productRepository->getProductById($orderData['product_id']);

        // Use the injected customer repository to get the customer information
        $customer = $this->customerRepository->getCustomer

Facade vs Helper trong Laravel

Facade

  • Là một tập hợp các static methods cung cấp cách gọi dễ dàng đến các đối tượng không phải là tĩnh (như các class của Service Container).
  • Facade cung cấp một cách tiếp cận rất thuận tiện cho các đối tượng Laravel, vì nó cho phép bạn gọi các phương thức như bạn đang gọi tới một static methods, mặc dù thực tế là các phương thức được đóng gói trong Service Container.
  • Ví dụ, khi bạn gọi phương thức DB::table('table_name')->get(), thực tế bạn đang gọi đến phương thức get() của đối tượng DB, được quản lý bởi Service Container.

Helper

  • Là một tập hợp các hàm toàn cục (global) được định nghĩa để thực hiện các tác vụ phổ biến, và được sử dụng trong toàn bộ ứng dụng Laravel.
  • Helper không liên quan đến Service Container, và không cung cấp các phương thức cho các đối tượng không phải là tĩnh.
  • Ví dụ, route() là một helper để tạo URL của một route được định nghĩa trong ứng dụng Laravel.

Bất cập của Facade

Giả sử bạn có một ứng dụng Laravel đơn giản, nơi bạn cần thực hiện một số thao tác với đối tượng Request của Laravel. Bạn muốn lấy giá trị của một tham số trong URL và hiển thị nó trên trang web.

Một cách để thực hiện điều này là sử dụng Facade của Laravel, đó là Illuminate\Support\Facades\Request. Bằng cách sử dụng Facade này, bạn có thể lấy giá trị của một tham số bằng cách gọi phương thức input() trên Facade, như sau:

$value = Request::input('parameter');

Tuy nhiên, điều gì sẽ xảy ra nếu Request không được đăng ký trong Service Container của Laravel hoặc không có đối tượng Request nào được trả về từ Service Container? Trong trường hợp này, việc gọi Request::input('parameter') sẽ dẫn đến lỗi runtime, vì Facade không thể truy cập đối tượng Request và sử dụng phương thức input().

Điều này có thể xảy ra nếu bạn đang thực hiện một chức năng đơn giản như hiển thị trang web, nhưng vấn đề sẽ trở nên nghiêm trọng hơn nếu bạn đang phát triển một ứng dụng lớn hơn với nhiều phương thức và đối tượng phức tạp. Việc sử dụng quá nhiều Facade trong trường hợp này có thể dẫn đến mã khó bảo trì và khó hiểu, đặc biệt là khi bạn phải theo dõi nhiều phương thức và đối tượng phức tạp.

redWEB

At redWEB, I had the opportunity to work as a Backend Developer and Team Lead for redSHOP – an e-commerce platform. I was fully dedicated to the project as a core leader, analyzing every aspect of the system, its scale, solutions, and the business to make planning for the next version of it easy.

My time at redWEB allowed me to expand my technical skills in various areas, including design patterns, team management, PHPUnit, WebDrive/Codeception, and more. I became proficient in implementing these technologies in projects, which helped me solve complex problems and deliver high-quality results.

As a Team Lead, I was responsible for leading a team of developers to ensure that the project was completed to the highest standards. I mentored junior developers, conducted code reviews, and provided constructive feedback to help them grow their skills. I also created a training program for the team to learn new technologies and keep up with the latest industry trends.

One of my primary responsibilities at redWEB was to ensure that the platform was running smoothly and that any issues were resolved quickly. I took a proactive approach to problem-solving, identifying potential issues before they became significant problems and finding solutions that could be implemented quickly.

My experience as a Team Lead allowed me to develop my leadership skills further. I learned how to delegate tasks effectively, communicate with team members, manage project timelines, and coordinate with stakeholders. I also encouraged a positive team culture and ensured that everyone on the team felt supported and motivated.

In summary, my experience at redWEB was incredibly valuable, as it allowed me to develop my technical skills and leadership abilities. The opportunities that I had at redWEB helped me grow both personally and professionally, and I am grateful for the experiences that I had while working there.

Project: redSHOP

It’s an e-Commercial based on Joomla! allow user build up e-Commercial website by themself.

We also provide web development based on redSHOP

JoomlArt

Working at JoomlArt as a Technical Support Specialist was a challenging and rewarding experience that helped me develop my skills in customer support and problem-solving. I began my role at JoomlArt at the same time as my role at Directive, and I found that my experiences at both companies complemented each other well.

As a Technical Support Specialist at JoomlArt, I was responsible for helping customers through the ticket system and forum for the company’s products. I loved the practical nature of this role, as I enjoyed searching for bugs in the products and fixing them directly without committing because of not dealing with job developer. Additionally, I was responsible for resolving errors that arose from conflicts with third-party extensions and providing suggestions to customers for their requirements, including analyzing on the real site.

One of my primary responsibilities at JoomlArt was to support customers who had purchased the company’s products. If a customer had a problem or wanted to add something to the product, I would work to solve it or send it to another team to be resolved. I found this to be a rewarding experience that allowed me to improve my skills in problem-solving and customer support.

Overall, my experience at JoomlArt provided me with valuable experience in customer support and problem-solving, and allowed me to develop my skills in searching for and fixing bugs in products. I am grateful for the experiences and skills that I gained while working at JoomlArt, and I believe that these experiences have helped me grow both personally and professionally.

JomSocial

Working at JomSocial as a Backend Developer and Team Lead was a challenging and rewarding experience that helped me grow both personally and professionally. As a core member of the team, I was responsible for developing the JomSocial component directly, utilizing my skills in Mercurial code management, feature analysis, and project planning.

One of my primary responsibilities at JomSocial was to analyze customer requests for new features and provide real plans for the project. This involved working closely with my colleagues to determine the feasibility and impact of new features, and making informed decisions about whether to include them in the core product or develop them as extensions. Additionally, I supported customers with specific products through the forum and support system, which helped me improve my language skills, especially in English.

As I progressed in my career at JomSocial, I took on additional responsibilities as a Team Lead. This involved researching and developing new technologies, working with my colleagues to develop project plans and timelines, and guiding team members to achieve their goals. I found this to be a challenging but rewarding experience that helped me enhance my leadership and communication skills.

Overall, my experience at JomSocial provided me with a deep understanding of backend development principles and helped me improve my skills in Mercurial code management, feature analysis, and project planning.

Additionally, my experience as a Team Lead provided me with a solid foundation for future endeavors.

Project: JomSocial – An Joomla! extension for Social Networking ( likely Facebook )

Directive

Working as a Full Stack Developer at Directive Company was a significant milestone in my career. My role at Directive included providing customer support as well as developing new features for the company’s website. This experience provided me with a unique opportunity to learn and grow in many areas of web development.

As a supporter at Directive company, I was tasked with inspecting and resolving errors on customers’ websites. This involved identifying errors that may have been caused by code extensions, conflicts with third-party extensions, or user configuration errors. I utilized my skills in Joomla!, PHP & MySQL, HTML / CSS, Javascript / jQuery to diagnose the issues and provide solutions. In addition to providing customer support, I was also responsible for developing new features for the company’s website. This experience allowed me to expand my skill set and learn new technologies. I worked closely with my colleagues to implement requirements for the company, and I was able to apply my knowledge to develop new features that enhanced the user experience.

Overall, my experience at Directive Company provided me with an opportunity to learn new skills, gain experience in customer support, and hone my skills as a full stack developer. I am grateful for the experiences and skills that I gained while working at Directive.

VietProtocol

Working experience can be invaluable for personal and professional growth, and working with the right company can provide a wealth of opportunities for learning and development. For me, VietProtocol was that company. As the first and only Vietnamese company that I worked with, it provided me with a unique set of experiences that helped me hone my web development skills.

One of the most valuable experiences I gained while working at Vietprotocol was developing a website based on Joomla!. This involved using CSS for HTML, developing Joomla! templates from PSD, building complete websites on Joomla!, customizing templates and extensions, and working closely with designers to turn PSD design files into functional websites.

Additionally, there was no specific process for customer contact and feedback, which required me to be adaptable and flexible in my approach to working with clients. Through my experience at VietProtocol, I gained a deep understanding of web development principles and honed my skills in creating stunning and user-friendly websites. This experience provided me with a solid foundation for future endeavors and helped me grow both personally and professionally.

Kind of websites

  • Company portfolio
  • E-Commercial