To create new wiki account, please join us on #znc at Libera.Chat and ask admins to create a wiki account for you. You can say thanks to spambots for this inconvenience.
Ideas: Difference between revisions
>Jpnurmi Removing the versioning paragraph. ZNC is already using MAJOR.MINOR.PATCH since 1.6.0. |
DarthGandalf (talk | contribs) |
||
Line 37: | Line 37: | ||
Consistency, consistency, and consistency... ;) | Consistency, consistency, and consistency... ;) | ||
:Also here's an interesting read: http://google-styleguide.googlecode.com/svn/trunk/cppguide.html --[[User:DarthGandalf|DarthGandalf]] ([[User talk:DarthGandalf|talk]]) 09:42, 15 March 2015 (CET) | |||
=== Class/header naming convention === | === Class/header naming convention === |
Latest revision as of 08:42, 15 March 2015
This page collects random ideas for the future development of ZNC. Everyone is welcome to add their ideas on the list. Please tag each idea with your username.
Note: Feature requests should be filed at GitHub.
Disclaimer: Some of the ideas are not going to be taken seriously, some are shot down right away, and some might even cause fuss and anger. Yet, please put emotions aside and try to be constructive with your comments.
Project structure (jpnurmi)
Modularity and extensibility is admittely one of the key ingredients in ZNC's recipe for success. These days there is a ZNC module for pretty much any imaginable IRC task. Therefore modules deserve to be treated as first class citizens, with good care. ;)
Related to versioning and compatibility as discussed below; since ZNC offers no stable module API and only does major feature releases, modules have somewhat high tendency to break on every ZNC version upgrade. This in turn makes such stakeholders as Linux distributions and ZNC hosting providers resistant to upgrade to the latest version. A stable module API would not only help module developers, but also anyone hosting a ZNC service.
In order to achieve a stable module API, the ZNC core could be refactored so that the core types would be gradually moved to a separate library. It would be nice to make it a separate build unit to avoid undesired backwards dependencies to the ZNC application code.
___________ ___________ / ZNC app \ / ZNC lib \ ___________ | | | | / \ | - main() | --> | - CModule | <-- | ZNC modules | | - CModules | | - CString | \___________/ | - ... | | - ... | \___________/ \___________/
Notice that the library should be absolutely minimal. Most importantly, the public API should not contain anything ZNC application specific. That library would then eventually act as an interface for modules. This restructuring would greatly help maintaining a stable module API in the future, and thus make modules much less prone to break. ZNC would have full control over what modules have access to ie. modules would no longer be able to mess with ZNC internals that have no promise of API compatibility.
J-P Nurmi (talk) 13:50, 7 March 2014 (CET)
- If interface for modules is limited, modules can't do much... --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- I don't wish to cripple it either, but things like CModules and CModule::SetUser/Client/Network() etc. are probably irrelevant for module developers. It's better to start with less and expose more upon demand. The proposed versioning model also allows freely adding new stuff in minor versions, as long as it doesn't completely break the existing set. :) Anyway, since you already have a nice collection of various modules, it should be easy to figure out what is actually needed and what could be "cleaned up" as in kept on the app side. J-P Nurmi (talk) 23:09, 7 March 2014 (CET)
Module interfaces (jpnurmi)
Especially for those occasional module developers that don't know the ZNC APIs by heart, browsing the monolithic CModule Class Reference can challenging and time consuming. It could be easier to grasp and find the relevant hooks (and even lead to cleaner design) if the hooks were logically grouped. For instance, there could be separate interfaces for network, user, channel, web, timer etc. related hooks. J-P Nurmi (talk) 00:34, 9 March 2014 (CET)
Coding style and conventions (jpnurmi)
Consistency, consistency, and consistency... ;)
- Also here's an interesting read: http://google-styleguide.googlecode.com/svn/trunk/cppguide.html --DarthGandalf (talk) 09:42, 15 March 2015 (CET)
Class/header naming convention
Currently, class names are C-prefixed (eg. CBuffer) and some have an additional IRC-prefix (why CIRCNetwork but CChan - is it not an IRC channel? :P). Header file names don't have the C-prefix, but some have a ZNC-prefix (eg. ZNCString.h for historical reasons to avoid name clashes). First of all, I'd like to propose getting rid of the MFC-like C-prefix (shivers). Secondly, for the library parts, I'd like to propose a one to one mapping between class names and the corresponding header file names. That way developers always know which header to include when they want to use a particular type.
Options:
- znc namespace: znc::Buffer, znc::Channel, znc::Network, znc::String...
- *note*: make sure that no public header has "using znc" statements
- Qt-style static Z-prefix: ZBuffer, ZChannel, ZNetwork, ZString...
- not that much of an improvement, besides it looks prettier than the C-prefix?
- lower-case header files that follow the class names: (z)buffer.h, (z)channel.h, (z)network.h, (z)string.h, ...
- string.h is asking for trouble even if it's in a znc-folder?
- How so? --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- Intentional name clashes with system headers just sounds questionable. I know znc-buildmod is responsible for taking care of correct include paths and making sure not add the znc subfolder so that module developers are forced to use the <znc/string.h> syntax, but still. It feels short-sighted, because who knows how libznc evolves in the future. J-P Nurmi (talk) 23:09, 7 March 2014 (CET)
- How so? --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- string.h is asking for trouble even if it's in a znc-folder?
- forwarding convenience headers: (Z)Buffer, (Z)Channel, (Z)Network, (Z)String...
- no need for a .h suffix
- does nothing but includes the actual header
- Any reason for those, except "to look like Qt"? --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- This is definitely the least important suggestion on this particular list. :) Sometimes, for the sake of sanity, you might want to declare multiple classes in the same header. Such reasons could be inheritance or tight coupling. For example, Foo has tiny little subclasses FooBar & FooBaz that are all placed in the same header foo.h. That's where such forwarding convenience headers step in. When module developers use either FooBar or FooBaz, they can be also sure that they can include <FooBar> or <FooBaz> respectively, without having to care about or dig into implementation details. J-P Nurmi (talk) 00:02, 8 March 2014 (CET)
- Any reason for those, except "to look like Qt"? --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
Big renames are always painful. There's the initial hurdle, but the goal is to make the module interface beautiful and consistent for the greater benefit. Developers love consistency - let's make the ZNC module interface lovable. ;)
Calling convention
Pass value types by reference
Copyable value types (excluding primitive types) such as strings and containers should be passed by reference. I believe this is already done all around the ZNC code base, but I want to make a clear distinction to complex/polymorphic types.
Pass complex/polymorphic types as pointers
Most C++ books recommend using references whenever possible, according to the general perception that references are "safer and nicer" than pointers. This is exactly what ZNC is currently doing. The downside of this approach is that it leads to a hassle with taking addresses of references vs. dereferencing pointers back and forth.
- Anything wrong with taking addresses of references? --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- Nothing in particular when formed like that. The calling sequence often goes back and forth between a module and the core, right? It gets a bit clumsy when such operations are done repeatedly. It's more convenient to pass an argument further to other methods as is, without having to think about such things. J-P Nurmi (talk) 23:09, 7 March 2014 (CET)
Such inconsistency makes module developers unsure which calling convention applies to which function. The need of looking up the documentation/header, or having to try'n'error with compiler causes frustration that could be easily avoided.
- Or use some IDE which shows you the function signatures while you type (e.g. vim :P). If someone is not familiar with codebase, they will need to lookup such signatures anyway. --DarthGandalf (talk) 21:19, 7 March 2014 (CET)
- Yeah, tools can help. Combine that with muscle memory and nothing stops you. Muscle memory doesn't develop well, though, if one needs to constantly pause to check the auto-completion signature or for the poor ones, to read the docs. My preference would be simply not to call methods when the argument would be null. If it can be null, it needs to be document, and that's the case already. J-P Nurmi (talk) 23:09, 7 March 2014 (CET)
Furthermore, the distinction between value types vs. complex/polymorphic types makes it easier to see at a glance that which types are copyable and which are not but have the danger of getting sliced.