I removed the prefixes from my code – and immediately saw a bunch of problems that were hidden by bad naming

I recently came to a startup as the only developer. The dudes splash with ideas and demands, and have little idea how difficult it is to build all this. There was so much work there that I went crazy – I had to knock out a budget for a small team. I quickly hunted a trio of tough coders and became a team lead for them.

The team will perform well, you have to look at the code very often. But the tasks that I personally have to code have not been canceled either, so there is no question of any detailed analysis of the code for review. I don’t have the budget to think well over each line, and I don’t have each of my comments either – I do such things automatically.

I take a quick look at the code for bright anti-patterns, obvious game, or security holes – and if none of this is there – leave a dozen on duty comments on readability, naming, and code structure.

Yesterday the teammate sent the following code to the review

const isAdmin = IdentityService.CurrentUserHasRole(Roles.Admin);

The eye immediately caught the prefix – bro, do not use is for naming booleans. In the same place in the github, the guy replied – now I will remove it, this is shit from previous developers. But I was just this previous developer – I made a mistake long ago and forgot.

I laughed, took a screenshot and uploaded it to Twitter.

A crowd of people rushed at me in an instant. Instead of laughing at the situation, they started explaining to me that it was a great idea to name bools with the is prefix. I did not argue – I began to threaten with an article. That’s her.

In fact, the is prefix is ​​rarely needed.

In most cases, we add is to convey – the value is binary, shows “Yes / No”. But when we talk about statically typed languages ​​(I don’t want to talk about others, they will not be saved by any readability) – we already have a thing that tells us that the variable is binary. This is her type. For example, some UI element, and it has a field – enabled.

UsersPanel.enabled = true;
// или
UsersPanel.isEnabled = true;

I write code in the IDE, and it shows me the type of this field – I perfectly understand the semantics and meaning of working with it, without any is.

On the other hand, well, okay, even if is is redundant, but after all, no one will die from the fact that we add it? Just two characters. This is a very dangerous thinking. Our goal is to write as succinctly as possible, but never to the detriment of readability. If you follow this simple rule, you will write very good code. There is little to do – learning to separate what is detrimental to readability and what is not.

If you decide that a boolean without a prefix is ​​detrimental to readability, but in fact it is not – believe me, your mistake will be repeated more than once, and on much more important cases.

I thought for a long time, and found only one powerful argument for the is prefix for object fields – the code will be more readable outside the IDE. But if you decide to write your code in such a way that it is as convenient as possible for working without an IDE, you will have to write a lot more characters than I and s. The sisharpa, for example, has enough illustrations of this approach.

There we figure the I prefix for interfaces, the Exception postfix for exceptions, “_” for private fields, the Event postfix for events … All these things the IDE is able to distinguish and show us in different colors itself.

We know this, but we deliberately ignore it – because we want to understand the code without an IDE, for example, from the page from the github. This is certainly a big plus, but not as big as it seems.

In fact, any more or less serious code cannot be understood without information from the compiler, and it will only get worse – after all, the C # team has been stepping towards type inference for a long time. The code that we used to shove into the source now does not have to be written – the compiler “adds” it for me.

And the shift of approaches in the same C # towards greater brevity, as it were, tells me – bro, sooner or later you won’t understand anything at all from the listing from the github. Half of what you have in sorts now, the IDE will output and show you out of context. And then what’s the point of clinging to little things like the I prefix on the interface? For a person to enter my complex code, understand five percent of it, but know exactly where are the interfaces and where are the classes (what difference does it make to him)?

But in Dotnet it is customary to call interfaces with the I. IApi prefix. This thing is not even discussed. It came from the days when IDEs didn’t know how fucking it, and the developers wanted to quickly understand what was in front of them – an interface, a class. structure, pointer … My today’s IDE can color, underline and overexpose any character of any programming language exactly the way I want it. Ryder, on my orders, writes interfaces in italics. Why do I need a prefix? Because it is so accepted, but it is accepted so, because it is accepted – and do not be smart.

But I’ve grown eggs big enough to do things differently when I strongly disagree. When they tell me that nothing will be clear in a stupid github, my point is simple: well, fuck it. Development is not carried out in github, its results are displayed there. If you want to understand where what is – clone the turnip, open the IDE and see.
For me personally, the key argument is one – why are you guys, then don’t write prefixes for everything at all?

public class CApi {  // C - класс
  private int _some;  // _ - field
  public IMyType PSome { get; }  // P - property

  public void MDoStuff(){..} // M - method
  public event EventHandler MyEvent; // event, event, event
}

Shut up now? The listing of the code will make everything clear. Go for it.

There is no reason why I should prefix interfaces and fields (only these two characters will prefix in the dotnet). So I choose consistency, and I don’t prefix at all.

And this conversation is not about the beauty of the code at all. If you forget about high-quality naming, there will be serious and disguised problems in the code base

For example, the same interfaces in sisharp. I am making the IEmailManager interface and the only implementation is EmailManager. If it were not for the letter I – I would be struck by the idiocy with the same names – I would have to write:

internal class EmailManager : EmailManager

Compile would slap my hands, and so I would write crap like this:

internal class EmailManager : Interface.EmailManager

And on the way I would have broken my head on the naming of the folder where the interfaces will be. I saw how people in real Java projects called the Interface and Implementation folders. There are a couple of steps from such naming to creating directories like ‘/ Logic’ or, hehe, ‘/ Code’.

But they threw it at me – look, what a funny fool, digs into the names of folders.

This is one of the rare times when in fact I’m not such a fool. Names are part of architecture and design. They control not only how the code looks – but also how it will work.

One bad directory name can – and will certainly – give rise to bad architecture. Because the developers on the project will not think every time where to correctly embed the module, at what level and application layer it will lie. They will see a folder called ‘/ Code’, think like this – well, in my class the code, everything converges – and put it there. And we will get a code base in which logically unrelated things will be nailed to each other.


When you think carefully about naming, you notice deeper things. For example, that the tradition of prefix-postfix hides from you the possibility of how to improve everything.

When you have an interface and its only possible successor – and they can get different names only if you play with pre-postfixes like “I, Impl” – you do something wrong. We all know why we have interfaces with a single possible heir. Because we want to test, and to test, we need to make mocks. And to make mocks, you need to inject interfaces.

We could create testing systems for ourselves that would not need interfaces – for example, as done in typescript and jest. And we could also not write well-testable code in projects where our cat cried even the tests. But we chose to create a bunch of entities, which in fact do not give any profit to the project – they are needed only for testing. Well, so that the fictional Fowler from our heads does not call us incompetent fools.

And as a result, in a large project, I can have literally a thousand files with interfaces that are essentially unnecessary – they duplicate the code of their only heirs. Thousands of files to maintain. To write a document there, bring it in line with the changes in the heirs, apply new code conventions to them – in short, they still cost us a lot.

Every time I create an interface with a single heir, I feel a little prick – I do some shit. In one of my projects, I abandoned interface prefixes, and got a completely different code design – because I could no longer cope with the groaning, long-lasting pain of the wrongness of what was happening when I had Api Extendil Api.


And then they come to me and say – in fact, you are stupid Phil, all this complexity of making decisions on semantics can be sewn into one regular season for a linter. Such things should not be checked by a person.

Not a damn thing like that. Well, if you write a regular season that dipricate is in booleans, you will still have hundreds of cases where it is most appropriate. For example, in the same local variables – because the record of the form

const admin = IdentityService.CurrentUserHasRole(Roles.Admin);

confusing even though I have type information. A good naming would be something like this:

const currentUserIsAdmin = IdentityService.CurrentUserHasRole(Roles.Admin);
// или 
const currentUserHasAdminRole = IdentityService.CurrentUserHasRole(Roles.Admin);

What do we have here? “Is / has” anti-patterns for bools.

Only here they are really needed here. And in order to understand this, you have to be not a cunning regular expression, but an experienced developer who once again thought carefully.

I got drunk years ago and screwed up very badly. Proved to be a disgusting piece of shit, with a large number of loved ones. I screwed up so badly that even now, when I remember that incident, I start to choke with shame. To suppress this state, I begin to remember the same case with other people, especially with famous and respected. It becomes an order of magnitude easier for me – this is a working scheme, a powerful mechanism for combating shame.

So it is with the code – I made a strange decision, but came into the industry – and saw the same thing in everyone. People have even written big and clever books about how it’s okay to do this. And it lets go.

The shame that you got drunk as a teenager and called a prostitute into a house full of parents and relatives is much stronger than when the full name of your class looks like this:

cs
App.Exception.BusinessLayerException.BusinessLayerException : BusinessLayerExceptionBase

But there is a big difference. I stopped drinking and messing around – but to stop writing ugly code, you need to convince everyone else to do the same.


Advertising

Development servers – this is epic from Vdsina.
We use extremely fast NVMe drives from Intel and do not save on hardware – only branded equipment and the most modern solutions on the market!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *