At which point do you decide that some of your subroutines and common code should be placed in a class library or DLL? In one of my applications, I would like to share some of my common code between different projects (as we all know, it's a programming sin to duplicate code).
The vast majority of my code is all within a single project. I also have one small utility that's partitioned from the main executable that runs with elevated permissions for a sole purpose. The two items have, at most, three subroutines in common. Should these common subroutines be placed and called from a class library? How do you decide when to do this? When you have at least one shared subroutine? Twenty-plus lines of code?
I don't believe that this should be language specific or framework dependent, but if so, I'm using the .NET framework.
There's more ways to share code between applications than with a DLL. From what it sounds like, you're not talking about a lot of code, so it sounds like you don't need to worry about it too much.
In general, I use the following rule of thumb:
For trivial code duplication (a couple simple 1-2 line functions, that are easy to understand and debug) I'll just copy and paste the code.
For more complicated functions (a small library of stand-alone helper functions, contained in a file or two, which require a modest level of maintenance and debugging) I'll simply include the file in both projects (either by linking, or defining a subrepository, or something like that).
For more extensive code sharing (a group of interrelated classes, or a database communication layer, which is useful for multiple projects) I'll refactor them out into a standalone library, and package and distribute them using whatever's appropriate for whatever I'm programming in.
Because the complexity of managing your code increases by an order of magnitude for each step (when you're packaging DLLs for multiple projects you now need to think about versioning issues) you only want to move to the next level when you need to. It doesn't sound like you're feeling the pain of handling your common code yet, and if that's the case there's no real need.
If code is shared between multiple applications, then it has to reside in a DLL or class library.
For a larger application you might also want to break different subsystems of the application into separate libraries. That way each project can focus on one particular task. This simplifies the structure of your application and makes it easier to find any one piece of code. For example, you might have a GUI application with different DLL's (.NET projects) for:
Working with a specific Network protocol
Accessing common code, for example utility classes
Access to legacy code (via PInvoke)
etc...
Related
This may seem like an elementary question, or one that may not have a finite answer, in which I apologize.
My question is what are the major pluses and/or minus for having database calls (SQL in my case) in an DLL (its own project) vs. having them inside the project/website with the application (in like a app_code folder for example). All of the DB calls are for this one particular application ONLY, there are no other applications that need to look at this DLL. I'm not sure why my predecessor did this, and trying to understand it.
Thanks
It's just a general good practice to layer your application.
The actual layering can be done using various techniques:
using namespaces, creating DLL's, using folders within the project, putting each layer on a different fysical machine (although this is technically also a different "tier")
Your predecessor just chose to put it in a different DLL, so that he would later have the flexibility to reuse the DLL in its entirety. Although it's only for one project, you never know.
As they say: it doesn't cost anything to create a class, the same goes for a DLL. (not counting minor performance differences)
I usually split projects into layers i.e. presentation layer, business logic layer and data logic layer. Sometimes I will separate the layers using namespaces and sometimes I will have three separate DLL's (using tiers).
I see developers splitting tiers into multiple DLL's. For example, I once saw a business logic layer with over one hundred different project files and hence over one hundred different DLLs. Also the MSDN documentation shows that the .NET framework contains multiple DLL's e.g. mscorlib etc.
I believe that the reasoning behind having separate DLLs is that it minimizes the memory footprint and also it allows multiple developers to work on different projects e.g. one team could work on one project and another team on another project etc.
I work in a two developer team. What criteria do developers use deciding to split into separate DLLs?
What is the reasoning for separating layers into multiple DLLs?
There are various reasons to do this.
It adds isolation, which can help the compiler prevent you from mixing concerns. Without adding a reference explicitly, you can't use internal types in the other DLLs "by accident", which allows the compiler to help you keep your code cleaner.
If you don't use an assembly at runtime, it won't be loaded. This can keep the memory footprint smaller. (If all assemblies are used, however, it won't help).
It provides a logical separation within your APIs and projects, which can help with organization and maintainability of your code. Note that too many projects is just as bad (or sometimes worse) than too few, however, as many projects adds complexity that may not be beneficial.
Separating code into more than one assembly is done for many reasons, some more technical than others. Assemblies can be used for logical grouping of code much like namespaces and, in fact, one common pattern is to separate large namespaces (concerns) into separate assemblies for that namespace. But that reason is most definitely not the best reason to use more than one assembly.
Code reuse is like the number one factor for placing code into different assemblies. For example, you may have a console application and all of the code in is the one execute file that is compiled. Later on, you decide to create a web app front-nd for the same application. Instead of copying the core code from your console app to your web app, you would likely refactor the solution into three projects: a class library for the code code (the main implementation), a console app (which already exists) and a web app. The console app and web app projects/assemblies will reference the class library project/assembly and the main code is reused across both implementations. This is an oversimplification, mind you.
Another reason to separate code into multiple assemblies to separate concerns while managing dependencies. In this case, you may have code that requires references to web-oriented dependencies (other assemblies) that you may not want to reference in your core application assemblies. You would do that so that you may reuse your core assemblies without taking unnecesary dependencies when they are not needed by breaking up the app into additional assemblies/projects.
Another reason is to facilitate concurrent development of a large team where sub-teams may each work on a different assembly, helping to reduce the number of "collissions" between developers working on different concerns of the application.
There is plenty of documentation out there that talks about design patterns (e.g. Visitor), SOLID (Single Responsibility etc), KISS (Keep it Simple, Stupid), tiered design etc.
One thing I don't fully understand is how to decide when a new project/DLL is required when extending an application. Is there any criteria that is used?
For example, System.Windows.Forms (http://msdn.microsoft.com/en-us/library/system.windows.forms.containercontrol.aspx) is part of System.Windows.Forms.dll yet it derives from System.MarshalByRefObject, which is part of mscorlib.dll.
You're mixing up assemblies (DLLs) and namespaces.
Assemblies are the binary files which contain the implementations of classes, etc.
Namespaces are just a way to organize classes, enums, etc. into logical groups, to prevent from having every class accessible from every level, and prevent naming conflicts (eg. System.Windows.Forms.Timer and System.Threading.Timer).
System.Windows.Forms doesn't derive from System, and System doesn't live solely in mscorlib.dll. Anyone can put anything in the System namespace - even you could do it. It's just a sub-namespace of System.
There are several reasons for breaking a subset of code out into a separate assembly. A big one is re-usability. If you have some common controls or utilities, you can maintain it in its own DLL and use it across projects without copy-and-pasting of code.
Don't confuse tiers with layers. Layering your code is almost always a must. Splitting your code out into separate physical tiers, however, is something that you usually don't want to do until you actually need to (following the KISS principle).
If you layer your code properly, then when the time comes that you need to break it out into separate tiers, doing so should be a very painless process. If, however, you never layered your code properly you'll find that splitting out the tiers will be very difficult.
As a simple example, lets say you create a login form and lets say you put all the logic to gather the system information, access the database, validate the user credentials, and build the permissions, all directly into the WinForm class. The code I just described has only 1 layer and it has only 1 tier. If you then found yourself needing to create a web-based login page using ASP.NET, you would find it very difficult to reuse that existing code. With the web based login, you'd want to at the very least, separate the UI logic from the business/data access logic, but because it's all directly in the WinForm class, it's all unusable without re-factoring the code.
Now, let's say, instead of putting all that code in the form, you took the time to layer it properly. Let's say you broke out all of the code that accessed the database about put it all into data access classes. And then you put all of the business logic code put it all in business classes. At that point, the actual code in the WinForm class should be limited to doing nothing but UI related logic such as handling control events, setting labels, etc. In this second example. you still only have 1 tier, but you have three distinct and independent layers (viz. UI, Business, Data Access).
If you had already layered your code like that, then when the time came that you needed to reuse it in the web-based project, you could easily move the business and data access layers into a class library (dll) and then reuse them in the ASP.NET project for the server-side tier.
Breaking your code into separate class libraries is only typically necessary in two situations:
You need to reuse the code in multiple projects
You need to divide your project into multiple tiers
Even if you put all your code in a single project, as long as it is well-layered, it will be very easy to split the project up into multiple class libraries when such a situation arises. So the big design issue is not how many DLL's you have. Rather, the big design issue is how many layers you have. Once you have the code layered, it will be easy to move it around between different projects as necessary.
In practical terms, even when you don't need to reuse the code between projects nor support n-tiers, you may still legitimately choose to divide your layers into separate class libraries. It may make sense to do so purely for organizational purposes, or for consistency. For instance, if another developer comes behind you and sees classes in a class library called "MyCompany.Feature.Business", they can safely assume that those classes are all part of the business logic layer. In that way, breaking your code up into separate class libraries can be self-documenting.
There are other reasons too, for putting code in dlls. For instance, it makes it easy to support plug-in architectures or to make it easier to update one part of the application at a time.
If I build several classes and I import the same library for each class, am I going to make my project heavy ?
Or is exactly the same as importing it only once ?
thanks
Typically the linker (or it's equivalent) will ensure you have only one copy.
There are some subtleties with things such as Java Application Servers where you may want to "isolate" classes (typically applications) and so pay the cost of having duplicate copies of some common libraries.
Generally speaking just design/code naturally and the right thing will happen.
Highly embedded (limited code and ram size) projects pose unique challenges for code organization.
I have seen quite a few projects with no organization at all. (Mostly by hardware engineers who, in my experience are not typically concerned with non-functional aspects of code.)
However, I have been trying to organize my code accordingly:
hardware specific (drivers, initialization)
application specific (not likely to be reused)
reusable, hardware independent
For each module I try to keep the purpose to one of these three types.
Due to limited size of embedded projects and the emphasis on performance, it is often keep this organization.
For some context, my current project is a limited DSP application on a MSP430 with 8k flash and 256 bytes ram.
I've written and maintained multiple embedded products (30+ and counting) on a variety of target micros, including MSP430's. The "rules of thumb" I have been most successful with are:
Try to modularize generic concepts as much as possible (e.g. separate driver code from application code). -- It makes for easier maintenance and reuse/porting of a project to another target micro in the future.
DO NOT start by worrying about optimized code at the very beginning. Try to solve the domain's problem first and optimize second. -- Your target micro can handle a lot more "stuff" than you might expect.
Work to ensure readability. Although most embedded projects seem to have short development-cycles, the projects often live longer than you might expect and another developer will undoubtedly have to work with your code.
I've worked on 8-bit PIC processors with similar limitations.
One restriction you don't have is how many comments you make or what you choose to name your methods, variables, etc.. Take advantage. Speed and size constraints do sometimes trump organization, but you can always explain.
Another tip is to break up a logical source file into even more pieces than you need, then bind them by #includeing them in a compilation unit. This allows you to have lots of reusable code (even one routine per file) but combine in whatever order you need. This is useful e.g. when trying to meet compilation unit size restrictions, or to pick and choose which common subroutines you need on the next project.
I try to organize it as if I had unlimited RAM and ROM, and it usually works out fine. As mentioned elsewhere, do not try to optimize it until you absolutely need to.
If you can get a pin-compatible processor that has more resources, it's better to get it working on that, concentrating on good structure and layout, then optimize for size later when you understand the code better.
Except under exceptional circumstances (see note), the organisation of your code will have no impact on the final product. (contents of the code are obviously a different matter)
So with that in mind you should organise your code as you would any other project.
With that said, the following are fairly typical:
If this is a processor that you've worked on before, or will be working on in the future, you will usually want to keep a dedicated hardware abstraction layer that can be shared between projects in the future. Typically this module would contain items like routines for managing any uarts, timers etc.
Usually it's reasonable to maintain a set of platform specific code for initialisation and setup that performs all of the configuration and initialisation up to the point where your executive takes over and runs your application. It will also include platform specific hal routines.
The executive/application is probably maintained as a separate module. All of the hardware specific code should be hidden in the hal (as mentioned above).
By splitting your code up like this you also have the option of compiling and running your application as a simulation, on a completely different platform, just by replacing the hardware specific code with routines that mimic the hardware.
This can be good for unit testing and debugging and algorithmic problems you might have.
Exceptional circumstances as might be imposed by unusual compiler restrictions. eg. I've come across some compilers that expect all interrupt service routines to be compiled within a single object file.
I've worked with some sensors like the Tmote Sky, I too have seen poor organization, and I have to admit i have contributed to it. Anyway I'd say that some confusion has to be, because loading too much modules or too much part of program will be (imho) resource killing too, so try to be aware of a threshold between organization and usability on the low resources.
Obviously this don't mean let caos begin, but for example try to get a look on the organization of the tinyOS source code and applications, it's an idea on what I'm trying to say.
Although it is a bit painful, one organization technique that is somewhat common with embedded C libraries is to split every single function and variable into a separate C source file, and then aggregate the resulting collection of O files into a library file.
The motivation for doing this is that for most normal linkers the unit of linkage is an object, for every object you either get the whole object or none of it. Since there is a 1-1 relationship between C files and object files, putting each symbol in it's own C file gives each one it's own object. This in turn lets the linker pull in only that subset of functions and variables that are actually used.
This sort of game doesn't help at all for headers they can happily be left as single files.