今天去一个小公司面试,面试官是公司的软件总监,眼镜老花到看笔记本电脑困难,用win7的IE打开leetcode网页半天打不开,公司的wifi连接不上,用自己手机热点,却在笔记本电脑上找不到。还是我用自己的手机做热点,让贵公司的老古董笔记本电脑能wifi上网。然后用chrome浏览器打开了leetcode 中文网页。
Leetcode做题,毫不费劲完成了。然后面试官开始面试。第一个问题是什么是软件开发原则?我蒙圈了,说可以有各种不同的说法或解读,具体是哪个范围?他说,这个原则是统一的,是大公司google等都认可的。然后问我知不知道什么叫SRP。我都没听过。然后这个面试官不停地说这些原则多么地重要,不懂这些原则不可能团队合作,开发出高质量的大规模程序。我反问,这个有什么难度吗?我很快就可以了解。他说,这个知识点学习不难,但是真正理解,并且在项目中实施很难。然后以此为由,我作为senior programmar不胜任,面试结束。
我回家后google了software development principles,发现各种网站冒出来,五花八门的各种说法。点开了其中一个 “Foundations of Excellence: The Core Principles of Software Development”, 里面提到了包括SOLID, simplicity, DRY, YAGNI: You Aren't Gonna Need It, ... 等等。其中SOLID中第一条就是SRP,single responsibility principle。我再到Youtube上搜“solid principles interview questions” ,出现的视频没有超过20多分钟的,有的只有几分钟。我点开了其中一个比较新,播放量比较高的看。SRP,简单来说,就是让你的模块和class设计功能简单化,这样的好处是比较容易维护和扩展。这其实是我以前做架构设计,开发过程中已经应用的原则,只是不知道SRR这个名字。但是现实中我看到很多代码,包括我在Apple工作期间看到的代码,明显违反了这个原则,把一大堆功能都塞到一个class里,造成可读性,可维护性很差。但是,这么多的legacy代码,而且是基础代码,也就是很多不同的应用上层代码都要调用的。除非你有充足的时间,而且有相当的容错空间,否则不可能推导重构的。另外,单一功能这种说法,本身就是一个形容词,而不是一个数量词。怎样才算单一功能,在不同的应用场景,不同人的理解,都会不一样。把class或模块的功能单一化固然可以让这个模块或class易于维护,测试和扩展。但是如果分得太细,你的程序的class和模块的数量将几何数量上升,这将导致代码的可维护性,可测试性,和可拓展性都变得非常困难。而如何找到一个平衡,本身就是要依据具体情况而定,包括任务的复杂程度,未来的路标,软件开发人员数量,水平,历史代码规模,质量,等等。
我在chatGPT上提问,
得到的回答和我的观点一致:
You're absolutely correct that applying the Single Responsibility Principle (SRP), while an essential guideline for writing maintainable code, often requires context-based interpretation and doesn't have a one-size-fits-all solution. The complexity of real-world scenarios introduces nuances that make SRP less about following rigid rules and more about making thoughtful trade-offs.
Why SRP Isn't Always Clear-Cut
How to Apply SRP in Real Scenarios
Think in Terms of Change:
- A good litmus test for SRP is to ask: If this class changes, why would it need to?
- If a class has multiple reasons to change, it might be violating SRP.
- Example: A class handling both file I/O and business logic would likely change for different reasons (e.g., a new storage format or new business rules).
Start with Clear Boundaries:
- When designing new components, establish clear boundaries based on responsibilities. This is easier than retrofitting SRP into a messy, existing codebase.
Prioritize Practicality:
- Don't split responsibilities for the sake of purity. Ensure that separating responsibilities adds value, such as easier testing, better readability, or more maintainability.
- Example: In a small, throwaway script, strict adherence to SRP might be overkill.
Refactor Incrementally:
- When working with legacy code, gradually apply SRP by:
- Extracting methods or functions for secondary responsibilities.
- Creating small, focused classes or modules over time.
Leverage Code Reviews and Discussions:
- Use code reviews to discuss and refine the scope of responsibilities. Different perspectives can help strike the right balance.
SRP as a Guideline, Not a Rule
As you pointed out, software design doesn’t have "unique correct answers" like solving algorithmic problems. SRP is a principle to guide decision-making, not a rigid rule. The ultimate goal is to create a system that is:
- Understandable: Easier for others (and your future self) to reason about.
- Maintainable: Easier to update, fix, and extend.
- Flexible: Adaptable to changing requirements.
By recognizing the nuances of SRP and applying it pragmatically, you can achieve these goals without being overly constrained by theoretical ideals.
面试过程中,这位华为老将面试官,看我的编码书写风格:
if(a==b)
{
...
}
else
{
...
}
说这是10几年前微软的风格。单括号占一行,空间利用效率低,会占用多的行数。
现在的代码书写风格应该是:
if(a==b){
...
}else{
...
}
以此判断我已经很久没写程序了,或者没有团队合作写程序了。
我上面提到的那个讲述SOLID原则的视频(一年前发布的,12万观看)里面的书写风格就是和我一致。
然后又问了chatGPT,答复也是两种书写方式各有利弊,也没有说是第一种方式是古老的,依然很多公司和组织,个人在用。
总结一下:
1. 技术面试最好都问有确定,可量化答案的问题,而不是一些类似于形而上学的东西。因为这些问题的回答本身就是有ambiguity,站在面试者的角度来看,他可能有不同的解读。
2. 软件开发是一个很灵活的东西,面试最关键要考察候选人的灵活解决问题,正确解决问题的能力。一些关于操作性方面的理论,而不是计算机科学本身的理论如操作系统,算法等,不能作为决定性标准。
因篇幅问题不能全部显示,请点此查看更多更全内容