📜 ⬆️ ⬇️

Bicycle liquidator: reusable code

Hello! Remember, once upon a time there was a good series of articles? So I want to continue it. However, this time I will not consider a huge number of libraries that solve ubiquitous problems, and consider only one, but able to solve a huge pile of problems. It seems to me that each of you once wrote lines of the form:

void SomeMethod(IEmployee lazyguy) { if(lazyguy == null) throw new ArgumentException(“lazyguy”); // Do something with lazy guy. Fire him, for example. } 


Someone tried to turn it into:
')
 void SomeMethod(IEmployee lazyguy) { UniversalValidator.CheckNotNull(lazyguy); // Meet with him and talk about motivations } 


Someone turned it into something similar. However, at all, I can argue, there was a deposit that something was wrong here. More beautiful would be somehow different. What is the result? A huge number of bicycles with square wheels! How to do differently?

So in a different way, when the soul is happy and the code is clean, this is when you write like this:
 void SomeMethod([NotNull] IEmployee lazyguy) { // Promote him to be head of department } 

Agree, nice! You can argue to me, saying that attributes are like tags to an article: until no one reads them, magic will not work. And you will be right. That program that I want to talk about - PostSharp , allows you to do such things. You write an attribute that will be attached to the parameters of the method and which will insert a null check into the program code. If null, then generate exception. From now on, you do not need to litter each method with garbage. Now you just need to mark the required methods with the necessary attributes:

 public class LazyEmployee : IEmployee { string Name { get; } string LastName { get; } [GreaterThan(VeryCleverGuySalary)] int Salary { get; set; } [Only(true)] bool NeedsPersonalSecretary { get; set; } [TypeOf(typeof(IRoomWithSaunaAndPersonalPlayStation))] IRoom Room { get; set; } } 


Now let's talk about another problem that has been discussed many times already, but people persistently make their loggers, their tracers, and other joys of cycling (by the way, do you know that they recently made a bike with an “ automatic ”?). Well that did things like log4net, for example. However, this does not always work as quickly as you want. With our program, logging implementation will work as fast as possible, and logging itself will work at the speed of the samopisny code:
 public class PerisherEmployee : IEmployee { [NotNull, StartingWithUpperCase] string Name { get; } [NotNull, StartingWithUpperCase] string Lastname { get; } [Tracing, WriteToDatabaseEachTransaction, CheckHistory] int Salary{ get; set; } [AbuseEachWhoTriesToBuySomething, Trace] int FreeMoney { get; set; } } 


In this example, a miser wants every action with his money to be recorded in the database, while checking the history of operations and cursing everyone who tries to buy something with this money. An example, of course, invented, and these attributes (except for tracing) are unlikely to be needed, but they clearly show the possibilities of what is happening. Here you are working with the base and tracing and checking values ​​on ranges. You can argue: here I will fence an incomprehensible cloud of attributes, clutter up space! However, I'll try to pair: does this code look simpler?

 public class PerisherEmployee : IEmployee { string _name, _lastname; int _salary, _freemoney; string Name { set { if(value == null) throw new ArgumentNullException("value"); if(!IsStartsFromUpperCase(value)) throw new ArgumentOutOfRangeException("value"); _name = value; } get { return _name; } } string Lastname { set { if(value == null) throw new ArgumentNullException("value"); if(!IsStartsFromUpperCase(value)) throw new ArgumentOutOfRangeException("value"); _surname = value; } get { return _surname; } } [Tracing, WriteToDatabaseEachTransaction, CheckHistory] int Salary { get { return _salary; } set { Console.WriteLine("value: {0}", value); DatabaseEngine.SaveSalary(value); _salary = value; if(!CheckHistory(this)) throw new WrongOperationException(); } } int FreeMoney { get { return _freememory; } set { if(value < _freememory) throw new OutOfRangeException(); Console.WriteLine("value: {0}", value); } } } 

Not at all, but you decide :) There is also a large number of options when it works great! When it works on 10 points out of 5. For example, tracing messages on ASP.NET to the developer console while the website is already working ... You can see the history of the stack trace at any time during the operation of the web page. How? Just write the aspect that will save the stack somewhere and lay it on the assembly. Or some strange things at first glance. I will talk about them a bit later ... For now, I’ll just give a number of links to articles in which I already talked about the features implemented by this program:

Source: https://habr.com/ru/post/127575/


All Articles