Apply software design principles across architecture and implementation using deterministic decision workflows, SOLID checks, structural patterns, and anti-pattern detection; use when reviewing designs, refactoring modules, or resolving maintainability and coupling risks.
Does it follow best practices?
Evaluation — 99%
↑ 1.01xAgent success when using this tile
Validation for skill structure
Logging frameworks are infrastructure details. Define logging interfaces in the application layer; implement them in infrastructure. This enables switching loggers and keeps domain pure.
Incorrect (logging framework in domain/application):
package usecases
import (
"github.com/sirupsen/logrus" // Framework dependency
)
type CreateOrderUseCase struct {
repo OrderRepository
logger *logrus.Logger // Concrete logger
}
func (uc *CreateOrderUseCase) Execute(cmd CreateOrderCommand) (*Order, error) {
uc.logger.WithFields(logrus.Fields{
"customer_id": cmd.CustomerID,
"item_count": len(cmd.Items),
}).Info("Creating order")
order, err := uc.repo.Create(cmd)
if err != nil {
uc.logger.WithError(err).Error("Failed to create order")
return nil, err
}
uc.logger.WithField("order_id", order.ID).Info("Order created")
return order, nil
}
// Switching from logrus to zap requires changing all use casesCorrect (logging behind interface):
// application/ports/logger.go
package ports
type Logger interface {
Info(msg string, fields ...Field)
Error(msg string, err error, fields ...Field)
Debug(msg string, fields ...Field)
}
type Field struct {
Key string
Value interface{}
}
func F(key string, value interface{}) Field {
return Field{Key: key, Value: value}
}
// application/usecases/create_order.go
package usecases
import "myapp/application/ports"
type CreateOrderUseCase struct {
repo OrderRepository
logger ports.Logger
}
func (uc *CreateOrderUseCase) Execute(cmd CreateOrderCommand) (*Order, error) {
uc.logger.Info("Creating order",
ports.F("customer_id", cmd.CustomerID),
ports.F("item_count", len(cmd.Items)),
)
order, err := uc.repo.Create(cmd)
if err != nil {
uc.logger.Error("Failed to create order", err,
ports.F("customer_id", cmd.CustomerID),
)
return nil, err
}
uc.logger.Info("Order created", ports.F("order_id", order.ID))
return order, nil
}
// infrastructure/logging/logrus_logger.go
package logging
import (
"github.com/sirupsen/logrus"
"myapp/application/ports"
)
type LogrusLogger struct {
logger *logrus.Logger
}
func (l *LogrusLogger) Info(msg string, fields ...ports.Field) {
l.logger.WithFields(toLogrusFields(fields)).Info(msg)
}
func toLogrusFields(fields []ports.Field) logrus.Fields {
result := logrus.Fields{}
for _, f := range fields {
result[f.Key] = f.Value
}
return result
}
// infrastructure/logging/zap_logger.go - Alternative implementation
// Switch without touching use casesBenefits:
Reference: Clean Architecture - Frameworks are Details
Install with Tessl CLI
npx tessl i pantheon-ai/software-design-principlesevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
references