Na orientação a objetos, uma classe selada não pode ser extendida e tomar esta decisão design pode ter diferentes impactos no consumo do seu código. Neste artigo vamos entender melhor quando utilizá-las.
Flunt é um pacote que criei para aplicar validações e o padrão Domain Notification. Com o tempo ele se tornou popular e tem até versões em Java/JS, o que é bem legal.
No C# e em diversas outras linguagens orientadas à objetos nós temos um modificador chamado sealed
que previne a classe de ser extendida.
Por tempos eu fiquei me perguntando onde eu usaria este modificador, qual seria um caso real para ele, e em 2017 acabei utilizando no Flunt.
Para tornar uma classe selada (Impedir que a mesma seja extendida), basta utilizar o seguinte exemplo.
public sealed class Notification
{
...
}
Desta forma, se tentarmos criar uma nova classe que derive de Notification
nos depararemos com o seguinte erro.
public class CustomNotification : Notification
{
...
}
ERRO
'Program.CustomNotification': cannot derive from sealed type 'Program.Notification'
Tudo bem, você já entendeu o que é o sealed
e como utilizar, mas agora vem a motivação para o seu uso.
Nas primeiras versões do Flunt eu não selei a classe Notification
o que permitiu que outras classes fossem criadas sobre ela, e durante uma passagem por um dos meus clientes, notei que ele possuiam customizações destas notificações.
Não vou me recordar 100% agora, mas era algo como isto.
// Classe do Flunt
public class Notification
{
...
}
// Derivações (No cliente)
public class ErrorNotification
{
...
}
public class WarningNotification
{
...
}
public class SuccessNotification
{
...
}
Cada uma destas derivações tinha suas próprias customizações, seus métodos e suas propriedades. Como temos a possibilidade de upcast
na OOP, estas classes também podiam substituir sua classe pai, a Notification
.
Mas qual o problema nisso? Qual problema em criar customizações?
Algumas coisas não foram feitas para serem customizadas ou você não quer permitir que elas sejam feitas de formas diferentes.
A ideia por trás das notificações é ter uma padronização nas APIs por exemplo, onde todo erro 400 (BadRequest) retorna uma lista de notificações, algo parecido com isto.
{
"status": 400,
"message": "Falha na requisição",
"data": null,
"notifications": [
{ "Name": "Nome inválido" },
{ "Document": "CPF inválido" },
]
}
Desta forma, qualquer aplicação que consuma a API pode se preparar para o mesmo padrão, isto facilita a vida do Frontend que pode ter uma tipagem sobre o retorno de qualquer método da API, em suma, qualquer requisição a API resulta neste modelo.
Focando apenas no nó notifications
, a classe Notification
do Flunt deveria garantir que seu resultado fosse sempre neste padrão, ou seja, quem consome a API sempre pode esperar uma lista de notificações contendo chave/valor.
Porém, ao customizar (Extender) as notificações, o resultado podia variar de acordo com o tipo da notificação.
{
"status": 400,
"message": "Falha na requisição",
"data": null,
"notifications": [
{ "Name": "Nome inválido" },
{ "Document": "CPF inválido" },
]
}
{
"status": 200,
"message": "Cadastro realizado",
"data": null,
"notifications": [
{ "id": 1, "type": "success", "value":"Cadastro OK" }
]
}
{
"status": 200,
"message": "Cadastro realizado",
"data": null,
"notifications": [
{ "type": "success", "key":"XYZ", "value":"XPTO" }
]
}
Isto geraria no mínimo um switch
no Frontend para saber o tipo de notificação e então tratá-la de forma diferente. Ainda vale lembrar que o Frontend não está limitado a Web, tem Flutter, Xamarin e várias outras tecnologias/linguagens.
Deste primeiro cenário veio a motivação para selar a classe Notification
e padronizar todas as notificações dos sistemas que usam o Flunt.
Como comentei no começo deste artigo, esta foi uma decisão que tomei em 2017, mas o que me motivou a escrever este artigo foi outro cenário que passei hoje.
Em alguns pontos críticos de leitura das Apps/Apis do balta eu utilizo o Dapper
para acesso à dados, inclusive tem um curso sobre isto aqui.
Porém, o Dapper é um micro-orm que extende o IDbConnection
apenas, o que significa que estamos literalmente por conta própria para tudo, inclusive para gerenciar a conexão com o banco de dados.
Desta forma, eu sempre crio um classe para gerenciar a conexão e garantir que não vou deixar conexão aberta no meu SQL Server
.
Fazer isto não é uma tarefa difícil, basta implementar a interface IDisposable
e chamar o método Connection.Dispose
para encerrar a conexão.
public sealed class DbSession : IDisposable
{
private Guid _id;
public IDbConnection Connection { get; }
public IDbTransaction Transaction { get; set; }
public DbSession()
{
_id = Guid.NewGuid();
Connection = new SqlConnection(Settings.ConnectionString);
Connection.Open();
}
public void Dispose() => Connection?.Dispose();
}
Mas e aí, você notou algo de diferente nesta classe? Sim, ela está selada e você já deve imaginar o motivo!
Pois é, se tem uma classe que não quero que alguém extenda é esta, ela é uma das mais importantes e sensíveis da aplicação, e sem o sealed
nela, poderiam ter várias versões da mesma.
Ainda pior, com a possibilidade de upcast
poderiamos facilmente substituir a conexão padrão por uma customizada que talvez esquecesse de fechar a conexão com o banco de dados.
Imagina o problemão que não arrumaríamos?
As vezes, na correria do dia-a-dia tendemos a fazer o mais fácil, e em diversos cenários, optaríamos por criar uma nova versão de uma classe do que dar manutenção e melhorá-la.
O modificador sealed
age neste ponto, ele te ajuda a travar as classes que você não quer que sejam extendidas e forçar as coisas a seguirem um padrão.
Mas calma, não é para sair selando todas as classes do sistema só porque aprendeu algo novo hoje!
Este artigo atualmente utiliza a versão 5.0.0-rc.1 do ASP.NET/.NET, o que significa que ainda não...
Saiba como manter seu código limpo (Clean Code) seguindo algumas práticas sugeridas pelo Robert C...
Git é um sistema de controle de versões distribuídas, enquanto GitHub é uma plataforma que tem o ...
O Visual Studio Code é um editor de código criado pela Microsoft e que tem uma grande adoção pela...
O Angular nos fornece um esquema de rotas e navegação completo, simples e fácil de utilizar.
Me dedico ao desenvolvimento de software desde 2003, sendo minha maior especialidade o Desenvolvimento Web. Durante esta jornada pude trabalhar presencialmente aqui no Brasil e Estados Unidos, atender remotamente times da ?ndia, Inglaterra e Holanda, receber 8x Microsoft MVP e realizar diversas consultorias em empresas e projetos de todos os tamanhos.
Aulas disponíveis
horas de conteúdo
Alunos matriculados
Certificados emitidos
Temos mais de 16 cursos totalmente de graça e todos com certificado de conclusão.
Prefere algo mais Premium?
Compra única, parcelada em até
12x no cartão de crédito
Cobrado mensalmente via
cartão de crédito
Precisa de ajuda?
Sim! Basta criar sua conta gratuita no balta.io e começar seus estudos. Nós contamos com diversos cursos TOTALMENTE gratuitos e com certificado de conclusão.
Nós temos cursos gratuitos e pagos, porém você não precisa informar nenhum dado de pagamento
para começar seus estudos gratuitamente conosco. Os cursos gratuitos são completos e com
certificado de conclusão, você não paga nada por eles.
Porém, caso queira algo mais Premium,
você terá acesso à diversos benefícios que vão te ajudar ainda mais em sua carreira.
Siga SEMPRE as nossas Carreiras, elas vão te orientar em todos
os sentidos. Os cursos já estão organizados em categorias e carreiras para facilitar seu
aprendizado.
Nossa sugestão para aprendizado é começar pelo Backend e seguindo para Frontend e Mobile.
Nenhum curso no mundo vai te ensinar tudo, desculpa ser sincero! Os cursos são uma base, eles fornecem por volta de 30% do que você precisa aprender, o resto é com você, com dedicação e MUITA prática.
Java ou .NET? Angular ou React? Xamarin ou Flutter? A resposta é simples e direta: "Você já sabe
o básico?"
Se você ainda não sabe BEM o básico, ou seja, os fundamentos, OOP, SOLID, Clean Code, está
perdendo tempo estudando Frameworks ou até coisas mais avançadas como Docker. Foque nos seus
objetivos primeiro.
Agora se você está indeciso sobre qual Framework estudar, a boa notícia é que o mercado neste
momento está bem aquecido e você tem várias oportunidade. Desta forma o que levaríamos em conta
para tomar esta decisão seria:
Com certeza! O primeiro passo é começar e você pode fazer isto agora mesmo!
Começar de
graça
Receba em primeira mão todas as nossas novidades.