Portman
Extensão do VSCode para gerenciar portas em qualquer sistema operacional a partir de uma interface gráfica integrada.
Durante o desenvolvimento de software, um obstáculo operacional recorrente é a colisão na alocação de portas de rede (conhecida em ambientes Node.js como o erro EADDRINUSE). Isso ocorre quando um processo anterior, seja em execução intencional ou órfão (zumbi), mantém um socket em escuta aberto em uma interface de rede e porta específicas, impedindo que uma nova instância se vincule a esse recurso.
A resolução manual desse estado exige que o desenvolvedor interaja diretamente com o sistema operacional por meio de uma interface de linha de comando (CLI) para:
- Sondar: Executar utilitários de análise de rede (por exemplo,
lsof,netstat,ss). - Filtrar: Processar a saída padrão (stdout) para isolar o processo vinculado à porta em conflito.
- Identificar: Extrair o Identificador de Processo (PID).
- Encerrar: Enviar um sinal do sistema (como
SIGKILL) ao PID identificado.
A Solução Operacional
O Portman automatiza e abstrai esse fluxo de diagnóstico e intervenção, integrando-o diretamente ao Ambiente de Desenvolvimento Integrado (IDE).
O fluxo de trabalho funcional se resume a:
- Extração do Estado do Sistema: A extensão interage de forma transparente com as APIs e os binários nativos do sistema operacional hospedeiro para obter o estado atual das conexões de rede.
- Transformação e Mapeamento: As informações brutas extraídas do SO são normalizadas em modelos de domínio estruturados.
- Apresentação em Tempo Real: Os modelos normalizados são renderizados em uma estrutura de árvore interativa dentro da interface gráfica do VS Code.
- Execução de Ações: Por meio de comandos integrados, a ferramenta permite ao usuário selecionar um nó da árvore e enviar o sinal de encerramento ao processo subjacente de forma unificada, independentemente do sistema operacional utilizado.
Análise Técnica: Arquitetura e Modelos
Para garantir que o ciclo de vida do software suporte um crescimento sustentável, testabilidade isolada e adaptabilidade transversal entre múltiplos sistemas operacionais (Linux, macOS, Windows), projetei a estrutura do projeto sob os princípios de Clean Architecture e Domain-Driven Design (DDD).
O código está dividido conceitualmente em quatro camadas concêntricas, nas quais a dependência flui estritamente em direção ao centro (o Domínio).
graph TD
subgraph ext["Camada Externa (Infraestrutura e Apresentação)"]
VS[VS Code Extension API]
CLI[Binários do SO: netstat, lsof, ss]
end
subgraph pres["Camada de Apresentação"]
PTD[ProcessTreeDataProvider]
Cmds[KillProcessCommand]
end
subgraph app["Camada de Aplicação"]
SP[UseCase: SearchProcesses]
KP[UseCase: KillProcess]
end
subgraph dom["Camada de Domínio"]
Model[Aggregate Root: Process]
RepoInt[Interface: ProcessRepository]
end
VS --> PTD
VS --> Cmds
PTD --> SP
Cmds --> KP
SP --> RepoInt
KP --> RepoInt
CLI -.->|Implementação| RepoInt
classDef domain fill:#14b8a6,fill-opacity:0.3,stroke:#0d9488,stroke-width:2px;
classDef app fill:#14b8a6,fill-opacity:0.12,stroke:#0d9488,stroke-width:2px;
classDef pres fill:#737373,fill-opacity:0.14,stroke:#737373,stroke-width:2px;
classDef external fill:#737373,fill-opacity:0.06,stroke:#737373,stroke-width:1px,stroke-dasharray:4 4;
class Model,RepoInt domain;
class SP,KP app;
class PTD,Cmds pres;
class VS,CLI external;
1. O Núcleo do Domínio
O modelo de domínio está isolado de qualquer dependência externa, framework ou detalhe do sistema operacional. Seu objetivo principal é modelar a abstração de um processo de rede.
O Agregado Process
A entidade central é Process, que atua como Aggregate Root. É composta por múltiplos Value Objects que garantem a integridade dos dados no momento de sua instanciação:
ProcessId: Identificador único (PID).ProcessProgram: Nome do executável ou daemon.Protocol: Protocolo de transporte (TCP, UDP).Address: Composição deAddressHost(IP local/remoto ou nome do host) eAddressPort(porta numérica).ProcessStatus: Estado atual da conexão (por exemplo, LISTEN, ESTABLISHED).
classDiagram
class Process {
+ProcessId id
+ProcessProgram program
+Protocol protocol
+Address local
+Address remote
+ProcessStatus status
+String icon
+String label
+String description
+String tooltip
}
class Address {
+AddressHost host
+AddressPort port
}
class ProcessRepository {
<<Interface>>
+search() Promise~Process[]~
+kill(process: Process) Promise~void~
}
Process "1" *-- "2" Address : local/remote
ProcessRepository --> Process : gerencia
Além disso, o domínio define o contrato ProcessRepository, que estabelece as operações fundamentais de busca e encerramento exigidas pelo sistema, sem ditar como elas são implementadas.
2. Camada de Aplicação
A camada de aplicação orquestra as regras de negócio usando os contratos do domínio. Está estruturada em torno de Casos de Uso específicos:
SearchProcesses: Emite uma Query ao repositório para obter o array de objetosProcess.KillProcess: Emite um Command ao repositório para encerrar um objetoProcessespecífico.
Esses casos de uso não têm estado e dependem da injeção do repositório concreto em tempo de execução.
3. Camada de Infraestrutura
Aqui residem as implementações técnicas da interface ProcessRepository. A injeção de dependências é gerenciada no ponto de entrada da aplicação (extension.ts), avaliando a variável de ambiente process.platform para instanciar o adaptador correto.
LinuxProcessRepository: Prioriza a extração vianetstat. Conta com um mecanismo de fallback gradual para o bináriosscaso o primeiro não esteja disponível. Além disso, avalia a configuraçãoportman.linux.asRootUserpara elevar privilégios usandopkexecousudo, se necessário.MacProcessRepository: Interage nativamente comlsof -i -P -n.WindowsProcessRepository: Invoca implementações baseadas em PowerShell (Get-NetTCPConnection) ou comandos legados do MS-DOS (netstat -a -b -n -o).
Cada repositório delega a análise da saída padrão a classes transformadoras específicas (por exemplo, MacNetstatProcessTransformer), que analisam as strings de texto bruto, validam a estrutura e mapeiam os dados para o objeto de domínio Process.
4. Camada de Apresentação
Esta camada isola a lógica de negócio da extensa API do Visual Studio Code.
O componente principal é o ProcessTreeDataProvider, que implementa a interface TreeDataProvider do VS Code. Sua responsabilidade é assinar os eventos da IDE, consumir o caso de uso SearchProcesses e transformar o array de entidades Process em instâncias de ProcessTreeItem (ou ProcessQuickPickItem) para a renderização final da árvore visual na Interface do Usuário. Também gerencia a captura e a apresentação de erros operacionais por meio das caixas de diálogo integradas do editor.
Stack Tecnológico
O conjunto de ferramentas escolhido para este projeto reflete a necessidade de construir um artefato empacotado otimizado, fortemente tipado e estreitamente acoplado a um ambiente de execução Node.js (Electron).
| Tecnologia / Ferramenta | Papel Arquitetural | Propósito Funcional |
|---|---|---|
| TypeScript (v5.x) | Linguagem Principal | Fornece análise estática e tipagem forte, essenciais para modelar as entidades da camada de Domínio e garantir os contratos entre camadas. |
| VS Code Extension API | Ambiente de Execução | Fornece a interface programática (vscode.*) para a renderização nativa da UI, o registro de comandos e o acesso ao painel lateral. |
| Webpack (v5.x) | Bundler | Combina, transpila e minifica o código-fonte em um arquivo extension.js otimizado, reduzindo a latência de ativação do plugin. |
Conclusão
A adoção estrita da Clean Architecture em um projeto de extensão de IDE —um ambiente fundamentalmente acoplado à camada de visualização— resultou em uma separação rigorosa de responsabilidades. O núcleo lógico para resolver as dependências de rede é completamente agnóstico tanto ao sistema operacional subjacente quanto ao framework de apresentação do VS Code. Essa abstração garante que as integrações nativas possam ser modificadas, otimizadas ou substituídas (por exemplo, migrando de comandos CLI para invocações de kernel em C++) sem produzir efeitos colaterais nas regras de negócio ou na lógica de apresentação do fluxo de encerramento de portas.
Arraste para mover o diagrama. Use + e − para dar zoom, as setas para movê-lo e 0 para redefinir a visualização.
Vamos trabalhar juntos
Engenheiro de Software e desenvolvedor Senior Full-Stack, trabalho remotamente a partir de Santa Cruz, Bolívia. Aberto a novas oportunidades.