在程序員的世界里,雖然別號碼農,可是相當多的時間并不是在寫代碼,而是畫圖,誰叫人是視覺動物呢。
在日常工作會經常繪制或閱讀 UML中的那些類圖,時序圖,狀態圖,以及常用的框圖,流程圖, 和思維導圖等,可用的工具也很多,比如 Visio, Gliffy, StarUml, XMind 等等,各有善長,有功能有限的免費產品,也有功能強大的收費產品。當然,我用的比較趁手的基本上都是要收費的。
其實,在程序員的世界里,更喜歡寫代碼來生成圖表,比較我最常用的
這兩個站點很好用,但是只有基本功能是免費的,高級功能是要另外收費的。其實自己基于兩個很有用的工具庫 Graphviz 和 PlantUML,自己寫一款畫圖工具,通過寫腳本來生成各種圖形是很容易的事。
這不,我用 Python Flask 框架簡單包裝了一下,搭建一個本地站點,可以很輕松的繪制各種程序員常用的圖形。
先寫一個簡單的例子,用這個站點來繪制一個思維導圖:
NIO -> Channel
NIO -> Buffer
NIO -> Selector
Buffer -> ByteBuffer
Buffer -> CharBuffer
Buffer -> MappedByteBuffer
Channel -> FileChannel
Channel -> DatagramChannel
Channel -> SocketChannel
Channel -> ServerSocketChannel
如上圖,用 python flask 框架寫一個 web 應用,再通過調用 Graphviz 支持的各種流程圖,線框圖和思維導圖,通過調用 plantuml 繪制各種 UML 圖形。
再舉幾例:
流程圖 - 網站登錄
- 先寫幾行如下的腳本
start -> IsExceedMaxAttempts
IsExceedMaxAttempts -> Login[cond=no]
IsExceedMaxAttempts -> LockAccount[cond=yes]
LockAccount -> DisplayAlert
Login -> IsAuthorized
IsAuthorized -> GrantAccess[cond="yes"]
IsAuthorized -> IsExceedMaxAttempts[cond="no"]
GrantAccess -> end
DisplayAlert -> end
可以通過上面的 web 界面,也可以通過如下的命令行來生成圖形:
fab draw:./examples/login-flowchart.txt,./examples/login-flowchart.png
時序圖 - TCP 握手和揮手
- 先寫一個如下的腳本
title TCP handshake
participant client
participant server
autonumber "<b>[00]"
== open ==
note right of server: LISTEN
client -> server: SYN
note left of client: SYN_SENT
note right of server: SYN_RCVD
server --> client: ACK/SYN
server -> client: ACK
note over client, server: ESTABILISHED
== close ==
client -> server: FIN
note left of client: FIN_WAIT_1
note right of server: CLOSE_WAIT
server --> client: ACK
note left of client: FIN_WAIT_2
server -> client: FIN
note right of server: LAST_ACK
note left of client: TIME_WAIT
client --> server: ACK
note right of server #FFAAAA: CLOSED
即可生成如下的圖形
狀態圖
- 線程狀態圖
[*] --> Created: new
Created --> Ready: start
Ready --> Running: run
Running --> Ready: yield, interrupt
Running --> Waiting: wait, sleep, suspend
Waiting --> Ready: notify, resume
Running --> Terminated
Terminated --> [*]
類圖 Netty 的 Event Loop 相關類
interface EventExecutorGroup
interface ScheduledExecutorService
interface Iterable
interface EventExecutor
interface EventLoop
abstract class SingleThreadEventLoop
class EpollEventLoop
abstract class Selector
class SelectedSelectionKeySetSelector
EventExecutorGroup --|> ScheduledExecutorService
EventExecutorGroup --|> Iterable
EventExecutor --|> EventExecutorGroup
EventLoopGroup --|> EventExecutorGroup
EventLoop --|> EventLoopGroup
SingleThreadEventLoop --|> EventLoop
EpollEventLoop --|> SingleThreadEventLoop
NioEventLoop --|> SingleThreadEventLoop
SelectedSelectionKeySetSelector --|> Selector
NioEventLoop o-- Selector
interface EventExecutorGroup {
EventExecutor next();
Iterator<EventExecutor> iterator();
Future<?> submit(Runnable task);
<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit);
size();
}
interface EventLoopGroup {
next();
ChannelFuture register(Channel channel);
ChannelFuture register(ChannelPromise promise);
}
interface EventExecutor {
EventExecutor next();
EventExecutorGroup parent();
boolean inEventLoop();
boolean inEventLoop(Thread thread);
<V> Promise<V> newPromise();
<V> ProgressivePromise<V> newProgressivePromise();
<V> Future<V> newSucceededFuture(V result);
<V> Future<V> newFailedFuture(Throwable cause);
}
interface EventLoop {
EventLoopGroup parent();
}
class NioEventLoop {
private Selector selector;
private Selector unwrappedSelector;
private SelectedSelectionKeySet selectedKeys;
private final SelectorProvider provider;
}
還可以舉出許多例子,詳細的搭建步驟和相關代碼請參見 https://github.com/walterfan/webdiagram