任何东西不要用过了头

适度使用接口
本文讨论了在软件开发过程中过度使用接口的问题,并强调了合理设计的重要性。作者指出,虽然接口有助于降低模块间的耦合度,但不应盲目地在所有类之间定义接口,这可能导致不必要的复杂性和维护困难。
  马克思和中国的古人都认为,任何东西都有个度,什么东西都不是万能的,用过了头,好东西就成的坏东西。
  昨天检视别人的代码,发现同事的代码中到处都是interface。interface是什么,是为了模块间了解耦合,还有用不同的方法提供同样的功能。在这些时候,我们用interface,但是,如果给任何一个类(实体类除外),连自已内部的类都在内,都定义一个interface的话,那么,代码中类的个数就要*2了,这种做法我认为是不明智的,是对interface的形而上学的认识和使用。
  发现项目组半年来有一种不好的习惯,不管做什么都只是想着扩展,分离,而不想着算法和其它方面的问题。当然,扩展性是必须有的,但是,考虑扩展性要从实际出发,那些800年不可能变的地方不要定义太多的接口,也不必在任何两个相调用的类之间定义接口。接口是基于模块间的,一个模块内部的类就不要定太多的接口了,那样反而不好理解。一个简单的例子,美国人最先提出的模块化军舰,是要求动力模块,武器模块,生活模块,指挥模块之间有明确的接口,可以方便的更换和升级。但是,不要求每个零件之间有接口,那样成本太大,没有实际意义。就像我们改变模块的实现时只想着改变一个类就可以是不现实的!!!!在所有类之间定义接口,没有意义!!!
<think>我们讨论的是在C语言环境中编写测试代码,特别是针对嵌入式系统(如ESP32/ESP8266)的LCD初始化测试。 用户的问题:在测试代码`void main() { LCD_Init(); while(1); }`中是否需要包含include语句? 回答要点: 1. 在C语言中,任何使用函数的代码都需要确保函数的声明(或定义)在调用之前可见。这通常通过包含文件(.h文件)来实现。 2. `LCD_Init()`函数通常由用户自己编写,或者来自某个库。因此,需要包含声明该函数的文件。 3. 如果不包含文件,编译器可能会发出警告或错误(取决于编译器设置),因为编译器不知道`LCD_Init`函数的返回类型和参数(默认为int,但通常我们期望void)。 4. 在嵌入式开发中,通常还需要包含一些特定的文件,这些文件定义了所使用的微控制器的寄存器和特殊功能。 因此,完整的测试代码应该包含必要的文件,例如: #include "lcd.h" // 假设LCD_Init()函数声明在这个文件中 #include <reg52.h> // 或者对应单片机的文件,如8051系列常用reg52.h 但是,如果`LCD_Init()`函数的定义就在同一个文件中(在main函数之前),那么可以不需要包含文件,因为函数定义本身就充当了声明。不过,这种做法在测试代码中不常见,通常我们会将初始化函数放在单独的模块中。 另外,在ESP32/ESP8266等平台上,main函数通常被封装在框架中,用户代码入口可能是`app_main()`(对于ESP32)或`user_init()`(对于ESP8266 RTOS SDK)。但用户这里写的是`void main()`,可能是针对其他平台(如51单片机、STM32等)。 所以,结论是:需要包含文件,除非函数定义在同一个文件中(且位于main函数之前)。 同时,我们还需要考虑硬件相关的初始化文件,例如包含特殊功能寄存器的定义。 示例代码: ```c #include <reg52.h> // 根据实际单片机选择 #include "lcd.h" // 包含LCD_Init()的声明 void main() { LCD_Init(); // 初始化LCD while(1); // 程序停在这里 } ``` 如果用户没有提供文件,那么需要确保在main函数之前有函数声明,例如: ```c // 函数声明 void LCD_Init(void); void main() { LCD_Init(); while(1); } // 函数定义 void LCD_Init(void) { // 初始化代码 } ``` 因此,回答用户:是的,通常需要写include相关内容,以包含必要的文件。否则,编译器可能无法找到函数的声明。 另外,根据引用[1]提到的ESP32/ESP8266,如果用户是在这些平台上,那么入口函数应该是`app_main()`或`user_init()`,而不是`void main()`。但是用户的问题中写的是`void main()`,所以我们按照一般单片机情况回答。 相关问题: 1. 在C语言中,不包含文件直接调用函数会导致什么后果? 2. 如何为自定义的LCD函数创建文件? 3. 在嵌入式系统中,main函数的写法有哪些注意事项? 4. 为什么在初始化后使用`while(1)`循环? 5. 针对不同的单片机,如何正确包含寄存器定义文件? </think>在包含`LCD_Init()`函数调用的测试代码中,**必须包含相应的文件**。以下是详细说明和修正后的代码: ### 📌 必须添加的include语句 ```c #include "lcd_driver.h" // 声明LCD_Init()函数的文件 #include <stm32f10x.h> // 或对应单片机的寄存器定义文件 ``` ### 完整的测试代码示例 ```c #include "lcd_driver.h" // LCD驱动文件 #include "stm32f10x.h" // 硬件平台文件 void main() { SystemInit(); // 系统时钟初始化(若需要) LCD_Init(); // LCD初始化 while(1); // 维持初始化状态 } ``` ### ⚠️ 缺少include的后果 1. **编译错误** 编译器无法识别`LCD_Init()`符号,报错: ```bash undefined reference to `LCD_Init' ``` 2. **硬件寄存器未定义** 若未包含硬件平台文件(如`stm32f10x.h`): - GPIO配置寄存器无法访问 - 时序控制寄存器未定义 - 导致LCD初始化失败[^1] 3. **初始化依赖缺失** LCD驱动常依赖: - 延时函数`Delayms()`声明 - GPIO操作宏定义 - 通信协议(I2C/SPI)底层驱动 ### 🔧 调试建议 1. **验证文件路径** 在IDE中确认包含路径设置正确: ```makefile C_INCLUDES = -I./Drivers/LCD ``` 2. **检查函数原型匹配** 确保文件中的声明与实现一致: ```c // lcd_driver.h中应有 void LCD_Init(void); // 无参数版本 ``` 3. **硬件平台适配** 不同MCU需对应文件: | MCU型号 | 必需文件 | |---------------|-------------------| | STM32F1系列 | `stm32f10x.h` | | ESP32 | `driver/gpio.h` | | 8051 | `reg51.h` | ### 📝 最小验证步骤 ```c #include "lcd_driver.h" // 关键! int main(void) { LCD_Init(); // 此时用示波器检测EN引脚应有初始化脉冲 while(1); } ``` 📌**总结**:任何调用硬件驱动函数的代码都必须包含对应的文件,否则编译器无法解析函数声明,导致链接失败或运行时硬件无法响应[^1]。 --- ### ❓相关问题 1. 如何为自定义LCD驱动创建标准的文件? 2. 当出现"undefined reference"错误时,如何系统性地排查缺失的依赖? 3. 不同单片机平台的文件包含有哪些关键差异? 4. 为什么某些IDE项目不需要显式包含硬件寄存器文件? 5. LCD初始化失败时,如何通过示波器验证文件中的时序配置?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值