Abstract classes in Constellation

My team needs to create a set of abstract classes in Constellation.

There’s an excellent article on this: Abstract classes in Constellation not a best practice

My team wants to use a pattern in which abstract classes are required: This is the Facade pattern from the famous Design Patterns book.

Solution without Facade

Here is how our solution looks without a Facade:

Physical data model: Consists of concrete data objects with records in the DB.

Case layer: represents user journey. The case is straightforward but very data-driven – there are subflows, and subflows-within-subflows, that iterate as many times as there are data instances.

The challenge is that the physical data model is determined by today’s business requireme nts – for MLP1.

However, there are other MLPs coming later which involve major changes to the data model – not just adding objects and relationships but changing relationships from 1:M to M:M, and even wholesale replacement of some objects with new objects. We don’t have sight of all the future requirements – and even if we did, designing our data model around requirements that may or may not happen next year is not agile.

Therefore, think of today’s physical data model as an ‘implementation’.

When these big changes happen the case will have to be re-engineered to accommodate them, because it is tightly coupled to the implementation, which will be a big development.

Solution with Facade

Here is how our solution would look with a Facade:

Facade layer: This represents the abstract and unchanging aspects of the data model that the case needs to interact with. Modelled as a set of abstract classes with data pages to form the interface that the case uses. Data pages invoke data transforms that reach into the physical layer and transform the data into instances of abstract classes which are returned to the case: There are no DB records for these abstract classes – they are created on the fly. Hence we need abstract classes for this.

Some of the physical layer data objects don’t even need to be known about by the case, though they do change the way that other objects are returned to the case - hence the facade layer can hide these objects from the case and perform the transformations that use them.

The facade layer decouples the case from the current implementation (the physical data layer). When future change happens in the physical layer (i.e. the implementation changes) our changes are localised to the Facade layer. We don’ t need to re-engineer the case.

(Think about the way that Pega Connectors work – where they map Application layer data to Int layer data on the outgoing call, and map Int layer data to Application layer data on the incoming response – it’s a similar principle – those classes don’t have to be concrete – very often they are abstract because the data is not saved to the database)

Our challenge

As far as I am aware App Studio does not easily support abstract classes, therefore we will have to create them as concrete and switch to Dev Studio to change them to abstract. I am concerned that our case (created in App Studio) might not find it easy to plug into the facade layer.

Does anyone have experience of using App Studio and Constellation to create abstract classes? What challenges did you face? Any thoughts or tips?

Hi @MCCAR1
Short version :slight_smile: : Abstract classes can be used in Constellation, but they should be introduced only when they genuinely add decoupling value, not just because the pattern exists as a standard.

If we separate the business pattern from the Pega implementation constraint, the Facade pattern you describe is a reasonable way to isolate the case layer from the physical data model. However, from a Pega perspective, I would suggest being careful about introducing abstract classes unless they are truly adding value to the design. The main challenge with such design patterns w.r.t. constellation is to find out what is the smallest abstraction that gives the decoupling without fighting the platform :slight_smile: .

If we keep the case layer focused on business intent, not on physical data structure, you can use data pages as the main facade boundary and use data transforms to shape data at the boundary..
The facade can be expressed cleanly with data pages + data transform rules and that is usually the better Pega solution.
It is simpler, easier to troubleshoot, and more aligned with Constellation’s low-code model. Abstract classes are not wrong, but in I have seen they are often overused because teams try to protect themselves from future data-model changes that may never arrive.

My Initial thoughts are-

  • The pattern itself is valid.. a facade layer can help decouple case logic from implementation changes in the physical layer..
  • The implementation in Pega should be lightweight.. don’t create abstract classes just because the pattern says so.. Introduce abstract classes only where they genuinely represent a stable contract, not as a blanket architectural pattern..
  • If the case is only consuming data through data pages / data transforms, you may already have most of the decoupling benefit without needing a large abstract class hierarchy.
  • In many solutions, a data page acting as the facade is enough, with the underlying physical classes hidden behind it.

I would typically recommend using App Studio for the case layer and initial data object modelling and use data pages as the facade boundary between the case and the physical data model. Move to Dev Studio only where you need advanced class design, such as abstract classes or more complex rule layering. Keep the facade focused on stable business semantics, not on reproducing every physical object exactly.

Yes, abstract classes can be useful when the data is not persisted or the class is purely an interface/contract or if you want a stable semantic layer above volatile physical object. But if the only reason to introduce abstract classes is future proofing for changes that may or may not happen, I would be cautious. In Pega, over-abstracting too early can make the solution harder to maintain, especially in Constellation where low-code configuration is intended to stay the primary implementation path.

My recommendation for your case would be to position the solution to use a facade layer and yes, abstract classes may also be part of that facade if they represent a stable contract. But don’t force everything into abstract classes up front. Prefer data pages + data transforms as the main abstraction mechanism and introduce abstract classes only where they provide clear modelling value.
That gives you decoupling without overengineering the case layer.

I would strongly avoid designing the case directly against the physical model. That creates brittle coupling and guarantees rework later. And I would also avoid creating an elaborate abstract-class hierarchy to mirror a pattern. That tends to add complexity without enough payoff.

Thanks Ravi, lots of great advice there. We will certainly take this into consideration.

@MCCAR1 I am curious why you feel the need to introduce abstract classes?

Blueprint / App Studio create only Concrete Data Classes, sure, however, there is a key difference between data objects that have records and those that don’t.

  • In Blueprint this is handled between those data objects defined in the Data & Integrations step, and those defined as an embedded class
  • In platform, this is handled in the Data Pages tab - those connected to a system or record (Pega/External) and those not

So, I wouldn’t challenge the need for a fascade, more if you need to manually create abstract classes in dev studio to create a fascade. BP / App Studio (Infinity Studio in '26) would all allow this, then you stay inside the model.

Thanks Marc. We will definitely be proceeding with a facade. I agree that in Pega there is not much difference between an abstract class and a concrete one that has not been connected to a SoR - other than that by setting a class to ‘abstract’ this has the effect of removing the Keys section from the rule form (which arguably could be a useful indicator to developers of the intent of the class). Those of us originating from a traditional coding background (admittedly a long time ago in my case) may have more deeply held beliefs about abstract classes that don’t align with Product. But who are we to argue! :sweat_smile: