Setting Up WSL 2: My Development Environment Scripts

Setting Up WSL 2: My Development Environment Scripts

After a problematic Windows update on my Surface computer that prevented me from compiling .NET applications, I spent days trying various fixes without success. Eventually, I had to format my computer and start fresh. This meant setting up everything again – Visual Studio, testing databases, and all the other development tools.To make future setups easier, I created a collection of WSL 2 scripts that automate the installation of tools I frequently use, like PostgreSQL and MySQL for testing purposes. While these scripts contain some practices that wouldn’t be recommended for production (like hardcoded passwords), they’re specifically designed for testing environments. The passwords used are already present in the sync framework source code, so there’s no additional security risk.I decided to share these scripts not as a perfect solution, but as a starting point for others who might need to set up similar testing environments. You can use them as inspiration for your own scripts or modify the default passwords to match your needs.

Note that these are specifically for testing purposes – particularly for working with the sync framework – and the hardcoded credentials should never be used in a production environment.

https://github.com/egarim/MyWslScripts

LDAP Scripts

MyWslScripts/ldap-setup.sh at master · egarim/MyWslScripts

MyWslScripts/add-ldap-user.sh at master · egarim/MyWslScripts

MySQL

MyWslScripts/install_mysql.sh at master · egarim/MyWslScripts

Postgres

MyWslScripts/install_postgres.sh at master · egarim/MyWslScripts

Redis

MyWslScripts/redis-install.sh at master · egarim/MyWslScripts

Let me know if you’d like me to share the actual scripts in a follow-up post!
Extending Interfaces in the Sync Framework: Best Practices and Trade-offs

Extending Interfaces in the Sync Framework: Best Practices and Trade-offs

In modern software development, extending the functionality of a framework while maintaining its integrity and usability can be a complex task. One common scenario involves extending interfaces to add new events or methods. In this post, we’ll explore the impact of extending interfaces within the Sync Framework, specifically looking at IDeltaStore and IDeltaProcessor interfaces to include SavingDelta and SavedDelta events, as well as ProcessingDelta and ProcessedDelta events. We’ll discuss the options available—extending existing interfaces versus adding new interfaces—and examine the side effects of each approach.

Background

The Sync Framework is designed to synchronize data across different data stores, ensuring consistency and integrity. The IDeltaStore interface typically handles delta storage operations, while the IDeltaProcessor interface manages delta (change) processing. To enhance the functionality, you might want to add events such as SavingDelta, SavedDelta, ProcessingDelta, and ProcessedDelta to these interfaces.

Extending Existing Interfaces

Extending existing interfaces involves directly adding new events or methods to the current interface definitions. Here’s an example:

public interface IDeltaStore {
    void SaveData(Data data);
    // New events
    event EventHandler<DeltaEventArgs> SavingDelta;
    event EventHandler<DeltaEventArgs> SavedDelta;
}

public interface IDeltaProcessor {
    void ProcessDelta(Delta delta);
    // New events
    event EventHandler<DeltaEventArgs> ProcessingDelta;
    event EventHandler<DeltaEventArgs> ProcessedDelta;
}

Pros of Extending Existing Interfaces

  • Simplicity: The existing implementations need to be updated to include the new functionality, making the overall design simpler.
  • Direct Integration: The new events are directly available in the existing interface, making them easy to use and understand within the current framework.

Cons of Extending Existing Interfaces

  • Breaks Existing Implementations: All existing classes implementing these interfaces must be updated to handle the new events. This can lead to significant refactoring, especially in large codebases.
  • Violates SOLID Principles: Adding new responsibilities to existing interfaces can violate the Single Responsibility Principle (SRP) and Interface Segregation Principle (ISP), leading to bloated interfaces.
  • Potential for Bugs: The necessity to modify all implementing classes increases the risk of introducing bugs and inconsistencies.

Adding New Interfaces

An alternative approach is to create new interfaces that extend the existing ones, encapsulating the new events. Here’s how you can do it:

public interface IDeltaStore {
    void SaveData(Data data);
}

public interface IDeltaStoreWithEvents : IDeltaStore {
    event EventHandler<DeltaEventArgs> SavingDelta;
    event EventHandler<DeltaEventArgs> SavedDelta;
}

public interface IDeltaProcessor {
    void ProcessDelta(Delta delta);
}

public interface IDeltaProcessorWithEvents : IDeltaProcessor {
    event EventHandler<DeltaEventArgs> ProcessingDelta;
    event EventHandler<DeltaEventArgs> ProcessedDelta;
}

Pros of Adding New Interfaces

  • Adheres to SOLID Principles: This approach keeps the existing interfaces clean and focused, adhering to the SRP and ISP.
  • Backward Compatibility: Existing implementations remain functional without modification, ensuring backward compatibility.
  • Flexibility: New functionality can be selectively adopted by implementing the new interfaces where needed.

Cons of Adding New Interfaces

  • Complexity: Introducing new interfaces can increase the complexity of the codebase, as developers need to understand and manage multiple interfaces.
  • Redundancy: There can be redundancy in code, where some classes might need to implement both the original and new interfaces.
  • Learning Curve: Developers need to be aware of and understand the new interfaces, which might require additional documentation and training.

Conclusion

Deciding between extending existing interfaces and adding new ones depends on your specific context and priorities. Extending interfaces can simplify the design but at the cost of violating SOLID principles and potentially breaking existing code. On the other hand, adding new interfaces preserves existing functionality and adheres to best practices but can introduce additional complexity.

In general, if maintaining backward compatibility and adhering to SOLID principles are high priorities, adding new interfaces is the preferred approach. However, if you are working within a controlled environment where updating existing implementations is manageable, extending the interfaces might be a viable option.

By carefully considering the trade-offs and understanding the implications of each approach, you can make an informed decision that best suits your project’s needs.