TysonMN / tysonmn.github.io

Blog of Tyson Williams about software engineering and functional programming
https://tysonwilliams.coding.blog/
MIT License
3 stars 7 forks source link

2020-07-17_naming_optimization_problem #8

Closed utterances-bot closed 4 years ago

utterances-bot commented 4 years ago

Naming Optimization Problem

https://tysonwilliams.coding.blog/2020-07-17_naming_optimization_problem

dharmaturtle commented 4 years ago

Depending on the language/tool you're in, there are other properties that may communicate what a thing is or does. For example, in C# in Visual Studio, it's a bit excessive to call a method GetUserById(int userId). The tooling and context should communicate that clearly enough, and the name could be shortened to GetUser(int userId) or perhaps even Get(int userId) if it's on some kind of UserController or UserRepository. Similarly, there's no real need to name a database column UserStreetAddress if it's on the User table.

It is sometimes necessary to model a single concept with multiple different classes as it travels through your application. For example, you may have a database entity, a business model, and a view model, all for the single concept of "User". It is reasonable to create UserEntity, UserModel, and UserViewModel classes. You may also elect to create 3 User classes and differentiate them via namespace. However, since domain logic should be the driving force behind the implementation details that are the database and view, I believe that the domain should be privileged with the User class - no Model - and the other classes in the other application layers should retain their descriptive adjectives of Entity and ViewModel. But YMMV.

TysonMN commented 4 years ago

...in C# in Visual Studio, it's a bit excessive to call a method GetUserById(int userId). The tooling and context should communicate that clearly enough, and the name could be shortened to GetUser(int userId) or perhaps even Get(int userId) if it's on some kind of UserController or UserRepository.

Yes, I typically favor this naming convention. Sometimes there is another method like GetUser(string userName). Such methods are in the same method group, which means this method is overloaded.

The idiomatic way to code this in F# is to use functions, which cannot be overloaded. Attempting to overload F# functions results in shadowing. I find it interesting to contrast this difference between C# and F#. On the one hand, method overloading is one approach to expressing alternative ways to achieve the same result. As an example, @cmeeren decided on this approach for the binding API in Elmish.WPF, which is written in F#. On the other hand, a unique name for each function makes things very clear, and the absence of function overloading probably makes F#'s type inference easier to implement (perhaps even possible).

It is sometimes necessary to model a single concept with multiple different classes as it travels through your application. For example, you may have a database entity, a business model, and a view model, all for the single concept of "User". It is reasonable to create UserEntity, UserModel, and UserViewModel classes. You may also elect to create 3 User classes and differentiate them via namespace. However, since domain logic should be the driving force behind the implementation details that are the database and view, I believe that the domain should be privileged with the User class - no Model - and the other classes in the other application layers should retain their descriptive adjectives of Entity and ViewModel.

Oh, yes. I am glad that you reminded me of this. I was recently refactoring some F# code from

to

as Scott Wlaschin discusses here. Where Scott called the type T, I was calling it Model, just like all the samples in Elmish.WPF. When I moved the types out of the module containing the functions, I kept Model in the name but prefixed it with the name of the module that it just left. Now that you made me conscious of this, I will go back and remove the Model suffix from these type names.

As a side note, I am refactoring from the organization that Scott says is more idiomatic of functional languages to one that is "more .NET like". One difference between Scott's code and mine is that I am still using a top-level module (instead of a top-level namespace). I wonder if he would be favor of my organization.

TysonMN commented 4 years ago

I just happened to watch a talk that is partly about naming and its importance in communication. The whole talk is about 70 minutes, but the part about naming starts here and lasts 10 minutes. Here are some particularly relevant quotes. In the words of my post, I think it is fair to define "label" as he uses it as "a name that communicates a minimal amount of information."