Home avatar

东东东尼君

东尼君的世界

C#编程实践(一):深入System.Net.NetworkInformation获取系统网络信息

在工业软件、设备控制系统、网络诊断工具开发中,经常需要获取当前计算机的网络状态,例如:

  • 当前有哪些网卡?
  • 网卡是否连接?
  • IP地址是多少?
  • MAC地址是多少?
  • 网络连接速度是多少?
  • DNS、网关、DHCP信息是什么?

.NET提供了一个非常方便的命名空间System.Net.NetworkInformation,其中核心类:

作用
NetworkInterface 获取网卡信息
IPInterfaceProperties 获取 IP 配置
IPAddressInformation 获取 IP 地址状态
PhysicalAddress 获取 MAC 地址
NetworkChange 监听网络变化

本文将系统介绍如何使用这些API构建一个网络信息采集工具。

代码整洁之道 (Robert C. Martin)

在软件开发过程中,代码并不是写完提交之后就结束了。一个项目真正的生命周期,往往伴随着持续的修改、扩展和维护。需求会不断变化,新的功能会不断加入,原本简单的模块可能逐渐变得复杂。如果代码经过良好的设计和整理,随着时间推移,系统会慢慢演变成难以理解、难以修改,甚至无人敢触碰“遗留代码”。

正如软件工程领域常说的一句话:

代码的第一读者是人,第二读者才是机器。

计算机只关心代码是否能够正确运行,而开发人员需要面对代码背后的意图、结构以及未来变化的可能性。一段能够运行的代码,并不一定是一段优秀的代码。

由Robert C. Martin(人称Uncle Bob)编写的《代码整洁之道》正是围绕这一问题展开讨论。本书从变量命名、函数设计、类的职责划分,到错误处理、测试、架构设计等多个方面,系统总结了如何编写更加清晰、可维护的软件代码。

书中提出:

“Clean code always looks like it was written by someone who cares.”

优秀的代码不仅仅是满足需求,更体现了开发者对软件质量的关注。在实际开发中,我们经常会遇到这样的代码:

  • 一个几百行甚至上千行的函数
  • 一个承担几十种职责的巨大类
  • 大量重复逻辑散落在项目各处
  • 修改一个小需求,却需要影响多个模块
  • 新成员接手项目,需要花费大量时间理解代码

这些问题并不是某一天突然出现的,而是在一次次“先实现功能,以后再优化”的过程中逐渐累积形成的。《代码整洁之道》提供了一套思考方式:

  • 如何通过命名让代码表达真实意图
  • 如何设计短小、专注的函数
  • 如何让类保持单一职责
  • 如何降低模块之间的耦合
  • 如何通过测试保护代码质量
  • 如何让软件具备持续演进的能力

学习整洁代码,并不是为了追求代码形式上的“漂亮”,而是为了降低软件长期维护的成本,让系统能够面对未来的不确定变化。在本文中,我将结合书中的核心思想,并结合实际工程开发中的案例,对《代码整洁之道》进行深入学习和总结,希望能够探索:

什么样的代码才是真正适合长期维护的软件代码?

NETworkManager源码剖析:一个网络管理工具的实现细节

在 GitHub 闲逛时,我偶然发现了NETworkManager这个开源项目。作为一款网络管理和故障排查工具,它已经积累了超过 8.5k Star,足以说明社区对它的认可。更让我感兴趣的是,这个项目采用 C# + WPF 进行开发,与我当前正在深入学习和实践的技术栈高度契合。因此,我产生了一个想法:通过深入分析 NETworkManager 的源码,探索一个成熟的 WPF 桌面应用是如何进行架构设计、模块划分以及工程实践的。接下来,我将以 NETworkManager 为切入点,逐步拆解它在 WPF UI 设计、MVVM 架构、依赖注入、配置管理、网络通信、异步编程以及工程化实践 等方面的实现,希望能够从优秀的开源项目中学习桌面应用开发的最佳实践。

Loguru:替代标准logging的现代方案

日志是软件工程中最基础也是最重要的能力之一。无论是Web服务、AI应用、数据处理任务、自动化脚本、后台Worker,都离不开日志。Python标准库提供了logging。它功能强大,但实际工程使用中经常会遇到一些问题:

  • 配置复杂
  • 格式设置繁琐
  • 文件滚动需要额外配置
  • 多模块项目初始化麻烦

例如标准logging:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import logging

logger = logging.getLogger(__name__)

logger.setLevel(logging.INFO)

handler = logging.FileHandler('app.log')

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

handler.setFormatter(formatter)

logger.addHandler(handler)

logger.info("Application started")

简单记录一条日志到文件,需要很多代码。这也是为什么可以尝试用Loguru

百万级CSV导入MongoDB性能实战

在日常开发中CSV导入是一个比较常见的数据处理场景。例如:

  • 用户信息导入
  • 商品数据同步
  • 日志分析
  • 财务流水导入

很多项目开始都会写出类似下面的代码:

1
2
3
4
5
6
7
8
9
foreach(var line in FileReadLines(path))
{
  var user = Parse(line);

  if (!Validate(user))
    continue;

    await collection.InsertOneAsync(user);
}

数据只有几千条时,这段代码运行地非常流畅。然而,当数据增长到几十万甚至几百万条之后,问题便开始暴露出来:

  • CPU利用率很低
  • MongoDB写入速度跟不上
  • IO长时间阻塞
  • GC次数明显增加
  • 导入时间从几秒增长到数十分钟

C++ Pimpl设计模式详解

在阅读一些大型 C++ 项目源码时,经常会看到类似下面这样的代码:

1
2
3
4
5
6
7
8
class MyClass {
public:
  MyClass();
  ~MyClass();
private:
  class Impl;
  std::unique_ptr<Impl> impl_;
};

第一次看到这种写法,很多人都会疑惑:

  • 为什么真正的数据成员不放在类里面?
  • 为什么要多定义一个Impl类?
  • 为什么析构函数要放到.cpp中实现?
  • 这样设计有什么好处?

实际上,这就是C++中非常经典的Pimpl(Pointer to Implementation)设计模式。本文将从设计思想、实现方式、优缺点以及使用场景几个方面详细介绍Pimpl。

让Hugo支持HDevelop代码高亮

Hugo基于 Chroma 实现代码高亮,对 Go、Python、C++、Matlab 等主流语言都提供了开箱即用的支持。最近阅读机器视觉算法与应用 第2版 (Carsten Steger)时,需要在博客中展示 HDevelop 代码,却发现 Hugo 默认并不支持这种语言。与其退而求其次使用普通文本展示,不如直接扩展 Hugo 的语法高亮能力。因此本文记录整个实现过程,包括:

  • Hugo如何找到对应的Lexer
  • Chroma 的语法解析机制
  • 如何新增一个HDevelop Lexer
  • 最终让Hugo支持HDevelop代码高亮

PowerShell脚本实践指南

在软件开发、系统运维和DevOps 等领域,有一个永远存在的问题:大量重复性的工作正在消耗工程师的时间。每天登录服务器、检查日志、修改配置、部署应用、整理数据、生成报告……这些事情单次并不复杂,但重复几十次、几百次之后,就变成了巨大的时间成本。PowerShell(pwsh)就是解决这类问题的工具之一。它不仅是一门脚本语言,更是一套现代化自动化平台。本文将从基础语法开始,一直到脚本工程实践,全面介绍如何使用 pwsh 构建可靠、高效的自动化工具。