Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decoupled architecture

I'm working on a system where I'd like to have my layers decoupled as much as possible, you know, some kind of modular application to be able to switch databases and stuff without a serious modification of the rest of the system.

So, I've been watching for x-the time one of the talks of Robert C. Martin about good practices, clean code, decoupling architecture etc, to get some inspiration. What I find kinda weird is his description of the system Fitnesse and the way they've implemented store/load methods for WikiPages. I'm linking the video as well: Robert C. Martin - Clean Architecture and Design

What's he describing (at least from my understanding) is that the entity is aware of the mechanism how to store and load itself from some persistent layer. When he wanted to store WikiPages in-memory, he simply overrode the WikiPage and created a new InMemoryWikiPage. When he wanted to store them in a database, he did the same thing...

So, one of my questions is - what is this approach called? I've been learning the whole time about Repository patterns and stuff, and why should be classes like this persistence-ignorant, but I can't seem to find any materials on this thing he did. Because my application will consist of modules, I think this may help to solve my problems without a need for creating some centralized store for my entities... Every module would simply take care of itself including persistence of its entities.

I think the code would look like is something like this:

public class Person : IEntity
{
   public int ID { get;set; }
   public string Name { get;set; }

   public void Save()
   {
       ..
   }

   public void Update()
   {
   }

   public void Delete()
   {
   }

   ...
}

Seems a bit weird, but... Or maybe I misunderstood what he said in the video?

My second question would be, if you don't agree with this approach, what would be the path you'd take in such modular application?

Please provide an example if possible with some explanation.

like image 911
walther Avatar asked Apr 12 '13 10:04

walther


People also ask

What is meant by decoupled system?

Decoupled, or decoupling, is a state of an IT environment in which two or more systems somehow work or are connected without being directly connected. In a decoupled microservices architecture, for example, software services have none or very little knowledge about the other services.

What is AWS decoupled architecture?

A decoupled application architecture facilitates scalability, resiliency, reliability, and elasticity in the system. Messaging is one of the tactics, which can be utilized to implement the highly decoupled system.

What is decoupling in design?

In formal design, decoupling means to make the features of a formal system as independent as possible from each other. Decoupling tends to make the features semantically more primitive and the overall system more general.

What is a decoupled application?

A decoupled application architecture allows each component to perform its tasks independently - it allows components to remain completely autonomous and unaware of each other. A change in one service shouldn't require a change in the other services.


2 Answers

I'll answer your second question. I think you will be interested as well in Dependency Injection.

I'm not an expert on DI but I'll try to explain as clear as I'm able to.

First off, from wikipedia:

Dependency injection is a software design pattern that allows removing hard-coded dependencies and making it possible to change them, whether at run-time or compile-time.

The primary purpose of the dependency injection pattern is to allow selection among multiple implementations of a given dependency interface at runtime, or via configuration files, instead of at compile time.

There are many libraries around that help you implement this design pattern: AutoFac, SimpleInjector, Ninject, Spring .NET, and many others.

In theory, this is what your code would look like (AutoFac example)

var containerBuilder = new ContainerBuilder();
//This is your container builder. It will be used to register interfaces
// with concrete implementations

Then, you register concrete implementations for interface types:

containerBuilder.RegisterType<MockDatabase>().As<IDatabase>().InstancePerDependency();
containerBuilder.RegisterType<Person>().As<IPerson>().InstancePerDependency();

In this case, InstancePerDependency means that whenever you try to resolve IPerson, you'll get a new instance. It could be for example SingleInstance, so whenever you tried to resolve IPerson, you would get the same shared instance.

Then you build your container, and use it:

 var container = containerBuilder.Build();
 
 IPerson myPerson = container.Resolve<IPerson>(); //This will retrieve the object based on whatever implementation you registered for IPerson
 myPerson.Id = 1;

 myPerson.Save(); //Save your changes

The model I used in this example:

interface IEntity
{            
    int Id { get; set; }            
    string TableName { get; }
    //etc
}

interface IPerson: IEntity
{
    void Save();
}

interface IDatabase
{
    void Save(IEntity entity);
}

class SQLDatabase : IDatabase
{
    public void Save(IEntity entity)
    {
        //Your sql execution (very simplified)
        //yada yada INSERT INTO entity.TableName VALUES (entity.Id)
        //If you use EntityFramework it will be even easier
    }
}

class MockDatabase : IDatabase
{
    public void Save(IEntity entity)
    {
        return;
    }
}

class Person : IPerson
{
    IDatabase _database;

    public Person(IDatabase database)
    {
        this._database = database;
    }

    public void Save()
    {
        _database.Save(this);
    }

    public int Id
    {
        get;
        set;
    }

    public string TableName
    {
        get { return "Person"; }
    }
}

Don't worry, AutoFac will automatically resolve any Person Dependencies, such as IDatabase.

This way, in case you wanted to switch your database, you could simply do this:

containerBuilder.RegisterType<SqlDatabase>().As<IDatabase>().InstancePerDependency();

I wrote an over simplified (not suitable for use) code which serves just as a kickstart, google "Dependency Injection" for further information. I hope this helps. Good luck.

like image 147
Conrad Clark Avatar answered Sep 30 '22 14:09

Conrad Clark


The pattern you posted is an Active Record.

The difference between Repository and Active Record Pattern is that in Active Record pattern, data query and persistence, and the domain object are in one class, where as in Repository, the data persistence and query are decoupled from the domain object itself.

Another pattern that you may want to look into is the Query Object which, unlike respository pattern where its number of methods will increase in every possible query (filter, sorting, grouping, etc) the query object can use fluent interface to be expressive [1] or dedicated in which one you may pass parameter [2]

Lastly, you may look at Command Query Responsibility Segregation architecture for ideas. I personally loosely followed it, just picked up ideas that can help me.

Hope this helps.

Update base on comment

One variation of Repository pattern is this

UserRepository
{
    IEnumerable<User> GetAllUsers()
    IEnumerable<User> GetAllByStatus(Status status)
    User GetUserById(int id)
    ...
}

This one does not scale since the repository get's updated for additional query that way be requested

Another variation is to pass query object as parameter to the data query

UserRepository
{
    IEnumerable<User> GetAll(QueryObject)
    User GetUserById(int id)
    ...
}


var query = new UserQueryObject(status: Status.Single)
var singleUsers = userRepo.GetAll(query)

Some in .Net world, Linq expression is passed instead of QueryObject

var singleUsers = userRepo.GetAll(user => user.Status == Status.Single)

Another variation is to do dedicate Repository for retrieval on one entity by its unique identifier and save it, while query object is used to submit data retrieval, just like in CQRS.

Update 2

I suggest you get familiar with the SOLID principles. These principles are very helpful in guiding you creating a loosely coupled, high cohesive architecture.

Los Techies compilation on SOLID pricples contains good introductory articles regarding SOLID priciples.

like image 35
OnesimusUnbound Avatar answered Sep 30 '22 14:09

OnesimusUnbound