How to prevent this type of code duplication / fragmentation
So I'm having like 15 Models. (7 of them only have title field for things like Category, Education, Salary)
Each model is unlocked by a (Dingo) API REST Controller.
Each model is managed with a AdminLTE themed Controller that consumes the Dingo Controller with an InternalRequest.
I already abstracted a lot of the redundant REST methods to Traits and views to reusable template includes to prevent code repetition (that a lot of scaffolders and generator packages generate), so I can create minimal classes like this (i leave the docblocks and namespaces out):
class ContractType extends Model
{
protected $fillable = [
'title'
];
}
// Api endpoint : REST methods are moved to a custom RequestlessRestMethodsTrait
// and a DingoCrudRequestHandlerTrait that injects the ContractTypeRequest
class ContractTypesApiController extends AbstractApiController
{
public $model = ContractType::class; // resolves to ContractTypeRequest and ContractTypeTransformer
}
// admin crud controller : this class calls the ContractTypesApiController with Dingo InternalRequest
// CRUD methods are moved to a custom RequestlessRestMethodsTrait and a DingoApiConsumerTrait
class ContractTypesController extends AbstractTitleOnlyModelController
{
}
class ContractTypeTransformer extends ApiTransformer
{
public function transform(ContractType $item)
{
return [
'id' => $item->getKey(),
'title' => $item->title,
'links' => $this->getLinks($item),
];
}
}
class ContractTypeRequest extends ApiRequest
{
public function authorize()
{
return true; // for now ... untill permissions and roles are clear
}
public function rules()
{
// all API REST methods need to pass this Request
switch ($this->method()) {
case 'GET':
case 'DELETE': {
return [];
}
case 'POST': {
return [
'title' => 'required'
];
}
case 'PUT':
case 'PATCH': {
return [
'title' => 'required'
];
}
default:
break;
}
}
}
But still, trying to DRY and SOLID all the way, that still leaves me with:
- 15 SomeModelFormRequests
- 15 SomeModelTransFormers (Fractal)
- 15 SomeModelRepositories (Prettus)
- 8 A list (table) blade template (7 of them default to a fallback template)
- 8 A form blade template (7 of them default to a fallback template)
By using a seperate class for Model, ApiController, CrudAdminController, FormRequest, FractalTransformer, RepositoryClass, a set of resource routes (api, admin) a set of blade templates (list, edit), gives me 8 files to handle 1 Model. Without the abstraction layers, I would end up with 8 * 15 models = 120 seperate files.. When using the abstraction a simple title only model can be managed with around 7 files.
That feels like a lot of repetition and a lot of fragmentation(or 'separation of concerns' as we have been taught..) and in case of the templates some code duplication.
Yes, once the most of the classes are in place ,they probably won't change very often. But regardering the templates I forsee a lot of applying the same html change for seperate file that do more or less the same for a lot of models.
Is there a design flaw in my solution, or should I deal with the fact that SOLID will lead to some code repetition and fragmentation? I cannot see how working with Laravel generators or one of the thirdparty scaffolder packages leads to DRY code...
How do you guys handle this? Am I missing something obvious?
Please or to participate in this conversation.