提升你的技能第 1 部分
介绍
学习如何成为一名更优秀的开发人员需要不断提升技能。一个人如何学习成长并成为一名更优秀的开发人员?让我们来探讨一些总体上适用于大多数开发人员的想法。代码示例全部使用 C# 编写,之所以选择这些语言,是因为它们对大多数开发人员来说并不常见,并且是内部完成的。
步骤
-
Pluralsight是一个付费网站,提供数百门 C# 课程。不妨先使用他们的 AI 测评,它会指引你走上正确的道路。许多课程也提供独立的测评。Pluralsight 让你可以轻松地从高评价的作者那里学习,也可以通过笔记本电脑、手机或平板电脑等任何设备访问课程。Pluralsite 提供免费试用,并且订阅后还会不时提供折扣。
-
使用Microsoft Learn。无论您是职业生涯的起步者,还是经验丰富的专业人士,我们的自主学习方法都能帮助您更快、更自信地按照自己的节奏实现目标。您可以通过互动模块和学习路径培养技能,也可以跟随讲师学习。按照您的方式学习和成长。
-
花时间阅读 Microsoft 文档,例如阅读C# 程序的一般结构、类型运算符和表达式语句、各种类、 面向对象编程等等。
-
在学习过程中,尝试使用控制台或单元测试项目使事情变得简单,换句话说,将后端学习与前端用户界面学习分开。
-
当你感觉舒服的时候,先确定一个简单的项目,在写代码之前先写好任务,然后再写代码,而不是一边思考一边写代码。新手水平的思考和写代码简直就是一场灾难。
-
当在网上寻找信息并找到解决方案时,不要简单地复制和粘贴,检查代码,在使用该代码之前先尝试弄清楚它在做什么。
-
了解如何在 Visual Studio 中使用 GitHub 备份和版本控制代码。假设你编写了代码并将其破坏,通过在 GitHub 存储库中进行适当的版本控制,你可以还原更改并恢复破坏的代码。
-
使用 .NET Framework Core 6 或 .NET Core Framework 8 而不是 .NET Framework Classic,因为使用 .NET Core 有更多好处
-
如果学习处理数据,请从 SQL-Server Express 开始并安装 SSMS(SQL-Server Management Studio)以及学习使用 Entity Framework Core。
-
要知道,学习任何语言时,慢比快要好,而且没有人知道所有语言。
加速学习的工具
Microsoft Visual Studio 是绝对最好的 IDE(集成开发环境),它通过以下项目可以增加学习并节省编码时间。
- 适用于 Visual Studio 和 SSMS 的 Red Gate SQL-Prompt
- 高级 IntelliSense 风格代码完成
- 重构 SQL 代码
- SSMS SQL 历史记录
- 以及更多
- Jetbrains ReSharper是一款非常有价值的 Visual Studio 扩展。
- EF Power Tools轻松对 EF Core 的 SQL-Server 数据库进行逆向工程
深入代码基础知识
一旦掌握了基础知识,就可以寻找有助于成长为更好的开发人员的代码示例。
一种可能的途径是使用Microsoft Entity Framework Core (EF Core) 或使用Dapper等数据提供程序来处理数据库。
还有其他处理数据的方法,但 EF Core 和 Dapper 在性能和易学性方面是最好的。
在网上查找代码示例时,请确保它们适用于您的项目的 .NET Framework,因为 .NET Framework 4.8 代码示例与 .NET Core 8 Framework 有很大不同。
微软每年都会为 EF Core 创建代码示例,但在许多情况下,这些示例可能不适合没有经验的开发人员学习,因此 Karen Payne 采用了 EF Core 8 代码示例并创建了以下文章/存储库,在大多数情况下,这些示例都很容易学习。
第 1 课 - SQL-Server 计算列
EF Core 版本
计算列是一个虚拟列,除非该列标记为“PERSISTED”,否则它不会以物理方式存储在表中。计算列表达式可以使用其他列中的数据来计算其所属列的值。您可以使用 SQL Server Management Studio (SSMS) 或 Transact-SQL (T-SQL) 在 SQL Server 中为计算列指定表达式。
有关完整文章,请参阅SQL-Server:使用 Ef Core 的计算列
但在这里我们将从头创建一个计算列,并使用 EF Core 和 Dapper 演示用法。
原文来自以下 Stackoverflow帖子。取出生日期和当前日期,用出生日期减去当前日期,再除以 10,000。
在 SSMS(SQL Server Management Studio)中
请注意,在代码示例中,完整的数据库位于脚本文件夹下的 EF_CoreBirthdaysComputedColumns 项目中。在运行脚本之前,请在 SSMS 中创建数据库,然后运行脚本来创建表并填充数据。
另请注意,在代码示例中,连接字符串位于使用 NuGet 包ConsoleConfigurationLibrary 的appsettings.json 中。
表结构
SQL
将声明拆分开来。
-
使用日期分隔符格式化两个日期,并将每个日期转换为整数。
-
从当前日期中减去出生日期,括号很重要。
-
将上述数字除以 10,000 即可得出年龄。
结果
现在为名为 YearsOld 的表创建一个新的 nvarchar 类型的列,并将此语句放入计算列属性中,然后保存更改。
(CAST(FORMAT(GETDATE(), 'yyyyMMdd') AS INTEGER) - CAST(FORMAT(BirthDate, 'yyyyMMdd') AS INTEGER)) / 10000
-
创建一个新的 C# 控制台项目。
-
安装 Visual Studio 扩展EF Power Tools。要了解如何使用 EF Power Tools,请观看作者提供的以下视频。添加完整文档。
一旦使用 EF Power Tools,就会生成以下类。
代表 SQL-Server 数据库表的模型。
public partial class BirthDays
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateOnly? BirthDate { get; set; }
public int? YearsOld { get; set; }
}
所谓的DbContext和配置用于与数据库交互。
注意YearsOld 上的HasComputedColumnSql是我们计算的列。
public partial class Context : DbContext
{
public Context()
{
}
public Context(DbContextOptions<Context> options)
: base(options)
{
}
public virtual DbSet<BirthDays> BirthDays { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer(DataConnections.Instance.MainConnection);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BirthDays>(entity =>
{
entity.Property(e => e.YearsOld).HasComputedColumnSql("((CONVERT([int],format(getdate(),'yyyyMMdd'))-CONVERT([int],format([BirthDate],'yyyyMMdd')))/(10000))", false);
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
注意:
执行上述工作有两种方式:数据库优先或代码优先。对于刚开始使用 EF Core 的用户来说,数据库优先是最佳选择。
为了查看数据,Spectre.Console用于创建一个漂亮的表格。
internal partial class Program
{
static async Task Main(string[] args)
{
await Setup();
var table = CreateTable();
await using (var context = new Context())
{
var list = await context.BirthDays.ToListAsync();
foreach (var bd in list)
{
table.AddRow(
bd.Id.ToString(),
bd.FirstName,
bd.LastName,
bd.BirthDate.ToString(),
bd.YearsOld.ToString());
}
AnsiConsole.Write(table);
}
ExitPrompt();
}
public static Table CreateTable()
{
var table = new Table()
.AddColumn("[b]Id[/]")
.AddColumn("[b]First[/]")
.AddColumn("[b]Last[/]")
.AddColumn("[b]Birth date[/]")
.AddColumn("[b]Age[/]")
.Alignment(Justify.Left)
.BorderColor(Color.LightSlateGrey);
return table;
}
}
要获取数据,只需一行代码实例化 EF Core,再用一行代码读取数据。EF Core 也非常适合关系数据库,请参阅以下存储库。
要记录 EF Core 生成的 SQL,请参阅以下项目,其中还展示了如何使用两个不同的 SQL-Server 实例。
Dapper 版本
与 EF Core 不同,使用 Dapper,开发人员可以在 SSMS 中编写 SQL 语句,并将有效的语句添加到代码中。有关 Dapper 的更多信息,请参阅我的系列文章。
这里,SQL 存储在只读字符串中,另一种方法是将其(或任何语句)存储在存储过程中。
internal class SqlStatements
{
public static string GetBirthdays =>
"""
SELECT Id
,FirstName
,LastName
,BirthDate
,YearsOld
FROM BirthDaysDatabase.dbo.BirthDays
""";
}
读取数据的代码。
internal class DapperOperations
{
private IDbConnection _cn;
public DapperOperations()
{
_cn = new SqlConnection(DataConnections.Instance.MainConnection);
SqlMapper.AddTypeHandler(new SqlDateOnlyTypeHandler());
SqlMapper.AddTypeHandler(new SqlTimeOnlyTypeHandler());
}
public async Task<List<BirthDays>> GetBirthdaysAsync()
{
return (await _cn.QueryAsync<BirthDays>(SqlStatements.GetBirthdays)).AsList();
}
}
在类构造函数中
-
使用Microsoft.Data.SqlClient NuGet 包创建连接。
-
使用kp.Dapper.Handlers NuGet 包为 Dapper 添加了理解 DateOnly 类型的能力。
读取数据只有一行,表示我们想要异步获取 BirthDays 列表。
public async Task<List<BirthDays>> GetBirthdaysAsync()
{
return (await _cn.QueryAsync<BirthDays>(SqlStatements.GetBirthdays)).AsList();
}
回到 Program.cs,除了创建 Dapper 类的实例和调用方法之外,代码与 EF Core 相同。
internal partial class Program
{
static async Task Main(string[] args)
{
await Setup();
var table = CreateTable();
var operations = new DapperOperations();
var list = await operations.GetBirthdaysAsync();
foreach (var bd in list)
{
table.AddRow(
bd.Id.ToString(),
bd.FirstName,
bd.LastName,
bd.BirthDate.ToString(),
bd.YearsOld.ToString());
}
AnsiConsole.Write(table);
ExitPrompt();
}
public static Table CreateTable()
{
var table = new Table()
.AddColumn("[b]Id[/]")
.AddColumn("[b]First[/]")
.AddColumn("[b]Last[/]")
.AddColumn("[b]Birth date[/]")
.AddColumn("[b]Age[/]")
.Alignment(Justify.Left)
.BorderColor(Color.LightSlateGrey);
return table;
}
}
计算列摘要
本书并非涵盖代码的方方面面,这意味着在将这些技术应用于你的项目之前,你需要花时间仔细分析代码以及所使用的 NuGet 包。此外,还可以考虑通过Visual Studio 调试器运行代码。
调试是许多新手开发人员容易忽略的功能,但它却是 Visual Studio 的最佳功能之一。学习如何调试并不需要花费太多时间。
第 2 课 - 重构代码
很多人认为,编程的重点是让代码运行起来,然后再回头重构代码。但从个人经验来看,这往往不会发生。这正是开发人员需要在工作项目之外磨练技能的原因。
示例 1
要求开发人员将字符串按大写字母拆分,并将字符串放在前面。
例如,给定 ThisIsATest,输出将是 This Is A Test。开发人员在网上搜索后,找到了以下内容。
public static class StringExtensions
{
private static readonly Regex CamelCaseRegex = new(@"([A-Z][a-z]+)");
/// <summary>
/// KarenPayne => Karen Payne
/// </summary>
[DebuggerStepThrough]
public static string SplitCamelCase(this string sender) =>
string.Join(" ", CamelCaseRegex.Matches(sender)
.Select(m => m.Value));
}
这是可行的,但是还有一个更好的版本,在下面的例子中,它是由 GitHub Copilot 编写的,并且是第二次迭代,这意味着第一次询问 copilot 时,它提供了一个未优化的解决方案,因为问题是如何提出的。
[DebuggerStepThrough]
public static string SplitCamelCase(this string input)
{
if (string.IsNullOrEmpty(input))
{
return input;
}
Span<char> result = stackalloc char[input.Length * 2];
var resultIndex = 0;
for (var index = 0; index < input.Length; index++)
{
var currentChar = input[index];
if (index > 0 && char.IsUpper(currentChar))
{
result[resultIndex++] = ' ';
}
result[resultIndex++] = currentChar;
}
return result[..resultIndex].ToString();
}
等一下,第二个版本代码量这么大,这个版本怎么会更好呢?无论是新手还是经验丰富的开发人员,都认为代码行数越少越好,或许是为了提高可读性。当然,开发人员应该始终努力编写可读性强的代码,但代码行数多的代码也可以很容易阅读。
如何编写可读的代码。
- 使用有意义的变量名,例如在 for 语句中,使用 index 而不是 i 或 firstName 而不是 fName。
- 折叠代码而不是一行,如下所示
public static class CheckedListBoxExtensions
{
public static List<T> CheckedList<T>(this CheckedListBox sender)
=> sender.Items.Cast<T>()
.Where((_, index) => sender.GetItemChecked(index))
.Select(item => item)
.ToList();
}
而不是
public static class CheckedListBoxExtensions
{
public static List<T> CheckedList<T>(this CheckedListBox sender)
=> sender.Items.Cast<T>().Where((_, index) => sender.GetItemChecked(index)).Select(item => item).ToList();
}
后续步骤Next steps
这里有一些想法,甚至许多经验丰富的开发人员都会避免,但你不会!!!
- 泛型
- 接口
- 创建通用库
- JSON 序列化和反序列化
概括
这些只是成为更优秀开发者的众多技巧中的一小部分。而实现这一目标的唯一方法就是在项目之外不断学习。
如果您的老板或团队负责人不提供时间来学习新技能,那么您需要每周花一两个小时来学习和成长。
文章来源:https://dev.to/karenpayneoregon/push-your-skills-2pho