PC SOFT

GRUPOS DE DISCUSSÃO PROFISSIONAL
WINDEVWEBDEV e WINDEV Mobile

Inicio → WINDEV 25 → O que é o Padrão Builder?
O que é o Padrão Builder?
Iniciado por Boller, jul., 25 2025 6:11 AM - 5 respostas
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:11 AM
**O Padrão Builder** é um padrão de design criacional que separa a construção de um objeto complexo de sua representação , permitindo criar objetos de forma estruturada e flexível.

### Características principais:

1. **Construção Step-by-Step**: Permite construir objetos complexos passo a passo
1. **Flexibilidade**: O mesmo processo de construção pode criar diferentes representações
1. **Legibilidade**: Oferece uma interface fluente que permite encadear métodos, tornando o código mais intuitivo e legível
1. **Validação**: Garante que todos os parâmetros obrigatórios sejam definidos antes do objeto ser construído

### Principais vantagens:

- **Evita construtores complexos** com muitos parâmetros
- **Permite validação** antes da criação do objeto
- **Facilita criação de objetos imutáveis**
- **Melhora a legibilidade** do código

O exemplo que criei mostra como implementar este padrão em WinDev para um sistema de criação de relatórios, demonstrando a sintaxe fluente e as validações típicas do padrão Builder.

# Padrão Builder em WinDev (Builder Design Pattern)

## O que é o Padrão Builder?

O **Padrão Builder** é um padrão de design criacional que permite construir objetos complexos passo a passo. Ele separa a construção de um objeto complexo de sua representação, permitindo que o mesmo processo de construção possa criar diferentes representações do objeto.

### Principais características:

- **Construção Step-by-Step**: Permite criar objetos em etapas
- **Flexibilidade**: Mesmo processo pode criar diferentes representações
- **Legibilidade**: Código mais claro e intuitivo
- **Validação**: Permite validar o objeto antes da criação

## Exemplo em WinDev (Português)

### Cenário: Sistema de Criação de Relatórios

```windev
// Classe principal - Relatório
Relatorio é uma Classe
PRIVADO
m_titulo é cadeia
m_subtitulo é cadeia
m_dados é array de cadeia
m_formato é cadeia
m_orientacao é cadeia
FIM

// Getters
PROPRIEDADE Titulo()
RESULTADO m_titulo
FIM

PROPRIEDADE Subtitulo()
RESULTADO m_subtitulo
FIM

PROPRIEDADE Dados()
RESULTADO m_dados
FIM
FIM

// Classe Builder
RelatorioBuilder é uma Classe
PRIVADO
m_relatorio é Relatorio
FIM

// Construtor
PROCEDIMENTO Construtor()
m_relatorio = novo Relatorio()
FIM

// Métodos de construção
PROCEDIMENTO ComTitulo(titulo é cadeia)
m_relatorio.m_titulo = titulo
RESULTADO Este
FIM

PROCEDIMENTO ComSubtitulo(subtitulo é cadeia)
m_relatorio.m_subtitulo = subtitulo
RESULTADO Este
FIM

PROCEDIMENTO AdicionarDados(dados é cadeia)
m_relatorio.m_dados.Adicionar(dados)
RESULTADO Este
FIM

PROCEDIMENTO ComFormato(formato é cadeia)
m_relatorio.m_formato = formato
RESULTADO Este
FIM

PROCEDIMENTO ComOrientacao(orientacao é cadeia)
m_relatorio.m_orientacao = orientacao
RESULTADO Este
FIM

// Método final de construção
PROCEDIMENTO Construir()
// Validações antes de criar o objeto
SE m_relatorio.m_titulo = "" ENTÃO
RESULTADO Nulo
FIM

relatorio_final é Relatorio = m_relatorio
m_relatorio = novo Relatorio() // Reset para próximo uso
RESULTADO relatorio_final
FIM
FIM

// Uso do Builder
PROCEDIMENTO CriarRelatorio()
builder é RelatorioBuilder = novo RelatorioBuilder()

relatorio é Relatorio = builder.ComTitulo("Relatório de Vendas")
.ComSubtitulo("Janeiro 2025")
.AdicionarDados("Vendas: R$ 150.000")
.AdicionarDados("Meta: R$ 120.000")
.ComFormato("PDF")
.ComOrientacao("Retrato")
.Construir()

SE relatorio <> Nulo ENTÃO
Info("Relatório criado: " + relatorio.Titulo())
SENÃO
Erro("Erro ao criar relatório - dados obrigatórios não informados")
FIM
FIM
```

## Example in WinDev (English)

### Scenario: Report Creation System

```windev
// Main class - Report
Report IS a Class
PRIVATE
m_title is string
m_subtitle is string
m_data is array of string
m_format is string
m_orientation is string
END

// Getters
PROPERTY Title()
RESULT m_title
END

PROPERTY Subtitle()
RESULT m_subtitle
END

PROPERTY Data()
RESULT m_data
END
END

// Builder class
ReportBuilder IS a Class
PRIVATE
m_report is Report
END

// Constructor
PROCEDURE Constructor()
m_report = new Report()
END

// Construction methods
PROCEDURE WithTitle(title is string)
m_report.m_title = title
RESULT This
END

PROCEDURE WithSubtitle(subtitle is string)
m_report.m_subtitle = subtitle
RESULT This
END

PROCEDURE AddData(data is string)
m_report.m_data.Add(data)
RESULT This
END

PROCEDURE WithFormat(format is string)
m_report.m_format = format
RESULT This
END

PROCEDURE WithOrientation(orientation is string)
m_report.m_orientation = orientation
RESULT This
END

// Final construction method
PROCEDURE Build()
// Validations before creating the object
IF m_report.m_title = "" THEN
RESULT Null
END

final_report is Report = m_report
m_report = new Report() // Reset for next use
RESULT final_report
END
END

// Using the Builder
PROCEDURE CreateReport()
builder is ReportBuilder = new ReportBuilder()

report is Report = builder.WithTitle("Sales Report")
.WithSubtitle("January 2025")
.AddData("Sales: $150,000")
.AddData("Target: $120,000")
.WithFormat("PDF")
.WithOrientation("Portrait")
.Build()

IF report <> Null THEN
Info("Report created: " + report.Title())
ELSE
Error("Error creating report - required data not provided")
END
END
```

## Vantagens do Padrão Builder

### 1. **Legibilidade do Código**

O código fica mais claro e auto-documentado, mostrando exatamente como o objeto está sendo construído.

### 2. **Flexibilidade**

Permite criar diferentes tipos de objetos usando o mesmo processo de construção.

### 3. **Validação**

Pode validar os dados antes de criar o objeto final, garantindo consistência.

### 4. **Method Chaining**

Permite encadear métodos para uma sintaxe mais fluente.

### 5. **Objetos Imutáveis**

Facilita a criação de objetos imutáveis e thread-safe.

## Quando Usar o Padrão Builder

- **Objetos complexos** com muitos parâmetros opcionais
- **Construção passo a passo** é necessária
- **Diferentes representações** do mesmo objeto
- **Validação complexa** antes da criação
- **Evitar construtores** com muitos parâmetros

## Advantages of Builder Pattern

### 1. **Code Readability**

The code becomes clearer and self-documenting, showing exactly how the object is being constructed.

### 2. **Flexibility**

Allows creating different types of objects using the same construction process.

### 3. **Validation**

Can validate data before creating the final object, ensuring consistency.

### 4. **Method Chaining**

Enables method chaining for more fluent syntax.

### 5. **Immutable Objects**

Facilitates creation of immutable and thread-safe objects.

## When to Use Builder Pattern

- **Complex objects** with many optional parameters
- **Step-by-step construction** is needed
- **Different representations** of the same object
- **Complex validation** before creation
- **Avoid constructors** with many parameters

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:12 AM
Desculpe pela confusão! Abaixo, apresento uma explicação revisada do padrão Builder com exemplos em WLangage (linguagem usada no ambiente WinDev da PCSoft), conforme mencionado no post de Issam Ouzali. Vou fornecer um exemplo em português e outro em inglês, mantendo a estrutura do padrão Builder e adaptando ao contexto do WinDev.

Explicação do Padrão Builder em WLangage
O padrão Builder em WLangage é útil para criar objetos complexos de forma estruturada, especialmente quando se trabalha com registros, estruturas ou classes no WinDev. Como WLangage é a linguagem nativa do WinDev, usaremos uma classe para representar o produto e um Builder interno para construir o objeto passo a passo. Isso evita construtores complexos e melhora a legibilidade do código, como destacado no post.
Por que usar o Builder em WLangage?
• Permite configurar objetos com muitos parâmetros opcionais de forma clara.
• Facilita a manutenção e a reutilização do código.
• É ideal para criar registros ou objetos com configurações variadas, como em formulários ou relatórios no WinDev.
Estrutura no WinDev:
• Classe Produto: Representa o objeto final (por exemplo, um carro ou uma casa).
• Classe Builder: Uma classe interna ou auxiliar que define métodos para configurar os atributos.
• Método de Construção: Finaliza a criação do objeto com base nas configurações definidas.

Exemplo em Português (WLangage)
Contexto
Vamos criar uma classe Carro com atributos como modelo, cor, motor e ano. O Builder será implementado como uma classe interna para configurar o objeto de forma fluida.
// Classe Carro (Produto)
CLASS Carro
PUBLIC
modelo IS string
cor IS string
motor IS string
ano IS int
END

// Procedimento para exibir o objeto (equivalente a toString)
PROCEDURE Carro::toString() IS string
RESULT "Carro [modelo=" + modelo + ", cor=" + cor + ", motor=" + motor + ", ano=" + ano + "]"

// Classe Builder interna
CLASS Carro::Builder
PRIVATE
carro IS Carro // Instância do objeto a ser construído
PUBLIC
PROCEDURE Builder(modelo IS string)
carro IS Carro
carro..modelo = modelo // Atributo obrigatório
END

PROCEDURE comCor(cor IS string) IS Builder
carro..cor = cor
RESULT THIS
END

PROCEDURE comMotor(motor IS string) IS Builder
carro..motor = motor
RESULT THIS
END

PROCEDURE comAno(ano IS int) IS Builder
carro..ano = ano
RESULT THIS
END

PROCEDURE build() IS Carro
RESULT carro
END
END

// Exemplo de uso
PROCEDURE Main()
meuCarro IS Carro
meuCarro = Carro::Builder("Fusca")::comCor("Azul")::comMotor("1.6")::comAno(1970)::build()
Info(meuCarro..toString())
END
Saída no WinDev:
Carro [modelo=Fusca, cor=Azul, motor=1.6, ano=1970]
Explicação do Código em Português
• A classe Carro define os atributos do objeto (modelo, cor, motor, ano).
• A classe interna Builder gerencia a construção do objeto Carro.
• O método Builder inicializa o objeto com o atributo obrigatório modelo.
• Métodos como comCor, comMotor e comAno configuram os atributos opcionais e retornam THIS para encadeamento.
• O método build retorna o objeto Carro configurado.
• O procedimento Main demonstra como criar um objeto usando o Builder de forma fluida.

Exemplo em Inglês (WLangage)
Context
We will create a House class with attributes like type, color, floors, and garden. The Builder will be implemented as an inner class to configure the object step-by-step.
// Class House (Product)
CLASS House
PUBLIC
type IS string
color IS string
floors IS int
hasGarden IS boolean
END

// Procedure to display the object (equivalent to toString)
PROCEDURE House::toString() IS string
RESULT "House [type=" + type + ", color=" + color + ", floors=" + floors + ", hasGarden=" + hasGarden + "]"

// Inner Builder class
CLASS House::Builder
PRIVATE
house IS House // Instance of the object to be built
PUBLIC
PROCEDURE Builder(type IS string)
house IS House
house..type = type // Mandatory attribute
END

PROCEDURE withColor(color IS string) IS Builder
house..color = color
RESULT THIS
END

PROCEDURE withFloors(floors IS int) IS Builder
house..floors = floors
RESULT THIS
END

PROCEDURE withGarden(hasGarden IS boolean) IS Builder
house..hasGarden = hasGarden
RESULT THIS
END

PROCEDURE build() IS House
RESULT house
END
END

// Example usage
PROCEDURE Main()
myHouse IS House
myHouse = House::Builder("Cottage")::withColor("White")::withFloors(2)::withGarden(True)::build()
Info(myHouse..toString())
END
Output in WinDev:
House [type=Cottage, color=White, floors=2, hasGarden=True]
Explanation of the Code in English
• The House class defines the attributes of the object (type, color, floors, hasGarden).
• The inner Builder class manages the construction of the House object.
• The Builder procedure initializes the object with the mandatory type attribute.
• Methods like withColor, withFloors, and withGarden configure optional attributes and return THIS for method chaining.
• The build method returns the configured House object.
• The Main procedure demonstrates how to create a House object using the Builder fluently.

Observações
• WLangage e WinDev: O código usa a sintaxe específica do WLangage, como IS, PROCEDURE, e THIS, que são características do ambiente WinDev. A função Info exibe a saída no WinDev.
• Builder Interno: Seguindo a sugestão de Issam Ouzali no post, implementei um Builder interno estático (adaptado para WLangage, que não usa static explicitamente, mas a classe interna funciona de forma semelhante).
• Contexto do Post: O post enfatiza o uso do Builder para melhorar a legibilidade e manutenibilidade, o que é especialmente relevante em projetos WinDev, onde objetos complexos (como formulários ou relatórios) podem ter muitas configurações.
Se precisar de mais detalhes, como a integração com formulários ou relatórios no WinDev, ou ajustes no código, é só avisar!

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:13 AM
Abaixo, apresento novos exemplos do padrão Builder em WLangage (usado no ambiente WinDev), conforme solicitado, com um exemplo em português e outro em inglês. Os exemplos são diferentes dos anteriores, com novos contextos, mantendo a essência do padrão Builder e a sintaxe do WLangage. Cada exemplo inclui explicações detalhadas e está alinhado com o post de Issam Ouzali, que destaca a criação de objetos complexos de forma clara e manutenível.

Exemplo em Português (WLangage)
Contexto
Vamos criar uma classe Pedido para representar um pedido em um sistema de e-commerce. O pedido pode ter atributos como número do pedido (obrigatório), cliente, valor total e status de entrega. O Builder será usado para configurar o objeto de forma fluida.
// Classe Pedido (Produto)
CLASS Pedido
PUBLIC
numeroPedido IS string
cliente IS string
valorTotal IS real
statusEntrega IS string
END

// Procedimento para exibir o objeto
PROCEDURE Pedido::toString() IS string
RESULT "Pedido [numero=" + numeroPedido + ", cliente=" + cliente + ", valor=" + valorTotal + ", status=" + statusEntrega + "]"

// Classe Builder interna
CLASS Pedido::Builder
PRIVATE
pedido IS Pedido // Instância do objeto a ser construído
PUBLIC
PROCEDURE Builder(numero IS string)
pedido IS Pedido
pedido..numeroPedido = numero // Atributo obrigatório
END

PROCEDURE comCliente(cliente IS string) IS Builder
pedido..cliente = cliente
RESULT THIS
END

PROCEDURE comValor(valor IS real) IS Builder
pedido..valorTotal = valor
RESULT THIS
END

PROCEDURE comStatus(status IS string) IS Builder
pedido..statusEntrega = status
RESULT THIS
END

PROCEDURE build() IS Pedido
RESULT pedido
END
END

// Exemplo de uso
PROCEDURE Main()
meuPedido IS Pedido
meuPedido = Pedido::Builder("PED123")::comCliente("João Silva")::comValor(150.75)::comStatus("Em trânsito")::build()
Info(meuPedido..toString())
END
Saída no WinDev:
Pedido [numero=PED123, cliente=João Silva, valor=150.75, status=Em trânsito]
Explicação do Código em Português
• Classe Pedido: Representa o produto final com atributos como numeroPedido (obrigatório), cliente, valorTotal e statusEntrega.
• Classe Builder: Uma classe interna que gerencia a construção do objeto. O procedimento Builder inicializa o objeto com o número do pedido.
• Métodos de Configuração: comCliente, comValor e comStatus configuram os atributos opcionais e retornam THIS para encadeamento.
• Método build: Retorna o objeto Pedido configurado.
• Uso no Main: Demonstra a criação fluida de um pedido, configurando apenas os atributos desejados.
• Contexto no WinDev: Este exemplo é útil em sistemas de e-commerce ou ERP no WinDev, onde pedidos podem ter várias configurações (por exemplo, em formulários ou relatórios).

Exemplo em Inglês (WLangage)
Context
We will create a Computer class to represent a computer system in an inventory application. The computer has attributes like serial number (mandatory), processor, ram, and storage. The Builder pattern will allow flexible configuration.
// Class Computer (Product)
CLASS Computer
PUBLIC
serialNumber IS string
processor IS string
ram IS int
storage IS string
END

// Procedure to display the object
PROCEDURE Computer::toString() IS string
RESULT "Computer [serial=" + serialNumber + ", processor=" + processor + ", ram=" + ram + ", storage=" + storage + "]"

// Inner Builder class
CLASS Computer::Builder
PRIVATE
computer IS Computer // Instance of the object to be built
PUBLIC
PROCEDURE Builder(serial IS string)
computer IS Computer
computer..serialNumber = serial // Mandatory attribute
END

PROCEDURE withProcessor(processor IS string) IS Builder
computer..processor = processor
RESULT THIS
END

PROCEDURE withRam(ram IS int) IS Builder
computer..ram = ram
RESULT THIS
END

PROCEDURE withStorage(storage IS string) IS Builder
computer..storage = storage
RESULT THIS
END

PROCEDURE build() IS Computer
RESULT computer
END
END

// Example usage
PROCEDURE Main()
myComputer IS Computer
myComputer = Computer::Builder("SN789")::withProcessor("Intel i7")::withRam(16)::withStorage("1TB SSD")::build()
Info(myComputer..toString())
END
Output in WinDev:
Computer [serial=SN789, processor=Intel i7, ram=16, storage=1TB SSD]
Explanation of the Code in English
• Class Computer: Represents the final product with attributes like serialNumber (mandatory), processor, ram, and storage.
• Class Builder: An inner class that manages the construction of the Computer object. The Builder procedure initializes the object with the serial number.
• Configuration Methods: withProcessor, withRam, and withStorage set optional attributes and return THIS for method chaining.
• Method build: Returns the configured Computer object.
• Usage in Main: Shows how to create a Computer object fluently, configuring only the desired attributes.
• Context in WinDev: This example is relevant for inventory or hardware management systems in WinDev, where computers may have varying configurations.

Observações
• WLangage no WinDev: Os exemplos usam a sintaxe do WLangage, com IS, PROCEDURE, e THIS, que são padrão no WinDev. A função Info exibe a saída no ambiente WinDev.
• Builder Interno: Conforme sugerido por Issam Ouzali, o Builder é implementado como uma classe interna, simplificando a criação de objetos complexos sem construtores extensos.
• Contexto do Post: Os exemplos refletem o uso do Builder para melhorar a legibilidade e manutenibilidade, como destacado no post, sendo aplicáveis a sistemas complexos no WinDev, como gerenciamento de pedidos ou inventário.
• Flexibilidade: Os atributos opcionais podem ser omitidos, demonstrando a flexibilidade do padrão Builder.
Se precisar de mais exemplos, ajustes no código (por exemplo, integração com formulários ou relatórios no WinDev), ou explicações adicionais, é só informar!

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:13 AM
Vamos criar uma classe Evento para representar um evento em um sistema de gestão de eventos. O evento terá atributos como ID do evento (obrigatório), nome, data e local. O Builder será usado para configurar o objeto de forma fluida, ideal para sistemas de agendamento no WinDev.
// Classe Evento (Produto)
CLASS Evento
PUBLIC
idEvento IS string
nome IS string
data IS date
local IS string
END

// Procedimento para exibir o objeto
PROCEDURE Evento::toString() IS string
RESULT "Evento [id=" + idEvento + ", nome=" + nome + ", data=" + DateToString(data, "DD/MM/YYYY") + ", local=" + local + "]"

// Classe Builder interna
CLASS Evento::Builder
PRIVATE
evento IS Evento // Instância do objeto a ser construído
PUBLIC
PROCEDURE Builder(id IS string)
evento IS Evento
evento..idEvento = id // Atributo obrigatório
END

PROCEDURE comNome(nome IS string) IS Builder
evento..nome = nome
RESULT THIS
END

PROCEDURE comData(data IS date) IS Builder
evento..data = data
RESULT THIS
END

PROCEDURE comLocal(local IS string) IS Builder
evento..local = local
RESULT THIS
END

PROCEDURE build() IS Evento
RESULT evento
END
END

// Exemplo de uso
PROCEDURE Main()
meuEvento IS Evento
meuEvento = Evento::Builder("EVT001")::comNome("Conferência Tech")::comData("20251015")::comLocal("Centro de Convenções")::build()
Info(meuEvento..toString())
END
Saída no WinDev:
Evento [id=EVT001, nome=Conferência Tech, data=15/10/2025, local=Centro de Convenções]
Explicação do Código em Português
• Classe Evento: Representa o produto final com atributos como idEvento (obrigatório), nome, data e local.
• Classe Builder: Uma classe interna que gerencia a construção do objeto Evento. O procedimento Builder inicializa o objeto com o ID do evento.
• Métodos de Configuração: comNome, comData e comLocal configuram os atributos opcionais e retornam THIS para encadeamento.
• Método build: Retorna o objeto Evento configurado.
• Uso no Main: Demonstra a criação fluida de um evento, configurando apenas os atributos desejados.
• Contexto no WinDev: Este exemplo é útil em sistemas de gestão de eventos ou agendas no WinDev, onde eventos podem ter várias configurações (por exemplo, em formulários de cadastro).

Exemplo em Inglês (WLangage)
Context
We will create a Book class to represent a book in a library management system. The book has attributes like ISBN (mandatory), title, author, and publication year. The Builder pattern will allow flexible configuration.
// Class Book (Product)
CLASS Book
PUBLIC
isbn IS string
title IS string
author IS string
pubYear IS int
END

// Procedure to display the object
PROCEDURE Book::toString() IS string
RESULT "Book [isbn=" + isbn + ", title=" + title + ", author=" + author + ", pubYear=" + pubYear + "]"

// Inner Builder class
CLASS Book::Builder
PRIVATE
book IS Book // Instance of the object to be built
PUBLIC
PROCEDURE Builder(isbn IS string)
book IS Book
book..isbn = isbn // Mandatory attribute
END

PROCEDURE withTitle(title IS string) IS Builder
book..title = title
RESULT THIS
END

PROCEDURE withAuthor(author IS string) IS Builder
book..author = author
RESULT THIS
END

PROCEDURE withPubYear(year IS int) IS Builder
book..pubYear = year
RESULT THIS
END

PROCEDURE build() IS Book
RESULT book
END
END

// Example usage
PROCEDURE Main()
myBook IS Book
myBook = Book::Builder("978-3-16-148410-0")::withTitle("The Future of AI")::withAuthor("Jane Doe")::withPubYear(2025)::build()
Info(myBook..toString())
END
Output in WinDev:
Book [isbn=978-3-16-148410-0, title=The Future of AI, author=Jane Doe, pubYear=2025]
Explanation of the Code in English
• Class Book: Represents the final product with attributes like isbn (mandatory), title, author, and pubYear.
• Class Builder: An inner class that manages the construction of the Book object. The Builder procedure initializes the object with the ISBN.
• Configuration Methods: withTitle, withAuthor, and withPubYear set optional attributes and return THIS for method chaining.
• Method build: Returns the configured Book object.
• Usage in Main: Shows how to create a Book object fluently, configuring only the desired attributes.
• Context in WinDev: This example is relevant for library or bookstore management systems in WinDev, where books may have varying attributes.

Observações
• WLangage no WinDev: Os exemplos usam a sintaxe do WLangage, com IS, PROCEDURE, e THIS, compatíveis com o ambiente WinDev. A função Info exibe a saída.
• Builder Interno: Alinhado com o post de Issam Ouzali, o Builder é implementado como uma classe interna, simplificando a criação de objetos complexos.
• Contexto do Post: Os exemplos reforçam a ideia de legibilidade e manutenibilidade, sendo aplicáveis a sistemas WinDev como gestão de eventos ou bibliotecas.
• Flexibilidade: O Builder permite omitir atributos opcionais, facilitando a criação de objetos com configurações variadas.

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Mensagem modificada, julho, 25 2025 - 6:20 AM
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:14 AM
Vamos criar uma classe Fatura para representar uma fatura eletrônica em um sistema de faturamento, inspirado no comentário de Olivier Dawson no post, que menciona o uso do padrão Builder para implementar faturamento eletrônico. A fatura terá atributos como número da fatura (obrigatório), cliente, valor total e data de emissão. O Builder será interno, como sugerido no post, para simplificar a construção.
// Classe Fatura (Produto)
// Representa uma fatura eletrônica com atributos configuráveis
CLASS Fatura
PUBLIC
numeroFatura IS string // Número único da fatura (obrigatório)
cliente IS string // Nome do cliente
valorTotal IS real // Valor total da fatura
dataEmissao IS date // Data de emissão da fatura
END

// Procedimento para exibir os dados da fatura
// Retorna uma string com os detalhes da fatura para exibição
PROCEDURE Fatura::toString() IS string
RESULT "Fatura [numero=" + numeroFatura + ", cliente=" + cliente + ", valor=" + valorTotal + ", data=" + DateToString(dataEmissao, "DD/MM/YYYY") + "]"

// Classe Builder interna
// Gerencia a construção passo a passo do objeto Fatura
CLASS Fatura::Builder
PRIVATE
fatura IS Fatura // Instância da fatura sendo construída
PUBLIC
// Construtor do Builder
// Recebe o número da fatura (obrigatório) e inicializa o objeto
PROCEDURE Builder(numero IS string)
fatura IS Fatura
fatura..numeroFatura = numero
END

// Configura o cliente da fatura
// Retorna THIS para permitir encadeamento
PROCEDURE comCliente(cliente IS string) IS Builder
fatura..cliente = cliente
RESULT THIS
END

// Configura o valor total da fatura
// Retorna THIS para permitir encadeamento
PROCEDURE comValor(valor IS real) IS Builder
fatura..valorTotal = valor
RESULT THIS
END

// Configura a data de emissão da fatura
// Retorna THIS para permitir encadeamento
PROCEDURE comDataEmissao(data IS date) IS Builder
fatura..dataEmissao = data
RESULT THIS
END

// Finaliza a construção e retorna o objeto Fatura
PROCEDURE build() IS Fatura
RESULT fatura
END
END

// Procedimento principal para demonstrar o uso do Builder
PROCEDURE Main()
// Cria uma fatura usando o Builder
minhaFatura IS Fatura
minhaFatura = Fatura::Builder("FAT2025-001")::comCliente("Empresa XYZ")::comValor(2500.99)::comDataEmissao("20250725")::build()
// Exibe os detalhes da fatura
Info(minhaFatura..toString())
END
Saída no WinDev:
Fatura [numero=FAT2025-001, cliente=Empresa XYZ, valor=2500.99, data=25/07/2025]
Explicação do Código em Português
• Classe Fatura: Define o objeto final (produto) com atributos relevantes para uma fatura eletrônica, como numeroFatura (obrigatório), cliente, valorTotal e dataEmissao.
• Procedimento toString: Formata os dados da fatura para exibição, usando DateToString para a data no formato brasileiro.
• Classe Builder: Uma classe interna que gerencia a construção da fatura. O procedimento Builder inicializa o objeto com o atributo obrigatório numeroFatura.
• Métodos de Configuração: comCliente, comValor e comDataEmissao configuram os atributos opcionais e retornam THIS para encadeamento fluido, conforme sugerido no post para melhorar a legibilidade.
• Método build: Retorna o objeto Fatura configurado.
• Procedimento Main: Demonstra a criação fluida de uma fatura, configurando apenas os atributos desejados.
• Contexto no WinDev: Este exemplo é diretamente inspirado no comentário de Olivier Dawson sobre faturamento eletrônico, sendo útil em sistemas de gestão financeira ou ERP no WinDev, onde faturas têm configurações variadas (por exemplo, integração com HFSQL ou relatórios).

Exemplo em Inglês (WLangage)
Context
We will create a Product class to represent a product in an inventory management system. The product has attributes like product code (mandatory), name, price, and category. The Builder pattern will be implemented as an inner class, as suggested in the original post, to ensure clear and maintainable object creation.
// Class Product (Product)
// Represents a product in an inventory system with configurable attributes
CLASS Product
PUBLIC
productCode IS string // Unique product code (mandatory)
name IS string // Product name
price IS real // Product price
category IS string // Product category
END

// Procedure to display the product details
// Returns a string with the product information for display
PROCEDURE Product::toString() IS string
RESULT "Product [code=" + productCode + ", name=" + name + ", price=" + price + ", category=" + category + "]"

// Inner Builder class
// Manages the step-by-step construction of the Product object
CLASS Product::Builder
PRIVATE
product IS Product // Instance of the product being built
PUBLIC
// Builder constructor
// Takes the product code (mandatory) and initializes the object
PROCEDURE Builder(code IS string)
product IS Product
product..productCode = code
END

// Sets the product name
// Returns THIS to enable method chaining
PROCEDURE withName(name IS string) IS Builder
product..name = name
RESULT THIS
END

// Sets the product price
// Returns THIS to enable method chaining
PROCEDURE withPrice(price IS real) IS Builder
product..price = price
RESULT THIS
END

// Sets the product category
// Returns THIS to enable method chaining
PROCEDURE withCategory(category IS string) IS Builder
product..category = category
RESULT THIS
END

// Completes the construction and returns the Product object
PROCEDURE build() IS Product
RESULT product
END
END

// Main procedure to demonstrate the Builder usage
PROCEDURE Main()
// Creates a product using the Builder
myProduct IS Product
myProduct = Product::Builder("PROD123")::withName("Laptop")::withPrice(999.99)::withCategory("Electronics")::build()
// Displays the product details
Info(myProduct..toString())
END
Output in WinDev:
Product [code=PROD123, name=Laptop, price=999.99, category=Electronics]
Explanation of the Code in English
• Class Product: Defines the final product with attributes like productCode (mandatory), name, price, and category.
• Procedure toString: Formats the product details for display, suitable for WinDev’s Info function.
• Class Builder: An inner class that manages the construction of the Product object. The Builder procedure initializes the object with the mandatory productCode.
• Configuration Methods: withName, withPrice, and withCategory set optional attributes and return THIS for fluent method chaining, aligning with the post’s emphasis on readability.
• Method build: Returns the configured Product object.
• Procedure Main: Demonstrates fluent creation of a product, configuring only the desired attributes.
• Context in WinDev: This example is suitable for inventory or e-commerce systems in WinDev, where products have varying attributes and may be integrated with HFSQL databases or UI forms.

Observações
• WLangage no WinDev: Os exemplos usam a sintaxe nativa do WLangage (IS, PROCEDURE, THIS) e a função Info para exibir a saída, compatível com o ambiente WinDev.
• Builder Interno: Conforme sugerido no post de Issam Ouzali, o Builder é implementado como uma classe interna, simplificando a construção de objetos complexos e evitando construtores extensos.
• Contexto do Post: O exemplo em português reflete diretamente o comentário de Olivier Dawson sobre faturamento eletrônico, enquanto o exemplo em inglês é aplicável a sistemas de inventário, ambos alinhados com a ideia de melhorar legibilidade e manutenibilidade.
• Flexibilidade: O padrão Builder permite omitir atributos opcionais, facilitando a criação de objetos com diferentes configurações.
• Integração com WinDev: Esses exemplos podem ser facilmente adaptados para integrar com bancos HFSQL, formulários ou relatórios no WinDev, como seria comum em aplicações práticas mencionadas no post.
Se precisar de mais exemplos, ajustes específicos (como integração com HFSQL, formulários, ou relatórios), ou quiser que eu foque em outro aspecto do post, por favor, detalhe!

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Mensagem modificada, julho, 25 2025 - 6:19 AM
Membro registado
4.618 mensagems
Publicado em julho, 25 2025 - 6:15 AM
Esses exemplos serão mais detalhados, incluindo integração com o ambiente WinDev (como uso de HFSQL para persistência de dados e formulários), refletindo cenários práticos mencionados no post, como faturamento eletrônico (citado por Olivier Dawson) e a ênfase em legibilidade e manutenibilidade. Também conectarei os exemplos diretamente ao post, explicando como eles se alinham com os benefícios destacados (evitar construtores longos, clarificar lógica, etc.).

Explicação Aprofundada do Padrão Builder no Contexto do Post
O post de Issam Ouzali destaca o padrão Builder como uma solução para construir objetos complexos de forma clara e manutenível, especialmente em WinDev com WLangage. Ele menciona que o Builder é útil quando:
• A criação de um objeto envolve várias etapas que variam por classe, mas seguem uma ordem fixa.
• Um construtor se torna longo e difícil de ler (problema do “construtor telescópico”).
• É necessário criar objetos com configurações diferentes.
Benefícios no Contexto do WinDev (conforme o post):
• Evitar construtores longos: Em WinDev, objetos como registros em bancos HFSQL ou dados de formulários podem ter muitos campos opcionais. O Builder simplifica a inicialização.
• Clarificar a lógica de construção: Separa a lógica de criação do objeto, facilitando a manutenção em projetos complexos, como sistemas ERP ou de faturamento.
• Facilitar configurações diferentes: Permite criar objetos com variações (ex.: faturas com ou sem descontos).
• Melhorar legibilidade e manutenibilidade: O código em WLangage fica mais fluido e fácil de entender, especialmente em formulários ou relatórios.
Integração com WinDev:
• HFSQL: O Builder pode ser usado para criar objetos que serão persistidos em um banco HFSQL, garantindo que apenas os campos necessários sejam configurados.
• Formulários: O padrão é ideal para coletar dados de formulários no WinDev, onde o usuário pode preencher campos opcionais de forma dinâmica.
• Relatórios: Objetos criados com Builder podem ser usados diretamente em relatórios, com atributos formatados adequadamente.
Contexto do Post: O comentário de Olivier Dawson sobre faturamento eletrônico sugere um caso prático onde o Builder pode ser aplicado para configurar faturas com campos opcionais (ex.: impostos, descontos). Além disso, Issam menciona um “Builder interno estático” (adaptado aqui como uma classe interna, já que WLangage não usa static explicitamente).

Exemplo em Português (WLangage com Integração HFSQL)
Contexto
Vamos criar uma classe FaturaEletronica para um sistema de faturamento, inspirada no comentário de Olivier Dawson. A fatura terá atributos como número da fatura (obrigatório), cliente, valor base, desconto e data de emissão. O Builder será usado para configurar a fatura, que será persistida em um banco HFSQL. O exemplo inclui integração com um formulário WinDev e comentários detalhados.
// Definição do arquivo HFSQL para armazenar faturas
// Arquivo: FaturasEletronicas
// Campos: NumeroFatura (string), Cliente (string), ValorBase (real), Desconto (real), DataEmissao (date)
HDeclare("FaturasEletronicas")

// Classe FaturaEletronica (Produto)
// Representa uma fatura eletrônica com atributos configuráveis
CLASS FaturaEletronica
PUBLIC
numeroFatura IS string // Número único da fatura (obrigatório)
cliente IS string // Nome do cliente
valorBase IS real // Valor base da fatura
desconto IS real // Desconto aplicado (opcional)
dataEmissao IS date // Data de emissão da fatura
END

// Procedimento para exibir os dados da fatura
// Formata os dados para exibição em formulários ou relatórios
PROCEDURE FaturaEletronica::toString() IS string
RESULT "Fatura [numero=" + numeroFatura + ", cliente=" + cliente + ", valorBase=" + valorBase + ", desconto=" + desconto + ", data=" + DateToString(dataEmissao, "DD/MM/YYYY") + "]"

// Procedimento para salvar a fatura no banco HFSQL
// Persiste os dados no arquivo FaturasEletronicas
PROCEDURE FaturaEletronica::salvarHFSQL()
HReset("FaturasEletronicas")
FaturasEletronicas.NumeroFatura = numeroFatura
FaturasEletronicas.Cliente = cliente
FaturasEletronicas.ValorBase = valorBase
FaturasEletronicas.Desconto = desconto
FaturasEletronicas.DataEmissao = dataEmissao
HAdd("FaturasEletronicas")
IF HError() THEN
Error("Erro ao salvar fatura: " + HErrorInfo())
ELSE
Info("Fatura salva com sucesso!")
END
END

// Classe Builder interna
// Gerencia a construção passo a passo da fatura
CLASS FaturaEletronica::Builder
PRIVATE
fatura IS FaturaEletronica // Instância da fatura sendo construída
PUBLIC
// Construtor do Builder
// Inicializa a fatura com o número (obrigatório)
PROCEDURE Builder(numero IS string)
fatura IS FaturaEletronica
fatura..numeroFatura = numero
END

// Configura o cliente da fatura
// Retorna THIS para encadeamento fluido
PROCEDURE comCliente(cliente IS string) IS Builder
fatura..cliente = cliente
RESULT THIS
END

// Configura o valor base da fatura
// Retorna THIS para encadeamento fluido
PROCEDURE comValorBase(valor IS real) IS Builder
fatura..valorBase = valor
RESULT THIS
END

// Configura o desconto da fatura (opcional)
// Retorna THIS para encadeamento fluido
PROCEDURE comDesconto(desconto IS real) IS Builder
fatura..desconto = desconto
RESULT THIS
END

// Configura a data de emissão da fatura
// Retorna THIS para encadeamento fluido
PROCEDURE comDataEmissao(data IS date) IS Builder
fatura..dataEmissao = data
RESULT THIS
END

// Finaliza a construção e retorna a fatura
PROCEDURE build() IS FaturaEletronica
RESULT fatura
END
END

// Procedimento para criar uma fatura a partir de um formulário
// Simula um formulário WinDev com campos preenchidos pelo usuário
PROCEDURE CriarFaturaFormulario()
// Suponha que os dados vêm de campos de um formulário
numero IS string = EDT_NumeroFatura // Campo do formulário
cliente IS string = EDT_Cliente
valor IS real = EDT_ValorBase
desconto IS real = EDT_Desconto
data IS date = EDT_DataEmissao

// Cria a fatura usando o Builder
minhaFatura IS FaturaEletronica
minhaFatura = FaturaEletronica::Builder(numero)
IF cliente <> "" THEN minhaFatura::comCliente(cliente)
IF valor > 0 THEN minhaFatura::comValorBase(valor)
IF desconto > 0 THEN minhaFatura::comDesconto(desconto)
IF data <> "" THEN minhaFatura::comDataEmissao(data)
minhaFatura = minhaFatura::build()

// Salva no banco HFSQL
minhaFatura..salvarHFSQL()
// Exibe os detalhes no formulário
Info(minhaFatura..toString())
END

// Procedimento principal para teste
PROCEDURE Main()
// Exemplo de criação direta
minhaFatura IS FaturaEletronica
minhaFatura = FaturaEletronica::Builder("FAT2025-002")::comCliente("Acme Corp")::comValorBase(5000.00)::comDesconto(200.00)::comDataEmissao("20250725")::build()
minhaFatura..salvarHFSQL()
Info(minhaFatura..toString())
END
Saída no WinDev:
Fatura salva com sucesso!
Fatura [numero=FAT2025-002, cliente=Acme Corp, valorBase=5000, desconto=200, data=25/07/2025]
Explicação Detalhada em Português
• Classe FaturaEletronica: Representa uma fatura eletrônica, com atributos como numeroFatura (obrigatório), cliente, valorBase, desconto e dataEmissao.
• Procedimento toString: Formata os dados para exibição, útil para formulários ou relatórios no WinDev.
• Procedimento salvarHFSQL: Persiste a fatura em um arquivo HFSQL, simulando integração com o banco de dados do WinDev.
• Classe Builder: Uma classe interna que inicializa a fatura com numeroFatura e permite configurar os outros atributos de forma fluida, conforme sugerido no post de Issam Ouzali.
• Procedimento CriarFaturaFormulario: Simula a criação de uma fatura a partir de um formulário WinDev, verificando campos opcionais antes de configurá-los, demonstrando a flexibilidade do Builder.
• Procedimento Main: Mostra a criação direta de uma fatura, com salvamento no HFSQL e exibição dos detalhes.
• Conexão com o Post: O exemplo reflete o caso de uso de faturamento eletrônico (mencionado por Olivier Dawson), evita construtores longos (problema destacado por Issam) e melhora a legibilidade com métodos encadeados.
• Integração com WinDev: A persistência no HFSQL e o uso em formulários mostram como o Builder se integra a aplicações reais no WinDev, como sistemas de faturamento ou ERP.

Exemplo em Inglês (WLangage with Form Integration)
Context
We will create a Reservation class for a restaurant reservation system. The reservation has attributes like reservation ID (mandatory), customer name, date, and number of guests. The Builder will be an inner class, and the object will be used in a WinDev form, aligning with the post’s focus on clean code and maintainability.
// Class Reservation (Product)
// Represents a restaurant reservation with configurable attributes
CLASS Reservation
PUBLIC
reservationID IS string // Unique reservation ID (mandatory)
customerName IS string // Name of the customer
reservationDate IS date // Date of the reservation
guests IS int // Number of guests
END

// Procedure to display the reservation details
// Formats the data for display in forms or reports
PROCEDURE Reservation::toString() IS string
RESULT "Reservation [ID=" + reservationID + ", customer=" + customerName + ", date=" + DateToString(reservationDate, "MM/DD/YYYY") + ", guests=" + guests + "]"

// Inner Builder class
// Manages the step-by-step construction of the Reservation object
CLASS Reservation::Builder
PRIVATE
reservation IS Reservation // Instance of the reservation being built
PUBLIC
// Builder constructor
// Initializes the reservation with the ID (mandatory)
PROCEDURE Builder(id IS string)
reservation IS Reservation
reservation..reservationID = id
END

// Sets the customer name
// Returns THIS for method chaining
PROCEDURE withCustomerName(name IS string) IS Builder
reservation..customerName = name
RESULT THIS
END

// Sets the reservation date
// Returns THIS for method chaining
PROCEDURE withDate(date IS date) IS Builder
reservation..reservationDate = date
RESULT THIS
END

// Sets the number of guests
// Returns THIS for method chaining
PROCEDURE withGuests(guests IS int) IS Builder
reservation..guests = guests
RESULT THIS
END

// Completes the construction and returns the Reservation object
PROCEDURE build() IS Reservation
RESULT reservation
END
END

// Procedure to create a reservation from a WinDev form
// Simulates a form where users input reservation details
PROCEDURE CreateReservationFromForm()
// Assume data comes from form fields
id IS string = EDT_ReservationID // Form field
customer IS string = EDT_CustomerName
date IS date = EDT_ReservationDate
guests IS int = EDT_Guests

// Create the reservation using the Builder
myReservation IS Reservation
myReservation = Reservation::Builder(id)
IF customer <> "" THEN myReservation::withCustomerName(customer)
IF date <> "" THEN myReservation::withDate(date)
IF guests > 0 THEN myReservation::withGuests(guests)
myReservation = myReservation::build()

// Display the reservation details
Info(myReservation..toString())
END

// Main procedure for testing
PROCEDURE Main()
// Example of direct reservation creation
myReservation IS Reservation
myReservation = Reservation::Builder("RES2025-001")::withCustomerName("John Doe")::withDate("20250725")::withGuests(4)::build()
Info(myReservation..toString())
END
Output in WinDev:
Reservation [ID=RES2025-001, customer=John Doe, date=07/25/2025, guests=4]
Detailed Explanation in English
• Class Reservation: Represents a restaurant reservation with attributes like reservationID (mandatory), customerName, reservationDate, and guests.
• Procedure toString: Formats the reservation details for display, using a US date format (MM/DD/YYYY).
• Class Builder: An inner class that initializes the reservation with reservationID and allows fluent configuration of optional attributes, aligning with the post’s focus on readability.
• Procedure CreateReservationFromForm: Simulates a WinDev form where users input reservation details, checking for optional fields before setting them, demonstrating the Builder’s flexibility.
• Procedure Main: Shows direct creation of a reservation with fluent method chaining.
• Connection to the Post: The example avoids long constructors, clarifies construction logic, and supports different configurations, as emphasized by Issam Ouzali. It’s suitable for a restaurant management system in WinDev.
• WinDev Integration: The form integration shows how the Builder can be used in real WinDev applications, such as reservation systems with UI components.

Conexão com o Post de Issam Ouzali
• Faturamento Eletrônico: O exemplo em português atende diretamente ao comentário de Olivier Dawson, aplicando o Builder a um sistema de faturas eletrônicas, com integração ao HFSQL para persistência, refletindo cenários reais de ERP no WinDev.
• Builder Interno: Ambos os exemplos usam uma classe interna, como sugerido por Issam para casos mais simples, evitando a necessidade de classes externas e mantendo o código organizado.
• Benefícios do Post: Os exemplos demonstram como o Builder:
◦ Evita construtores longos: Sem Builder, a classe FaturaEletronica ou Reservation exigiria múltiplos construtores ou parâmetros opcionais confusos.
◦ Clarifica a lógica: A construção passo a passo é clara e fluida, especialmente em formulários.
◦ Facilita configurações diferentes: Atributos como desconto ou guests podem ser omitidos.
◦ Melhora a legibilidade: O encadeamento de métodos (comCliente, withGuests) torna o código mais intuitivo.
• WinDev e WLangage: Os exemplos usam a sintaxe do WLangage (IS, PROCEDURE, THIS) e recursos do WinDev (HFSQL, formulários), mostrando como o Builder se integra a projetos reais.

Possíveis Extensões
• Relatórios no WinDev: A classe FaturaEletronica ou Reservation pode ser usada em relatórios WinDev, com o método toString formatando dados para exibição.
• Validações: Adicionar validações no Builder (ex.: verificar se valorBase é positivo) para robustez.
• Formulários Avançados: Integrar com controles de formulário WinDev (ex.: combos, grids) para preencher dados dinamicamente.
• HFSQL Avançado: Adicionar consultas HFSQL para recuperar faturas ou reservas criadas com o Builder.
Se precisar de mais detalhes, como implementação de relatórios, validações, ou outro cenário (ex.: integração com WebDev ou WinDev Mobile), ou quiser exemplos adicionais com outros contextos, é só especificar!

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Mensagem modificada, julho, 25 2025 - 6:17 AM