Quiz: Camada de Serviço e Arquitetura
Teste seus conhecimentos sobre a camada de serviço, validação e arquitetura MVC.
30 questões - Clique em cada pergunta para revelar a resposta.
Questões 1-10: Camada de Serviço
Pergunta 1: Qual é o papel da camada Service na arquitetura MVC?
Resposta: A camada Service contém a lógica de negócio da aplicação. Ela:
- Orquestra as operações entre controllers e repositories
- Aplica as regras de negócio
- Gerencia transações
- É independente do protocolo HTTP
Pergunta 2: Qual anotação é usada para declarar um service no Spring?
Resposta: @Service - É um estereótipo especializado de @Component que indica que a classe contém lógica de negócio.
@Service
public class UserService {
// lógica de negócio
}
Pergunta 3: Por que não colocar a lógica de negócio no controller?
Resposta: Separar a lógica de negócio do controller permite:
- Reutilização: o service pode ser chamado por vários controllers
- Testabilidade: testar a lógica sem HTTP
- Manutenibilidade: código mais organizado
- Separação de responsabilidades: cada camada tem um papel definido
Pergunta 4: Como injetar um Repository em um Service?
Resposta: Por injeção via construtor (recomendado):
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Pergunta 5: O que é um DTO (Data Transfer Object)?
Resposta: Um DTO é um objeto simples usado para transferir dados entre as camadas. Ele:
- Não contém lógica de negócio
- Expõe apenas os dados necessários
- Protege a entidade JPA de exposição direta
- Permite formatar os dados para a API
Pergunta 6: Por que usar DTOs em vez das entidades JPA diretamente?
Resposta:
- Segurança: não expor campos sensíveis (senha)
- Performance: evitar carregamento lazy de relações
- Flexibilidade: formato diferente da entidade
- Desacoplamento: mudanças internas não afetam a API
- Validação: regras específicas para entrada/saída
Pergunta 7: Como converter uma entidade em DTO?
Resposta: Várias abordagens:
// 1. Método manual
public UserDto toDto(User user) {
return new UserDto(user.getId(), user.getName(), user.getEmail());
}
// 2. Com MapStruct
@Mapper
public interface UserMapper {
UserDto toDto(User user);
}
// 3. Com ModelMapper
modelMapper.map(user, UserDto.class);
Pergunta 8: Qual a diferença entre um RequestDTO e um ResponseDTO?
Resposta:
- RequestDTO: dados de entrada (criação, atualização), contém validação
- ResponseDTO: dados de saída, formatados para o cliente
// Request
public class CreateUserRequest {
@NotBlank
private String email;
@Size(min = 8)
private String password;
}
// Response
public class UserResponse {
private Long id;
private String email;
// Sem senha!
}
Pergunta 9: Como tratar erros na camada Service?
Resposta: Lançar exceções personalizadas:
@Service
public class UserService {
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found: " + id));
}
}
Essas exceções são tratadas por @ControllerAdvice.
Pergunta 10: O que é @Transactional em um service?
Resposta: @Transactional gerencia automaticamente as transações:
- Inicia uma transação no começo do método
- Faz commit se tiver sucesso
- Faz rollback se houver exceção
@Service
@Transactional
public class OrderService {
// Todos os métodos são transacionais
}
Questões 11-20: Validação
Pergunta 11: Qual dependência adicionar para validação?
Resposta: spring-boot-starter-validation
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Pergunta 12: Como ativar a validação em um controller?
Resposta: Com @Valid ou @Validated no parâmetro:
@PostMapping
public ResponseEntity<User> create(@Valid @RequestBody CreateUserRequest request) {
// Se a validação falhar, MethodArgumentNotValidException é lançada
}
Pergunta 13: Quais são as anotações de validação mais comuns?
Resposta:
| Anotação | Descrição |
|---|---|
@NotNull | Não pode ser null |
@NotBlank | Não null, não vazio, sem espaços |
@NotEmpty | Não null e não vazio |
@Size(min, max) | Tamanho entre min e max |
@Min, @Max | Valor numérico mínimo/máximo |
@Email | Formato de e-mail válido |
@Pattern | Regex personalizada |
@Past, @Future | Data no passado/futuro |
Pergunta 14: Como personalizar a mensagem de erro de validação?
Resposta: Com o atributo message:
public class CreateUserRequest {
@NotBlank(message = "O e-mail é obrigatório")
@Email(message = "Formato de e-mail inválido")
private String email;
@Size(min = 8, message = "A senha deve ter pelo menos 8 caracteres")
private String password;
}
Pergunta 15: Como criar uma validação personalizada?
Resposta: Criar uma anotação e um validador:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
public @interface UniqueEmail {
String message() default "E-mail já utilizado";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
// Verificar se o e-mail existe
}
}
Pergunta 16: Qual a diferença entre @Valid e @Validated?
Resposta:
@Valid: padrão Java (JSR-380), faz validação em cascata@Validated: Spring, suporta grupos de validação
// Grupos de validação
public interface OnCreate {}
public interface OnUpdate {}
@NotNull(groups = OnUpdate.class)
private Long id;
@Validated(OnCreate.class)
public void create(...) { }
Pergunta 17: Como validar parâmetros de requisição (query params)?
Resposta: Adicionar @Validated no controller:
@RestController
@Validated
public class UserController {
@GetMapping("/users")
public List<User> search(
@RequestParam @Min(0) int page,
@RequestParam @Max(100) int size) {
// ...
}
}
Pergunta 18: Como validar um objeto aninhado?
Resposta: Usar @Valid no campo aninhado:
public class OrderRequest {
@Valid // Validação em cascata
@NotNull
private AddressDto shippingAddress;
}
public class AddressDto {
@NotBlank
private String street;
@NotBlank
private String city;
}
Pergunta 19: Como recuperar os erros de validação?
Resposta: Via BindingResult ou @ExceptionHandler:
// Opção 1: BindingResult
@PostMapping
public ResponseEntity<?> create(@Valid @RequestBody Request req, BindingResult result) {
if (result.hasErrors()) {
return ResponseEntity.badRequest().body(result.getAllErrors());
}
}
// Opção 2: ControllerAdvice (recomendado)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidation(MethodArgumentNotValidException ex) {
// Extrair os erros
}
Pergunta 20: O que é validação na camada de serviço?
Resposta: Validação da lógica de negócio (não apenas do formato):
@Service
public class OrderService {
public Order createOrder(OrderRequest request) {
// Validação de negócio
if (request.getQuantity() > productService.getStock(request.getProductId())) {
throw new InsufficientStockException("Estoque insuficiente");
}
// ...
}
}
Questões 21-30: Arquitetura
Pergunta 21: Quais são as 3 camadas principais da arquitetura MVC?
Resposta:
- Controller (Apresentação): gerencia HTTP, validação de entrada
- Service (Negócio): lógica de negócio, transações
- Repository (Dados): acesso ao banco de dados
Cliente → Controller → Service → Repository → Database
Pergunta 22: Em qual camada colocar o gerenciamento de transações?
Resposta: Na camada Service. É onde está a lógica de negócio que define o que constitui uma unidade de trabalho atômica.
@Service
@Transactional
public class TransferService {
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// Toda a operação é atômica
}
}
Pergunta 23: Como organizar os packages de um projeto Spring Boot?
Resposta: Por camada ou por funcionalidade:
// Por camada
com.example.app
├── controller/
├── service/
├── repository/
├── model/
└── dto/
// Por funcionalidade (recomendado para projetos grandes)
com.example.app
├── user/
│ ├── UserController
│ ├── UserService
│ └── UserRepository
├── order/
└── product/
Pergunta 24: O que é o princípio da responsabilidade única (SRP)?
Resposta: Uma classe deve ter apenas uma razão para mudar. Cada classe tem uma única responsabilidade:
- Controller: gerenciar requisições HTTP
- Service: lógica de negócio
- Repository: acesso a dados
Exemplo ruim: um controller que faz tudo (HTTP + negócio + banco de dados).
Pergunta 25: Por que usar interfaces para os services?
Resposta:
- Desacoplamento: os clientes dependem da abstração
- Testabilidade: fácil de mockar
- Flexibilidade: trocar a implementação
- Proxying: Spring AOP funciona melhor
public interface UserService {
User findById(Long id);
}
@Service
public class UserServiceImpl implements UserService { }
Pergunta 26: O que é um @ControllerAdvice?
Resposta: Um componente que gerencia exceções globalmente para todos os controllers:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(UserNotFoundException ex) {
return ResponseEntity.status(404).body(new ErrorResponse(ex.getMessage()));
}
}
Pergunta 27: Como estruturar uma resposta de erro padrão?
Resposta: Criar um DTO de erro consistente:
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
}
// Ou formato ProblemDetail (RFC 7807)
Pergunta 28: Qual a diferença entre @RestController e @Controller?
Resposta:
@Controller: retorna views (HTML)@RestController: retorna dados (JSON/XML)
@RestController = @Controller + @ResponseBody
@RestController // Tudo é JSON
public class UserController { }
@Controller
public class ViewController {
@GetMapping("/")
public String home() {
return "index"; // View Thymeleaf
}
}
Pergunta 29: Como tratar os códigos HTTP apropriados?
Resposta: Usar ResponseEntity:
@PostMapping
public ResponseEntity<User> create(@RequestBody UserRequest req) {
User user = userService.create(req);
return ResponseEntity
.status(HttpStatus.CREATED) // 201
.body(user);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204
}
Pergunta 30: Quais são os códigos HTTP comuns em REST?
Resposta:
| Código | Significado | Uso |
|---|---|---|
| 200 | OK | GET, PUT bem-sucedido |
| 201 | Created | POST bem-sucedido |
| 204 | No Content | DELETE bem-sucedido |
| 400 | Bad Request | Validação falhou |
| 401 | Unauthorized | Não autenticado |
| 403 | Forbidden | Não autorizado |
| 404 | Not Found | Recurso inexistente |
| 500 | Server Error | Erro interno |
Pontuação
| Pontuação | Nível |
|---|---|
| 27-30 | Excelente - Arquitetura dominada |
| 21-26 | Bom - Algumas revisões |
| 15-20 | Médio - Releia os capítulos |
| Menos de 15 | A revisar - Refaça os fundamentos |