We have a core library in the form of a DLL that is used by more than one client application. It has gotten somewhat bloated and some applications need only a tiny fraction of the functionality that this DLL provides. So now we're looking at dividing this behemoth into smaller components.
My question is this: Can anyone recommend a path to take to divide this bloated DLL into a set of modules that have some interdepencies but do not necessarily require all other modules?
Here are the options as I see them but I'm hoping someone can offer other possibilities:
Create a "core" dll and several "satellite" dlls which use the core and possibly other satellite DLLs.
Subdivide the contents of the bloated DLL into static libraries that the main DLL uses (to maintain the same functionality) but apps that don't want to use the bloated version can assemble the static libraries they need into their own dll or into the app itself.
I was hesitant to mention this but I think it may be important to note that the app uses MFC.
Thanks for your thoughts.
Somewhat related to your question is this question, about splitting up a very large C module into smaller ones.
How do you introduce unit testing into a large, legacy (C/C++) codebase?
It seems your question has to do with the larger question of breaking some large blob of code into a more modular system. The link above is definitely recommended reading.
Without having all the details it is a little hard to help but here is what I would do in your situation
provide both static and dll versions of whate3ver you release - for MT and single threaded.
try to glean from the disparate clients which items should be grouped together to provide reasonable segmentation - without having layers of dependencies.
having a "core" module sounds like a good idea - and make sure you don't have too many levels of dependencies - you might want to keep it simple.
You may find after the exercise that one big dll is actually reasonable.
Another consideration is that maintaining multiple DLLs and both static libs and DLLs will hugely increase the complexity of maintenance.
Are you going to be releasing them all at once every time, or are they going to be mix and match? Be careful here - and know that you could create testing issues
If no one is complaining about the size of the DLL then you might want to consider leaving it as is.
Related
I recently decided to take a look at 2D graphics with C++, using MinGW on Windows 7.
Since I was only going to need 2D graphics any library would be viable more or less (OpenGL, SDL, etc..). I decided to take a quick look at a few and check how easy they'd be to get working on windows with MinGW.
I soon noticed every library I tested (which were Cairo, SDL and GTK+) required tons of dll files in order to work. After compiling even a simple program from something like a tutorial it would give me like 5 or 6 different dll errors, forcing me to copy all of them into my program's working directory for it to even run.
Of course my program worked, but it's very cubersome to have this many DLLs just for a simple program. Making the program run on someone else's computer would require to ship all those DLLs along with it as seperate files, plus other DLLs that I got globally installed but others don't.
It just seems so weird that something as popular as C++ would be so annoying to use because of all the DLLs required... Am I doing anything wrong? Could there be some magical solution to this problem? Some tool to minimize or even completely eliminate these complications? It'd be cool to have to use fewer DLLs for my application. Of course I won't be able to omit DLLs completely, but at least reducing the amount to a single one (one library = one DLL) or having the possibility to organize them in a subfolder of their own would be awesome.
Of course my program worked, but it's very cubersome to have this many DLLs just for a simple program. Making the program run on someone else's computer would require to ship all those DLLs along with it as seperate files, plus other DLLs that I got globally installed but others don't.
If you're making an installer for your program, the installer should take care of installing the DLLs right alongside your program. It's pretty common practice, and won't be inconvenient for your user at all. If you're just distributing a zip file with your app in it, just keep the DLLs in the folder you're zipping up (also a pretty common practice).
It's also worth noting that you'll already have to send DLLs with your app. GCC apps need libgcc_s_sjlj-1.dll and libstdc++-6.dll. MSVC apps, if I recall correctly, rely on the Visual C++ runtime library. A few more graphics libraries aren't likely to bother the user at all.
Am I doing anything wrong?
Nope, this seems like business as usual to me. I recommend you continue your project without worrying too much about the DLLs.
Could there be some magical solution to this problem? Some tool to minimize or even completely eliminate these complications?
You could look into a DLL/EXE packer. It's highly unrecommended, though, because antiviruses tend to not appreciate the modified EXEs. (A lot of malware uses packing techniques, so antiviruses are often suspicious of such packed apps by default.)
at least reducing the amount to a single one (one library = one DLL)
Technically you might be able to, but you'd probably need to rewrite the graphics library in question since right now it's set up for multiple DLLs. I really don't recommend this either; the DLLs are separate because they're meant to be. They offer different functionality (for example, a quick glance at GTK+'s changelog showed mentions of libraries for SVG, JPG, and other file formats, as well as a lot of backend stuff to interface with the host OS, printers, etc.) so they're encapsulated into different libraries. In some cases (libjpeg) these "sub-libraries" are even written by a different group, and the graphics library you're using just calls certain functions from the "sub-library".
If you're really that insistent on having just one DLL, I think you're better off looking for some little, minimal-functionality library. Since you just want 2D graphics you might be able to get away with that.
or having the possibility to organize them in a subfolder of their own would be awesome
Unfortunately you can't do this.
I've just finished a phase in my project where I wrote a small infrastructure to carry out a certain task, made of a core class with several auxiliary classes.
The C++'ness is quite basic - single inheritance, some STL containers, that's it.
No threads - client runs the show.
What I would like to do now is wrap it all up in a DLL, version it, and use
it as a standalone unit. I'd like that seperation in order to track changes and
development better, and perhaps for other projects as well.
As I don't have experience with classes in DLLs, I would like to hear yours:
What's your approach to this problem?
Specifically:
Is it worth the trouble?
Do you do that often or not at all?
What about compatibiliy issues (like clients compiled using a different compiler)?
I'm not really asking for a debate (though that's the probable outcome), but rather an advice from experience.
Thanks for your time.
I find it hard to see any benefit with this. I can see plenty of problems:
No type checking across a DLL boundary. Any version mismatches will result in runtime failures, harder to detect than compile time failures.
Extra deployment headaches. You may be tempted to update some but not all modules and so deal with complex dependencies.
All clients that want to use these DLLs must use the same compiler.
Only make this change if you can identify benefits that outweigh the negatives.
C++ code is not binary compatible between compilers, it's generally no use creating DLLs exposing C++ classes that aren't built as part of the project that uses them.
If you want to create a Windows DLL with a well-defined object-oriented interface that the rest of the world can use, make it a COM inproc server.
I have been throwing stuff together in a small test game over the past 6 months or so, and right now everything is in the one project. I would like to learn more about creating an "engine" for reusability and I am trying to figure out the best way to do this.
Static Libs are obviously a tiny bit faster, as they are compiled in rather than loaded at runtime, but that really does not matter to me. The advantages of DLLs over static libs seems rather large. So im wondering what the best approach/most used approach is for a "game engine".
I am using Ogre3D (rendering engine) which supports dll plugins that it loads and what not, but I would like to write my dlls where I could basically use them anywhere. So would my best bet be to write individual DLLs for each portion of my sample engine, such as sound.dll, gui.dll, etc? Or would I be better served by creating one large dll, deemed engine.dll or something? I am assuming the best approach would be to write something like...engine.dll for the general structure, then compose it of other dlls such as sound/gui/input/etc.
Would it be silly of me to write my dlls independently of Ogre's Plugin system? My Sound relies on the FMOD library, my GUI relies on the CEGUI library, and so on. I mainly just want to create my engine to a point where it is easily usable with the functions I need from the individual librarys.
If you are creating DLLs for re-usability it makes sense to split it up into self contained units of functions. Thus, if you have a general sound library that, for example, plays wav files, that could be separated out as sound.dll if you think lots of other programs might make use of that particular library. Likewise for anything you think would be re-usable elsewhere.
However, if it is mostly the case that the only people using your sound routines are those who will also load the rest of your game engine (or most of it) dll, I see little point in having so many separate libraries. I can see the sense in having engine.dll so that many games can be created from a single engine but not from splitting up the rest unnecessarily.
I am about to attempt reorganizing the way my group builds a set of large applications that share about 90% of their source files. Right now, these applications are built without any libraries whatsoever involved except for externally linked ones that are not under our control. The applications use the same common source files (we are not maintaining 5 versions of the same .h/.cpp files), but these are not built into any common library. So, at the moment, we are paying the price of building the same code over-and-over per application, each time we intend to release a version. To me, this sounds like a prime candidate for using libraries to capture the shared code and reduce build times. I do not have the option of using DLL's, so the approach is to use static libraries.
I would like to know what tips you would have for how to approach this task. I have limited experience with creating/organizing static libraries, so even the basic suggestions towards organization/gotchas are welcome. Maybe even a good book recommendation?
I have done a brief exercise by finding the entire subset of files that each application share in common. As a proof of concept, I took these files and placed them in a single "Common Monster" static library. Building the full application using this single static library certainly improves the build time for all of the applications, but should I leave it at this? The purpose of the library in this form is not very focused and seems like a lazy attempt at modularity. There is ongoing development with these applications, and I'm afraid this setup will cause problems further down the line.
It's very hard to give general guidelines in this area - how you structure libraries depends very much on how you use them. Perhaps if I describe my own code libraries this may help:
One general purpose library containing code that I expect all applications will have at least a 50/50 chance of needing to use. This includes string utilities, regexes, expression evaluation, XML parsing and ODBC support. Conceivably this should be split up a bit, but it makes distributing my code in FOSS projects easier to keep it monolithic.
A library supporting multi-threading, providing wrappers around threads, mutexes, semaphores etc.
One supporting SQLite via its native interface, rather than via ODBC.
A C++ web server wrapper round the Mongoose C web server.
The general purpose library is used in all the stuff I write, the others in more specialised circumstances. Headers for each library are held in separate directories, as are the library binaries themselves (though they should probably be in a single lib directory).
Make sure that the dependencies of your libraries form acyclic directed graph (a tree). While this is not necessarily a problem for static libs (I'm not sure in fact), it will be a problem if you ever decide to switch to dlls. Depending on your situation, this may require some redesign of interfaces.
Another thing I noticed (for sure on MSVC), which you may consider if build speed is an important concern: DLLs link much faster than static libraries. I assume this is because they don't have to be copied into the new executable and there's no need to search an eliminate unused code. Even if it's no option for production, you may use this trick while developing.
I also have the habit to create my solution files with CMake, because it is easier to overview the entire build process than clicking through an endless list of options in a GUI. It's up to you to decide if you want to walk that path.
I am developing a portable C++ application and looking for some best practices in doing that. This application will have frequent updates and I need to build it in such a way that parts of program can be updated easily.
For a frequently updating program, creating the program parts into libraries is the best practice? If program parts are in separate libraries, users can just replace the library when something changes.
If answer for point 1 is "yes", what type of library I have to use? In LINUX, I know I can create a "shared library", but I am not sure how portable is that to windows. What type of library I have to use? I am aware about the DLL hell issues in windows as well.
Any help would be great!
Yes, using libraries is good, but the idea of "simply" replacing a library with a new one may be unrealistic, as library APIs tend to change and apps often need to be updated to take advantage of, or even be compatible with, different versions of a library. With a good amount of integration testing though, you'll be able to 'support' a range of different versions of the library. Or, if you control the library code yourself, you can make sure that changes to the library code never breaks the application.
In Windows DLLs are the direct equivalent to shared libraries (so) in Linux, and if you compile both in a common environment (either cross-compiling or using MingW in Windows) then the linker will just do it the same way. Presuming, of course, that all the rest of your code is cross-platform and configures itself correctly for the target platform.
IMO, DLL hell was really more of a problem in the old days when applications all installed their DLLs into a common directory like C:\WINDOWS\SYSTEM, which people don't really do anymore simply because it creates DLL hell. You can place your shared libraries in a more appropriate place where it won't interfere with other non-aware apps, or - the simplest possible - just have them in the same directory as the executable that needs them.
I'm not entirely convinced that separating out the executable portions of your program in any way simplifies upgrades. It might, maybe, in some rare cases, make the update installer smaller, but the effort will be substantial, and certainly not worth it the one time you get it wrong. Replace all executable code as one in most cases.
On the other hand, you want to be very careful about messing with anything your users might have changed. Draw a bright line between the part of the application that is just code and the part that is user data. Handle the user data with care.
If it is an application my first choice would be to ship a statically-linked single executable. I had the opportunity to work on a product that was shipped to 5 platforms (Win2K,WinXp, Linux, Solaris, Tru64-Unix), and believe me maintaining shared libraries or DLLs with large codebase is a hell of a task.
Suppose this is a non-trivial application which involves use of 3rd Party GUI, Threads etc. Using C++, there is no real one way of doing it on all platforms. This means you will have to maintain different codebases for different platforms anyway. Then there are some wierd behaviours (bugs) of 3rd Party libraries on different platforms. All this will create a burden if application is shipped using different library versions i.e. different versions are to be attached to different platforms. I have seen people shipping libraries to all platforms when the fix is only for a particular platform just to avoid the versioning confusion. But it is not that simple, customer often has a different angle to how he/she wants to upgrade/patch which is also to be considered.
Ofcourse if the binary you are building is huge, then one can consider DLLs/shared-libraries. Even if that is the case, what i would suggest is to build your application in the form of layers like:-
Application-->GUI-->Platform-->Base-->Fundamental
So here some libraries can have common-code for all platforms. Only specific libraries like 'Platform' can be updated for specific behaviours. This will make you life a lot easier.
IMHO a DLL/shared-library option is viable when you are building a product that acts as a complete solution rather than just an application. In such a case different subsystems use common logic simultaneously within your product framework whose logic can then be shared in memory using DLLs/shared-libraries.
HTH,
As soon as you're trying to deal with both Windows and a UNIX system like Linux, life gets more complicated.
What are the service requirements you have to satisfy? Can you control when client systems get upgraded? How many systems will you need to support? How much of a backward-compatibility requirement do you have.
To answer your question with a question, why are you making the application native if being portable is one of the key goals?
You could consider moving to a a virtual platform like Java or .Net/Mono. You can still write C++ libraries (shared libraries on linux, DLL's on windows) for anything that would be better as native code, but the bulk of your application will be genuinely portable.