Why I do think respecting closely the template is really important

,

Traduction en français plus bas.

While YunoHost is not only about its apps, apps in YunoHost are still a very important part as it allows users to extend the possibilities of their server and to have the services they really need.

Because of that, apps packages in YunoHost should be resilient over time. When an user install an app, the app should not become obsolete after a few months/years just because the package does not get upgraded.
Yet, at the time I’m writing these lines, 112 apps out of 306 are not maintained anymore ! This is huge !!!

That situation shows also clearly that even when you write a new package, and you know that you will maintain it, for more than one app out or three, sooner or later, you’re going to not maintain it anymore. Meanwhile, many users may have installed your app and will end up with an app not maintain and possibly broken.
But to not maintain an app anymore shouldn’t be a problem, as long as another packager can continue your work and give to the users new upgrades.
No one here is, or should be, bond to life to his work.

From experience, we know that apps that are especially famous among our users, aside of often being the most difficult to maintain, are also the apps that change often of maintainers.
But actually, for any apps, we do expect to have different maintainers, while I’m running a test on dokuwiki, a quick look to its contributors list shows at least 4 “maintainers” over its history.

That prove mainly one very important thing, when you write a package for an app. One way or the other, you’re not going to be the only one working on this app.
A lot of other packagers will be involved in your package.
Considering this, when working on a package, for the sake of our final users, we should never forget that we’re not alone and that we have to consider it as a shared work.

To work as a team, and not as a lone dev implies to share some common rules, some restrictions to go together in the same way.
Finally to follow rules is not a constraint, it’s a form of respect for the others packagers that will get involved and for the users that will still have their favorite apps long after it was added to YunoHost.

While we’re working on the migration to Buster, confined in our houses, many packagers, new comers or not, are working on packages they didn’t write in the first place.
And because most of our packages do respect the template and the common rules, those packagers can work on this packages, fix issues or upgrade what need to be without having to spend time figuring out how the packagers before them did write the code. Without having to untangle the code to understand how it works.
They can just follow the template, and focus and what really matters, what are the specific needs of the app and what needs to be done.

For all those previous reasons, an app package, in my opinion, should be as simple and clear as possible.
To be as simple as possible is also, to be straight, easy to read, and as obvious as possible for everyone who read any of the scripts.
In the same idea, when a packager read a script of your app, to fix the app, to help an user in trouble, or just to find how you did solve a situation he has as well in its own package. This packager should be able to read your script easily and unambiguously, without stumbling on a laconic call to some personal function that hides an important part of the process or a helper like ynh_render_template or ynh_restore that does not say what it’s actually doing. Any app script should be clear and without any ambiguity on what’s its doing and when, that way, any packager reading it will know what’s done, how and when.

That’s the reason why we’ve defined the template in the example app, to have a template as clear and easy as possible. And especially to have a standard template for everyone.

Now that’s for sure, the template is not perfect, the template won’t satisfy everyone, the template may not correspond to your habits. But the first purpose of this template is not to be perfect or to please you, the first purpose of the template is to be universal among app packages.

To respect the template is, on one hand, to respect the syntax, the flow, and the spirit of the example app. And in the other hand to keep it as straightforward as possible for everyone who will read it.
Globally, as soon as you move the logic of the code, conditions, loops or anything else away of the main scripts, you obfuscate the understanding of the code for other packagers.

While all of that is said, I know, for I’m myself a developer, that to use a code without factorization, is far from what we’re use to do. Far from what is usually considered as a good practice. And can be source of errors if we forgot to modify every occurrences in the code.
But, app packages are not like any usual piece of code, app packages are common scripts, shared by all apps, that should be considered as part of a bigger code, the whole app packaging template.
That’s what will make apps resilient for our users.

If our apps are to become ephemeral, I think we would lose one of the main objective of YunoHost…


(La traduction française n’est pas parfaite, mais respecte plutôt bien l’idée originale).

Bien que YunoHost ne se limite pas à ses applications, les applications dans YunoHost sont une partie très importante car elles permettent aux utilisateurs d’étendre les possibilités de leur serveur et d’avoir les services dont ils ont vraiment besoin.

C’est pourquoi les applications de YunoHost doivent être résilientes dans le temps. Lorsqu’un utilisateur installe une application, celle-ci ne doit pas devenir obsolète après quelques mois/années juste parce que le package n’est pas mis à jour.
Pourtant, au moment où j’écris ces lignes, 112 applications sur 306 ne sont plus maintenues ! C’est énorme !!!

Cette situation montre aussi clairement que même lorsque vous écrivez un nouveau package, et que vous savez que vous allez le maintenir, pour plus d’une application sur trois, tôt ou tard, vous n’allez plus le maintenir. En attendant, de nombreux utilisateurs peuvent avoir installé votre application et se retrouver avec une application non maintenue et peut-être même cassée.
Mais ne plus maintenir une application ne devrait pas être un problème, tant qu’un autre packager peut continuer votre travail et donner aux utilisateurs de nouvelles mises à jour.
Personne ici n’est, ou ne devrait être, lié à vie à son travail.

Par expérience, nous savons que les applications qui sont particulièrement célèbres parmi nos utilisateurs, en plus d’être souvent les plus difficiles à maintenir, sont aussi celles qui changent souvent de mainteneurs.
Mais en fait, pour toute application, nous nous attendons à avoir différents mainteneurs. Alors que je fais un test sur dokuwiki, un coup d’oeil rapide à la liste de ses contributeurs montre au moins 4 “mainteneurs” au cours de son histoire.

Cela prouve principalement une chose très importante, quand vous écrivez un package pour une application. D’une manière ou d’une autre, vous ne serez pas le seul à travailler sur cette application.
Beaucoup d’autres personnes seront impliquées dans votre package.
C’est pourquoi, lorsque nous travaillons sur un package, nous ne devrions jamais oublier, pour le bien de nos utilisateurs finaux, que nous ne sommes pas seuls et que nous devons le considérer comme un travail partagé.

Travailler en équipe, et non comme un développeur isolé, implique de partager certaines règles communes, certaines restrictions pour aller dans la même direction.
Enfin, suivre des règles n’est pas une contrainte, c’est une forme de respect pour les autres packagers qui vont s’impliquer et pour les utilisateurs qui auront toujours leurs applications préférées bien après qu’elles aient été ajoutées à YunoHost.

Alors que nous travaillons sur la migration vers Buster, confinés dans nos logements, de nombreux packagers, nouveaux ou non, travaillent sur des packages qu’ils n’ont pas écrits au départ.
Et parce que la plupart de nos packages respectent le modèle et les règles communes, ces packagers peuvent travailler sur ces packages, corriger les problèmes ou mettre à jour ce qui doit l’être sans avoir à passer du temps à comprendre comment les packagers précédents ont écrit le code. Sans avoir à démêler le code pour comprendre comment il fonctionne.
Ils peuvent simplement suivre le modèle, et se concentrer sur ce qui est vraiment important, sur les besoins spécifiques de l’application et sur ce qui doit être fait.

Pour toutes ces raisons, je pense qu’une application doit être aussi simple et claire que possible.
Être aussi simple que possible, c’est aussi être direct, facile à lire et aussi évident que possible pour tous ceux qui lisent les scripts.
Dans le même ordre d’idée, lorsqu’un packager lit un script de votre application, pour réparer l’application, pour aider un utilisateur en difficulté, ou simplement pour trouver comment vous avez résolu une situation qu’il a également dans son propre package. Ce packager doit être capable de lire votre script facilement et sans ambiguïté, sans tomber sur un appel laconique à une fonction personnelle qui cache une partie importante du processus ou un helper comme ynh_render_template ou ynh_restore qui ne dit pas ce qu’il fait réellement. Tout script d’application doit être clair et sans ambiguïté sur ce qu’il fait et quand, de cette façon, tout packager qui le lit saura ce qui est fait, comment et quand.

C’est la raison pour laquelle nous avons défini le modèle dans l’application d’exemple, pour avoir un modèle aussi clair et facile que possible. Et surtout pour avoir un modèle standard pour tout le monde.

C’est sûr que le modèle n’est pas parfait, qu’il ne satisfera pas tout le monde, qu’il ne correspondra pas à vos habitudes. Mais le but premier de ce modèle n’est pas d’être parfait ou de vous satisfaire, le but premier du modèle est d’être universel parmi les packages d’applications.

Respecter le modèle, c’est, d’une part, respecter la syntaxe, le flux et l’esprit de l’application d’exemple. D’autre part, il doit être aussi simple que possible pour tous ceux qui le liront.
Globalement, dès que vous écarter la logique du code, les conditions, les boucles ou tout autre élément des scripts principaux, vous obscurcissez la compréhension du code pour les autres utilisateurs.

Avec tout cela dit, je sais, car je suis moi-même un développeur, que l’utilisation d’un code sans factorisation est loin d’être ce à quoi nous sommes habitués. Loin de ce que l’on considère généralement comme une bonne pratique. Et peut être source d’erreurs si nous avons oublié de modifier toutes les occurrences du code.
Mais, les packages d’applications ne sont pas comme n’importe quel morceau de code habituel, les packages d’applications sont des scripts communs, partagés par toutes les applications, qui devraient être considérés comme faisant partie d’un plus grand code, le modèle de package d’applications.
C’est ce qui rendra les applications résilientes pour nos utilisateurs.

Si nos applications devaient devenir éphémères, je pense que nous perdrions l’un des principaux objectifs de YunoHost…

8 Likes

I guess your post doesn’t hurt about recalling again the importance of sticking to the common practice to increase maintainabity and decrease bus factor, and that having a clear common practice brought by the example clearly made a difference in the lasts ~2 years. Imho this is not a huge debate as it just has become a clear necessity and nobody will argue against this (but idk).

However, it should be understood that some discussions related to this topic that happened in the past and will happen again are about what the common practices could be or in which direction they should evolve. And when that kind of question arises, the answer can’t be a dogmatic “we won’t change the common practice because that would be against sticking to the current common practice !”. (All while understanding that there’s a time and place for everything, and asking to change the common practice in the middle of a PR is clearly not the right time/place).

But, yeah, in particular :

I don’t understand where this obsession about ynh_render_template comes from. Everytime this topic is brought up, the same argument is made about how this helper is inherently obfuscated / not readable … and how the current helpers have supposedly inherent readability virtues.

But how comes this is the only the only helper that is ?

To give you a recent anecdote : yesterday I was working on the neutrinet app to help make it pass tests on the CI. This app is pretty old now, and maintained by people who are not really close the “official” packaging team, but they do maintain it in their own corner since a few years now. These “barbaric people” do not respect the template. In fact they didn’t even use the ynh_add_nginx_template and instead did some savage manual search&replace using sed and all the other usual stuff about “if path is just /” etc…

Now in my great goodness of willing to bring civilized practice to this package I immediately started replacing the whole thing by ynh_add_nginx_template. And I immediately started thinking at all the questions people could be asking about “but what does this abstract thing do !?”, and “what are the replaced keywords and where does the replace happens ?!” and “does it take care of the case where path is / !?” and all that stuff. And I’m not even talking about the fact that I had to change the names of some other variables for the magic happening in ynh_add_nginx_template to work properly and how the fact that var X is used by helper Y is absolutely not obvious.

Now you may say “well everything is written in the doc, they shall just read and learn!”. But no, it’s not. The doc doesn’t talk about the handling of path_url=/. It doesn’t talk about that #sub_path_only mechanism.

So THIS is obfuscation. There’s no way that for newcomers that stuff is going to be obvious. And even if ynh_add_nginx_template was properly documented, that would not fix other things like :

  • the fact that half of the variables have to named in very precise and inconsistent ways otherwise things won’t work properly (c.f. $path_url but the setting is called path, __DOMAIN__ is replaced by $domain but __PATH__ is replaced by $path_url, same weird stuff for finalpath, and we’re only talking about the nginx conf here)
  • the fact that, accross all helpers, there are inconsistencies in that some helpers, for example, you gotta feed explicitly $app but some other helpers magically use $app as a global-like value.
  • the fact that there’s at least three different ways a keyword in a template can be replaced by a var :
    • either because it’s hard-coded inside the helper code
    • either by doing some external sed or ynh_string_replace before/after calling helpers
    • either by feeding names in a special args of the helper
  • this is just plain madness. There is simply no world in which this makes more sense than using a template engine.

But yes, there’s the common practice and we should just stick to it because “that’s how things work and even if that’s inconsistent having a common practice greatly help maintainability”. Yes. And many things are here because of historical stuff and the cost of changing those is probably not worth it. Yes.

But let’s also cut the bullshit and try to make things clear:

  • pretending that we don’t have abstractions is ludicrous.
  • pretending that ynh_render_template or any “uncommon” helper is “too much abstraction” but that the more commonly used helpers are not is ludicrous.
  • common helpers are “acceptable” abstractions only because we agreed that they are, and because that’s what we are used to work with, they do not have any magic virtues such that their behavior is magically understood by anybody reading the helper name.
  • on the contrary, our current abstractions and other stupid naming issues like path_url vs. path are far from being intuitive / consistent, and we should be aware of it.
  • non-intuitive or inconsistent behaviors have a tendency to legitimately piss people off and to not make things fun for newcomers, especially when abstraction are supposed to reduce complexity, not increase it
  • documentation is not a remedy to non-intuitive / inconsistent behaviors
  • in the end, abstractions are something you learn, and learning actual template engines used by everybody is not more complex than learning yunohost super-specific helpers and historical naming details
  • and therefore, over time, people are naturally going to suggest that we could just change the way we do things so that it does become intuitive / consistent…

Saying that “the template is not perfect” and at the same time refusing debate on the common practice is a double-standard.
Saying “we should keep things clear” and at the same time refusing debate on practical solutions to remove inconsistencies is a double-standard.
Saying “we should refrain from using too much abstractions” and at the same time not realizing that we are implementing our very own super-weird abstractions where we could instead use existing standard tools that hundreds or projects use is a double-standard.

4 Likes

There’s a huge difference between ynh_render_template and any other helper we use.

ynh_add_nginx_config does the same thing in any app. For sure, a new packager would have to learn how the helper works, with all its specificities.
But when a packager knows what ynh_add_nginx_config does, he knows that the behavior will be the same in any other packages.
The same goes for all our helpers.

But ynh_render_template can do virtually everything, but you’ll never know what exactly it does when reading a script. And you can have a look to the helper to understand it, as you would do for nginx.
But the helper does

    mkdir -p "$(dirname $output_path)"
    # Taken from https://stackoverflow.com/a/35009576
    python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
                    jinja2.Template(sys.stdin.read()
                    ).render(os.environ));' < $template_path > $output_path

At the end, you can know or don’t know the syntax of jinja2, you can be in whichever package, you’ll never know what the helper actually does…


But actually, the purpose of this topic is not to try to convince anyone.

The reason is that I feel like the only one to fight for a clear and easy template around apps. II feel alone in this side of all those frays.
And yet, I’m probably not alone but I do myself waste my time trying to figure out how the shit was done, I do struggle with git blame and git history to go through factorize code across multiple files when it would be so easy to keep everything clear at the same place.

And I’m fed up of fighting for a clear template, especially if, at the end, I’m the only one to believe that’s for the best.

So… I was thinking to add this to the doc, so it would be somewhere everyone can read it.
I thought though that before, it would be better to know if I’m the only one thinking we should continue that way.
I don’t mind being the asshole that yells to others. But I have also a lot of other useful things to do.
So, if no one care, I won’t anymore.

But that goes both side, everyone’s free to do his package the way he wants. And I’m free as well to not give a shit anymore about the app packaging.

Yes that’s exactly what’s happening. Everybody is currently screaming “we don’t want to follow common practices !” :roll_eyes:

Because the helper calls the regular Jinja stuff that just renders a template. This is not something that suddenly changes behavior in app X or Y, why would it ? If you’re worried that people will start using non-standard names for their vars or whatever, well that’s up to us to add constrains to what can be replaced or not (just like ynh_add_nginx already does - what changes here is just that jinja is essentially a multiple ynh_replace_string at once).

The fact that the helper does not “say what it does” (sigh) is precisely because it does not re-implement the wheel. When you see “wget” in a script, you don’t think "Gosh this doesn’t say what this does, better to write myself a bash function that does http requests with just cat and sed" ! Not reinventing the wheel means you can do stuff more efficiently and not have to re-learn what everybody is doing, which is paradoxically precisely what you keep advocating for. But yeah using an existing tool, it also means that you gotta read the doc of the tool being used. Spoiler, it boils down to (in the case of Jinja) :

  • '{{ foo }}' is replaced by $foo
  • and (advanced feature!) '{% if foo = "bar" %}hello{% endif %}' is replaced by hello only if foo equals bar …
  • … such complexity…

But apparently there’s something super-duper special about not reusing the wheel in the super-duper special context of Yunohost such that we should absolutely rewrite everything ourselves in a more complex way.

Honestly fuck that shit.

I spent the whole night having a goddamn insomnia because of this stupid discussion, which is far from being the first time this happens since it happens everytime such a design issue arise and we can’t have a goddamn adult and reasonable conversations about it.

This project is already ambitious and complex enough without having to argue and fight against people who veto basic stuff like “not reinventing the goddamn fucking wheel” ?

If this project can’t agree that some elements of the current design are a mess, and that the tendency should be to evolve towards getting rid of the legacy mess, reducing inconsistencies and using standard tools, then fuck the project.

What the hell is hapenning here ??
I’m lacking a lot of context and reading so much texte is hard for me.

@Gofannon In summary, there are different views on how application packaging should evolve. We have been struggling to agree for the last 2 years on this subject. This includes whether or not to use a template engine, but in truth the subject is a bit broader than that. Somehow, there has to be enough freedom to allow packagers and core developers to improve the efficiency of app packaging.

What precisely triggered this discussion is that Maniack chose to implement a 2nd linter that checks apps for compliance with example_ynh. This is a very good initiative because it allows for example to detect apps that do not use the progress helper for example. But Maniack has chosen to put in error the fact of using some helpers (ynh_render_template, and ynh_restore) which are however integrated in YunoHost officially and for the moment are not declared as obsolete. Indeed several contributors still think that the use of a template engine would be a positive evolution.

So the question is how to get out of the conflict and go towards something constructive to find a common ground (or at least a solution).

I think we need contributors write the specifications and explain their vision for the future package format.

1 Like

Good evening,

This discussion makes me uncomfortable.

Nevertheless I just wanted to say that YunoHost is a fabulous project and that it allows me little by little to regain control of my data.

With my eyes as a simple user, I think the important thing at the moment is the switch to Buster.

It would be a shame if 2 of the contributors, among the pillars of this project moreover, were to tear each other apart like that.

You both have qualities and you are appreciated for that.

Besides, I would need your help to help me understand the application packaging, one of which is very important to me and which seems to be, with a little help at my fingertips: ZwiiCMS.

Because I tried to get started with the packaging but the code is not my mother tongue.

In short, I’m counting on you and your respective skills to guide me on my Github (pp-r) that you encouraged me to create for various reasons during these last months and weeks, and thus make me progress.

Such a project is difficult to set up, time-consuming to maintain and requires a lot of self-sacrifice from the members to carry it and make it evolve: we need the skills and strengths of all.

We need you and we appreciate you <3 :heavy_heart_exclamation:

ppr with the DeepL help

2 Likes

Oh my…

I think I need to comment as I’m probably among the ones who (re)started it all. As a very new contributor, i don’t feel like I have the legitimity to really do this, but well…

First of all, @Maniack_Crudelis please know that I agree with like 90% of your first comment. I do think the common template is good on overall, and I do think it’s really important to follow. Actually, that’s exactly why I commented on your PR in the first place: I do care. I actually care a lot about common practices and the maintainability of things. That’s why I commented. If I didn’t care, I’ll be like “well screw this” and would have moved on. I’m all for common practices and rules. If you want, I can help you burn the maintainers that don’t respect it :wink: (just kidding of course)

So I allow myself to comment because I care, and because as a newcomers, I think it’s really important to say what the first experience is like for me. Making new contributors flee is not a good thing either if you want to have your packages maintained ,-)

So thank you @Maniack_Crudelis for having opened such a subject. It’s a difficult thing to do, but as apparently it’s a matter of debate and frustration between you guys, maybe it must be done ?

First, the template is really useful for new package maintainers. When repackaging diaspora, I basically opened a tab for each level 8 ynh app github repo, and read all the install scripts. After like 5-10 min, I already had a good grasp on how things are done, and it’s mainly because of the template (also because I actually knew most of those apps, to have installed them on different context before). So on overall it’s great! I’m not saying we should trash it, quite the contrary.

So now that I have said where I agree, and how much I love ynh, the template, life in general blablabla, let’s happily jump to the part where we disagree:

Globally, as soon as you move the logic of the code, conditions, loops or anything else away of the main scripts, you obfuscate the understanding of the code for other packagers.

Well no. No, really no. It’s not “as soon as”. There’s an acceptable level of complexity, and this level, while not very high for app package I agree is not 0. I want to be able to use a moderate amount of if, loops, control flows and functions. Actually that’s not a want. It’s a need. If we have the need to limit their use, then there’s an (imperfect) metrics for it like the cyclomatic complexity. Or we could even count them. But please let’s not make it 0.

And I agree with @Aleks: if having functions is not good, then let’s force people to copy the content of the helper folder functions.

I don’t understand why control flows prevent other maintainer to take over. The biggest difficulty when taking over a package is not the ynh code, it’s the knowledge about the upstream package. As upstream packages are all different, there will be variations on install scripts.

On a more semantic POV: a function, a control flow is not an obfuscation, it’s an abstraction. Yes abtractions have costs, and it should probably be limited. But not having abstraction also has a cost. It’s a matter of balance, and as nearly everything in life, absolutes are harmful.

So anyway I also agree with @Aleks 100%, especially on the fact that you guys do have abstractions that a newcomer as myself needed to learn (basically the whole helper folder, but a bunch of other things too, not really the subject here. yes I need to note them and contribute to the doc :-)). And by learning, I actually mean read the functions code because the doc is not always enough (it’s normal, it’s the case in nearly every project).

That being said, I wouldn’t call this abstraction “super weird” like Aleks, I would just call it “normally weird” with some quite weirder part :wink:

So to enter the specifics:

about ynh_render_template:

But ynh_render_template can do virtually everything, but you’ll never know what exactly it does when reading a script. And you can have a look to the helper to understand it, as you would do for nginx.
But the helper does

As it is jinja2, one of the best template engine in the world, is well-known and consistent, I don’t get why it is a problem? Yes you need to read the template. Is it really a problem?

about the no-function rule

I’ve already said what I think about the “no abstraction” rule. To give one example, the restore process of some applications (like diaspora) is the following:

  • basically reinstall the app (I won’t backup a bunch of prebuilt stuff, minified css and js and stuff)
  • restore a DB
  • restore uploads folder or something
  • restart the services

So i end up having to duplicate like 90% of my install script. I wish I could use a function there. My feeling: I’m being stripped off of a bit chunk of the bash language that could be very useful for the quality of an app. I understand limitations is useful sometimes, but I feel this is too much.

But actually I think there could be some kind of middle-ground to avoid forbidding them entirely? Maybe what we want is actually a common convention here? Some ideas on top of my head:

  • limit the number of functions/abstractions to something quite low but > 0
  • actually implement cyclomatic complexities
  • force the declarations of functions to be all in the same file (_common.sh for instance) and enforce a documentation of each one at the beginning of the file (or just before the function or…). Like that, someone taking over the package would only have to read this description to have a clear grasp of specificities?

In the meantime, I’d advocate for the no-function rule (at least) to be removed from the automatic check.

I wish everyone a good day :slight_smile:

4 Likes

Hello all!

I want to share my POV (already shared on IRC). I’m a simple maintainer for zabbix app, I propose some evolution but nothing very impressive.
I’m an adminsys but I’ve had very good and intensive training (3 years) in coding, I’v learned best practices, functions, procedures, return code, exceptions, etc. Today, my package works : I have a level 7 since 14 or 16 months but I want to clean my old code, make it simple to read with the best integration of officials helpers and best practices. I want to make it simple but I have not this philosophy of “no function”, “read one script file is enough”. Yes, There are advantages in this conception but you must duplicate the code when restore script use a major part of remove script install script, upgrade use same controls, patch as install.
So, no this is not a good conception for me. We must follow an example (example_ynh), with strict rules and I agree with that. I agree with a cleaning code and “kiss” conception, but we can write a “beautiful”, comprehensive code with the respect of best practices like :

  • Nomenclature functions/procedures, for extra files, directories (why not, based on helpers syntax for functions/procedure)
  • Functions and procedures
  • Code return (with standard code, and why not Yunohost specific code)
  • Comments, in English by default, and in other languages why not?

You can see these standards in this page https://en.wikipedia.org/wiki/Best_coding_practices#Coding_standards
Today, a user can read a package source code, but to know and apply Yunohost helpers, you must to have experience : the documentation is great but it’s not enough for a beginner. Moreover, there’s a lot of operation that can’t be done with official helpers : mysql queries, sed with number of line, use apt-get to get somethings, etc. and you don’t have to create a helper for anything! Helpers are smart tools, I like them with real love, but It’s not enough. Then, If you must use 15-20 helpers to do the same think in your install file and your upgrade/restore file, you gain in reading and maintenance to store them in a procedure or function with a good same, good comment, ect. You avoid duplicate code : if you modify your function, you won’t forget to modify one of your scripts.

This is my opinion.

1 Like