O tym jak działa kontroler, czym powinien się zajmować i dlaczego nie powinien realizować zbyt wiele. W dzisiejszym wpisie powiem o tym dlaczego nie warto budować wielkich kontrolerów będących boskimi klasami.
@Controller('incomes')
export class IncomesController {
constructor(private readonly incomesService: IncomesService) {}
@Post('calculate/year')
async calculateYearIncome(@Body() request: CalculateYearIncomeRequest): Promise<YearIncomeResponse> {
const yearIncome = await this.incomesService.calculateYearIncome(request as CalculateYearIncomeDTO);
const response = YearIncomeResponseMapper.mapIncomeEntity(yearIncome);
return response;
}
}
Mamy tutaj przyjęcie i automatyczną walidację danych, wywołanie pewnej logiki biznesowej i użycie jej wyniku do sformatowania obiektu wyjściowego (ang. response object). Oczywistym jest także fakt, iż postać tej metody będzie się różnić w zależności od użytej technologii czy frameworka. Niejednokrotnie może okazać się, iż konieczne jest ręczne wywołanie pewnej metody walidującej, czy też sam obiekt wyjściowy może tworzyć się automatycznie. @Controller('incomes')
export class IncomesController {
constructor(private readonly incomesService: IncomesService) {}
@Post('calculate/year')
async calculateYearIncome(@Body() form: CalculateYearIncomeForm): Promise<YearIncomeResponse> {
form.validate();
const dto = CalculateYearIncomeDTOMapper.map(form.getData());
const yearIncome = await this.incomesService.calculateYearIncome(dto);
const response = YearIncomeResponseMapper.mapIncomeEntity(yearIncome);
return response;
}
}
@Controller('incomes')
export class IncomesController {
constructor(
private readonly incomeRepository: IncomeRepository,
private readonly invoiceRepository: InvoiceRepository
) {}
@Post('calculate/year')
async calculateYearIncome(@Body() request: YearIncomeRequest): Promise<Income> {
const { year, companyId } = request;
const invoices = await this.invoiceRepository.findByYearAndType(
year,
invoiceType: InvoiceTypeEnum.SELL,
companyId
);
const incomeValue = invoices.reduce((income: number, invoice: Invoice) =>
income += invoice.netValue, 0);
let income = await this.incomeRepository.findYearIncome(year, companyId);
if (income) {
income.value = incomeValue;
return this.incomeRepository.save(income);
}
income = IncomeFactory.createYearIncome({ year, companyId });
return this.incomeRepository.save(income);
}
}
Zasada DRY, to po przełożeniu na język polski: nie powtarzaj się. Brzmi bardzo banalnie, jednak dosyć często okazuje się, że mamy problem z jej stosowaniem w kodzie. Dziś dowiesz się, jak nie łamać tej reguły, a co za tym idzie nie powtarzać się.
Sprawdź ten wpisYAGNI to kwintesencja zasad clean code. Dotyczy ona bezużyteczności kodu, a dokładniej, konieczności usuwania tych fragmentów, które nie są potrzebne. W myśl "You aren't gonna need it" nie powinniśmy tworzyć niczego więcej, niż to, co jest potrzebne.
Sprawdź ten wpisZasada KISS: "Keep it simple, stupid", może zostać dosłownie przetłumaczona na: "rób to prosto, głupku". Mówi ona o tym, abyśmy tworzyli kod w jak najprostszy i najbardziej czytelny sposób. Już dziś sprawdź, czego się wystrzegać, aby spełniać KISS.
Sprawdź ten wpisWzorce projektowe zostały stworzone po to, aby nie wymyślać przysłowiowego koła na nowo. Znajomość wzorców projektowych i umiejętność ich stosowania pozwala na szybkie rozwiązywanie problemów. Wpis ten radzi, jakie wzorce zastosować u siebie.
Sprawdź ten wpisKolejny kreacyjny wzorzec projektowy omawiany na łamach tego bloga: singleton. Wzorzec dookoła którego narosło wiele mitów i legend. Dziś o tym dlaczego singleton jest antywzorcem, jakie problemy powoduje oraz kiedy warto po niego sięgnąć.
Sprawdź ten wpisFanatyk czystego i prostego kodu. Zwolennik podejść DDD oraz Modular Monolith. Na codzień pracuje jako programista i architekt. Po godzinach spełnia się w projektach open source, udziela się na blogach oraz czyta książki o kosmosie i astrofizyce.