最近往一个开源项目提交了一个 PR,作者很快回复我,并且修改了我的代码之后合并到主分支。
但我收获的却不止这些。这次 PR 给我带来的启示非常多,包括程序员与 AI 的关系,编程的哲学等等。本文将详细分享我的这些启示,希望能对读者有所启迪。
这个项目是一个跨设备互传工具,使用 flutter 开发,而我做的就是为几个页面增加了“按 Esc 返回上一页“的功能。实现这个功能的代码不到 100 行,并且完全是 ChatGPT 帮我写的。
GPT 帮我编写的版本:
import 'package:flutter/material.dart' ;
import 'package:flutter/services.dart' ;
class ShortcutWrapper extends StatelessWidget {
final Widget child ;
final Map < LogicalKeySet , Intent > additionalShortcuts ;
ShortcutWrapper ( {
required this . child ,
this . additionalShortcuts = const { } ,
} ) ;
@override
Widget build ( BuildContext context ) {
final shortcuts = {
LogicalKeySet ( LogicalKeyboardKey . escape ) : ActivateIntent ( ) ,
. . . additionalShortcuts ,
} ;
return Shortcuts (
shortcuts : shortcuts ,
child : Actions (
actions : {
ActivateIntent : CallbackAction < ActivateIntent > (
onInvoke : ( ActivateIntent intent ) = > Navigator . pop ( context ) ,
) ,
} ,
child : Focus (
autofocus : true ,
child : child ,
) ,
) ,
) ;
}
}
作者的修改版本:
import 'package:flutter/material.dart' ;
import 'package:flutter/services.dart' ;
import 'package:localsend_app/util/native/platform_check.dart' ;
import 'package:routerino/routerino.dart' ;
class ShortcutWatcher extends StatelessWidget {
final Widget child ;
const ShortcutWatcher ( { required this . child } ) ;
@override
Widget build ( BuildContext context ) {
return Shortcuts (
shortcuts : {
// The select button on AndroidTV needs this to work
LogicalKeySet ( LogicalKeyboardKey . select ) : const ActivateIntent ( ) ,
// Add Control+Q binding for Linux
// https://github.com/localsend/localsend/issues/194
if ( checkPlatform ( [ TargetPlatform . linux ] ) ) LogicalKeySet ( LogicalKeyboardKey . control , LogicalKeyboardKey . keyQ ) : _ExitAppIntent ( ) ,
LogicalKeySet ( LogicalKeyboardKey . escape ) : _PopPageIntent ( ) ,
} ,
child : Actions (
actions : {
_ExitAppIntent : CallbackAction ( onInvoke : ( _ ) = > exit ( 0 ) ) ,
_PopPageIntent : CallbackAction ( onInvoke : ( _ ) async = > Navigator . of ( Routerino . context ) . maybePop ( ) ) ,
} ,
child : child ,
) ,
) ;
}
}
class _ExitAppIntent extends Intent { }
class _PopPageIntent extends Intent { }
在此之前,我从没接触过 flutter,然后借助 GPT 快速地开发出了我自己的一个产品。我给自己的 flutter 项目用上了这个逻辑,然后再原封不动的往这个仓库提交了 PR 。
作者回复称:我们应该全局应用这个设计,并且大幅 **修改 **了我的代码 。我看完它的修改版本之后很震惊。
我一瞬间学到了几件事:
GPT 并不会主动帮我们考虑边缘情况 ,而是按照我们的指示精确地执行。在这个 PR 中,我只考虑到了 Windows 的退出逻辑,而没有考虑到 Linux 和 Android TV 的逻辑。如果我在编程时没有主动思考这些情况,那么我只可能会在收到用户反馈时再去修改。而考虑到种种极端情况应该是程序员的基本素养。
此外,仓库维护者修改我的代码时,使用了一些我从未见过的代码组织方式。如果不去自己尝试、解决 bug,或者不断调整代码结构,那么编程素养很难提升,仅仅是完成了一件事情而已。
会出现以上情况,是因为我们习惯于认为 GPT 给我们的代码是完美的 。
当我们习惯把需求给 GPT 完成,而不亲手编写代码时,编码能力会直线下降。如果是一个人开发的项目,就更可怕了,因为没有人指出你代码中潜在的问题和改进空间,只有用户反馈才能帮你提出问题。
所以,我们应该抱着代码评审的态度对待 GPT 生成的代码 ,而不是”能跑就行“。也许你会热衷于成为提示词工程师,但我认为这是成为一个真正高水平的程序员不可绕开的道路。
费曼说的话至今依然很有道理:”只有创造出一样东西,才是真正懂了“。