Sunday, November 17, 2024

Data Transfer Objects

Data Transfer Objects (DTOs) decouple the internal structure of your models, entities, or database schema from the data exposed to the external world (e.g., APIs, front-end). They serve as a contract for the data being transferred, which helps ensure that changes in your data layer don't inadvertently affect the consumer.

Another benefit of DTOs is to enforce structured data and eliminate errors from missing [string] keys. By using a constructor, you control how the raw data is mapped. If a key is missing, you can provide a default value or handle the absence gracefully or you can add validation logic centrally in constructor. Using DTOs allows tools like PhpStorm or VSCode to identify missing properties during development. When working with arrays, typos in keys can go unnoticed until runtime, with DTOs you are using object fields which don’t have this weakness. Example without DTO (note the usage of error prone string keys):

private function prepareProductDetails(array $product): array {
        $product['photos'] = $this->processProductPhotos($product['photos']??[]);
        $product['tr_currency_formatted'] = isset($product['deposit']) 
                ?Currency::formatTRY($product['deposit'])
        return $product;
    }

With DTO:

class ProductDetailsDTO {
    public array $photos;
    public ?float $deposit = null;
    public ?string $tr_currency_formatted = null;
    public function __construct(array $data) {
        $this->photos = $data['photos'] ?? [];
        $this->deposit = $data['deposit'] ?? null;
    }
    public function setFormattedCurrency(callable $formatter): void {
        if ($this->deposit !== null) {
            $this->tr_currency_formatted = $formatter($this->deposit);
        }
    }
}

Note the usage of object fields instead of string keys:

private function prepareProductDetails(array $product): ProductDetailsDTO {
    $productDTO = new ProductDetailsDTO($product);
    $productDTO->photos = $this->processProductPhotos($productDTO->photos);
    $productDTO->setFormattedCurrency(fn($amount) =>
        Currency::formatTRY($amount));
    return $productDTO;
}

Saturday, October 19, 2024

Using UI with AI

If your web or mobile app has multiple user interface (UI) commands, (such as log in, register, search, show products, change user settings), users might struggle to know exactly where to click. The UI would be much more user-friendly if an AI could interpret user speech and convert it into commands that can be handled by the backend. Today’s AI is robust enough to map different phrases that mean the same thing to a single command. For example, a user might say "register" or "create a new account," and both can be mapped to the command "sign_up." The AI can understand both English and Turkish, e.g. "bana yeni bir kullanıcı oluştur" correctly maps to "sign_up". Here is a demo in Python:
When you use an API, such as OpenAI, the main disadvantage is that you must pay for every API call. Therefore, using voice commands to control the UI should be limited to paying customers, and there should be rate limits in place to keep costs under control. You might use open-source models like LLaMA to run the AI on your own server, but that would require better computational and memory resources than you currently have.

Sunday, October 13, 2024

Evaluating fairness of an Investment/Shareholders' Agreement

When an investor invests in a startup, they present the company with an Investor/Shareholder Agreement, which outlines the rights and obligations of the shareholders within the company, including voting rights, share transfer procedures, dividend policies, and protections for minority shareholders. These agreements safeguard the investor's financial interests and govern their relationship with the company and other shareholders.
It is common for the initial investor to have more rights. Normally, early investors expect the following protections:
  • Board representation (a seat on the board).
  • Veto rights on major financial decisions (e.g., capital raises, mergers, or asset sales).
  • Approval rights over key hires or changes in the business direction.
  • Liquidation preferences to get paid first in case of a company exit.
But sometimes their demands can be excessive. To evaluate the fairness of such agreements, you can upload the proposed agreement to chatGPT and use the following prompt:
Does the contract reflect a balanced distribution of power? If not, what share percentage would correspond to the class B shareholder's power? Is this normal for an initial investor in the startup, considering that convincing the first investor is often the most difficult?
If the agreement grants a 15% share in the company but provides 50% control, which is more aligned with a controlling or near-majority stake, we can say the agreement is not fair. Common unfair clauses in such agreements are:
  • Even though the class A shareholder (founder) appoints the board member, any change in the board representative requires class B shareholder (investor) approval.
  • Class A shareholder cannot transfer shares without class B consent for 3 years, while class B share holder is free to transfer to affiliates or related parties without restriction.
  • Important strategic decisions need approval from the Steering Committee, where both A and B share holders have one representative each. Any deadlock in this two-person committee could give the B shareholder veto power over important business decisions​.
You can use the following questions to persuade the investor to be more flexible:
  • Do we agree that the founder/CEO of an ambitious startup with rapid growth goals needs to be able to act quickly, requiring minimal approval/bureaucracy?
  • To fund rapid growth, we most probably will need other investors. Can we foresee that this agreement might irritate potential investors, lower the company's value, and lead them to request the same privileges? 
  • If the same privileges are granted to other investors, would reaching an agreement on any matter outside of routine business—especially considering the potential for irrational behavior (such as ego conflicts, etc.)—become practically impossible?
The goal is to help the investor see the mutual benefits of more flexible terms. You want to highlight that while protecting their investment is important, collaboration, agility, and attracting future investment will ultimately lead to better outcomes for both parties.

Sunday, September 22, 2024

What tech to use when you are just starting

In the beginning, you are trying to find out if there is a need for your app, which means you personally have to find people to try your app. Since there is no marketing, there is no sudden spike in traffic you have to think about. Therefore, you should aim for quick prototyping instead of scalable solutions. Here is a list with the complex option in the first column and simpler option in the second:
# complex simple
1 Mobile app Progressive Web App
2 MySQL/PostgreSQL SQLite
3 Queue worker defer()
4 Broadcast with events Echo whisper
5 Mailgun PHPMailer + gmail
6 ElasticSearch SQL queries
The simpler options also use less resources which means that you can host your app on a cheap VPS for 10$/month.

Friday, September 20, 2024

The role of the CTO

The role of the Chief Technology Officer (CTO):

  1. Understand business goals, assess feasibility, and set technical priorities accordingly. Create a technical roadmap.
  2. In the early stages of the company, be the lead engineer. As the company grows, hire technical personnel, provide guidance to the team.
  3. Review team outputs (code & documentation), ensure effort is aligned with priorities and outputs are clean and of high quality.
  4. Review tests and verify that important test cases are included.
  5. In case of personnel loss, temporarily fill the gap until a replacement is hired.
  6. Oversee IT, CI/CD infrastructure and security.
  7. Stay updated with technological trends.
  8. Represent the company's technological vision to partners, investors, or at industry events.

Thursday, September 19, 2024

Financial projection for startups

If you have a startup and are seeking investment beyond friends and family, you have to offer a product or service with exponential growth potential. Given that most startups fail, linear growth doesn’t justify the risk for investors. Your investors would also like to see your revenue estimates, i.e. financial projection/forecast.

Once you can genuinely convince yourself and others of your startup's exponential growth potential, the next step is to estimate the total addressable market and your projected share of it 12 months after launching your product and beginning aggressive marketing. You should also make a realistic revenue estimate for the first month. Assuming a logistic growth pattern—characterized by rapid early growth that slows as it nears a saturation point—you can then project revenue for each subsequent month.

For example, if revenue at product launch + 1 month is estimated as 30K$, and revenue at +12months as 5M$, the logistic function becomes (n: month):

Using this equation, you can calculate revenue targets for each month:

Friday, August 30, 2024

Why use SQLite?

SQLite is optimized for situations where the workload is predominantly reads with occasional writes, making it ideal for small to medium-sized applications. SQLite is very efficient and can operate comfortably within a few megabytes of RAM.

For highly concurrent environments where many users need to write to the database simultaneously, SQLite might not be the best choice, and a more robust client-server database like MySQL or PostgreSQL would be more appropriate. Recommended RAM for light use for MySQL is 1GB and for PostgreSQL 2GB, which is about 1000 times more than SQLite.

SQLite is an embedded database that runs in the same process as the application using it. This means it doesn’t require a separate server process to manage database connections, unlike MySQL, which operates as a server and listens for incoming connections on a specific port (e.g. 3306). SQLite databases are stored as files on the local filesystem. When an application wants to interact with an SQLite database, it directly accesses the database file without needing to communicate over a network. So with SQLite, if you run multiple apps, there won't be problems like port conflicts or the need for containers.

SQLite doesn't require authentication mechanisms like usernames and passwords. The database file is accessed directly without any user credentials.

If you want to use a cheap (5$/month) VPS with 512GB RAM, SQLite is your only option. It is not just a toy, it is used in popular apps like nomadlist, see Pieter Levels video. You can optimize SQLite even further.

Music: Mike Oldfield - Sentinel