前言
OpenAI 的 ChatGPT 是一种先进的人工智能语言模型,因其能够解释人类编写的文本并生成书面散文和编程代码的响应而脱颖而出。此功能使 ChatGPT 成为多方面的软件开发工具,有助于确保代码质量并避免技术债务。
软件设计模式的先驱者、《敏捷宣言》的 17 位原始签署者之一 Kent Beck 和软件工程师、面向对象设计和分析专家 Martin Fowler 为可能表明设计的模式创造了术语“代码气味”缺陷。这些缺陷不是 bug,而是可能导致这些缺陷或阻碍开发的因素,这对 Beck 和 Fowler 的极限编程实践提出了挑战。代码异味会产生技术债务——选择需要未来返工的快速、简单的解决方案而不是现在花精力寻找更有效的解决方案的隐性成本。
ChatGPT 使开发人员能够解决代码质量问题并有效管理技术债务。它有助于生成和完成代码、发现代码异味并提出修复建议、重构以及丰富代码文档。
本教程演示如何使用 ChatGPT 提高代码质量,包括识别代码异味和重构代码。然后,它检查了 ChatGPT 的局限性和软件开发的最佳实践。
ChatGPT 可帮助您查找 .NET 代码库中的代码异味。尽管您可以使用任何语言,但本教程使用 C#。
要识别代码异味,首先要准备代码。提取相关代码片段并确保它们格式正确且易于阅读。当您将代码分解为更小的块并为 AI 提供足够的上下文来理解代码时,ChatGPT 效果最佳。
接下来,提交清晰简洁的提示。例如,您可以要求 ChatGPT 识别代码片段中的代码味道,或者检查您的代码是否遵循特定的 SOLID 面向对象设计原则。SOLID 是一个缩写词,代表五个关键的面向对象设计原则:单一责任、开闭设计、里氏替换、接口隔离和依赖倒置。
然后,分析 ChatGPT 的响应。但请注意,它的反馈并不完美,如以下示例所示。因此,请始终根据您作为开发人员的判断来确定要实施哪些建议。
ChatGPT 提示:请分析以下 C# 代码并识别其中存在的任何潜在代码。
private void ComputeGloom(WordDictionary wordDictionary,
List<string> gloom)
{
wordDictionary._gloomScore = 0;
for (int i = 0; i < gloom.Count; i++)
{
if (wordDictionary.GloomWordsContain(gloom[i]))
{
int val; }
wordDictionary.GloomWords.TryGetValue(gloom[i], out val);
wordDictionary._gloomScore += val;
} }
}
WordDictionary
,经常使用它的数据和操作。这表明该方法可能更适合WordDictionary
其本身。wordDictionary._gloomScore
似乎是私有字段。该方法应该尊重对象的封装,并且不应该直接访问其字段。相反,使用方法来操纵它们。GloomWordsContain
检查和TryGetValue
操作是冗余的。该TryGetValue
方法本身可用于检查键是否存在并获取值。的使用gloom[i]
也可以替换为foreach
。wordDictionary
,这可能是该方法的用户所不希望的。更改传递给方法的对象的状态通常是一个坏主意。ChatGPT 的回应有效地指出了,指出函数 ComputeGloom 似乎更多地与 WordDictionary 类相关,而不是与它自己的类相关。当一个方法对一个类而不是它自己的类更感兴趣时,就会发生特征嫉妒。它通常表明您应该将该方法的职责放在它的类中。ChatGPT 还可以检测不适当的亲密关系或封装破坏、冗余代码以及可能的 API 不足。
最终的代码可能是误报。糟糕的 API 建议可能是错误的,因为该方法的用户希望应用程序以某种方式返回计算出的暗度。方法类型为 void 表明了这种期望。
ChatGPT 提示:呈现给定代码的重构版本,以解决任何检测到的代码异味或问题。提供所有所做修改的全面摘要,包括解释为什么重构后的代码比原始版本有所改进。
private void ComputeGloom(WordDictionary wordDictionary,
List<string> gloom)
{
wordDictionary._gloomScore = 0;
for (int i = 0; i < gloom.Count; i++)
{
if (wordDictionary.GloomWordsContain(gloom[i]))
{
int val;
wordDictionary.GloomWords.TryGetValue(gloom[i], out val);
wordDictionary._gloomScore += val;
}
}
}
public class WordDictionary
{
public Dictionary<string, int> GloomWords { get; private set; }
public int GloomScore { get; private set; }
public WordDictionary (Dictionary<string, int> gloomWords)
{
GloomWords gloomWords ?? new Dictionary<string, int>();
GloomScore = 0;
}
public void ComputeGloom(List<string> gloom)
{
GloomScore = 0;
foreach (var word in gloom)
{
if (GloomWords.TryGetValue(word, out int val))
{
GloomScore += val;
}
}
}
}
下面是一些变化的总结以及背后的原因:
遵守行业公认的软件开发最佳实践至关重要。这些准则增强了软件的可读性、可维护性和可扩展性,确保代码保持健壮且不易出现错误。
ChatGPT 可以分析您的代码,识别偏离最佳实践的区域,并提出改进建议。本节探讨 ChatGPT 如何帮助您在 C# 代码库中实现 SOLID 面向对象的设计原则,包括接口隔离原则 (ISP)。ISP 规定客户端不应被迫依赖他们不使用的接口。
ChatGPT 提示:您能否分析此代码并指出可以改进的地方?是否有任何最佳实践、设计原则或约定似乎缺失或未得到适当实施?
public interface IDictionaryOperations
{
void ComputeGloom(List<string> gloom);
int GetGloomScore();
void AddWord(string word, int score);
void RemoveWord(string word);
}
public class WordDictionary : IDictionaryOperations
{
private int _gloomScore;
private Dictionary<string, int> _gloomWords;
public WordDictionary(Dictionary<string, int> gloomWords)
{
_gloomWords = gloomWords;
_gloomScore = 0;
}
public void ComputeGloom(List<string> gloom)
{
_gloomScore = 0;
foreach (var word in gloom)
{
if (_gloomWords.TryGetValue(word, out int val))
{
_gloomScore += val;
}
}
}
public int GetGloomScore()
{
return _gloomScore;
}
public void AddWord(string word, int score)
{
// Not needed for this class but necessary because of the interface
throw new NotImplementedException();
}
public void RemoveWord(string word)
{
// Not needed for this class but necessary because of the interface
throw new NotImplementedException();
}
}
这是回应:
这段代码有几点需要讨论:
WordDictionary
实现IDictionaryOperations
但不需要AddWord
方法RemoveWord
,如注释中所示。因此,该代码违反了 ISP。如果这些方法并不与所有实现 的类相关IDictionaryOperations
,那么最好将此接口分成两个:一个用于计算和检索 gloom 分数,另一个用于操作字典。WordDictionary
依赖于Dictionary<string, int>。此依赖项通过其构造函数传递,并且可以从类外部访问。您可能需要重新考虑这一点,以将数据完全封装在您的类中。如果绝对有必要从外部提供它,那么请考虑进行深层复制以避免可变数据的潜在问题。ComputeGloom
并且GetGloomScore
可以有更好的名称来表明它们的作用。方法应该是动词或动词短语,并且应该清楚地传达其效果。例如,ComputeGloomScore
会比ComputeGloom
、 和GetGloomScore could
更好RetrieveGloomScore
。ComputeGloom
重置并重新计算。如果对和 的调用之间_gloomScore
存在潜在变化的可能性,则可能会导致意外的行为。为了避免这种情况,请考虑在gloomWords 更改之内或当时重新计算分数。_gloomWordsComputeGloomGetGloomScoreGetGloomScore
_gloomScore
是可变的。您可以考虑将其设为基于 的计算属性_gloomWords
,这将使您的类对状态操作和潜在错误更加稳健。ChatGPT 确定该代码违反了接口隔离原则 (ISP)。它建议将 IDictionaryOperations 接口拆分为更细粒度的接口,使类能够仅实现相关方法。ChatGPT 还指出了其他问题,例如 NotImplementedException 的误用、数据封装不足、方法命名不明确以及潜在的状态不一致。
将 ChatGPT 集成到 C#/.NET 开发流程中可以提高工作效率和代码质量。为了增强开发过程,您可以利用强大的工具(例如 GitHub 的 Copilot 和 CodeGPT)来帮助完成以下任务:
ChatGPT Whisper API 使您能够在 C#/.NET 开发流程中以编程方式使用 AI,从而提高生产力和代码质量。
实施这些最佳实践以将 ChatGPT 成功集成到您的 C#/.NET 开发流程中:
但请记住,人类开发人员最好查看并验证 ChatGPT 的建议。
如果有效且谨慎地使用,ChatGPT 可以帮助您提高代码质量并最大程度地减少技术债务。它有助于识别代码异味,并简化各种编程语言的重构。然而,它的局限性不应被忽视:最好使用 ChatGPT 来获取建议和想法,但不要用它来执行政策。
这种人工智能驱动的方法彻底改变了软件开发,提高了效率和创新,从而使代码更简洁并降低了技术债务。立即开始尝试使用 ChatGPT 来改变您的编码实践。