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
Use cases return domain data, not formatted strings, HTML, or UI-specific structures. Presentation logic belongs in the interface adapters layer.
Incorrect (presentation logic in use case):
class GetUserProfileUseCase {
execute(userId: string): UserProfileResponse {
const user = this.repo.findById(userId)
const orders = this.orderRepo.findByUser(userId)
return {
displayName: `${user.firstName} ${user.lastName}`, // Formatting
memberSince: user.createdAt.toLocaleDateString('en-US', {
month: 'long',
year: 'numeric'
}), // Locale-specific formatting
avatarHtml: `<img src="${user.avatarUrl}" alt="${user.firstName}"/>`, // HTML!
orderSummary: orders.length > 0
? `${orders.length} orders totaling $${this.sumOrders(orders).toFixed(2)}`
: 'No orders yet', // UI text
recentOrders: orders.slice(0, 5).map(o => ({
...o,
statusBadgeColor: this.getStatusColor(o.status) // UI styling
}))
}
}
private getStatusColor(status: string): string {
const colors = { pending: 'yellow', shipped: 'blue', delivered: 'green' }
return colors[status] || 'gray'
}
}Correct (use case returns domain data):
// application/usecases/GetUserProfileUseCase.ts
class GetUserProfileUseCase {
execute(userId: string): UserProfileResult {
const user = this.repo.findById(userId)
const orders = this.orderRepo.findByUser(userId)
return {
user: {
id: user.id.value,
firstName: user.firstName,
lastName: user.lastName,
email: user.email.value,
avatarUrl: user.avatarUrl,
createdAt: user.createdAt
},
orders: orders.map(o => ({
id: o.id.value,
total: o.total.amount,
currency: o.total.currency,
status: o.status,
createdAt: o.createdAt
})),
orderCount: orders.length,
totalSpent: this.sumOrders(orders)
}
}
}
// interface_adapters/presenters/UserProfilePresenter.ts
class UserProfilePresenter {
present(result: UserProfileResult, locale: string): UserProfileViewModel {
const formatter = new Intl.DateTimeFormat(locale, {
month: 'long',
year: 'numeric'
})
return {
displayName: `${result.user.firstName} ${result.user.lastName}`,
memberSince: formatter.format(result.user.createdAt),
avatarUrl: result.user.avatarUrl,
orderSummary: this.formatOrderSummary(result, locale),
recentOrders: result.orders.slice(0, 5).map(o =>
this.formatOrder(o, locale)
)
}
}
}Benefits:
Reference: Clean Architecture - Presenters
Install with Tessl CLI
npx tessl i pantheon-ai/software-design-principles@0.1.4evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
references