top of page

The Importance of Software Design Principles in the Age of Artificial Intelligence

Writer's picture: Carlos BastosCarlos Bastos

Artificial intelligence (AI) has revolutionized the way we approach software development, enabling faster prototyping and automating complex coding tasks. However, as powerful as generative AI tools have become, they often lack the nuance and understanding required to create maintainable, scalable, and human-readable code (at least by default, if an experienced software engineer gives guidance in that sense and iterates, it's a different scenario). This is especially true when these tools are used without a firm grasp of foundational software design principles.


My Chess Program Experiment: AI as a Double-Edged Sword


Recently, I embarked on an experiment to develop a chess program using the Cursor IDE, leveraging its AI-driven features such as the chat-based assistant and the "Composer" tool. The idea was to build a functional program by iteratively adding features with minimal manual intervention. While the AI was undoubtedly helpful in generating code snippets and implementing new functionality quickly, the experience highlighted some significant pitfalls:

  1. Frequent bugs and broken functionality: The AI often introduced bugs when implementing new features or modifying existing ones. Debugging these issues became increasingly challenging as the codebase grew more complex.

  2. Excessive code complexity: When the AI got things right, it was almost more dangerous. The solutions it produced were often unnecessarily intricate, with convoluted abstractions and sprawling logic that made the code difficult for humans to understand, even if it was perfectly logical to the AI. What the AI considers "understandable" often stems from patterns optimized for functionality rather than clarity, making it challenging for humans to follow or maintain.

  3. Spaghetti code and poor maintainability: Successive feature additions resulted in a tangled web of interdependencies. For example:

    • Unnecessary use of useState in React: The program ended up with multiple state variables that were redundant or could have been combined for simplicity.

    • Nested if statements: Deeply nested conditionals proliferated, making the logic hard to follow and prone to errors.

    • Repetitive logic and poor abstractions: The AI frequently duplicated code or created abstractions that were more confusing than helpful.


These issues culminated in a codebase that was brittle, opaque, and challenging to maintain. More importantly, it underscored a critical point: AI tools, as impressive as they are, lack the contextual understanding and strategic foresight required to write clean and maintainable code without human guidance.



This experiment served as a stark reminder of the importance of adhering to established software design principles, especially in an era where AI is becoming a key player in development workflows. Without these principles, developers risk creating systems that are:

  • Unmaintainable: When performance issues arise or features need modification, spaghetti code becomes a nightmare to debug and extend.

  • Opaque: Poorly structured code is difficult for humans to understand, leading to increased onboarding time for new developers and reduced team productivity.

  • Error-Prone: Complex, convoluted codebases are breeding grounds for subtle bugs that are hard to isolate and fix.


Lessons Learned: Guiding AI with Design Principles


To mitigate these risks, it’s essential to approach AI-assisted development with the same rigor as traditional coding practices:

  1. Understand the fundamentals: Ensure that you have a solid grasp of principles such as DRY (Don’t Repeat Yourself), KISS (Keep It Simple, Stupid), SOLID and up to 21 Design Principles before relying on AI tools.

  2. Review and refactor: Treat AI-generated code as a starting point, not a final product. Regularly review and refactor to simplify abstractions, reduce redundancy, and improve readability.

  3. Set clear guidelines for the AI: Be explicit about design constraints and standards when instructing AI tools. For example, ask for modular components, avoid unnecessary states (complexity), or specify that nested logic should be flattened.

  4. Think long-term: Consider how the code will scale, how easy it will be to debug, and how intuitive it will be for others (or yourself) to understand six months down the line.


Conclusion


Generative AI tools like those integrated into Cursor have the potential to revolutionize software development. However, their effectiveness is directly proportional to the expertise of the developers wielding them. Without a strong foundation in software design principles, developers risk creating unmaintainable, overly complex codebases that hinder long-term project success.


By combining the speed and power of AI with the discipline of good design practices, we can harness the best of both worlds—delivering robust, scalable, and human-readable software in the age of AI. My chess program experiment, though fraught with challenges, reinforced the value of this balanced approach and highlighted the critical role humans still play in the art of programming.


If you want to effectively guide the Generative AI to apply Design Principles, read the Software Design Principles book.

24 views0 comments

Recent Posts

See All

Contact

  • LinkedIn
  • email
  • https://www.cbastos.com/

© All rights reserved. Created by Carlos Bastos Pérez-Cuadrado

bottom of page