Explicit encapsulation is better than implicit hardcoding?

Hey there! I'm curious to know what this group thinks about the implicit design of many Python libraries, both core and open source. What I mean by "implicit design" is when an interface of library is established and initialised at module’s level rather than explicitly encapsulated in classes. Couple of the examples: 1. logging 2. asyncio Both of the libraries (by design) allow only 1 framework per process, which can be limiting. Although it's easier to hack the logging library to obtain an independent hierarchy with separate root node, it's a bit more challenging to obtain a separate asyncio loop. Allowing users to instantiate a fresh instance of framework would be advantageous in various ways: 1. "Explicit is better than implicit" - easier to understand, inherit, and edit. 2. The ability to instantiate multiple framework nodes leads in a modifiable, therefore easier to comprehend workflow. For example, having separate logging and asyncio on a thread would provide for greater design freedom. 3. Code reusability. When I am looking for code (to avoid reinventing the wheel), whenever I find initialisations at the module level it is a signal that the code is not easily reusable, and I continue my search. I'll return to such code as a last option. I think such design is reasonable for “end result” products, that are not at the risk of becoming standard dependencies, but is it a good idea to continue this standard practice for "building block" libraries? It is not a complaint in and of itself (maybe a bit), but rather an attempt to spark a discussion about whether more modular and explicitly contained architecture would help the Python community the most in the long run.

"it's a bit more challenging to obtain a separate asyncio loop." Just call `asyncio.new_event_loop` and you can have as many event loops in the same thread as you want. On Thu, Jun 8, 2023 at 10:58 AM Dom Grigonis <dom.grigonis@gmail.com> wrote:
Hey there! I'm curious to know what this group thinks about the implicit design of many Python libraries, both core and open source. What I mean by "implicit design" is when an interface of library is established and initialised at module’s level rather than explicitly encapsulated in classes.
Couple of the examples: 1. logging 2. asyncio
Both of the libraries (by design) allow only 1 framework per process, which can be limiting. Although it's easier to hack the logging library to obtain an independent hierarchy with separate root node, it's a bit more challenging to obtain a separate asyncio loop.
Allowing users to instantiate a fresh instance of framework would be advantageous in various ways:
1. "Explicit is better than implicit" - easier to understand, inherit, and edit. 2. The ability to instantiate multiple framework nodes leads in a modifiable, therefore easier to comprehend workflow. For example, having separate logging and asyncio on a thread would provide for greater design freedom. 3. Code reusability. When I am looking for code (to avoid reinventing the wheel), whenever I find initialisations at the module level it is a signal that the code is not easily reusable, and I continue my search. I'll return to such code as a last option.
I think such design is reasonable for “end result” products, that are not at the risk of becoming standard dependencies, but is it a good idea to continue this standard practice for "building block" libraries?
It is not a complaint in and of itself (maybe a bit), but rather an attempt to spark a discussion about whether more modular and explicitly contained architecture would help the Python community the most in the long run.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/M7D7G6... Code of Conduct: http://python.org/psf/codeofconduct/

I stand corrected.! I have very little experience with asyncio. I ended up postponing it’s learning one of the reasons being this query. (Another - extra keywords). Still, the query is more concerned with module level interfaces. That includes module level initialisations as well as interface functions acting on variables defined at module’s level while partly (if not completely) abstracting architecture from the user. What I am aiming at is providing easier explicit instantiation of root objects, rather than abstracting their creation and usage. There would be much smoother library learning path if the first line the user wrote was: ``` loop = asyncio.Loop() ``` or ``` log_manager = logging.Manager(logging.BaseLogger()) logger = log_manager.getLogger(’name') ``` Whether to provide default arguments or force user to set them explicitly is another question. (Maybe can provide class methods for construction with some default presets) The key is that if user started with explicitly defined objects, the transition to understanding/modifying/extending source would be smoother than playing with an interface, which abstracts the architecture. For asyncio, learning curve is already steep. And this approach, in my opinion, is an extra obstacle, which prevents a significant portion of basic users crossing to the next level. In my experience, this would save few lines of code and also only 1 interface is easier to maintain. Also, I think this suggestion to some extent intersects with: "There should be one-- and preferably only one --obvious way to do it.” Now, with these libraries it feels like: “There is one obvious way to do it, but it changes to another obvious way for advanced usage” Having said that, just want to emphasise that I am trying to argue general point, rather than complain about specific libraries. I think the same holds for many 3rd party libraries too. Also, personally I lean strongly towards modularity so just trying to find out if anyone else agrees or I am simply over-extending here, in python case.
Begin forwarded message:
From: "Joao S. O. Bueno" <jsbueno@python.org.br> Subject: Re: [Python-ideas] Explicit encapsulation is better than implicit hardcoding? Date: 8 June 2023 at 20:36:11 EEST To: Dom Grigonis <dom.grigonis@gmail.com> Cc: python-ideas@python.org
"it's a bit more challenging to obtain a separate asyncio loop."
Just call `asyncio.new_event_loop` and you can have as many event loops in the same thread as you want.
On Thu, Jun 8, 2023 at 10:58 AM Dom Grigonis <dom.grigonis@gmail.com <mailto:dom.grigonis@gmail.com>> wrote: Hey there! I'm curious to know what this group thinks about the implicit design of many Python libraries, both core and open source. What I mean by "implicit design" is when an interface of library is established and initialised at module’s level rather than explicitly encapsulated in classes.
Couple of the examples: 1. logging 2. asyncio
Both of the libraries (by design) allow only 1 framework per process, which can be limiting. Although it's easier to hack the logging library to obtain an independent hierarchy with separate root node, it's a bit more challenging to obtain a separate asyncio loop.
Allowing users to instantiate a fresh instance of framework would be advantageous in various ways:
1. "Explicit is better than implicit" - easier to understand, inherit, and edit. 2. The ability to instantiate multiple framework nodes leads in a modifiable, therefore easier to comprehend workflow. For example, having separate logging and asyncio on a thread would provide for greater design freedom. 3. Code reusability. When I am looking for code (to avoid reinventing the wheel), whenever I find initialisations at the module level it is a signal that the code is not easily reusable, and I continue my search. I'll return to such code as a last option.
I think such design is reasonable for “end result” products, that are not at the risk of becoming standard dependencies, but is it a good idea to continue this standard practice for "building block" libraries?
It is not a complaint in and of itself (maybe a bit), but rather an attempt to spark a discussion about whether more modular and explicitly contained architecture would help the Python community the most in the long run.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org <mailto:python-ideas@python.org> To unsubscribe send an email to python-ideas-leave@python.org <mailto:python-ideas-leave@python.org> https://mail.python.org/mailman3/lists/python-ideas.python.org/ <https://mail.python.org/mailman3/lists/python-ideas.python.org/> Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/M7D7G6... <https://mail.python.org/archives/list/python-ideas@python.org/message/M7D7G6...> Code of Conduct: http://python.org/psf/codeofconduct/ <http://python.org/psf/codeofconduct/>
participants (2)
-
Dom Grigonis
-
Joao S. O. Bueno