Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Why not invent low-code DSL in the name of DRY

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "Why not invent low-code DSL in the name of DRY". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "Why not invent low-code DSL in the name of DRY".

DRY means Dont' Repeat Yourself, which means to eliminate duplication when you see duplicate code. For example, we found that the four operations have common parameters with each other. We only need to define it once to get four interfaces and complete front and back end behavior.

From django.db import models class Author (models.Model): name = models.CharField (max_length=100) title = models.CharField (max_length=3) birth_date = models.DateField (blank=True, null=True) from django.contrib import admin class AuthorAdmin (admin.ModelAdmin): exclude = ('birth_date',)

Such things are sometimes called low code and sometimes called DSL. Students who have used django know that the above code is Django Admin. The characteristic of these tools is that they can complete 80% of the functions in 1% of the time, and they all call it the future when they first use it. However, Neal Ford found that "# last10%rule", that is, the last 10% will pay a very high price, and users always need 100% functionality.

Why is that? Is it true that copying and pasting code without a brain and writing 1000 lines in a file is the characteristic of a good programmer? Is it wrong that we have ideals and pursuits?

There is nothing wrong with the ideal, but in the wrong way.

Don't get me wrong, I'm not on the opposite side of you. I am definitely a hardcore grammar sugar maker. Only sometimes, people need to jump out of their original thinking habits in order to realize the cognitive blind spot.

Misunderstanding 1: the abstraction of wishful thinking

I have already said in "if the code is not well written, don't always think that you are not abstract well." Most of the time, the product manager has the final say on business logic and the appearance of the interface. To put it inappropriately, you programmers are just pens in the hands of product managers. Although this is unacceptable, it is indeed the real daily life of most people.

When we see that the two places are similar. Don't extract common code with wishful thinking and eliminate duplication. First of all, you have to reach an agreement with the product manager, which should be consistent in business. When a product has a group of product managers, or they often don't pull together ideas, the same list filtering function may come up with a variety of practices. At this time, you need to use roles such as UI designers to pull together horizontally.

In short, we must first hold down the source of demand. Instead of using reusable abstract code downstream of the requirements. This is why "domain-driven development" requires customers, product managers, and programmers to communicate more and form more consensus.

Myth 2: you can't find your own code on the call stack

Many people will attribute CRUD code generation such as Django Admin to the fact that the code is generated. But the problem is not that the code is generated, but that we can't find our own code on the call stack: when we see that an exception is thrown and look for it line by line in stack trace, we can't find the code we wrote. Why is there such a phenomenon?

Suppose we wrote three methods at first.

Import {f1_impl, f2_impl, f3_impl} from 'some-lib'; function F1 () {f1_impl (arg1, arg2);} function f2 () {f2_impl (arg1, arg3);} function f3 () {f3_impl (arg1, arg4);}

We can see that the user is required to write three methods, f1/f2/f3, which is the amount of code. And the parameter arg1 has to be repeated everywhere. So we should use the name of DRY to simplify the code to

Import {f1_impl, f2_impl, f3_impl} from 'some-lib'; const theModel = {arg1, arg2, arg3, arg4} function F1 () {f1_impl (theModel.arg1, theModel.arg2);} function f2 () {f2_impl (theModel.arg1, theModel.arg3);} function f3 () {f3_impl (theModel.arg1, theModel.arg4);}

Here we extract a common global theModel to define all the parameters. Then the behavior of F1, f2, f3 is all model-driven. So it seems that users don't need to write any f1/f2/f3, they just write this:

Export const theModel = {arg1, arg2, arg3, arg4}

This is not only a small amount of code, but also "decoupled" from the specific implementation. If the technology is to be upgraded in the future, you only need to upgrade the framework, and the business logic does not need to be moved. What is the disadvantage of this kind of "making users unable to find their own code on the call stack"?

It is easy not to find a configuration item, a parameter, the location of the impact. It could be anywhere in the framework code. There is no symbolic dependency that can be tracked at compile time between where the code is written and where the behavior is actually generated. Of course, this is the problem with all mutable data, all the places written, do not know where to read, what impact it will have on the place of reading. Programmers do these things every day, and of course they are good at dealing with such problems. But that doesn't mean there's no cost. The more indirectness there is, the harder the code will be to read.

The second problem here is that theModel contains a set of parameters for F1, f2, and f3. When all the parameters are flattened and mixed together, although repetitive parameters such as arg1 can be eliminated, which parameter is used by whom is more blurred. such as

Class ArticleAdmin (admin.ModelAdmin): prepopulated_fields = {"slug": ("title",)}

When we read the above definition, prepopulated_fields affects which fields in which interface to add, delete, modify and check, and how does it affect it?

Some students may say that there are dozens of component parameters of Antd. But when we see the calling code for such a React component,

Return

We can click into the code of EditorForm to see the implementation of EditorForm. You can find out where the passed-in parameter prepopulatedFields is used. But when you write code as a declaration like Django Admin, you can't easily find out where to read prepopulated_fields. The most likely is the code that starts working on a global text search framework.

DSL authors don't think this is a problem. They added each parameter themselves, and within three months after DSL was invented, they did not need to look up the document (if any). But their colleagues are not so lucky.

Myth 3: modify the default behavior of language in unexpected places

Especially the two operations of assignment and value. For example, the following code

Function doSomething (a) {a.b = 'hello'; console.log (a.b);}

What is the output on console? It should be hello. Is it right?

So, what if the incoming an is like this?

Function doSomething (a) {a.b = 'hello'; console.log (a.b);} const a = {}; Object.defineProperty (a,' baked, {value: 'world'}); doSomething (a)

At this point, the output on console is world instead of hello.

C++ copy constructor, implicit conversion constructor. It's a similar problem. Secretly stuffed the behavior into the grammar of assignment.

That is, the framework code, the implementation of DSL, they can use magic to modify the assignment operation and the value operation. It's hard for most programmers to realize that extraordinary things can happen to an ordinary line of code. This will lead to a problem, the real problem is skipped, because that place may be just an one-line value operation, or an one-line assignment operation.

Write good code instead of playing with skills

Reach an agreement with the product manager or customer before reuse.

Don't try to save so much code. When there should be an interface, define an interface. When there should be a back-end API, define an API. Even with one line of code. Let the user go to call library, instead of defining a framework, ask the user to give a bunch of config.

Do not modify the behavior of assignments and values, do not create surprises.

Don't do anything in the name of DRY. The result may be DRY from other motives. But don't do anything with DRY as a starting point.

I would like to take this article as a warning to criticize some of the mistakes I made in the past.

Thank you for reading, the above is the content of "Why not invent low-code DSL in the name of DRY". After the study of this article, I believe you have a deeper understanding of why you should not invent low-code DSL in the name of DRY, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report