Interface Oriented Code Organization(IOCO)

Singapore Cityscape


When I started experimenting with TDD and specifically writing the test first, I had a sudden realization as I began to contemplate where should I place this new test I was about to create. 

I realized that the simplest place for the test would be in a folder structure that matched the UI for a web app or the API for a web API, and then quickly realized it would be helpful to have the production code folder structure match as well.

I had been working on several large complex code bases, some web apps, and some web APIs, and trying to find the code that needed to change or where to add new code wasn't obvious from the code organization.

The code was organized in the layered architecture style with UI layer, Service Layer, Repository Layer, etc. kind of like the structure Microsoft uses in "Traditional N-Layer architecture applications".

With folders for Controllers, Views, ViewModels, etc.


This architecture-oriented code organization(AOCO) is really good at telling you what architecture the solution is using but not so great at pointing you to where functionality X is residing. 

And even worse there is no single place where functionality X is residing. 

Some of it's in the Controllers folder, the Services folder, the ViewModels folder, the Views folder, etc. 

Could you spread out the functionality any further?

I find that it would perhaps be better for the code organization to point you in the direction of where most of the code for functionality X is residing based on the UI/API. 

This has several benefits beyond just making it simpler to navigate the code. 

It makes the code more modular.

It makes the code more cohesive, the code that changes together stays together.

I did some googling to see if this is something that others have started doing as well.

I found a few: 

Vertical Slice Architecture by Jimmy Bogard


 Organizing Code by Feature using Vertical Slices by Derek Comartin


And I found this tweet by Jessica Joy Kerr, which sums it up nicely:

These are all similar to what I envisioned, I just like to also have the code organization match the UI/API as closely as possible.

If there is common code across folders, then it's a judgment call to pull that code out to its own folder that doesn't match the UI/API and sacrifice modularity to remove duplication.

For an example of IOCO, I cloned the eShopOnWeb sample ASP.NET Core reference application and refactored the Web project of this app.

I refactored most of the Web project code into the following top-level folders of the Web project:


These folders were chosen based on the URL, for example, Manage comes from https://localhost:44315/manage/my-account. 

Although I had to make an exception for Catalog which is the default page and has just the site URL https://localhost:44315/ so in this case, I used the page title as the folder.

In the process I removed the Extensions, Interfaces, Pages, Services, ViewModels\Manage, Views\Manage, and Views\Order folders:


All that is left in the Controllers folder is the BaseApiController.cs


I left the Areas folder because it is hardcoded in the .NET source code and can't be customized.

I left the ViewModels\Account folder and the following in the Views folder as they are needed for login security and I didn't want to mess with it.



This is the extreme/pure version of IOCO. 

You could compromise in several different ways. 

You could leave the Pages folder and move all the code into folders following the public Web app/Web API interface starting under there. 

Having done that you may consider renaming the Pages folder as Derek Comartin did.

IOCO is about organizing code to match the public interface to the Web app/Web API so that developers can use that public interface as a guide to finding and placing code in the codebase. 

Comments

Popular posts from this blog

Microsoft.ApplicationBlocks. ExceptionManagement The event source x does not exist error

.NET generics with private accessors not compatible with MSTest

404 error in a REST WCF service