Очистить свои #include операторы?

Они на самом деле не сопоставимы.

Apache Tomcat не является сервером J2EE. Это просто контейнер сервлетов для веб-приложений. Ничего более. Если вам нужны реализации J2EE API, вы должны взять их из других источников. Например, используя сервер Apache Geronimo, который использует Tomcat в качестве своего контейнера, или принимая файлы JAR из Glassfish.

Glassfish - это полный Java-сервер приложений с реализацией для таких API, как JPA, EJB и т. Д. Glassfish содержит Servlet Engine, первоначально использовавшийся Tomcat, но они улучшили его (не знаю, что именно). Более поздние серверы Glassfish используют другой контейнер, использующий grizzly, который использует NIO API для ввода / вывода и достаточно хорошо масштабируется. Насколько я знаю, сервлетный движок Glassfish более производительный. Здесь я нашел хороший тест (хотя он немного староват):

http://weblogs.java.net/blog/sdo/archive/2007/05/how_to_test_con.html

28
задан criddell 18 June 2009 в 19:26
поделиться

9 ответов

Чтобы убедиться, что файлы заголовков включают все, что они нужно, я бы создал исходный файл, все, что он делает, это включает файл заголовка и пытается его скомпилировать. Если компиляция завершится неудачно, то в самом заголовочном файле отсутствует включение.

Вы получите тот же эффект, сделав следующее правило: первый заголовочный файл, который foo .c или foo .cpp должен включать, должен иметь соответствующее имя foo .h. Это гарантирует, что foo .h включает все, что необходимо для компиляции.

Кроме того, в книге Лакоса Крупномасштабное проектирование программного обеспечения C ++ (например) перечислены многие-многие методы для перемещение деталей реализации из заголовка в соответствующий файл CPP. Если вы доведете это до крайности, используя такие методы, как Cheshire Cat (который скрывает все детали реализации) и Factory (который скрывает существование подклассов), то многие заголовки смогут работать самостоятельно, не включая другие заголовки, и вместо этого обходиться только вместо этого передайте объявление непрозрачным типам ... за исключением, возможно, классов шаблонов.

В конце, каждый файл заголовка может нуждаться в включении:

  • Нет файлов заголовков для типов, которые являются членами данных (вместо этого члены данных определены / скрытый в файле CPP с помощью символа " X> как детали реализации определенного пользователем типа, например ListX ).

На практике я мог бы сделать «standard.h», который включает все системные файлы (например, заголовки STL, Типы, специфичные для O / S и / или любые #define s и т. Д.), Которые используются любыми / всеми файлами заголовков в проекте, и включать его в качестве первого заголовка в каждый файл заголовка приложения (и сообщать компилятор обрабатывает этот "standard.h" как "предварительно скомпилированный заголовочный файл").


//contents of foo.h
#ifndef INC_FOO_H //or #pragma once
#define INC_FOO_H

#include "standard.h"
class Foo
{
public: //methods
  ... Foo-specific methods here ...
private: //data
  struct Impl;
  Impl* m_impl;
};
#endif//INC_FOO_H

//contents of foo.cpp
#include "foo.h"
#include "bar.h"
Foo::Foo()
{
  m_impl = new Impl();
}
struct Foo::Impl
{
  Bar m_bar;
  ... etc ...
};
... etc ...
24
ответ дан 28 November 2019 в 03:01
поделиться

У меня есть привычка упорядочивать свои включения с высокого уровня абстракции на низкий уровень абстракции. Для этого требуется, чтобы заголовки были самодостаточными, а скрытые зависимости быстро обнаруживались как ошибки компилятора.

Например, класс «Тетрис» имеет файлы Tetris.h и Tetris.cpp. Порядок включения для Tetris.cpp будет

#include "Tetris.h"     // corresponding header first
#include "Block.h"      // ..then application level includes
#include "Utils/Grid.h" // ..then library dependencies
#include <vector>       // ..then stl
#include <windows.h>    // ..then system includes

И теперь я понимаю, что это не совсем ответ на ваш вопрос, поскольку эта система на самом деле не помогает очистить ненужные включения. Ну что ж ..

11
ответ дан 28 November 2019 в 03:01
поделиться

Обнаружение лишних включений уже обсуждалось в , этот вопрос .

Мне не известны какие-либо инструменты, помогающие обнаруживать недостаточные, но случающиеся с работой, включения , но здесь могут помочь хорошие соглашения о кодировании. Например, в Руководстве по стилю Google C ++ с целью уменьшения скрытых зависимостей предписывается следующее:

В dir / foo.cc , основная цель которого - реализовать или протестировать материал в dir2 / foo2.h , упорядочите ваши включения следующим образом:

  1. dir2 / foo2.h (предпочтительное расположение - см. подробности ниже).
  2. Системные файлы C.
  3. Системные файлы C ++.
6
ответ дан 28 November 2019 в 03:01
поделиться

У вас есть несколько вариантов:

Я неравнодушен к Gtk2.

6
ответ дан 28 November 2019 в 03:01
поделиться

Одна большая проблема с техникой удаления заголовка и перекомпиляции - что это может привести к компиляции, но неправильному или неэффективному коду.

  1. Специализация шаблона: если у вас есть специализация шаблона для определенного типа, который находится в одном заголовке, а более общий шаблон - в другом, удаление специализации может оставить код в компилируемом состоянии, но с нежелательными результатами.

  2. Разрешение перегрузки: аналогичная проблема - если у вас есть две перегрузки одной функции в разных заголовках, но для этого используются несколько совместимые типы, вы можете в конечном итоге удалить версию, которая лучше подходит в одном случае, но при этом код будет скомпилирован. Это, вероятно, менее вероятно, чем версия со специализацией шаблона, но возможно.

5
ответ дан 28 November 2019 в 03:01
поделиться

Я думал написать что-то, что компилирует каждый файл без заголовка индивидуально много раз, каждый раз удаляя #include заявление. Продолжайте делать это, пока достигнут минимальный набор включений.

Я думаю, что это неверно и приведет к "недостаточным, но просто работающим" включаемым наборам.

Предположим, что ваш исходный файл использует numeric_limits , но также включает какой-то заголовочный файл, который по собственным причинам включает . Это не означает, что ваш исходный файл не должен включать . Этот другой файл заголовка, вероятно, не задокументирован для определения всего, что определено в , просто так получилось. Когда-нибудь это может прекратиться: возможно, он использует только одно значение в качестве параметра по умолчанию для некоторой функции, и, возможно, это значение по умолчанию изменится с std :: numeric_limits :: min () на 0. А теперь ваш исходный файл больше не компилируется, а сопровождающий этого файла заголовка даже не знал, что ваш файл существует, пока он не сломал его сборку.

Если у вас не возникнут серьезные проблемы сборки прямо сейчас, я думаю, что лучший способ удалить избыточные включения - это просто войти в привычка просматривать список всякий раз, когда вы касаетесь файла для обслуживания. Если вы обнаружите, что у вас есть десятки включений, и, просмотрев файл, вы все еще не можете понять, для чего каждый из них, подумайте о разделении на файлы меньшего размера.

2
ответ дан 28 November 2019 в 03:01
поделиться

Я обычно создаю один исходный файл (например, main.c) и один файл заголовка для этого исходного файла (main.h). В исходный файл я помещаю все основные виды «интерфейсных» функций, которые использую в этом файле (в основном это будет main () ), а затем все функции, которые я получаю после рефакторинга этих функции (детали реализации) см. ниже. В файле заголовка я объявляю некоторые функции extern , которые определены в других исходных файлах, но используются в исходном файле, который использует этот заголовок. Затем я объявляю любые структуры или другие типы данных, которые использую в этом исходном файле.

Затем я просто компилирую и связываю их все вместе. Он остается красивым и чистым. Типичный раздел include ... в моем текущем проекте выглядит так

#include<windows.h>
#include<windowsx.h>
#include<stdio.h>

#include"interface.h"
#include"thissourcefile.h"

//function prototypes

//source

there ' s заголовок интерфейса , который отслеживает структуры данных, которые я использую во всех формах проекта, а затем thissourcefile.h , который делает именно то, что я только что объяснил (объявляет ] externs и т. д.)

Кроме того, я никогда ничего не определяю в своих заголовках, я только помещаю туда объявления. Таким образом, они могут быть включены в разные исходные файлы и при этом успешно связываться. Прототипы функций (внешние, статические или другие) и объявления помещаются в заголовок, поэтому их можно использовать много раз - определения находятся в исходном коде, потому что они должны быть только в одном месте.

Это, очевидно, будет быть другим, если вы создавали библиотеку или что-то в этом роде. Но я считаю, что это позволяет сохранить все в порядке и чистоте только для внутреннего связывания проекта. Кроме того, если вы напишете make-файл (или просто используете IDE),

-1
ответ дан 28 November 2019 в 03:01
поделиться

Ага. У нас есть собственный препроцессор, который дает нам доступ к нашему собственному макроязыку. Он также проверяет, что файлы заголовков включаются только один раз. Создание простого препроцессора, проверяющего несколько включений, должно быть довольно простым.

1
ответ дан 28 November 2019 в 03:01
поделиться

Что касается инструментов, я использовал Imagix (это было около 6 лет назад) в Windows, чтобы идентифицировать ненужные включения, а также включения, которые необходимы, но косвенно включены через другой включить.

1
ответ дан 28 November 2019 в 03:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: