The TCMS Onion Info Services Layers
How Func<T,T> creates the Onion Architecture
This is the fifth installment of the Technologist Career Management System series.
If you wish to catch up with previous posts:
The Modern Developer’s Showcase Projects
The TCMS Domains and Sub-Domain Layers
The TCMS Architecture has Two Domains:
-
The Application Domain – The Web Application Client for the Information Services Data
-
The Information Services Domain – Cloud and Data Repository Services for the TCMS Web Services Access Layer
These Two Architectural Domains Create
… The TCMS Business Domain
The Information Services domain has three Service Layer sub-domains and a Cross Cutting Concerns sub-domain.
The Three Service Sub-domains:
-
Cloud Services – Web Services for Skill Set Information Support Services
-
Data Services –Data Repository Data Acquisition and Transformation Services
-
Business Services –Cloud and Data Client Request and Delivery Services
The Cross Cutting Concerns Sub-domain:
-
Infrastructure Services – Logging, Module Messages and Exception Support Services
Info Services appears to follow traditional n-Tier Layers
The database repository Services Data is abstracted from DataOps by the DataDAL.
DataOps feeds transformed ORM Class Object Data, as complex composite data transfer objects to Business Services
Business Services delivers the Response DTOs to the Application Domain for consumption.
The Programmatic Access to the Services
… Are Actually Using an Onion Architecture
Func<TRequest, TResult> and the Services Onion
In traditional n-Tier architecture your session moves from higher layers to the lower lowers. In some cases your session may move directly to lower layers.
As your calls moves you to the next layer your session with your previous layer closes. When you return from a lower layer a new session is opened. As you traverse back up the layers you open and close new sessions as you return to the source layer.
The TCMS “Onion Architecture” uses a “Wrapper Class” Design
Each Sub-domain Layer in the n-Tier Schema
… Is Accessed through a Sub-domain Wrapper Class
+CODE: The Data Services Onion Wrapper
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public static class DataOpsPeopleServices { private static PeopleOps _peopleOps { get; set; } static DataOpsPeopleServices() { _peopleOps = new PeopleOps(); } public static TechnologistInfoResponseDto GetTechnologistInfo(TechnologistInfoRequestDto requestDto) { return DataOpsHelpers.ExecuteServiceRequestWithLogging(_peopleOps.GetTechnologistInfo, requestDto); } } |
The Data Services’ DataOps assembly is the highest layer in the Data Services sub-domain.
The root of the DataOps assembly holds access to the Domain Entity: People by using the Onion Wrapper Class: DataOpsPeopleServices.
The calling Client requests a Technologist with a PeopleId of ‘1’ using the TechnologistInfoRequestDto as a State object parameter in the Method: GetTechnologistInfo (TechnologistInfoRequestDto requestDto) and expects a DTO return of: TechnologistInfoResponseDto.
This call to the Wrapper Class has the same Method signature as the underlying PeopleOps data layer Class Method but it is being passed as a ‘Method Data Parameter’ in the Constructor.
So when you see Func<> think: This means I’m passing a Method as Data
Func<TRequest, TResponse> where TRequest : BaseRequest where TResponse : BaseResponse, new()translated to English:
“A method that takes an “Object with a Base Class of Type BaseRequest“, as a parameter, and returns an “Object with a Base Class of Type BaseResponse” with the ability to create a new BaseResponse object in the code”
+CODE: The Helper Method using the Func<TRequest, TResponse> as a Method being Passed as Data
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public static TResponse ExecuteServiceRequestWithLogging<trequest, tresponse="">(Func<trequest, tresponse=""> methodCall, TRequest request) where TRequest : BaseRequest where TResponse : BaseResponse, new() { LogResponseDTO logResponse; var response = new TResponse(); var startTime = DateTime.Now; try { response = methodCall(request); } catch (Exception error) { logResponse = CreateExceptionLogEntry(error, startTime, response); response.IsLogSuccess = logResponse.Success; if (logResponse.ErrorList.Count > 0) response.BubbleErrors(response.ErrorList); response.ErrorList.Add(new ErrorInfo(error)); return response; } logResponse = CreateSuccessLogEntry(startTime, response); if (logResponse.ErrorList.Count > 0) { response.BubbleErrors(response.ErrorList); return response; } response.IsLogSuccess = logResponse.Success; if (response.ErrorList.Count > 0) return response; response.Success = true; return response; } |
The Func<TRequest, TResult> is a way of treating a Behavior Method
… As if it were a State Data Method Parameter
Stay Tuned for the Next Installment
… of the TCMS Showcase Application
The following two tabs change content below.
I am a Principal Architect at Liquid Hub in the Philadelphia area specializing in Agile Practices as a Certified Scrum Master (CSM). I use Test Driven Development (TDD) and Acceptance Test Driven Development (ATDD) with Behavior Driven Development (BDD) as my bridge to Agile User Stories Acceptance Criteria in a Domain Driven Design (DDD) implementing true RESTful services
Latest posts by Brad Huett (see all)
- DevOps: A Bridge to Your DevOps Culture - March 25, 2016
- Embracing Test Driven Development (TDD) - March 25, 2016
- DevOps: Delivering Agile Projects - March 25, 2016


