Olá pessoal.
Nos primeiros cinco anos da minha carreira de programação, trabalhei em um projeto interno, nos próximos sete anos trabalhei em várias startups, com uma equipe de no máximo cinco desenvolvedores.
Estou trabalhando há alguns meses em um projeto com mais de 20 desenvolvedores, o trabalho é realizado simultaneamente em cerca de 30 branches, há cinco ambientes para desenvolvimento de código (draft, dev, testing, hotfix, prod), cada ambiente tem seu próprio banco de dados (antes de lançar o kamit para stand / ambiente, um teste de rollout ocorre usando um banco de dados separado, ou seja, temos 10 bancos de dados separados para cinco ambientes).
Desenvolver em vários ramos não é novidade para mim, sempre fiz isso. A descoberta para mim foi que a versão do código e a versão do esquema do banco de dados não estão sincronizadas de forma alguma. Em um projeto pequeno, não é um problema largar o esquema inteiro e rolar por completo, leva alguns minutos, neste projeto, rolar um esquema do zero com semeadura leva cerca de uma hora.
Há um grande problema em como sincronizar a versão do código e a versão do esquema do banco de dados.
Abaixo, contarei a você as regras que aceitei para mim e ficarei feliz se você compartilhar suas técnicas e técnicas que o ajudam a lidar com este desastre.
Isenção de responsabilidade
O código apresentado a seguir é um código de combate ofuscado, não o depurei, pode ser necessário modificá-lo com um arquivo. Eu só compartilho ideias com você.
Descrição do problema
, , , - -. .
, - , , , , , ? , ?
, , . , , , . , .
.
: " "
, . , migrations, , , .
, .
:
#
php artisan migrate --path="services/best-team-servise/database/migrations/2021_02_04_240000_alter_data_model_table_add_unique_index.php" --pretend
# --pretend SQL ,
#
php artisan migrate:rollback --step=1
# ,
,
php artisan ide-helper:models "Project\Models\DataModel"
:
php artisan db:seed --class=DataModelSeeder
? up() down() , , .
, , , .
Builder :
$conn = (new DataModel())->connection;
$builder = Schema::connection($conn);
( ):
$isExists = $builder->hasColumn(
'data_model',
'deleted_at'
);
, :
if (!$isExists) {
$builder->table(
'data_model',
function (Blueprint $table) {
$table->softDeletesTz();
}
);
}
- , - , , , :
$alias = (new DataModel())->connection;
$builder = Schema
::connection($alias)
->getConnection()
->getDoctrineSchemaManager();
$existingIndexes = $builder->listTableIndexes('data_model');
Laravel , :
Blueprint::unique('index_name');
:
Blueprint::dropUnique('index_name');
Laravel , , , SQL, Laravel ? , !
SQL, :
DROP TRIGGER IF EXISTS trigger_name
ON public.data_model;
CREATE TRIGGER trigger_name
BEFORE INSERT
ON public.data_model
FOR EACH ROW
EXECUTE PROCEDURE public.function_name();
, :
DROP TRIGGER IF EXISTS trigger_name
ON public.data_model;
: " "
, 1000+ . 1000 , .
, 50+ , "" .
, create, alter, , drop.
.
alter_data_model_add_property_column alter_data_model_alter_property_column_to_text alter_data_model_alter_property_column_set_default_value alter_data_model_create_index_on_code_type_columns alter_data_model_create_unique_index_on_code_column
, , MVP.
:
#
php artisan make:migration create_profile_table --create=profile
#
php artisan make:migration add_confirmed_to_profile --table=profile
database/migrations , .
: , nullable()
, NOT NULL, , , , .
, .
nullable(), , .
, , - :
$columns = Schema
::connection((new DataModel())->connection)
->getConnection()
->getDoctrineSchemaManager()
->listTableColumns($(new DataModel())->getTable());
$data = [];
foreach ($columns as $column) {
$name = $column->getName();
/* @var array[] $record */
$exists = key_exists($name, $record);
if ($exists) {
$data[$name] = $record[$name];
}
}
$isSuccess = DataModel
::withTrashed()
->updateOrCreate(
['uniqe_index_column' => $data['uniqe_index_column'],],
$data
)->exists;
: , null
, , , , , .
Ou você pode usar algum valor padrão no código, mas não gosto desse método, porque é um código rígido e isso mata a flexibilidade de nosso aplicativo. A operação do aplicativo deve ser configurada por meio de variáveis de ambiente, arquivos de configuração ou registros de banco de dados.
Conclusão
Esse conjunto de regras certamente não é absoluto, em primeiro lugar ligamos a cabeça e usamos o bom senso.
Vamos discutir nos comentários. Por favor, compartilhe sua experiência.