在程序员的世界里,虽然别号码农,可是相当多的时间并不是在写代码,而是画图,谁叫人是视觉动物呢。
在日常工作会经常绘制或阅读 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