Can you give Practical Advice on how to apply SOLID principals of OOP to N Tier Data Driven Web Apps

sao123

Lifer
May 27, 2002
12,653
205
106
So one of the things I am discovering in my career is that Data Driven (database) Web Applications in an N tier architecture are very difficult to test and maintain (enhance/fix).
I think that is true across the board in all software development, but some areas suffer more than others.

Since Data Driven applications (Lets say Asp.net in C# with Ado.net) are about 65% CRUD operations and 35% WorkFlow/business logic, that generally results in complex data model objects being tightly coupled the entire way through the UI, BL, and DAL. This makes independent unit testing very difficult.

And if God forbid, you have to add fields to the data models/tables because of new requirements, maintenance time is multipled to the extreme.

So i am looking for practical advice on (if starting a new application from scratch) how you can apply SOLID principles to a data driven application.

Generically speaking, there is little business reason for inheritance as custom complex data models are rarely reused. However a level of decoupling and abstraction might help to make the design more maintainable.
Furthermore, decoupling will make unit testing of UI & CRUD operations much more easier.
 

KB

Diamond Member
Nov 8, 1999
5,404
386
126
Holy buzzword soup!

I support many N-Tier applications so I know where you are coming from. I have subscribed to the KISS principle over the SOLID principle. Keeping my objects simple makes maintenance and testing much easier. I avoid inheritance for N-Tier as WCF doesn't handle inheritance well.
Using ADO.net for entities and POCO objects makes adding new fields and serializing relationships much easier. Often I don't even need any DTO objects, I can send the Entity object as is from tier to tier. Tools like AutoMapper help when a DTO becomes necessary. In addition using partial classes I can then add business logic to the entity/DTO object in the middle tier or UI.
 
  • Like
Reactions: cytg111

beginner99

Diamond Member
Jun 2, 2009
5,237
1,616
136
Since Data Driven applications (Lets say Asp.net in C# with Ado.net) are about 65% CRUD operations and 35% WorkFlow/business logic, that generally results in complex data model objects being tightly coupled the entire way through the UI, BL, and DAL. This makes independent unit testing very difficult.

This simply means your design is *redacted*. General rule of thumb is "composition over inheritance".

For your average CRUD web app, drop all the stupid all-in one frameworks. They force that tightly coupled behavior on you. The general design is simple. You create an API for all the operations. How you call it (webservice, REST, RPC) or what it returns (xml, json,..) doesn't really matter much albeit *redacted* xml. The point is the api on server side.

Your GUI be it html/js or a native phone app calls this api. See the benefit? You can now easily create different end-user apps with 0 change to backend. UI and backend are now decoupled.

As for the backend, does it need to be OOP? I say no but also depends on complexity of the app and dev team size. I mean what does a web service do? it takes parameters, makes a DB call and returns data (xml, json). That can be mostly procedural. OK, that doesn't help with unit testing. But why not to integration testing? that is needed anyway.

Edited for content to maintain a "Technical Forums" rating. -- Programming Moderator Ken g6
 
Last edited by a moderator:

sao123

Lifer
May 27, 2002
12,653
205
106
This simply means your design is *redacted*. General rule of thumb is "composition over inheritance".

For your average CRUD web app, drop all the stupid all-in one frameworks. They force that tightly coupled behavior on you. The general design is simple. You create an API for all the operations. How you call it (webservice, REST, RPC) or what it returns (xml, json,..) doesn't really matter much albeit *redacted* xml. The point is the api on server side.

Your GUI be it html/js or a native phone app calls this api. See the benefit? You can now easily create different end-user apps with 0 change to backend. UI and backend are now decoupled.

As for the backend, does it need to be OOP? I say no but also depends on complexity of the app and dev team size. I mean what does a web service do? it takes parameters, makes a DB call and returns data (xml, json). That can be mostly procedural. OK, that doesn't help with unit testing. But why not to integration testing? that is needed anyway.

Edited for content to maintain a "Technical Forums" rating. -- Programming Moderator Ken g6


Unfortunately, the platform is dictated by management and enterprise rules.
The chosen platform is Asp.net webforms with C# and SQL Server.
The reason why is pretty clear, ever try making an row addable/editable/deletable table control in ANY mvvm framework? its pretty close to impossible unless you buy the telerik library. its a design & maintenance nightmare.
Asp.net gives you a very simple GridView control that is templated and does nearly everything out of the box. (Oh look, I can make this column a textbox, and this one a dropdown, and this one a radio button, and this one a list box) NO mvvm framework gives you such control over the UI.

Does it need to be OOP? Yes. When you are dealing with hundreds of fields from dozens of tables, yes it needs to be OOP so the data organization is possible.

using solid principals of design: composition IS the real problem as it defies the first principal of solid: A class should do exactly one thing. Composition is exactly what we are doing that causes such a problem.

When a complex data model is composed of smaller related but still complex data models, modifying a single one changes the data structure (especially if one is a primary/foreign key), and then changing the structure, forces changes on the entire application from DAL to BLL to PL.
 

beginner99

Diamond Member
Jun 2, 2009
5,237
1,616
136
Unfortunately, the platform is dictated by management and enterprise rules.
The chosen platform is Asp.net webforms with C# and SQL Server.
The reason why is pretty clear, ever try making an row addable/editable/deletable table control in ANY mvvm framework? its pretty close to impossible unless you buy the telerik library. its a design & maintenance nightmare.

Asp.net gives you a very simple GridView control that is templated and does nearly everything out of the box. (Oh look, I can make this column a textbox, and this one a dropdown, and this one a radio button, and this one a list box) NO mvvm framework gives you such control over the UI.

There are many client-side (speak javascript grids, example) commercial and free that can do this. However you obviously don't get a gui wizard to pull in the fields. But you are programmers right? Everything has a cost. But doesn't matter if it is enterprise rules. In your case I would simply state, officially on the record, that the rule is stupid and being forced on a tech will greatly increase the risk of the project failing.


Does it need to be OOP? Yes. When you are dealing with hundreds of fields from dozens of tables, yes it needs to be OOP so the data organization is possible.

using solid principals of design: composition IS the real problem as it defies the first principal of solid: A class should do exactly one thing. Composition is exactly what we are doing that causes such a problem.

When a complex data model is composed of smaller related but still complex data models, modifying a single one changes the data structure (especially if one is a primary/foreign key), and then changing the structure, forces changes on the entire application from DAL to BLL to PL.

I mean you know your application and data. I can only make very vague and maybe completely unusable suggestions for your problem. Maybe look at other paradigms like data-oriented design? Why do I need OOP for data organization? Data can be held in simple structures (arrays, lists,dicts, dataframes).
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
So i am looking for practical advice on (if starting a new application from scratch) how you can apply SOLID principles to a data driven application.

Don't build it in WebForms. It's a dead-end technology for a reason. The nature of WebForms (IME anyway) tends to lead to tightly coupled and messy code. The way it tries to coerce the web into behaving like a desktop application ultimately makes life more difficult for devs and again leads to messier code. At the very least you should be starting new projects today in .NET MVC (ideally MVC Core), and for any serious project you're probably going to want a modern frontend framework like React (my preference), Angular, etc. I realize that you may not have a choice in the matter at your job, but IMO part of our job as engineers is poking management and being vocal when they're making the wrong choices in terms of technology.

As far as SOLID, I would argue that a lot of it doesn't really apply that much to web applications, at least based on my experience. If we go through the list...
  • Single responsibility: Good idea but kind of abstract, since "do a single thing" depends on your perspective. It might be literally a single action, say, send an email. But you can easily have one "action" with many sub steps. For example taking a payment might consist of, a) record transaction info, b) process credit card, c) record payment success/failure, d) email receipt on success. I don't know if there's one right answer here, but in my personal projects I've moved towards using the CQRS pattern, and I really like the way it organizes code into smaller components dedicated to one task (compared to the traditional service layer). That article doesn't go into detail, but you can also dispatch commands while inside of a command, allowing you to break apart common reusable chunks of business logic.
  • Open-closed: Honestly I'm struggling to think of where I've really used this, at least in MVC apps. To me it seems more oriented towards library code, since we just don't tend to use inheritance very much.
  • Liskov substituion: Critical for library code (an interface should be a contract), but hard to apply to web apps since we usually only have one implementation, because we're only using interfaces to allow for testing/mocking.
  • Interface segregation: Again more of a library code thing. I did have one project where we were using the repository pattern and split the interfaces into IReadOnlyXXXRepo and IXXXRepo (extends readonly), it was kind of nice, but also a bit overkill. For the most part I'm struggling to think of any place it could/would be beneficial.
  • Dependency inversion: IMO this is the biggest one on the list, because to me it means dependency injection. I don't know if WinForms even supports DI, but IMO it's mandatory in a modern application since it's very hard to write decoupled testable C# code without it.