Package and module interdependence best practices

User avatar
Vadi
Posts: 5042
Joined: Sat Mar 14, 2009 3:13 pm

Re: Package and module interdependence best practices

Post by Vadi »

Deletion is necessary if the file is conflicting with another one, for example - or if the package was uninstalled.

> I would assume the file(s) would have to be copied over when a library needs to be updated

A simply copy on an update - what if a file was renamed? Now there are two copies of the file.

fordpinto
Posts: 34
Joined: Wed Sep 25, 2019 4:59 pm

Re: Package and module interdependence best practices

Post by fordpinto »

> Deletion is necessary if the file is conflicting with another one, for example - or if the package was uninstalled.
In case of de-installation of a package that uses a shared library, I think it's fine to leave shared library in place by default. I do not see a problem with that.

Not sure what you mean by file conflicting with another one, what kind of conflict you have in mind? Would that be a newly created problem or something that would be the case presently anyway?

>> I would assume the file(s) would have to be copied over when a library needs to be updated
>A simply copy on an update - what if a file was renamed? Now there are two copies of the file.
Well, renaming a shared library file is just one example of human error. Like with all conventions, success is predicated on people following the instructions. Actually, in this specific case, not going around renaming files is one of those Darwinian selection things, everybody who thought it is a good idea most likely has given up on using computers by now, I do not hear it as an issue very often ;) .

In terms of hypothetical scenarios, I think it's important to focus on the issues that would be *new* to the proposed arrangement. The human error you described is possible in the present situation too.

fordpinto
Posts: 34
Joined: Wed Sep 25, 2019 4:59 pm

Re: Package and module interdependence best practices

Post by fordpinto »

.mpackage/.xml vs require()

As I mentioned earlier, currently require() makes more sense to me as means for inclusion of the shared code. I do not think it's a radical notion, since require() was put in place by Lua developers specifically for code sharing and library creation. I am listing some advantages that I can think of below. The disadvantage of course is that xml file allows easier access to Mudlet objects. However, I think those mixed projects would more likely be mud specific. I do not expect those to have Mudlet-wide application, and my main question here is Mudlet-wide reusable code.

For Lua-code-only shared library, here are the advantages of require() that I am thinking about:

1) Namespace conflict avoidance. The present require() best practice it seems to me is to not create "static" objects, but rather return a "local" object that is assigned to the library code handle variable, also local (as in the example in my 1st post of this thread local lib = require "libfilename"). The purpose behind this best practice from Lua developers I think is that library data structures do not clutter the _G table, but they still persist through caching mechanism of require(). Thus the namespace conflicts amongst various libraries, and also with the user code, are avoided.
2) User (in)visibility. Somewhat related to the _G table clutter mentioned above. The require() code does not have to be exposed to the user via Script window (no static objects created). I think shared libraries is not something to be tinkered with, so having that taken away is actually a plus. Hiding the shared code I think also would make the package/module code more accessible due to less clutter. Of course, it's a choice, and static objects can be created via require() if necessary.
3) No penalty on granularity. There are additional steps to adding the module, namely installing it into the profile. That is left to the user to manage, and I think the tendency would then be for fewer and larger modules to simplify the module management. But that is in conflict to what the optimal coding strategy is.
4) More smooth handling of sub-dependencies. Typically shared libraries have multiple "layers" of dependence. Library A may need library B and C, and library C may also need library D, etc, etc. With require() the details of those relationships are hidden from the end user. Module library sub-dependencies handling can be further automated with routines added to allow API manipulation of module priorities, but what if there is more than one package for the profile that user wants to load, which one will have a final say how to shuffle the module load order? I think with require() the chain of dependencies is resolved as needed, one just needs to make sure the files are in the right place.

User avatar
demonnic
Posts: 886
Joined: Sat Dec 05, 2009 3:19 pm

Re: Package and module interdependence best practices

Post by demonnic »

So, this isn't the first time this topic has come up. Nor the second, or third....

There are a few problems with this overall, in my opinion.

The first is the requirement for it to be lua code only. The much more common use case involves sharing a collection of triggers, aliases, and lua code. While it's true that the lua API is exetensive and can do most of the things you can do in the Mudlet script editor, a great deal of things are simply easier to do in the UI editor. Particularly in and around triggers.

Now, there are certainly some lua only packages out there. I've written more than my fair share of them. But adding yet another way of managing Mudlet code with special requirements adds complexity before you even get around to recreating luarocks-for-mudlet in order to deal with indexing, searching, dependency resolution, download, and installation.

Which brings me to the next thing, which is that the vast majority of Mudlet users aren't actually developers. Even the ones writing scripts, a great many of them know very little about writing code or developing software before they start working on writing their first Mudlet scripts. While I do encourage using tables for namespacing and local variables wherever possible, even having that table as a global is already breaking technical lua best practices, and some amount of 'dirtying' the global namespace is required in order to pass variables between triggers, aliases, etc.

Tables are already one of the biggest sticking points when trying to help new users, and the thing I most often hear "I have no idea what any of that is" regarding. And writing modules to be required in lua depends on understanding tables. Further restricting the potential pool of code authors.

Next, and I fully admit this is a bit odd coming from the guy who wrote a build tool for making Mudlet xml and mpackages and maintains code snippets for writing Mudlet scripts in vscode, but by and large most people seem to prefer editing code for Mudlet inside Mudlet itself. There have been a few projects which primarily used lua files on disk and required or loaded them one way or another, and they've generally moved away from that and wound up using the established mudlet xml and mpackage formats with the code living inside Mudlet editor items.

Finally, since require is just base lua functionality, there's not really anything stopping you writing a very simple Mudlet module to implement this yourself, choosing reasonable locations for each OS, creating them, and adding it to the package.path variable. That's the easy part, honestly, Adding download and install functionality wouldn't even be particularly difficult. Dependency resolution is a bit more difficult, even in the best cases, but gets a lot more difficult the further you try to take it. And without the more difficult parts (dependency resolution and download) and a host to store the modules, you almost might as well just write some instructions on where they should unzip your module to on their harddrive based on what OS they use.

But I think even with that you'll run into problems with adoption, and find that there aren't that many people writing pure lua packages for Mudlet out there.

fordpinto
Posts: 34
Joined: Wed Sep 25, 2019 4:59 pm

Re: Package and module interdependence best practices

Post by fordpinto »

@demonnic

Appreciate you sharing your thoughts on this. I am not discouraged in the least that this apparently was already discussed many times. I am not trying to drive Mudlet into certain direction. Presently, I can code anything I like as a require() library, and use it just fine, since I am not playing 100 different muds. It's no skin off my back to copy my own lua files it into the few profiles I use, so Mudlet meets my own needs just fine. It's just that I see this bit as an imperfection, and so an opportunity to make things even better.

I am not sure what the downside is to actually support lua recommended ways for shared libraries. I may not see all the details, but it doesn't seem like much is needed at all. Like I said, simply establishing a standard location for such shared files in the "root" Mudlet data directory, not just in the profiles, and make sure that Mudlet lua looks there as well. That's it. Luarocks I think come in handy when C/++ interfacing is needed, but that level firmly belongs in the Mudlet code anyway, and that's not what I am talking about.

I am not surprised that Mudlet code editor is the most popular tool. It's a very strong Mudlet feature since it gives a very, VERY easy and convenient entry point into enhancing Mudlet experience. The way I see it, it's sort of code and debug environment at the same time. Having access to variables, and objects, as well as the code, error messages, etc, is exactly what is needed when prototyping ideas, playing with adding/removing features etc. But the natural progression would be then to clarify the object structures, modularize, optimize etc. If that's not done, the code becomes bloated, unreadable, unwieldy. The fact that it's all visible makes it harder to work with due to clutter, even if it's all nice and clean code. So I think continuously splitting off well defined, self contained shared library objects from a growing pile of code is a necessary process. I am not saying that every user is somehow supposed to produce universally applicable shared library in the process of using Mudlet, or to follow the best practices. That's the beauty of freedom and choice. But it seems to me that the "Lua recommended" way is somewhat handicapped at the moment. I completely agree, writing Lua require() library demands much deeper understanding of Lua. The good news is that it's not the case for *using* Lua require() libraries, so while not everybody might want to be involved in making such a module, everybody can benefit if one is made available.

I will not dispute that probably >95% of user activity will likely be in modifying/tweaking/enhancing Mud-specific packages. And that's much better served with easily editable code/object mixes stored in XML files. But that's not a good reason not to acknowledge room for improvement in an area that may lack in overall activity volume, but can have significant positive impact nonetheless.

Post Reply