Entiendo lo que se supone que SOLID debe lograr y lo uso regularmente en situaciones donde la modularidad es importante y sus objetivos son claramente útiles. Sin embargo, dos cosas me impiden aplicarlo consistentemente en mi base de código:
Quiero evitar la abstracción prematura. En mi experiencia, dibujar líneas de abstracción sin casos de uso concretos (del tipo que existe ahora o en el futuro previsible ) lleva a que se dibujen en los lugares equivocados. Cuando intento modificar dicho código, las líneas de abstracción se interponen en lugar de ayudar. Por lo tanto, tiendo a equivocarme al no dibujar líneas de abstracción hasta tener una buena idea de dónde serían útiles.
Me resulta difícil justificar el aumento de la modularidad por sí mismo si hace que mi código sea más detallado, más difícil de entender, etc. y no elimina ninguna duplicación. Encuentro que el código de procedimiento o de objeto de Dios simple y estrechamente acoplado a veces es más fácil de entender que el código de ravioles muy bien factorizado porque el flujo es simple y lineal. También es mucho más fácil escribir.
Por otro lado, esta mentalidad a menudo conduce a objetos de Dios. Generalmente los refactorizo de manera conservadora, agregando líneas de abstracción claras solo cuando veo que surgen patrones claros. ¿Qué hay de malo en los objetos de Dios y el código estrechamente acoplado, si es que no necesita más modularidad, no tiene una duplicación significativa y el código es legible?
EDITAR: En cuanto a los principios SÓLIDOS individuales, quise enfatizar que la sustitución de Liskov es en mi humilde opinión una formalización del sentido común y debe aplicarse en todas partes, ya que las abstracciones no tienen sentido si no lo es. Además, cada clase debe tener una responsabilidad única en algún nivel de abstracción, aunque puede ser un nivel muy alto con los detalles de implementación agrupados en una gran clase de 2,000 líneas. Básicamente, tus abstracciones deberían tener sentido donde elijas abstraer. Los principios que cuestiono en los casos en los que la modularidad no es claramente útil son los abiertos y cerrados, la segregación de la interfaz y especialmente la inversión de dependencia, ya que se trata de la modularidad, no solo de que las abstracciones tengan sentido.