29
loading...
This website collects cookies to deliver better user experience
IMPORTANTE Este artigo não descarta a leitura do livro, que é muito mais denso e profundo sobre o assunto.
public static class Settings {
public static string ConnectionString { get; set; }
}
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Settings.ConnectionString = Configuration.GetConnectionString("connectionString");
}
using(var connection = new SqlConnection(Settings.ConnectionString)) {
...
}
IMPORTANTE Esta regra não está 100% correta ou eficiente, é apenas uma demonstração
public class Pagamento {
public bool PodeSerPago() {
if(tipo == ETipoPagamento.Boleto)
{
if(vencimento.Day != IsWeekend())
return true;
}
if(tipo == ETipoPagamento.CartaoCredito)
...
}
}
public class Pagamento {
public virtual bool PodeSerPago() {
...
}
}
public class PagamentoBoleto : Pagamento {
public override bool PodeSerPago() {
if(vencimento.Day != IsWeekend())
return true;
}
}
[HttpGet("cursos")]
public IActionResult Index([FromServices] IContentRepository repository)
{
ViewBag.Courses = repository.GetContents(EContentType.Course);
return View();
}
[HttpGet("cursos")]
public async Task<IActionResult> Index([FromServices] IContentRepository repository)
{
ViewBag.Courses = await repository.GetContentsAsync(EContentType.Course);
return View();
}
public async Task<IEnumerable<Model>> GetAsync()
{
var model = new Model();
model.Courses = await _context.Courses.ToListAsync();
model.Tags = _context.Courses.ToList(); // Não async
return model;
}
public async Task<IEnumerable<Model>> GetAsync()
public void ConfiguraUsoMySql()
{
// ainda não sabemos se vamos ou não suportar MySQL também
throw new NotImplementedException();
}
public class Order()
{
public Discount Discount { get; set; }
}
public class Discount()
{
public decimal Amount { get; set; }
public void Apply() { ... }
}
public class OrderHandler()
{
var order = new Order();
order.Discount.Apply(); // <-
}
public class Order()
{
public Discount Discount { get; set; }
public void Place()
{
Discount?.Apply();
}
}
public class OrderHandler()
{
var order = new Order();
order.Place();
}
// Codificando em inglês
public class CustomerRepository { ... }
// Agora mudou para "portuglês"
public class ProdutoRepository { ... }
// Agora é português
public class RepositorioUnidadeMedida { ... }
// Utilizou sufixo ASYNC no método assíncrono
public async Task<Product> GetAsync() { ... }
// Agora não usou mais =/
public async Task<Course> Get() { ... }
// Total do que?
decimal total = 0;
// Total do carrinho de compras
decimal shoppingCartTotal = 0;
public class Customer
{
public string Email { get; set; }
public Customer
{
// Valida E-mail
}
}
public class Employee
{
public string Email { get; set; }
public Customer
{
// Valida E-mail novamente
}
}
// Value Object
public class Email
{
public string Address { get; set; }
public Email
{
// Valida E-mail
}
}
public class Customer
{
public Email Email { get; set; }
}
public class Employee
{
public Email Email { get; set; }
}
public class Student
{
public bool IsSubscriber { get; set; }
public void Xpto()
{
if(IsSubscriber)
... // Só executa se for assinante
}
}
public class Student
{
...
}
public class Subscriber : Student
{
public void Xpto()
{
...
}
}
// Evite
if(!IsSubscriber) { ... }
// Utilize
if(IsSubscriber) { ... }
// Evite
var x = 256;
// Duração do que? Qual a métrica?
int duration = 25;
// Muito mais expressivo
int durationInMinutes = 25;
// Evite
var salario = 7500M;
// Tem um significado maior
var salarioEmReais = 7500M;
// Evite
var strTexto = "Meu texto aqui";
// Evite
public void GenerateBoletoInLote() {}
// Evite
public void Cadastry() {}
// Evite
if(environment == "PROD")
...
// Utilize
const string ENV = "PROD";
if(environment == ENV)
...
// Evite
public class clsCustomer { ... }
// Evite
string strNome = "André";
// Evite
var situação - "Pendente";
// Evite
public void RealizarPedido()
{
// Cadastra o cliente
// Aplica o desconto
// Atualiza o estoque
// Salva o pedido
}
// Utilize
public void SaveCustomer() { ... }
public void ApplyDiscount() { ... }
public void UpdateInventoy() { ... }
public void PlaceOrder() { ... }
// Evite
// Calcular o que?
public void Calcular() { ... }
// Utilize
// Calcula o ICMS
public void CalcularICMS() { ... }
// Evite
public void SaveCustomer(string street, string number, string neighborhood, string city, string state, string country, string zipCode) { ... }
// Melhorando
public void SaveCustomer(Address address) { ... }
// Evite
public class Order
{
public decimal Total { get; set; }
}
var order = new Order();
// Qualquer um fora da classe Order
// pode atualizar seu total
order.Total = 250;
// Utilize
public class Order
{
public decimal Total { get; private set; }
public void CalculateTotal() { ... }
}
var order = new Order();
// Total é privado, ninguém de fora consegue
// modificá-lo, evitando efeitos colaterais
order.Total = 250; // ERRO
// Evite
public class CustomerRepository
{
public void CreateOrUpdate(Customer customer, bool create)
{
if(create)
...
else
...
}
}
// Utilize
public class CustomerRepository
{
public void Create(Customer customer) { ... }
public void Update(Customer customer) { ... }
}
// Evite
// Função principal do sistema
public void Main() { ... }
// Evite
// Comentário // <- Desnecessário
public void Main() { ... }
// Evite
public void MinhaFuncao()
{
// string texto = "1234";
// public void Metodo() {... }
}
// Utilize
// Retorna a lista de produtos inativos
// para o relatório de fechamento mensal
public IList<Product> ObtemProdutosInativos()
{
...
}
// Utilize
public void CancelarPedido()
{
// Caso o pedido já tenha sido enviado
// ele não pode mais ser cancelado.
if(DataEnvio > DateTime.Now)
{
AddNotification("O pedido já foi enviado e não pode ser cancelado");
}
}
// Utilize
/// <summary>
/// ATENÇÃO: Este método cancela o pedido e estorna o pagamento
/// </summary>
public void CancelarPedido()
{
...
}
// Evite
var total = 0;
public void CreateCustomer() { ... }
public void CreateOrder() { ... }
public void UpdateCustomer() { ... }
public void CalculateTotal()
{
total = 250; // <- Só é utilizada aqui
}
// Utilize
public void CreateCustomer() { ... }
public void CreateOrder() { ... }
public void UpdateCustomer() { ... }
var total = 0;
public void CalculateTotal()
{
total = 250;
}
// Evite
public void CreateCustomer() { ... }
public void CheckInventory() { ... }
public void CreateOrder() { ... }
public void UpdateCustomer() { ... }
public void CalculateTotal() { .. }
// Utilize
public void CreateCustomer() { ... }
public void UpdateCustomer() { ... }
public void CheckInventory() { ... }
public void CreateOrder() { ... }
public void CalculateTotal() { .. }
// Utilize
public void CreateCustomer(string name) { ... }
public void CreateCustomer(string name, int age) { ... }
public void CreateCustomer(string name, int age, Address address) { ... }
public void CreateCustomer(string name, int age, Address address, bool active) { ... }
// Utilize
public void CreateCustomer(string name)
{
var customer = new Customer(name);
_repository.Customers.Add(customer);
_repository.SaveChanges();
}
// Evite
private Long requestParsingTimeLimit;
protected Request request;
private FitNesseContent context;
this.context = context;
input = s.getInputStream()
requestParsingTimeLimit = 900;
// Utilize
private void meuMetodo(String parametro) {
variavel++;
int outraVariavel = algumArray.length();
total += algumMetodo();
outraClasse.algumMetodo(variavel, total);
outroMetodo(total);
}
// Evite
public class MinhaClasse{
var valor=12;
Console.WriteLine(valor);
}
SET
privados, mas não é uma regra do meu código e não aplico em todas as propriedades. Como consequência, sempre precisamos de mais métodos para manipulação destes valores.public class NotificationContext
{
private List<string> _notifications;
public void Add(string notification)
{
_notifications.Add(notification);
}
public bool IsValid() => _notifications.Any();
public IEnumerable Notifications { get => _notifications.AsEnumerable(); }
}
class
ou um struct
. Normalmente associamos as struct
mais a estrutura de dados do que as classes, mas podemos estruturar dados com qualquer uma delas.class
(OOP) temos recursos como abstração, herança, polimorfismo, dentre outros.// Usando estruturas
public struct Email
{
public Email(string address)
{
// Permite apenas E-mails hotmail, gmail, yahoo...
}
public string Address { get; private set; }
}
public class Customer
{
public Email Email { get; private set; }
}
// Usando classes
public class Email
{
public Email(string address)
{
// Permite qualquer tipo de E-mail
}
public string Address { get; private set; }
}
public class CommonEmail : Email
{
public Email(string address)
: base(address)
{
// Permite apenas E-mails hotmail, gmail, yahoo...
}
}
public class Customer
{
public Email Email { get; private set; }
}
Nos dois casos temos estruturas representando um E-mail como objeto de valor, porém no segundo cenário, podemos criar extensões e ter uma maior flexibilidade.
object
e parte com struct
eu confesso que a maior parte dos meus casos eu uso apenas o object
. Pode ser vício ou puro comodismo, mas acho estranho esta mistura.// Objeto de valor, representa um endereço, sua estrutura de dados
public class Address
{
public string ZipCode { get; set; }
public string Street { get; set; }
public string Number { get; set; }
public string Neighborhood { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
// Objeto do cliente... com seus comportamentos
public class Customer
{
public Address BillingAddress { get; private set; }
public Address ShippingAddress { get; private set; }
public void ChangeBillingAddress(Address address) { ... }
public void ChangeShippingAddress(Address address) { ... }
}
public class ShoppingCart
{
public decimal Total { get; private set; }
public decimal CalculateTotal()
{
var total = 0; // Desnecessário
foreach(var item in Items)
total += item.Price;
}
}
// Melhorando
public class ShoppingCart
{
public decimal Total { get; private set; }
private decimal CalculateTotal()
{
foreach(var item in Items)
Total += item.Price;
}
}
// N/A
// Evite
public class Order
{
public void Pay(CreditCard card)
{
if(card == null)
// Pagamento via boleto
// Pagamento via cartão
}
}
// Utilize
public class Order
{
public void Pay()
{
// Pagamento via boleto
}
public void Pay(CreditCard card)
{
// Pagamento via cartão de crédito
}
}
// Evite
public static class NotificationContext
{
public static IList<Notification> Notifications { get; set;}
}
// Utilize
public class NotificationContext
{
public IList<Notification> Notifications { get; set;}
}
assert
por teste. Mais de um assert pode confundir você e comprometer a escrita do seu teste.// Evite
[TestMethod]
public void ShouldReturnTrue
{
Assert.AreEqual(true);
Assert.AreEqual(1);
}
// Utilize
[TestMethod]
public void ShouldReturnTrue
{
Assert.AreEqual(true);
}
// N/A
// N/A
[TestMethod]
[DataRow("[email protected]", "[email protected]")]
public void ShouldValidateEmail(string email)
{
Assert.IsTrue(new Email(email).IsValid());
}
29