Jump to content

Clean Code

From Knowledge Base
Revision as of 13:06, 21 January 2025 by Chr1ss (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."
This quote is often attributed to Antoine de Saint-Exupéry, the French writer and aviator, from his book Terre des Hommes (1939), known in English as Wind, Sand and Stars.


KISS

Keep It Sweet & Simple - Simplicity is paramount. Methods should be concise, with one expression per line, and names MUST be meaningful. Classes should be focused and manageable in size to facilitate ease of change. The balance between readability and conciseness is essential.

DRY

Don't Repeat Yourself - Redundancy is a significant obstacle to clean code and system performance. Identifying and eliminating repetitive patterns is crucial for efficient and maintainable code.

YAGNI

You Ain't Gonna Need It - Solutions should be pragmatic and focused on current requirements. Extraneous features should be avoided unless they are necessary. It is important to remain open to potential future changes and to share any concerns with the team.

DTSTTCPW

Do The Simplest Thing That Could Possibly Work - This principle emphasizes starting with the simplest solution that effectively solves the problem. It is especially valuable for addressing complex issues, as it helps to clarify understanding and avoid over-engineering. However, simplicity should not extend to vague or overly generic names like value, list, or xclarity in naming is essential.

STUPID

Singleton, Tight Coupling, Untestable, Premature Optimization, Indecisiveness, Duplication - This acronym serves as a reminder of what to avoid in code. Striving to eliminate these qualities ensures code is maintainable and efficient. What to strive for is Simple, Testable, Ubiquitous, Proper, Incremental, Decoupled.

Error creating thumbnail: Unable to save thumbnail to destination

Levels of Clean Code

From the broader design of a system to the individual lines of code, each level benefits from adherence to clean code principles.

  1. Project Structure Level A well-structured project enables developers to quickly locate files, classes, and methods, improving overall productivity and reducing errors.
  2. File Name Level File names should clearly indicate their contents. Descriptive file names make it easier to understand the purpose of the file without needing to open it.
  3. Class Level At the class level, clean code emphasizes single responsibility and clear separation of concerns. Classes should do one thing and do it well. This helps in keeping the codebase maintainable, flexible, and easy to extend.
  4. Method Level Methods should be small, focused, and descriptive. They should do one thing and do it well, aligning with the Single Responsibility Principle. Long, complex methods should be refactored into smaller, more manageable ones.
  5. Type Level At the type level, the focus is on creating well-defined, consistent, and easy-to-understand data types.

Using meaningful names makes code self-documenting, improving both readability and maintainability.

Clean Code Philosophy

Writing clean code is a discipline that aligns with various aspects of personal and professional habits. The philosophy behind clean code includes:

  • Clarity: The code should be easy to read and understand. Use descriptive names for variables, functions, and classes.
  • Logic: Code should be logical and consistent, following the intended design and avoiding unnecessary complexity.
  • Consistency: Apply coding standards and practices consistently throughout the project.
  • Empathy: The ability to empathize with others and adopt their perspective to make the code more understandable for everyone.
  • Commitment: The willingness to produce high-quality code, going the extra mile rather than rushing to release the next feature. This mindset also supports thorough testing.
  • Openness to Criticism: Developers may have different opinions on various coding practices (e.g., "opening curly braces on the same line"). However, it's essential to understand that teamwork matters more than individual preferences. The majority's perspective on the code's readability and maintainability takes precedence, fostering a collaborative and cohesive work environment.
Meme about CleanCode Format Discussion

When Not to Use Clean Code

I recently read an article, Reverse Engineering Call Of Duty Anti-Cheat: there are situations where you intentionally avoid clean code. In this case, the developers behind the anti-cheat system deliberately made their code difficult to understand to protect it from malicious actors.

This realization was fascinating because it shows that clean code isn't always the right choice. It’s a reminder that as developers, we need to be adaptable—ready to "anticipate change" and embrace situations where clean code principles might not apply.

Techniques and Practices

Here are some common methods used to make code harder to understand:

  • Method Bloating: Write unnecessarily large methods by adding redundant or irrelevant logic, making it harder to focus on the core functionality.
  • Meaningless Names: Use nonsensical or random names for variables, methods, and classes (e.g., `XyZ123` or `aBcD`) instead of descriptive ones.
  • Control Flow Obfuscation: Add unnecessary conditionals, loops, or deeply nested structures to confuse the logical flow.
  • Inlined Code: Avoid modularization by placing all logic inline, removing the intuitive structure of smaller, focused methods.
  • Dynamic Code Generation: Generate parts of your code at runtime, complicating static analysis.
  • String Encryption: Encrypt strings (like error messages or configuration keys) and decrypt them only when needed.
  • Dead Code: Insert unused logic or functions to mislead anyone attempting to reverse-engineer the code.
  • Excessive Indirection: Break logical chains into multiple layers of indirect calls to obfuscate intent.
  • Heavy Reflection or Meta-programming: Dynamically access members or execute logic using reflection, which makes static analysis nearly impossible.
  • Custom Encoding: Serialize or encode data using non-standard or proprietary formats to complicate interpretation.

Practices:

  • Document the obfuscation strategy for trusted developers, ensuring updates or bug fixes remain possible.
  • Use automated tools to manage obfuscation instead of manually introducing complexity.
  • Regularly evaluate whether the benefits of obfuscation outweigh the long-term risks, particularly in projects requiring frequent updates or team collaboration.

Tools For .NET Applications

  • Dotfuscator (by PreEmptive): A leading tool for .NET obfuscation, integrated with Visual Studio.
  • ConfuserEx: An open-source obfuscator with many advanced features.
  • SmartAssembly: A commercial tool focused on obfuscating and protecting .NET code.