The Grails framework has a lot of constructs/features that allows for adhering to the DRY principle ("don't repeat yourself") within a project. That is: within a specific project you're seldom required to repeat identical blocks of settings or code. So far so good.
However, the more I've worked with Grails the more of I've observed that I repeat code not within the same project but between projects. That is project A has controllers, GSP:s and images that overlaps with project B. This is a maintenance nightmare since bug fixes in project A must also be fixed in project B, etc.
I'd like to take DRY to the next level by not duplicating code between my projects.
My question: How do you tackle this problem (violated "inter-projects DRY") in your own internal Grails projects?
Please be very specific/concrete. If possible try to include specific code examples on how you solve it in practice.
Writing a custom plugin is the best way. You don't need to release it to the public repository, as you can use a private repository somewhere within your own network.
I haven't had enough duplicated code yet to pull out a plugin (most of the code repeated in my projects seem to be covered by the various public plugins), but a plugin can be as simple as a few common domain classes or services.
I agree with Lee, Using common/shared plugins is probably the best way to go. At one place that I worked we had quite a few internal plugins for this very reason.
The most common pattern is to put your common domain objects into their own plugin. This works really well for domain classes or services. We didn't end up refactoring the controllers, views, and static resources into a plugin, but the same principle should apply.
Long story short: Reuse of Grails artifacts = use a plugin.
To add to Lee and Colin's points, which are both valid, I think thinking in terms of multiple plugins can yield other benefits.
For example, you can split up your application functinality into multiple pieces, and have different people work on them. Or it can yield results during deployment, if, say, you need to have two layers of access to an app - user-level and admin - if your domain model is in a separate plugin, as Colin suggested, you can easily build two applications and deploy them separately.
For my app, I have several plugins specific to my project - domain classes plugin, one that is a bunch of code for importing data (which I can run easily against my site), some other plugins for graphing and customization of scaffolding. It takes a bit more thinking, but I expect this factoring will yield dividends in the future as we bring on more people to the team.
Related
I'm planning an MVC application of which there will be two variants; one for the US and one for Europe. I can't foresee a 3rd (or nth) deployment ever happening.
The two applications will both share almost identical functionality but with some (reasonably) small variations in the Model, View and Controller.
We'll be using Entity Framework with a database-first approach.
The two options I see are:
Use a base MVC solution, alongside a solution for the specifics of each deployment - extended base Models, Controller event handlers, some carefully considered partial views and bundled CSS & JS.
Use a single solution for the whole project but use two version control (SVN) branches for the separate deployments
Which of these is the 'proper' approach for this type of project? Or is there a third option?
UPDATE: One alternative solution which has been pointed out to me, would be to actually make this one single application hosted on Azure/AWS, and with some conditional logic depending on whether the request is made from the US or EU host-header.
Option 2 will make it harder to apply enhancement. You must apply it in 2 places. It will be worse if either branch is incompatible so some adjustment / modification is needed. It will be useful if the differences between environment is big.
Option 1 is better. Please note that you will need good plan to design partial CSS / javascript code. However, with this design you will face with code duplication (which is also happen in option 2). Consider this code:
public void DoSomething(){
// retrieve data
// specific code for EU / NA
// save data
}
This can lead to duplication in retrieve data and save data.
There is some trick to handle this but I think the cleanest way is to use Dependency Injection. With DI and decent DI Container (I'm inexperienced in configuring DI Container, so I cannot give you some suggestion which one is good), you will have benefit:
Can handle duplicated code such as example above
Can define some profiles for easier configuration and wiring, making the maintenance easier
Testable
I have a question with regards to using the unit of work with the repository to handle transactions across multiple modules.
I have two modules called customer and warehouse and they both have their own databases.
At the moment I use the unit of work to update each module independently of each other. What I want now is to update both modules at the same time and if one of them is invalid then neither are committed.
Is this possible with the unit of work pattern?
I don't think a true unit of work pattern is possible in this scenario. I'd be looking to a service class that used both repositories.
Edit - okay it might be possible - this guy refers to a solution that looks plausible:
Unit of Work with multiple Data Sources?
I'd still look at just wrapping the existing repositories in service/manager classes and keeping things simple.
I am currently working on a Rails 3 project that is divided up into four parts:
The public facing website
The administration website/backend
The models
The API for third party data access
As the models are shared between the three key components I want to keep them away from being in one main project, however each part needs access to the models, but I don't want to repeat the code and have different versions everywhere.
Currently I have the model code in a gem, and in each project's Gemfile I am referencing them with the following line:
gem "my_models", :path => "../my_models/"
However when I deploy to our test servers for my co-workers to evaluate the system on I need to pull the models from an external repository, so I swap out the above line with the following:
gem "my_models", :git => "git#private.repository.com:username/my_models.git"
This in its self works well, but its quite clunky in terms of 'versions' (i.e. I need to bump the version every time I wish to deploy the changes to the test servers), switch the line over to use git instead of local, and make sure that I'm pushing the files properly.
Previously I was using a shared git submodule, but this was just as awkward.
I would rather not build everything into one mega-project, as these tend to become monstrous and difficult to maintain, and I would also like to separate concerns if possible, so any changes I make to the administration site doesn't have much of a chance to impact the other components - obviously the models have the potential to cause issues, but that is a risk I have considered and understand.
What would people out there suggest when it comes to something like this? Or, am I going about it completely the wrong way?
Some additional background:
This app is a rewrite of an existing website which followed the model of 'lump everything into the one project' - unfortunately there are two issues here:
The app was badly developed - I inherited this project and when I first picked it up the load times were ~2 minutes per page with a single user - this has since been reduced but still has issues throughout
We are currently at our capacity limit of the current site and we anticipate that we will need to take on more load in the next 6 months - however scaling out with an 'all in one' app means we'll be wasting resources on scaling out the back end of the site which doesn't need it.
Essentially there are two things I want to separate - the Front end (being the public website and the API) and the back end - everything I know about software development tells me that combining all this together is not an ideal solution (and past history shows me that splitting these two is a good move in terms of ensuring front end performance).
Perhaps I need to look at this from another angle - keep the models in each project, and instead of sharing them between projects have a cut-down subset of functionality for each functional area (i.e. the backend needs to know who created a post, but the front end doesn't really care about that, so omit that logic when reading in the model).
drop the models project(put models into one of other parts, i'd suggest whatever you consider "more important"), put all projects into single repository(separate project folders) and make symlinks to models/libs/apis/whatever
your code is highly coupled together and you often need to make changes to few projects at once(like updating models and updating APIs that use them, etc)
one nice thing about single-repo-symlink setup is that your commits will be less fragmented and will usually represent full feature implementation - easier to track bugs, read history and maintain codebase
also when you deploy you don't need to read from many repositories - one less point of failure right there
release process is also simpler with such model as branch will now hold the scope of all projects
there are some drawbacks like symlinks dont work that well on windows and whatnot but for me it works perfectly
You can create a mountable engine that contains the shared models and create a gem out of it. This will handle the name spacing issues elegantly. Other nice aspect here is you get to share your assets also.
Watch this railscast for more details.
You'll still have to manage the 'versions' by pushing changes that need to be tested to a remote repo, but you can use the new local config of Bundler 1.2
http://gembundler.com/man/bundle-config.1.html#LOCAL-GIT-REPOS
This way it will pick up your local commits and you won't have to keep change your Gemfile upon deployment.
I know that this is not an solution for your particular problem. But I really suggest you to merge all projects into one. It is very usual to have all this parts in one application and there is no overhead. I think there is no not-awkward solution for this problem.
Take look at Git subtree.
This may work for you..
http://igor-alexandrov.github.io/blog/2013/03/28/using-git-subtree-to-share-code-between-rails-applications/
OR
You can write Rake task..
Example:-
namespace :sync do
desc 'Copy common models and tests from Master'
task :copy do
source_path = '/home/project/src-path'
dest_path = '/home/project/dest-path'
# Copy all models & tests
%x{cp #{source_path}/app/models/*.rb #{dest_path}/app/models/}
%x{cp #{source_path}/spec/models/*_spec.rb #{dest_path}/spec/models/}
# Database YML
%x{cp #{source_path}/config/database.yml #{dest_path}/config/database.yml}
end
See the below link.
http://hiltmon.com/blog/2013/10/14/rails-tricks-sharing-the-model/
Does your project have enough code coverage? If it does, I would try to separate the logic where it makes sense, and if a model is used in different projects, just pick one that fits best and write an API on top of that.
Then you could use that API to access those models (preferably using something like ActiveModel) on the other project. You would still have a simple CRUD, but all the core model logic would be handled externally.
Be sure to think well before splitting them up, though. You want to keep your domain tight on each app you create out of the Behemoth you want to torn apart.
Regarding engines:
I have used Engines for the same issue and it does help, but I also had to change my Gemfile to either point to a local path when developing, pushing the gem, then pulling it on the current project, which is the behavior you're not fond of.
I’m writing an application with Ruby on Rails. This application will be delivered to a minimum of two different customer types. The base is always the same but some of the views differ. That’s mostly it. For now.
Is there any way, for example using branches, to use the same code base and separate only the views, for example? I read the Git manual for branching but am still not sure if this is the best way to achieve what I need.
Another idea would be forking. But, is that clever? If I change something in the code of fork A, is it easy to merge these changes into fork B?
Branching and forking in git is not bad at all, as the merge support is great (possible the best of al VCMs).
Personally, I don't like the idea of branching or forking a project to provide different customization as it can very quickly become really difficult, e.g. what are you going to do if you have 15 different deployments?
I think a better approach is to build the application so it behaves differently depending on some parameters. I'm well aware that sometimes the implementations are very different, so this might not be useful anymore.
Another approach is to build the core of your app in a GEM which acts as a service to the application, and the only thing you customize per client are the views. Of course, the GEM should be generic enough to provide all the services you need.
Please share with us what you decided, as there's no best answer for your question.
It would probably be better to make you product select between the types at either build or runtime, that way you can use a single set of source.
Otherwise it is possible with branches, and merging, but you'll have more difficulty managing things. Forking is basically branching at this level.
I agree with #Augusto. You could run your app in 2 different environments, ie production_A and production_B. From there, you could use SettingsLogic to define configurations based on Rails.env, then reference those settings in your app when selecting which view to use for example.
What are common reasons to split a development project (e.g. ASP.NET MVC application) into multiple projects? Code organization can be done via folders just as well. Multiple projects tend to generate circular reference conflicts and increase complexity by having to manage/resolve those.
So, why?
Some reasons are
Encapsulation - By packaging a set of routines into another library, either as a static library or a set of dlls, it becomes a black box. For it to be a good black box, all you need to do is to make sure you give the right inputs and get the right outputs. It helps when you re-use that library. It also enforces certain rules and prevent programming by hacks ('hmm...I'll just make that member function public for now')
Reduces compile time - the library is already complied; you don't have to rebuild it at compile time, just link to it (assuming you are doing C++).
Decoupling - By encasing your classes into a standalone libraries, you can reduce coupling and allows you to reuse the library for other purpose. Likewise, as long as the interface of the library does not change, you can make changes to the library all you like, and others who link to it or refer to it does not need to change their code at all. DLLs are useful in this aspect that no re-compilation is required, but can be tricky to work with if many applications install different versions of the same DLLs. You can update libraries without impacting the client's code. While you can do the same with just folders, there is no explicit mechanism to force this behaviour.
Also, by practicing this discipline of having different libraries, you can also make sure what you have written is generic and decoupled from implementation.
Licensing/Commercialization - Well, I think this is quite obvious.
One possibility is to have a system that a given group (or single developer) can work on independently of the rest of the code. Another is to factor out common utility code that the rest of the system needs -- things like error handling, logging, and common utilities come to mind.
Of course, just when thinking about what goes in a particular function / class / file, where the boundaries are is a matter of art, not science.
One example I can think of is that you might find in developing one project that you end up developing a library which may be of more general use and which deserves to be its own project. For instance maybe you're working on a video game, and you end up writing an audio library that's in no way tied specifically to the game project.
Code reuse. Let's say you have project A and you start a new project B which has many of the same functions as project A. It makes sense to pull out the shared parts of A and make them into a library which can be used by both A and B. This allows you to have the code in both without having to maintain the same code in two places.
Code reuse, inverted. Let's say you have a project which works on one platform. Now you want it to work on two platforms. If you can separate out the platform-dependent code, you can start different projects for each platform-dependent library and then compile your central codebase with different libraries for different platforms.
Some tips about split your project into multiple projects:
One reason for separating a project into multiple class libraries is re-usability. I’ve yet to see the BLL or DAL part of application re-used in another application. This is what textbooks from the 90s used to tell us! But most if not all modern applications are too specific and even in the same enterprise, I’ve never seen the same BLL or DAL parts re-used across multiple applications. Most of the time what you have in those class libraries is purely to serve what the user sees in that particular application, and it’s not something that can be easily re-used (if at all).
Another reason for separating a project into multiple class libraries is about deployability. If you want to independently version and deploy these pieces, it does make sense to go down this path. But this is often a use case for frameworks, not enterprise applications. Entity Framework is a good example. It’s composed of multiple assemblies each focusing on different areas of functionality. We have one core assembly which includes the main artifacts, we have another assembly for talking to a SQL Server database, another one for SQLite and so on. With this modular architecture, we can reference and download only the parts that we need.
Imagine if Entity Framework was only one assembly! It would be one gigantic assembly with lots of code that we won’t need. Also, every time the support team added a new feature or fixed a bug, the entire monolithic assembly would have to be compiled and deployed. This would make this assembly very fragile. If we’re using Entity Framework on top of SQL Server, why should an upgrade because of a bug fix for SQLite impact our application? It shouldn’t! That’s why it’s designed in a modular way.
In most web applications out there, we version and deploy all these assemblies (Web, BLL and DAL) together. So, separating a project into 3 projects do not add any values.
Layers are conceptual. They don’t have a physical representation in
code. Having a folder or an assembly called BLL or DAL doesn’t mean
you have properly layered your application, neither does it mean you
have improved maintainability. Maintainability is about clean code,
small methods, small classes each having a single responsibility and
limited coupling between these classes. Splitting a project with fat
classes and fat methods into BLL/DAL projects doesn’t improve the
maintainability of your software. Assemblies are units of versioning
and deployment. Split a project into multiple projects if you want to
re-use certain parts of that in other projects, or if you want to
independently version and deploy each project.
Source: https://programmingwithmosh.com/csharp/should-you-split-your-asp-net-mvc-project-into-multiple-projects/
Ownership for one thing. If you have developers responsible for different parts of the code base then splitting the project up is the natural thing to do. One would also split projects by functionality. This reduces conflicts and complexity. If it increases, that just means a lack of communication and you are just doing it wrong.
Instead of questioning the value of code in multiple assemblies, question the value of clumping all of your code in one place.
Would you put everything in your kitchen in a single cabinet?
Circular references are circular references, whether they happen between assemblies or within them. The design of the offending components is most likely sub-optimal; eschewing organization via assemblies ironically prevents the compiler from detecting the situation for you.
I don't understand the statement that you can organize code just as well with folders as with projects. If that were true, our operating systems wouldn't have the concept of separate drives; they would just have one giant folder structure. Higher-order organizational patterns express a different kind of intent than simple folders.
Projects say "These concepts are closely related, and only peripherally related to other concepts."
There are some good answers here so I'll try not to repeat.
One benefit of splitting code out to it's own project is to reuse the assembly across multiple applications.
I liked the functional approach mentioned as well (e.g. Inventory, Shipping, etc. could all get their own projects). Another idea is to consider the deployment model. Code shared between layers, tiers, or servers should probably be in it's own common project (or set of projects if finer control is desired). Code earmarked for a certain tier may be in it's own project. e.g. if you had a separate web server and application server then you wouldn't want to deploy the UI code on the application server.
Another reason to split may be to allow small incremental deploys once the application is in production. Let's say you get an emergency production bug that needs to be fixed. If the small change requires a rebuild of the entire (one project) application you might have a hard time justifying a small test cycle to QA. You might have an easier sell if you were deploying only one assembly with a smaller set of functionality.